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:
parent
01d8bf070a
commit
f6b64c3501
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue