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
This commit is contained in:
Richard Biener 2013-04-19 13:39:16 +00:00 committed by Richard Biener
parent 01d8bf070a
commit f6b64c3501
6 changed files with 102 additions and 20 deletions

View File

@ -1,3 +1,18 @@
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

View File

@ -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_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)

View File

@ -2729,6 +2729,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
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);
@ -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));
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);
}

View File

@ -1,3 +1,8 @@
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

View File

@ -0,0 +1,43 @@
#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);
}

View File

@ -967,25 +967,35 @@ make_abnormal_goto_edges (basic_block bb, bool for_call)
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;
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);
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))
{
/* 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. */
@ -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
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. */
@ -2302,6 +2313,11 @@ stmt_starts_bb_p (gimple stmt, gimple prev_stmt)
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;
}
@ -7532,7 +7548,8 @@ gimple_purge_dead_abnormal_call_edges (basic_block bb)
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))