]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR middle-end/59917
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 Jan 2014 11:02:46 +0000 (11:02 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 Jan 2014 11:02:46 +0000 (11:02 +0000)
PR tree-optimization/59920
* tree.c (build_common_builtin_nodes): Remove
__builtin_setjmp_dispatcher initialization.
* omp-low.h (make_gimple_omp_edges): Add a new int * argument.
* profile.c (branch_prob): Use gsi_start_nondebug_after_labels_bb
instead of gsi_after_labels + manually skipping debug stmts.
Don't ignore bbs with BUILT_IN_SETJMP_DISPATCHER, instead
ignore bbs with IFN_ABNORMAL_DISPATCHER.
* tree-inline.c (copy_edges_for_bb): Remove
can_make_abnormal_goto argument, instead add abnormal_goto_dest
argument.  Ignore computed_goto_p stmts.  Don't call
make_abnormal_goto_edges.  If a call might need abnormal edges
for non-local gotos, see if it already has an edge to
IFN_ABNORMAL_DISPATCHER or if it is IFN_ABNORMAL_DISPATCHER
with true argument, don't do anything then, otherwise add
EDGE_ABNORMAL from the call's bb to abnormal_goto_dest.
(copy_cfg_body): Compute abnormal_goto_dest, adjust copy_edges_for_bb
caller.
* gimple-low.c (struct lower_data): Remove calls_builtin_setjmp.
(lower_function_body): Don't emit __builtin_setjmp_dispatcher.
(lower_stmt): Don't set data->calls_builtin_setjmp.
(lower_builtin_setjmp): Adjust comment.
* builtins.def (BUILT_IN_SETJMP_DISPATCHER): Remove.
* tree-cfg.c (found_computed_goto): Remove.
(factor_computed_gotos): Remove.
(make_goto_expr_edges): Return bool, true for computed gotos.
Don't call make_abnormal_goto_edges.
(build_gimple_cfg): Don't set found_computed_goto, don't call
factor_computed_gotos.
(computed_goto_p): No longer static.
(make_blocks): Don't set found_computed_goto.
(get_abnormal_succ_dispatcher, handle_abnormal_edges): New functions.
(make_edges): If make_goto_expr_edges returns true, push bb
into ab_edge_goto vector, for stmt_can_make_abnormal_goto calls
instead of calling make_abnormal_goto_edges push bb into ab_edge_call
vector.  Record mapping between bbs and OpenMP regions if there
are any, adjust make_gimple_omp_edges caller.  Call
handle_abnormal_edges.
(make_abnormal_goto_edges): Remove.
* tree-cfg.h (make_abnormal_goto_edges): Remove.
(computed_goto_p, get_abnormal_succ_dispatcher): New prototypes.
* internal-fn.c (expand_ABNORMAL_DISPATCHER): New function.
* builtins.c (expand_builtin): Don't handle
BUILT_IN_SETJMP_DISPATCHER.
* internal-fn.def (ABNORMAL_DISPATCHER): New.
* omp-low.c (make_gimple_omp_edges): Add region_idx argument, when
filling *region also set *region_idx to (*region)->entry->index.

* gcc.dg/pr59920-1.c: New test.
* gcc.dg/pr59920-2.c: New test.
* gcc.dg/pr59920-3.c: New test.
* c-c++-common/gomp/pr59917-1.c: New test.
* c-c++-common/gomp/pr59917-2.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207231 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/gimple-low.c
gcc/internal-fn.c
gcc/internal-fn.def
gcc/omp-low.c
gcc/omp-low.h
gcc/profile.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/gomp/pr59917-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/pr59917-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr59920-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr59920-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr59920-3.c [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-cfg.h
gcc/tree-inline.c
gcc/tree.c

index c8a165828ac559eaf04890e9e297e956c4e03b76..14f0cfb6e18c2d7770974a19db2b128d98cd08f7 100644 (file)
@@ -1,5 +1,54 @@
 2014-01-29  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/59917
+       PR tree-optimization/59920
+       * tree.c (build_common_builtin_nodes): Remove
+       __builtin_setjmp_dispatcher initialization.
+       * omp-low.h (make_gimple_omp_edges): Add a new int * argument.
+       * profile.c (branch_prob): Use gsi_start_nondebug_after_labels_bb
+       instead of gsi_after_labels + manually skipping debug stmts.
+       Don't ignore bbs with BUILT_IN_SETJMP_DISPATCHER, instead
+       ignore bbs with IFN_ABNORMAL_DISPATCHER.
+       * tree-inline.c (copy_edges_for_bb): Remove
+       can_make_abnormal_goto argument, instead add abnormal_goto_dest
+       argument.  Ignore computed_goto_p stmts.  Don't call
+       make_abnormal_goto_edges.  If a call might need abnormal edges
+       for non-local gotos, see if it already has an edge to
+       IFN_ABNORMAL_DISPATCHER or if it is IFN_ABNORMAL_DISPATCHER
+       with true argument, don't do anything then, otherwise add
+       EDGE_ABNORMAL from the call's bb to abnormal_goto_dest.
+       (copy_cfg_body): Compute abnormal_goto_dest, adjust copy_edges_for_bb
+       caller.
+       * gimple-low.c (struct lower_data): Remove calls_builtin_setjmp.
+       (lower_function_body): Don't emit __builtin_setjmp_dispatcher.
+       (lower_stmt): Don't set data->calls_builtin_setjmp.
+       (lower_builtin_setjmp): Adjust comment.
+       * builtins.def (BUILT_IN_SETJMP_DISPATCHER): Remove.
+       * tree-cfg.c (found_computed_goto): Remove.
+       (factor_computed_gotos): Remove.
+       (make_goto_expr_edges): Return bool, true for computed gotos.
+       Don't call make_abnormal_goto_edges.
+       (build_gimple_cfg): Don't set found_computed_goto, don't call
+       factor_computed_gotos.
+       (computed_goto_p): No longer static.
+       (make_blocks): Don't set found_computed_goto.
+       (get_abnormal_succ_dispatcher, handle_abnormal_edges): New functions.
+       (make_edges): If make_goto_expr_edges returns true, push bb
+       into ab_edge_goto vector, for stmt_can_make_abnormal_goto calls
+       instead of calling make_abnormal_goto_edges push bb into ab_edge_call
+       vector.  Record mapping between bbs and OpenMP regions if there
+       are any, adjust make_gimple_omp_edges caller.  Call
+       handle_abnormal_edges.
+       (make_abnormal_goto_edges): Remove.
+       * tree-cfg.h (make_abnormal_goto_edges): Remove.
+       (computed_goto_p, get_abnormal_succ_dispatcher): New prototypes.
+       * internal-fn.c (expand_ABNORMAL_DISPATCHER): New function.
+       * builtins.c (expand_builtin): Don't handle
+       BUILT_IN_SETJMP_DISPATCHER.
+       * internal-fn.def (ABNORMAL_DISPATCHER): New.
+       * omp-low.c (make_gimple_omp_edges): Add region_idx argument, when
+       filling *region also set *region_idx to (*region)->entry->index.
+
        PR other/58712
        * read-rtl.c (read_rtx_code): Clear all of RTX_CODE_SIZE (code).
        For REGs set ORIGINAL_REGNO.
index 3e34c83858bc76efb2d433ea4585b7b7cb85817f..a45380ce8776f482f168803c73d29153092e42ab 100644 (file)
@@ -6205,20 +6205,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        }
       break;
 
-    case BUILT_IN_SETJMP_DISPATCHER:
-       /* __builtin_setjmp_dispatcher is passed the dispatcher label.  */
-      if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
-       {
-         tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
-         rtx label_r = label_rtx (label);
-
-         /* Remove the dispatcher label from the list of non-local labels
-            since the receiver labels have been added to it above.  */
-         remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
-         return const0_rtx;
-       }
-      break;
-
     case BUILT_IN_SETJMP_RECEIVER:
        /* __builtin_setjmp_receiver is passed the receiver label.  */
       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
index 524153f22a595a1c1f9eeab3b800bde6b4a930ec..2443a45751b5bfc475a571b7ccc3268dea2fd03e 100644 (file)
@@ -783,7 +783,6 @@ DEF_BUILTIN_STUB (BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto")
 
 /* Implementing __builtin_setjmp.  */
 DEF_BUILTIN_STUB (BUILT_IN_SETJMP_SETUP, "__builtin_setjmp_setup")
-DEF_BUILTIN_STUB (BUILT_IN_SETJMP_DISPATCHER, "__builtin_setjmp_dispatcher")
 DEF_BUILTIN_STUB (BUILT_IN_SETJMP_RECEIVER, "__builtin_setjmp_receiver")
 
 /* Implementing variable sized local variables.  */
index 8d2e71103a4faef30d7cd05d9730fe6b21e03980..c60e8177d389b263171232d450dde19419d5231d 100644 (file)
@@ -76,9 +76,6 @@ struct lower_data
 
   /* True if the current statement cannot fall through.  */
   bool cannot_fallthru;
-
-  /* True if the function calls __builtin_setjmp.  */
-  bool calls_builtin_setjmp;
 };
 
 static void lower_stmt (gimple_stmt_iterator *, struct lower_data *);
@@ -99,7 +96,6 @@ lower_function_body (void)
   gimple_seq lowered_body;
   gimple_stmt_iterator i;
   gimple bind;
-  tree t;
   gimple x;
 
   /* The gimplifier should've left a body of exactly one statement,
@@ -146,34 +142,6 @@ lower_function_body (void)
       gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING);
     }
 
-  /* If the function calls __builtin_setjmp, we need to emit the computed
-     goto that will serve as the unique dispatcher for all the receivers.  */
-  if (data.calls_builtin_setjmp)
-    {
-      tree disp_label, disp_var, arg;
-
-      /* Build 'DISP_LABEL:' and insert.  */
-      disp_label = create_artificial_label (cfun->function_end_locus);
-      /* This mark will create forward edges from every call site.  */
-      DECL_NONLOCAL (disp_label) = 1;
-      cfun->has_nonlocal_label = 1;
-      x = gimple_build_label (disp_label);
-      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
-
-      /* Build 'DISP_VAR = __builtin_setjmp_dispatcher (DISP_LABEL);'
-        and insert.  */
-      disp_var = create_tmp_var (ptr_type_node, "setjmpvar");
-      arg = build_addr (disp_label, current_function_decl);
-      t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER);
-      x = gimple_build_call (t, 1, arg);
-      gimple_call_set_lhs (x, disp_var);
-
-      /* Build 'goto DISP_VAR;' and insert.  */
-      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
-      x = gimple_build_goto (disp_var);
-      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
-    }
-
   /* Once the old body has been lowered, replace it with the new
      lowered sequence.  */
   gimple_set_body (current_function_decl, lowered_body);
@@ -364,7 +332,6 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
          {
            lower_builtin_setjmp (gsi);
            data->cannot_fallthru = false;
-           data->calls_builtin_setjmp = true;
            return;
          }
 
@@ -689,15 +656,12 @@ lower_gimple_return (gimple_stmt_iterator *gsi, struct lower_data *data)
    all will be used on all machines).  It operates similarly to the C
    library function of the same name, but is more efficient.
 
-   It is lowered into 3 other builtins, namely __builtin_setjmp_setup,
-   __builtin_setjmp_dispatcher and __builtin_setjmp_receiver, but with
-   __builtin_setjmp_dispatcher shared among all the instances; that's
-   why it is only emitted at the end by lower_function_body.
+   It is lowered into 2 other builtins, namely __builtin_setjmp_setup,
+   __builtin_setjmp_receiver.
 
    After full lowering, the body of the function should look like:
 
     {
-      void * setjmpvar.0;
       int D.1844;
       int D.2844;
 
@@ -727,14 +691,13 @@ lower_gimple_return (gimple_stmt_iterator *gsi, struct lower_data *data)
 
       <D3850>:;
       return;
-      <D3853>: [non-local];
-      setjmpvar.0 = __builtin_setjmp_dispatcher (&<D3853>);
-      goto setjmpvar.0;
     }
 
-   The dispatcher block will be both the unique destination of all the
-   abnormal call edges and the unique source of all the abnormal edges
-   to the receivers, thus keeping the complexity explosion localized.  */
+   During cfg creation an extra per-function (or per-OpenMP region)
+   block with ABNORMAL_DISPATCHER internal call will be added, unique
+   destination of all the abnormal call edges and the unique source of
+   all the abnormal edges to the receivers, thus keeping the complexity
+   explosion localized.  */
 
 static void
 lower_builtin_setjmp (gimple_stmt_iterator *gsi)
index 87a42e7e32ce2e7414c1fb6fb18442e5f6d55f85..43aaecba9718df0d045b4dd2dcb421625284c626 100644 (file)
@@ -857,6 +857,11 @@ expand_MASK_STORE (gimple stmt)
   expand_insn (optab_handler (maskstore_optab, TYPE_MODE (type)), 3, ops);
 }
 
+static void
+expand_ABNORMAL_DISPATCHER (gimple)
+{
+}
+
 /* Routines to expand each internal function, indexed by function number.
    Each routine has the prototype:
 
index ca93a0354a266b42d136a57c501e28d02788a13d..379b35241b51f263cf6a93999ceba4c7d156c92a 100644 (file)
@@ -51,3 +51,4 @@ DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN)
index eeba4ae84706f49eee97b39e94724fdbb59c4cea..d7589aa9ec14e9b544b5e056966ec437a4028276 100644 (file)
@@ -10449,7 +10449,8 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
    codes.  */
 bool
-make_gimple_omp_edges (basic_block bb, struct omp_region **region)
+make_gimple_omp_edges (basic_block bb, struct omp_region **region,
+                      int *region_idx)
 {
   gimple last = last_stmt (bb);
   enum gimple_code code = gimple_code (last);
@@ -10556,7 +10557,13 @@ make_gimple_omp_edges (basic_block bb, struct omp_region **region)
     }
 
   if (*region != cur_region)
-    *region = cur_region;
+    {
+      *region = cur_region;
+      if (cur_region)
+       *region_idx = cur_region->entry->index;
+      else
+       *region_idx = 0;
+    }
 
   return fallthru;
 }
index ce9cef9f5dd3217379f0ae85f3b94cf58912cf54..d80c2d6f5c08566b9025ea48e7ebe698c3984baa 100644 (file)
@@ -26,6 +26,6 @@ extern tree find_omp_clause (tree, enum omp_clause_code);
 extern void omp_expand_local (basic_block);
 extern void free_omp_regions (void);
 extern tree omp_reduction_init (tree, tree);
-extern bool make_gimple_omp_edges (basic_block, struct omp_region **);
+extern bool make_gimple_omp_edges (basic_block, struct omp_region **, int *);
 
 #endif /* GCC_OMP_LOW_H */
index e549453bfad6950e9a16ceab193f806cb40f5b8d..752d89fc3d87f3ffaf0fab1f06ebbd77e30ba916 100644 (file)
@@ -1106,27 +1106,22 @@ branch_prob (void)
              gimple first;
              tree fndecl;
 
-             gsi = gsi_after_labels (bb);
+             gsi = gsi_start_nondebug_after_labels_bb (bb);
              gcc_checking_assert (!gsi_end_p (gsi));
              first = gsi_stmt (gsi);
-             if (is_gimple_debug (first))
-               {
-                 gsi_next_nondebug (&gsi);
-                 gcc_checking_assert (!gsi_end_p (gsi));
-                 first = gsi_stmt (gsi);
-               }
              /* Don't split the bbs containing __builtin_setjmp_receiver
-                or __builtin_setjmp_dispatcher calls.  These are very
+                or ABNORMAL_DISPATCHER calls.  These are very
                 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
-                          || (DECL_FUNCTION_CODE (fndecl)
-                              == BUILT_IN_SETJMP_DISPATCHER)))
-                     || gimple_call_flags (first) & ECF_RETURNS_TWICE))
+                          == BUILT_IN_SETJMP_RECEIVER))
+                     || (gimple_call_flags (first) & ECF_RETURNS_TWICE)
+                     || (gimple_call_internal_p (first)
+                         && (gimple_call_internal_fn (first)
+                             == IFN_ABNORMAL_DISPATCHER))))
                continue;
 
              if (dump_file)
index 191845a3b35daf200f4efee3d56634374a92956d..a4684473ab7b1c08e4484301071b157c1fc786a1 100644 (file)
@@ -1,5 +1,13 @@
 2014-01-29  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/59917
+       PR tree-optimization/59920
+       * gcc.dg/pr59920-1.c: New test.
+       * gcc.dg/pr59920-2.c: New test.
+       * gcc.dg/pr59920-3.c: New test.
+       * c-c++-common/gomp/pr59917-1.c: New test.
+       * c-c++-common/gomp/pr59917-2.c: New test.
+
        PR tree-optimization/59594
        * gcc.dg/vect/no-vfa-vect-depend-2.c: New test.
        * gcc.dg/vect/no-vfa-vect-depend-3.c: New test.
diff --git a/gcc/testsuite/c-c++-common/gomp/pr59917-1.c b/gcc/testsuite/c-c++-common/gomp/pr59917-1.c
new file mode 100644 (file)
index 0000000..cca3976
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR middle-end/59917 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp" } */
+
+struct J { long buf[8]; };
+extern int setjmp (struct J[1]);
+extern struct J j[1];
+void foo (int);
+
+void
+bar (void)
+{
+  if (setjmp (j) == 0)
+    {
+      int k;
+      foo (-1);
+#pragma omp parallel
+      for (k = 0; k < 10; ++k)
+       foo (k);
+      foo (-2);
+    }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr59917-2.c b/gcc/testsuite/c-c++-common/gomp/pr59917-2.c
new file mode 100644 (file)
index 0000000..1d60342
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR middle-end/59917 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp" } */
+
+struct J { long buf[8]; };
+extern int setjmp (struct J[1]);
+void foo (int);
+
+void
+bar (void)
+{
+  int k;
+  foo (-1);
+#pragma omp parallel
+  for (k = 0; k < 10; ++k)
+    {
+      struct J j[1];
+      if (setjmp (j) == 0)
+       foo (k);
+    }
+  foo (-2);
+}
diff --git a/gcc/testsuite/gcc.dg/pr59920-1.c b/gcc/testsuite/gcc.dg/pr59920-1.c
new file mode 100644 (file)
index 0000000..3e60d37
--- /dev/null
@@ -0,0 +1,20 @@
+/* PR tree-optimization/59920 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+#include <setjmp.h>
+
+int bar (void);
+void baz (int);
+
+#define A { int x = bar (); if (setjmp (buf) == 0) baz (x); }
+#define B A A A A A A A A A A
+#define C B B B B B B B B B B
+
+extern jmp_buf buf;
+
+void
+foo (void)
+{
+  C C
+}
diff --git a/gcc/testsuite/gcc.dg/pr59920-2.c b/gcc/testsuite/gcc.dg/pr59920-2.c
new file mode 100644 (file)
index 0000000..bee5542
--- /dev/null
@@ -0,0 +1,30 @@
+/* PR tree-optimization/59920 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+void *bar (void **);
+void *baz (int, void **);
+
+#define A(n) \
+  { __label__ l1_##n, l2_##n, l3_##n;                  \
+    static void *a[] = { &&l1_##n, &&l2_##n, &&l3_##n };\
+    void *b = bar (a);                                 \
+    goto *b;                                           \
+   l1_##n:                                             \
+    b = baz (1, a);                                    \
+    goto *b;                                           \
+   l2_##n:                                             \
+    b = baz (2, a);                                    \
+    goto *b;                                           \
+   l3_##n:;                                            \
+  }
+#define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) \
+            A(n##5) A(n##6) A(n##7) A(n##8) A(n##9)
+#define C(n) B(n##0) B(n##1) B(n##2) B(n##3) B(n##4) \
+            B(n##5) B(n##6) B(n##7) B(n##8) B(n##9)
+
+void
+foo (void)
+{
+  C(1)
+}
diff --git a/gcc/testsuite/gcc.dg/pr59920-3.c b/gcc/testsuite/gcc.dg/pr59920-3.c
new file mode 100644 (file)
index 0000000..2159504
--- /dev/null
@@ -0,0 +1,47 @@
+/* PR tree-optimization/59920 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+void *bar (void **);
+void *baz (int, void **);
+
+#define A(n) __label__ l##n;
+#define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) \
+            A(n##5) A(n##6) A(n##7) A(n##8) A(n##9)
+#define C(n) B(n##0) B(n##1) B(n##2) B(n##3) B(n##4) \
+            B(n##5) B(n##6) B(n##7) B(n##8) B(n##9)
+#define D C(1)
+
+int
+foo (void)
+{
+  D
+  int bar (int i)
+  {
+    switch (i)
+      {
+#undef A
+#define A(n) \
+      case n: goto l##n;
+      D
+      }
+    return i;
+  }
+  int w = 0;
+#undef A
+#define A(n) int w##n = 0;
+  D
+#undef A
+#define A(n) \
+  { l##n:;                             \
+    w##n += bar (10000 + n) - 10000;   \
+    w##n += bar (10001 + n) - 10000;   \
+    bar (n + 1);                       \
+    return w##n;                       \
+  }
+  D
+#undef A
+#define A(n) w += w##n;
+  D
+  return w;
+}
index 32110a7fafac268a5e69a015edb7c8785eadc601..dfc9b7b4cef14add84b2c8570ff9c57eee3cb8a2 100644 (file)
@@ -106,9 +106,6 @@ struct cfg_stats_d
 
 static struct cfg_stats_d cfg_stats;
 
-/* Nonzero if we found a computed goto while building basic blocks.  */
-static bool found_computed_goto;
-
 /* Hash table to store last discriminator assigned for each locus.  */
 struct locus_discrim_map
 {
@@ -148,14 +145,13 @@ static hash_table <locus_discrim_hasher> discriminator_per_locus;
 
 /* Basic blocks and flowgraphs.  */
 static void make_blocks (gimple_seq);
-static void factor_computed_gotos (void);
 
 /* Edges.  */
 static void make_edges (void);
 static void assign_discriminators (void);
 static void make_cond_expr_edges (basic_block);
 static void make_gimple_switch_edges (basic_block);
-static void make_goto_expr_edges (basic_block);
+static bool make_goto_expr_edges (basic_block);
 static void make_gimple_asm_edges (basic_block);
 static edge gimple_redirect_edge_and_branch (edge, basic_block);
 static edge gimple_try_redirect_by_replacing_jump (edge, basic_block);
@@ -225,17 +221,8 @@ build_gimple_cfg (gimple_seq seq)
 
   init_empty_tree_cfg ();
 
-  found_computed_goto = 0;
   make_blocks (seq);
 
-  /* Computed gotos are hell to deal with, especially if there are
-     lots of them with a large number of destinations.  So we factor
-     them to a common computed goto location before we build the
-     edge list.  After we convert back to normal form, we will un-factor
-     the computed gotos since factoring introduces an unwanted jump.  */
-  if (found_computed_goto)
-    factor_computed_gotos ();
-
   /* Make sure there is always at least one block, even if it's empty.  */
   if (n_basic_blocks_for_fn (cfun) == NUM_FIXED_BLOCKS)
     create_empty_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
@@ -385,7 +372,7 @@ make_pass_build_cfg (gcc::context *ctxt)
 
 /* Return true if T is a computed goto.  */
 
-static bool
+bool
 computed_goto_p (gimple t)
 {
   return (gimple_code (t) == GIMPLE_GOTO
@@ -437,82 +424,6 @@ assert_unreachable_fallthru_edge_p (edge e)
 }
 
 
-/* Search the CFG for any computed gotos.  If found, factor them to a
-   common computed goto site.  Also record the location of that site so
-   that we can un-factor the gotos after we have converted back to
-   normal form.  */
-
-static void
-factor_computed_gotos (void)
-{
-  basic_block bb;
-  tree factored_label_decl = NULL;
-  tree var = NULL;
-  gimple factored_computed_goto_label = NULL;
-  gimple factored_computed_goto = NULL;
-
-  /* We know there are one or more computed gotos in this function.
-     Examine the last statement in each basic block to see if the block
-     ends with a computed goto.  */
-
-  FOR_EACH_BB_FN (bb, cfun)
-    {
-      gimple_stmt_iterator gsi = gsi_last_bb (bb);
-      gimple last;
-
-      if (gsi_end_p (gsi))
-       continue;
-
-      last = gsi_stmt (gsi);
-
-      /* Ignore the computed goto we create when we factor the original
-        computed gotos.  */
-      if (last == factored_computed_goto)
-       continue;
-
-      /* If the last statement is a computed goto, factor it.  */
-      if (computed_goto_p (last))
-       {
-         gimple assignment;
-
-         /* The first time we find a computed goto we need to create
-            the factored goto block and the variable each original
-            computed goto will use for their goto destination.  */
-         if (!factored_computed_goto)
-           {
-             basic_block new_bb = create_empty_bb (bb);
-             gimple_stmt_iterator new_gsi = gsi_start_bb (new_bb);
-
-             /* Create the destination of the factored goto.  Each original
-                computed goto will put its desired destination into this
-                variable and jump to the label we create immediately
-                below.  */
-             var = create_tmp_var (ptr_type_node, "gotovar");
-
-             /* Build a label for the new block which will contain the
-                factored computed goto.  */
-             factored_label_decl = create_artificial_label (UNKNOWN_LOCATION);
-             factored_computed_goto_label
-               = gimple_build_label (factored_label_decl);
-             gsi_insert_after (&new_gsi, factored_computed_goto_label,
-                               GSI_NEW_STMT);
-
-             /* Build our new computed goto.  */
-             factored_computed_goto = gimple_build_goto (var);
-             gsi_insert_after (&new_gsi, factored_computed_goto, GSI_NEW_STMT);
-           }
-
-         /* Copy the original computed goto's destination into VAR.  */
-         assignment = gimple_build_assign (var, gimple_goto_dest (last));
-         gsi_insert_before (&gsi, assignment, GSI_SAME_STMT);
-
-         /* And re-vector the computed goto to the new destination.  */
-         gimple_goto_set_dest (last, factored_label_decl);
-       }
-    }
-}
-
-
 /* Build a flowgraph for the sequence of stmts SEQ.  */
 
 static void
@@ -546,9 +457,6 @@ make_blocks (gimple_seq seq)
         codes.  */
       gimple_set_bb (stmt, bb);
 
-      if (computed_goto_p (stmt))
-       found_computed_goto = true;
-
       /* If STMT is a basic block terminator, set START_NEW_BLOCK for the
         next iteration.  */
       if (stmt_ends_bb_p (stmt))
@@ -666,6 +574,144 @@ fold_cond_expr_cond (void)
     }
 }
 
+/* If basic block BB has an abnormal edge to a basic block
+   containing IFN_ABNORMAL_DISPATCHER internal call, return
+   that the dispatcher's basic block, otherwise return NULL.  */
+
+basic_block
+get_abnormal_succ_dispatcher (basic_block bb)
+{
+  edge e;
+  edge_iterator ei;
+
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    if ((e->flags & (EDGE_ABNORMAL | EDGE_EH)) == EDGE_ABNORMAL)
+      {
+       gimple_stmt_iterator gsi
+         = gsi_start_nondebug_after_labels_bb (e->dest);
+       gimple g = gsi_stmt (gsi);
+       if (g
+           && is_gimple_call (g)
+           && gimple_call_internal_p (g)
+           && gimple_call_internal_fn (g) == IFN_ABNORMAL_DISPATCHER)
+         return e->dest;
+      }
+  return NULL;
+}
+
+/* Helper function for make_edges.  Create a basic block with
+   with ABNORMAL_DISPATCHER internal call in it if needed, and
+   create abnormal edges from BBS to it and from it to FOR_BB
+   if COMPUTED_GOTO is false, otherwise factor the computed gotos.  */
+
+static void
+handle_abnormal_edges (basic_block *dispatcher_bbs,
+                      basic_block for_bb, int *bb_to_omp_idx,
+                      auto_vec<basic_block> *bbs, bool computed_goto)
+{
+  basic_block *dispatcher = dispatcher_bbs + (computed_goto ? 1 : 0);
+  unsigned int idx = 0;
+  basic_block bb;
+  bool inner = false;
+
+  if (bb_to_omp_idx)
+    {
+      dispatcher = dispatcher_bbs + 2 * bb_to_omp_idx[for_bb->index];
+      if (bb_to_omp_idx[for_bb->index] != 0)
+       inner = true;
+    }
+
+  /* If the dispatcher has been created already, then there are basic
+     blocks with abnormal edges to it, so just make a new edge to
+     for_bb.  */
+  if (*dispatcher == NULL)
+    {
+      /* Check if there are any basic blocks that need to have
+        abnormal edges to this dispatcher.  If there are none, return
+        early.  */
+      if (bb_to_omp_idx == NULL)
+       {
+         if (bbs->is_empty ())
+           return;
+       }
+      else
+       {
+         FOR_EACH_VEC_ELT (*bbs, idx, bb)
+           if (bb_to_omp_idx[bb->index] == bb_to_omp_idx[for_bb->index])
+             break;
+         if (bb == NULL)
+           return;
+       }
+
+      /* Create the dispatcher bb.  */
+      *dispatcher = create_basic_block (NULL, NULL, for_bb);
+      if (computed_goto)
+       {
+         /* Factor computed gotos into a common computed goto site.  Also
+            record the location of that site so that we can un-factor the
+            gotos after we have converted back to normal form.  */
+         gimple_stmt_iterator gsi = gsi_start_bb (*dispatcher);
+
+         /* Create the destination of the factored goto.  Each original
+            computed goto will put its desired destination into this
+            variable and jump to the label we create immediately below.  */
+         tree var = create_tmp_var (ptr_type_node, "gotovar");
+
+         /* Build a label for the new block which will contain the
+            factored computed goto.  */
+         tree factored_label_decl
+           = create_artificial_label (UNKNOWN_LOCATION);
+         gimple factored_computed_goto_label
+           = gimple_build_label (factored_label_decl);
+         gsi_insert_after (&gsi, factored_computed_goto_label, GSI_NEW_STMT);
+
+         /* Build our new computed goto.  */
+         gimple factored_computed_goto = gimple_build_goto (var);
+         gsi_insert_after (&gsi, factored_computed_goto, GSI_NEW_STMT);
+
+         FOR_EACH_VEC_ELT (*bbs, idx, bb)
+           {
+             if (bb_to_omp_idx
+                 && bb_to_omp_idx[bb->index] != bb_to_omp_idx[for_bb->index])
+               continue;
+
+             gsi = gsi_last_bb (bb);
+             gimple last = gsi_stmt (gsi);
+
+             gcc_assert (computed_goto_p (last));
+
+             /* Copy the original computed goto's destination into VAR.  */
+             gimple assignment
+               = gimple_build_assign (var, gimple_goto_dest (last));
+             gsi_insert_before (&gsi, assignment, GSI_SAME_STMT);
+
+             edge e = make_edge (bb, *dispatcher, EDGE_FALLTHRU);
+             e->goto_locus = gimple_location (last);
+             gsi_remove (&gsi, true);
+           }
+       }
+      else
+       {
+         tree arg = inner ? boolean_true_node : boolean_false_node;
+         gimple g = gimple_build_call_internal (IFN_ABNORMAL_DISPATCHER,
+                                                1, arg);
+         gimple_stmt_iterator gsi = gsi_after_labels (*dispatcher);
+         gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+
+         /* Create predecessor edges of the dispatcher.  */
+         FOR_EACH_VEC_ELT (*bbs, idx, bb)
+           {
+             if (bb_to_omp_idx
+                 && bb_to_omp_idx[bb->index] != bb_to_omp_idx[for_bb->index])
+               continue;
+             make_edge (bb, *dispatcher, EDGE_ABNORMAL);
+           }
+       }
+    }
+
+  make_edge (*dispatcher, for_bb, EDGE_ABNORMAL);
+}
+
 /* Join all the blocks in the flowgraph.  */
 
 static void
@@ -673,6 +719,10 @@ make_edges (void)
 {
   basic_block bb;
   struct omp_region *cur_region = NULL;
+  auto_vec<basic_block> ab_edge_goto;
+  auto_vec<basic_block> ab_edge_call;
+  int *bb_to_omp_idx = NULL;
+  int cur_omp_region_idx = 0;
 
   /* Create an edge from entry to the first block with executable
      statements in it.  */
@@ -686,13 +736,17 @@ make_edges (void)
       gimple last = last_stmt (bb);
       bool fallthru;
 
+      if (bb_to_omp_idx)
+       bb_to_omp_idx[bb->index] = cur_omp_region_idx;
+
       if (last)
        {
          enum gimple_code code = gimple_code (last);
          switch (code)
            {
            case GIMPLE_GOTO:
-             make_goto_expr_edges (bb);
+             if (make_goto_expr_edges (bb))
+               ab_edge_goto.safe_push (bb);
              fallthru = false;
              break;
            case GIMPLE_RETURN:
@@ -720,7 +774,7 @@ make_edges (void)
                 make edges from this call site to all the nonlocal goto
                 handlers.  */
              if (stmt_can_make_abnormal_goto (last))
-               make_abnormal_goto_edges (bb, true);
+               ab_edge_call.safe_push (bb);
 
              /* If this statement has reachable exception handlers, then
                 create abnormal edges to them.  */
@@ -728,8 +782,10 @@ make_edges (void)
 
              /* BUILTIN_RETURN is really a return statement.  */
              if (gimple_call_builtin_p (last, BUILT_IN_RETURN))
-               make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0), fallthru =
-            false;
+               {
+                 make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+                 fallthru = false;
+               }
              /* Some calls are known not to return.  */
              else
                fallthru = !(gimple_call_flags (last) & ECF_NORETURN);
@@ -749,7 +805,10 @@ make_edges (void)
              break;
 
            CASE_GIMPLE_OMP:
-             fallthru = make_gimple_omp_edges (bb, &cur_region);
+             fallthru = make_gimple_omp_edges (bb, &cur_region,
+                                               &cur_omp_region_idx);
+             if (cur_region && bb_to_omp_idx == NULL)
+               bb_to_omp_idx = XCNEWVEC (int, n_basic_blocks_for_fn (cfun));
              break;
 
            case GIMPLE_TRANSACTION:
@@ -773,6 +832,77 @@ make_edges (void)
        make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
     }
 
+  /* Computed gotos are hell to deal with, especially if there are
+     lots of them with a large number of destinations.  So we factor
+     them to a common computed goto location before we build the
+     edge list.  After we convert back to normal form, we will un-factor
+     the computed gotos since factoring introduces an unwanted jump.
+     For non-local gotos and abnormal edges from calls to calls that return
+     twice or forced labels, factor the abnormal edges too, by having all
+     abnormal edges from the calls go to a common artificial basic block
+     with ABNORMAL_DISPATCHER internal call and abnormal edges from that
+     basic block to all forced labels and calls returning twice.
+     We do this per-OpenMP structured block, because those regions
+     are guaranteed to be single entry single exit by the standard,
+     so it is not allowed to enter or exit such regions abnormally this way,
+     thus all computed gotos, non-local gotos and setjmp/longjmp calls
+     must not transfer control across SESE region boundaries.  */
+  if (!ab_edge_goto.is_empty () || !ab_edge_call.is_empty ())
+    {
+      gimple_stmt_iterator gsi;
+      basic_block dispatcher_bb_array[2] = { NULL, NULL };
+      basic_block *dispatcher_bbs = dispatcher_bb_array;
+      int count = n_basic_blocks_for_fn (cfun);
+
+      if (bb_to_omp_idx)
+       dispatcher_bbs = XCNEWVEC (basic_block, 2 * count);
+
+      FOR_EACH_BB_FN (bb, cfun)
+       {
+         for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+           {
+             gimple label_stmt = gsi_stmt (gsi);
+             tree target;
+
+             if (gimple_code (label_stmt) != GIMPLE_LABEL)
+               break;
+
+             target = gimple_label_label (label_stmt);
+
+             /* Make an edge to every label block that has been marked as a
+                potential target for a computed goto or a non-local goto.  */
+             if (FORCED_LABEL (target))
+               handle_abnormal_edges (dispatcher_bbs, bb, bb_to_omp_idx,
+                                      &ab_edge_goto, true);
+             if (DECL_NONLOCAL (target))
+               {
+                 handle_abnormal_edges (dispatcher_bbs, bb, bb_to_omp_idx,
+                                        &ab_edge_call, false);
+                 break;
+               }
+           }
+
+         if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
+           gsi_next_nondebug (&gsi);
+         if (!gsi_end_p (gsi))
+           {
+             /* Make an edge to every setjmp-like call.  */
+             gimple call_stmt = gsi_stmt (gsi);
+             if (is_gimple_call (call_stmt)
+                 && ((gimple_call_flags (call_stmt) & ECF_RETURNS_TWICE)
+                     || gimple_call_builtin_p (call_stmt,
+                                               BUILT_IN_SETJMP_RECEIVER)))
+               handle_abnormal_edges (dispatcher_bbs, bb, bb_to_omp_idx,
+                                      &ab_edge_call, false);
+           }
+       }
+
+      if (bb_to_omp_idx)
+       XDELETE (dispatcher_bbs);
+    }
+
+  XDELETE (bb_to_omp_idx);
+
   free_omp_regions ();
 
   /* Fold COND_EXPR_COND of each COND_EXPR.  */
@@ -1045,53 +1175,10 @@ label_to_block_fn (struct function *ifun, tree dest)
   return (*ifun->cfg->x_label_to_block_map)[uid];
 }
 
-/* Create edges for an abnormal goto statement at block BB.  If FOR_CALL
-   is true, the source statement is a CALL_EXPR instead of a GOTO_EXPR.  */
-
-void
-make_abnormal_goto_edges (basic_block bb, bool for_call)
-{
-  basic_block target_bb;
-  gimple_stmt_iterator gsi;
-
-  FOR_EACH_BB_FN (target_bb, cfun)
-    {
-      for (gsi = gsi_start_bb (target_bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       {
-         gimple label_stmt = gsi_stmt (gsi);
-         tree target;
-
-         if (gimple_code (label_stmt) != GIMPLE_LABEL)
-           break;
-
-         target = gimple_label_label (label_stmt);
-
-         /* Make an edge to every label block that has been marked as a
-            potential target for a computed goto or a non-local goto.  */
-         if ((FORCED_LABEL (target) && !for_call)
-             || (DECL_NONLOCAL (target) && for_call))
-           {
-             make_edge (bb, target_bb, EDGE_ABNORMAL);
-             break;
-           }
-       }
-      if (!gsi_end_p (gsi)
-         && is_gimple_debug (gsi_stmt (gsi)))
-       gsi_next_nondebug (&gsi);
-      if (!gsi_end_p (gsi))
-       {
-         /* Make an edge to every setjmp-like call.  */
-         gimple call_stmt = gsi_stmt (gsi);
-         if (is_gimple_call (call_stmt)
-             && (gimple_call_flags (call_stmt) & ECF_RETURNS_TWICE))
-           make_edge (bb, target_bb, EDGE_ABNORMAL);
-       }
-    }
-}
-
-/* Create edges for a goto statement at block BB.  */
+/* Create edges for a goto statement at block BB.  Returns true
+   if abnormal edges should be created.  */
 
-static void
+static bool
 make_goto_expr_edges (basic_block bb)
 {
   gimple_stmt_iterator last = gsi_last_bb (bb);
@@ -1105,11 +1192,11 @@ make_goto_expr_edges (basic_block bb)
       edge e = make_edge (bb, label_bb, EDGE_FALLTHRU);
       e->goto_locus = gimple_location (goto_t);
       gsi_remove (&last, true);
-      return;
+      return false;
     }
 
   /* A computed GOTO creates abnormal edges.  */
-  make_abnormal_goto_edges (bb, false);
+  return true;
 }
 
 /* Create edges for an asm statement with labels at block BB.  */
index babbd2db2cabcef5e0ecf3b8455ad843c66c5335..a115df58b9d5c77f023465c8465080fe2bde8216 100644 (file)
@@ -31,7 +31,6 @@ extern void start_recording_case_labels (void);
 extern void end_recording_case_labels (void);
 extern basic_block label_to_block_fn (struct function *, tree);
 #define label_to_block(t) (label_to_block_fn (cfun, t))
-extern void make_abnormal_goto_edges (basic_block, bool);
 extern void cleanup_dead_labels (void);
 extern void group_case_labels_stmt (gimple);
 extern void group_case_labels (void);
@@ -46,7 +45,9 @@ extern void gimple_debug_cfg (int);
 extern void gimple_dump_cfg (FILE *, int);
 extern void dump_cfg_stats (FILE *);
 extern void debug_cfg_stats (void);
+extern bool computed_goto_p (gimple);
 extern bool stmt_can_make_abnormal_goto (gimple);
+extern basic_block get_abnormal_succ_dispatcher (basic_block);
 extern bool is_ctrl_stmt (gimple);
 extern bool is_ctrl_altering_stmt (gimple);
 extern bool simple_goto_p (gimple);
index a3175b34484899fc858a3f1c0308c9ac58f8acef..79a39bca136c71bccea6122fca358c9165e15a89 100644 (file)
@@ -1967,7 +1967,7 @@ update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb,
 
 static bool
 copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb,
-                  bool can_make_abnormal_goto)
+                  basic_block abnormal_goto_dest)
 {
   basic_block new_bb = (basic_block) bb->aux;
   edge_iterator ei;
@@ -2021,7 +2021,9 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb,
          into a COMPONENT_REF which doesn't.  If the copy
          can throw, the original could also throw.  */
       can_throw = stmt_can_throw_internal (copy_stmt);
-      nonlocal_goto = stmt_can_make_abnormal_goto (copy_stmt);
+      nonlocal_goto
+       = (stmt_can_make_abnormal_goto (copy_stmt)
+          && !computed_goto_p (copy_stmt));
 
       if (can_throw || nonlocal_goto)
        {
@@ -2052,9 +2054,26 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb,
       /* If the call we inline cannot make abnormal goto do not add
          additional abnormal edges but only retain those already present
         in the original function body.  */
-      nonlocal_goto &= can_make_abnormal_goto;
+      if (abnormal_goto_dest == NULL)
+       nonlocal_goto = false;
       if (nonlocal_goto)
-       make_abnormal_goto_edges (gimple_bb (copy_stmt), true);
+       {
+         basic_block copy_stmt_bb = gimple_bb (copy_stmt);
+
+         if (get_abnormal_succ_dispatcher (copy_stmt_bb))
+           nonlocal_goto = false;
+         /* ABNORMAL_DISPATCHER (1) is for longjmp/setjmp or nonlocal gotos
+            in OpenMP regions which aren't allowed to be left abnormally.
+            So, no need to add abnormal edge in that case.  */
+         else if (is_gimple_call (copy_stmt)
+                  && gimple_call_internal_p (copy_stmt)
+                  && (gimple_call_internal_fn (copy_stmt)
+                      == IFN_ABNORMAL_DISPATCHER)
+                  && gimple_call_arg (copy_stmt, 0) == boolean_true_node)
+           nonlocal_goto = false;
+         else
+           make_edge (copy_stmt_bb, abnormal_goto_dest, EDGE_ABNORMAL);
+       }
 
       if ((can_throw || nonlocal_goto)
          && gimple_in_ssa_p (cfun))
@@ -2493,13 +2512,22 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
   last = last_basic_block_for_fn (cfun);
 
   /* Now that we've duplicated the blocks, duplicate their edges.  */
-  bool can_make_abormal_goto
-    = id->gimple_call && stmt_can_make_abnormal_goto (id->gimple_call);
+  basic_block abnormal_goto_dest = NULL;
+  if (id->gimple_call
+      && stmt_can_make_abnormal_goto (id->gimple_call))
+    {
+      gimple_stmt_iterator gsi = gsi_for_stmt (id->gimple_call);
+
+      bb = gimple_bb (id->gimple_call);
+      gsi_next (&gsi);
+      if (gsi_end_p (gsi))
+       abnormal_goto_dest = get_abnormal_succ_dispatcher (bb);
+    }
   FOR_ALL_BB_FN (bb, cfun_to_copy)
     if (!id->blocks_to_copy
        || (bb->index > 0 && bitmap_bit_p (id->blocks_to_copy, bb->index)))
       need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map,
-                                              can_make_abormal_goto);
+                                              abnormal_goto_dest);
 
   if (new_entry)
     {
index 76e3efb4920d1b17e0033090313066caac6c8582..5fdd491a97de672dd9c9ec76a77013c04fe9e4a6 100644 (file)
@@ -9977,12 +9977,6 @@ build_common_builtin_nodes (void)
                        BUILT_IN_SETJMP_SETUP,
                        "__builtin_setjmp_setup", ECF_NOTHROW);
 
-  ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
-  local_define_builtin ("__builtin_setjmp_dispatcher", ftype,
-                       BUILT_IN_SETJMP_DISPATCHER,
-                       "__builtin_setjmp_dispatcher",
-                       ECF_PURE | ECF_NOTHROW);
-
   ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
   local_define_builtin ("__builtin_setjmp_receiver", ftype,
                        BUILT_IN_SETJMP_RECEIVER,