Commit f6b64c35 by Richard Biener Committed by Richard Biener

re PR tree-optimization/56982 (Bad optimization with setjmp())

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.

	* gcc.c-torture/execute/pr56982.c: New testcase.

From-SVN: r198096
parent 01d8bf07
2013-04-19 Richard Biener <rguenther@suse.de> 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 * tree-vectorizer.h (struct _slp_instance): Move load_permutation
member ... member ...
(struct _slp_tree): ... here. Make it a vector of unsigned ints. (struct _slp_tree): ... here. Make it a vector of unsigned ints.
......
...@@ -715,7 +715,7 @@ DEF_GCC_BUILTIN (BUILT_IN_ISLESSGREATER, "islessgreater", BT_FN_INT_VAR, ...@@ -715,7 +715,7 @@ DEF_GCC_BUILTIN (BUILT_IN_ISLESSGREATER, "islessgreater", BT_FN_INT_VAR,
DEF_GCC_BUILTIN (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) 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_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_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. */ /* [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_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) DEF_GCC_BUILTIN (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
......
...@@ -2729,6 +2729,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) ...@@ -2729,6 +2729,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
call = gimple_build_call_from_tree (*expr_p); call = gimple_build_call_from_tree (*expr_p);
gimple_call_set_fntype (call, TREE_TYPE (fnptrtype)); gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
notice_special_calls (call);
gimplify_seq_add_stmt (pre_p, call); gimplify_seq_add_stmt (pre_p, call);
gsi = gsi_last (*pre_p); gsi = gsi_last (*pre_p);
fold_stmt (&gsi); fold_stmt (&gsi);
...@@ -4968,6 +4969,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ...@@ -4968,6 +4969,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p)); STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
assign = gimple_build_call_from_tree (*from_p); assign = gimple_build_call_from_tree (*from_p);
gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype)); gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
notice_special_calls (assign);
if (!gimple_call_noreturn_p (assign)) if (!gimple_call_noreturn_p (assign))
gimple_call_set_lhs (assign, *to_p); 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> 2013-04-19 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/56718 PR tree-optimization/56718
......
#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);
}
...@@ -967,25 +967,35 @@ make_abnormal_goto_edges (basic_block bb, bool for_call) ...@@ -967,25 +967,35 @@ make_abnormal_goto_edges (basic_block bb, bool for_call)
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
FOR_EACH_BB (target_bb) FOR_EACH_BB (target_bb)
for (gsi = gsi_start_bb (target_bb); !gsi_end_p (gsi); gsi_next (&gsi)) {
{ for (gsi = gsi_start_bb (target_bb); !gsi_end_p (gsi); gsi_next (&gsi))
gimple label_stmt = gsi_stmt (gsi); {
tree target; gimple label_stmt = gsi_stmt (gsi);
tree target;
if (gimple_code (label_stmt) != GIMPLE_LABEL) if (gimple_code (label_stmt) != GIMPLE_LABEL)
break; 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 /* Make an edge to every label block that has been marked as a
potential target for a computed goto or a non-local goto. */ potential target for a computed goto or a non-local goto. */
if ((FORCED_LABEL (target) && !for_call) if ((FORCED_LABEL (target) && !for_call)
|| (DECL_NONLOCAL (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); make_edge (bb, target_bb, EDGE_ABNORMAL);
break; }
} }
}
} }
/* Create edges for a goto statement at block BB. */ /* Create edges for a goto statement at block BB. */
...@@ -2147,7 +2157,8 @@ call_can_make_abnormal_goto (gimple t) ...@@ -2147,7 +2157,8 @@ call_can_make_abnormal_goto (gimple t)
{ {
/* If the function has no non-local labels, then a call cannot make an /* If the function has no non-local labels, then a call cannot make an
abnormal transfer of control. */ abnormal transfer of control. */
if (!cfun->has_nonlocal_label) if (!cfun->has_nonlocal_label
&& !cfun->calls_setjmp)
return false; return false;
/* Likewise if the call has no side effects. */ /* Likewise if the call has no side effects. */
...@@ -2302,6 +2313,11 @@ stmt_starts_bb_p (gimple stmt, gimple prev_stmt) ...@@ -2302,6 +2313,11 @@ stmt_starts_bb_p (gimple stmt, gimple prev_stmt)
else else
return true; 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; return false;
} }
...@@ -7532,7 +7548,8 @@ gimple_purge_dead_abnormal_call_edges (basic_block bb) ...@@ -7532,7 +7548,8 @@ gimple_purge_dead_abnormal_call_edges (basic_block bb)
edge_iterator ei; edge_iterator ei;
gimple stmt = last_stmt (bb); gimple stmt = last_stmt (bb);
if (!cfun->has_nonlocal_label) if (!cfun->has_nonlocal_label
&& !cfun->calls_setjmp)
return false; return false;
if (stmt && stmt_can_make_abnormal_goto (stmt)) if (stmt && stmt_can_make_abnormal_goto (stmt))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment