+2014-02-01 Jakub Jelinek <jakub@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.
+
2014-01-31 Vladimir Makarov <vmakarov@redhat.com>
PR bootstrap/59985
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;
{
gimple_stmt_iterator gsi;
gimple first;
- tree fndecl;
gsi = gsi_start_nondebug_after_labels_bb (bb);
gcc_checking_assert (!gsi_end_p (gsi));
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)
+2014-02-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/60003
+ * gcc.c-torture/execute/pr60003.c: New test.
+
2014-01-31 Vladimir Makarov <vmakarov@redhat.com>
PR bootstrap/59985
--- /dev/null
+/* 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;
+}
if (is_gimple_call (stmt))
{
struct cgraph_edge *edge;
- int flags;
switch (id->transform_call_graph_edges)
{
}
}
- 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,