+2013-04-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/56982
+ * builtins.def (BUILT_IN_LONGJMP): longjmp is not a leaf
+ function.
+ * gimplify.c (gimplify_call_expr): Notice special calls.
+ (gimplify_modify_expr): Likewise.
+ * tree-cfg.c (make_abnormal_goto_edges): Handle setjmp-like
+ abnormal control flow receivers.
+ (call_can_make_abnormal_goto): Handle cfun->calls_setjmp
+ in the same way as cfun->has_nonlocal_labels.
+ (gimple_purge_dead_abnormal_call_edges): Likewise.
+ (stmt_starts_bb_p): Make setjmp-like abnormal control flow
+ receivers start a basic-block.
+
2013-04-19 Richard Biener <rguenther@suse.de>
* tree-vectorizer.h (struct _slp_instance): Move load_permutation
DEF_GCC_BUILTIN (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
-DEF_GCC_BUILTIN (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LIST)
/* [trans-mem]: Adjust BUILT_IN_TM_MALLOC if BUILT_IN_MALLOC is changed. */
DEF_LIB_BUILTIN (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
gimple_stmt_iterator gsi;
call = gimple_build_call_from_tree (*expr_p);
gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
+ notice_special_calls (call);
gimplify_seq_add_stmt (pre_p, call);
gsi = gsi_last (*pre_p);
fold_stmt (&gsi);
STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
assign = gimple_build_call_from_tree (*from_p);
gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
+ notice_special_calls (assign);
if (!gimple_call_noreturn_p (assign))
gimple_call_set_lhs (assign, *to_p);
}
+2013-04-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/56982
+ * gcc.c-torture/execute/pr56982.c: New testcase.
+
2013-04-19 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/56718
--- /dev/null
+#include <stdlib.h>
+#include <setjmp.h>
+
+static sigjmp_buf env;
+void *stderr;
+void baz (void)
+{
+ __asm__ volatile ("" : : : "memory");
+}
+
+static inline int g(int x)
+{
+ if (x)
+ {
+ baz();
+ return 0;
+ }
+ else
+ {
+ baz();
+ return 1;
+ }
+}
+
+int f(int *e)
+{
+ if (*e)
+ return 1;
+
+ int x = setjmp(env);
+ int n = g(x);
+ if (n == 0)
+ exit(0);
+ if (x)
+ abort();
+ longjmp(env, 42);
+}
+
+int main(int argc, char** argv)
+{
+ int v = 0;
+ return f(&v);
+}
gimple_stmt_iterator gsi;
FOR_EACH_BB (target_bb)
- for (gsi = gsi_start_bb (target_bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple label_stmt = gsi_stmt (gsi);
- tree target;
+ {
+ 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;
+ if (gimple_code (label_stmt) != GIMPLE_LABEL)
+ break;
- target = gimple_label_label (label_stmt);
+ 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 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))
+ {
+ /* 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);
- break;
- }
- }
+ }
+ }
}
/* Create edges for a goto statement at block BB. */
{
/* If the function has no non-local labels, then a call cannot make an
abnormal transfer of control. */
- if (!cfun->has_nonlocal_label)
+ if (!cfun->has_nonlocal_label
+ && !cfun->calls_setjmp)
return false;
/* Likewise if the call has no side effects. */
else
return true;
}
+ else if (gimple_code (stmt) == GIMPLE_CALL
+ && gimple_call_flags (stmt) & ECF_RETURNS_TWICE)
+ /* setjmp acts similar to a nonlocal GOTO target and thus should
+ start a new block. */
+ return true;
return false;
}
edge_iterator ei;
gimple stmt = last_stmt (bb);
- if (!cfun->has_nonlocal_label)
+ if (!cfun->has_nonlocal_label
+ && !cfun->calls_setjmp)
return false;
if (stmt && stmt_can_make_abnormal_goto (stmt))