summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-29 11:02:46 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-29 11:02:46 +0000
commitb2c0e0b7ef152a85eadd3c1bb7522f2ef5639750 (patch)
tree4b721b57c74c1349afc462b869e17ae0bdb8fa90
parent2975871c2ec24554516712ff598390408d84d4ab (diff)
downloadgcc-b2c0e0b7ef152a85eadd3c1bb7522f2ef5639750.tar.gz
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. * 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
-rw-r--r--gcc/ChangeLog49
-rw-r--r--gcc/builtins.c14
-rw-r--r--gcc/builtins.def1
-rw-r--r--gcc/gimple-low.c51
-rw-r--r--gcc/internal-fn.c5
-rw-r--r--gcc/internal-fn.def1
-rw-r--r--gcc/omp-low.c11
-rw-r--r--gcc/omp-low.h2
-rw-r--r--gcc/profile.c19
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr59917-1.c22
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr59917-2.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr59920-1.c20
-rw-r--r--gcc/testsuite/gcc.dg/pr59920-2.c30
-rw-r--r--gcc/testsuite/gcc.dg/pr59920-3.c47
-rw-r--r--gcc/tree-cfg.c381
-rw-r--r--gcc/tree-cfg.h3
-rw-r--r--gcc/tree-inline.c42
-rw-r--r--gcc/tree.c6
19 files changed, 499 insertions, 235 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c8a165828ac..14f0cfb6e18 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 3e34c83858b..a45380ce877 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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))
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 524153f22a5..2443a45751b 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -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. */
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 8d2e71103a4..c60e8177d38 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -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)
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 87a42e7e32c..43aaecba971 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -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:
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index ca93a0354a2..379b35241b5 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -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)
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index eeba4ae8470..d7589aa9ec1 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -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;
}
diff --git a/gcc/omp-low.h b/gcc/omp-low.h
index ce9cef9f5dd..d80c2d6f5c0 100644
--- a/gcc/omp-low.h
+++ b/gcc/omp-low.h
@@ -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 */
diff --git a/gcc/profile.c b/gcc/profile.c
index e549453bfad..752d89fc3d8 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 191845a3b35..a4684473ab7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..cca3976ccb7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr59917-1.c
@@ -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
index 00000000000..1d603422f66
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr59917-2.c
@@ -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
index 00000000000..3e60d37ae20
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr59920-1.c
@@ -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
index 00000000000..bee5542748b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr59920-2.c
@@ -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
index 00000000000..2159504e363
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr59920-3.c
@@ -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;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 32110a7fafa..dfc9b7b4cef 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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. */
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index babbd2db2ca..a115df58b9d 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -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);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index a3175b34484..79a39bca136 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -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)
{
diff --git a/gcc/tree.c b/gcc/tree.c
index 76e3efb4920..5fdd491a97d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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,