re PR middle-end/23848 (stack deallocation can be more efficient)

PR middle-end/23848
	* tree-ssa-ccp.c (optimize_stack_restore): New function.
	(execute_fold_all_builtins): Call optimize_stack_restore for
	BUILT_IN_STACK_RESTORE.

	* gcc.dg/tree-ssa/pr23848-1.c: New test.
	* gcc.dg/tree-ssa/pr23848-2.c: New test.
	* gcc.dg/tree-ssa/pr23848-3.c: New test.
	* gcc.dg/tree-ssa/pr23848-4.c: New test.

From-SVN: r130206
This commit is contained in:
Jakub Jelinek 2007-11-15 20:02:54 +01:00 committed by Jakub Jelinek
parent 62e66076c6
commit cb8e078d3f
7 changed files with 201 additions and 0 deletions

View File

@ -1,3 +1,10 @@
2007-11-15 Jakub Jelinek <jakub@redhat.com>
PR middle-end/23848
* tree-ssa-ccp.c (optimize_stack_restore): New function.
(execute_fold_all_builtins): Call optimize_stack_restore for
BUILT_IN_STACK_RESTORE.
2007-11-15 Paolo Bonzini <bonzini@gnu.org>
* fwprop.c (try_fwprop_subst): Skip profitability check for forward

View File

@ -1,3 +1,11 @@
2007-11-15 Jakub Jelinek <jakub@redhat.com>
PR middle-end/23848
* gcc.dg/tree-ssa/pr23848-1.c: New test.
* gcc.dg/tree-ssa/pr23848-2.c: New test.
* gcc.dg/tree-ssa/pr23848-3.c: New test.
* gcc.dg/tree-ssa/pr23848-4.c: New test.
2007-11-15 Tobias Burnus <burnus@net-b.de>
PR fortran/33917

View File

@ -0,0 +1,32 @@
/* PR middle-end/23848 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
void bar1 (char *, int);
void foo1 (int size)
{
char temp[size];
temp[size-1] = '\0';
bar1 (temp, size);
}
void bar2 (char *, char *, char *, char *, int);
void foo2 (int size)
{
char temp[size];
temp[size-1] = '\0';
{
char temp2[size];
{
char temp3[size];
{
char temp4[size];
bar2 (temp, temp2, temp3, temp4, size);
}
}
}
}
/* { dg-final { scan-tree-dump-not "__builtin_stack_save" "optimized"} } */
/* { dg-final { scan-tree-dump-not "__builtin_stack_restore" "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,25 @@
/* PR middle-end/23848 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
void bar (char *, char *, char *, char *, int);
void foo (int size)
{
char temp[size];
temp[size-1] = '\0';
{
char temp2[size];
{
char temp3[size];
{
char temp4[size];
bar (temp, temp2, temp3, temp4, size);
}
}
bar (temp, temp2, (char *) 0, (char *) 0, size);
}
}
/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */
/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,28 @@
/* PR middle-end/23848 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
void bar (int, char *, char *, char *, char *, int);
void foo (int size)
{
int i;
for (i = 0; i < size; i++)
{
char temp[size];
temp[size-1] = '\0';
{
char temp2[size];
{
char temp3[size];
{
char temp4[size];
bar (i, temp, temp2, temp3, temp4, size);
}
}
}
}
}
/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */
/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,25 @@
/* PR middle-end/23848 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
void bar (char *, char *, char *, char *, int);
void foo (int size)
{
char temp[size];
temp[size-1] = '\0';
{
char temp2[size];
{
char temp3[size];
{
char temp4[size];
bar (temp, temp2, temp3, temp4, size);
}
}
__asm __volatile ("" : : "r" (&temp[0]), "r" (&temp2[0]) : "memory");
}
}
/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */
/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -2601,6 +2601,76 @@ fold_stmt_inplace (tree stmt)
return changed;
}
/* Try to optimize out __builtin_stack_restore. Optimize it out
if there is another __builtin_stack_restore in the same basic
block and no calls or ASM_EXPRs are in between, or if this block's
only outgoing edge is to EXIT_BLOCK and there are no calls or
ASM_EXPRs after this __builtin_stack_restore. */
static tree
optimize_stack_restore (basic_block bb, tree call, block_stmt_iterator i)
{
tree stack_save, stmt, callee;
if (TREE_CODE (call) != CALL_EXPR
|| call_expr_nargs (call) != 1
|| TREE_CODE (CALL_EXPR_ARG (call, 0)) != SSA_NAME
|| !POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call, 0))))
return NULL_TREE;
for (bsi_next (&i); !bsi_end_p (i); bsi_next (&i))
{
tree call;
stmt = bsi_stmt (i);
if (TREE_CODE (stmt) == ASM_EXPR)
return NULL_TREE;
call = get_call_expr_in (stmt);
if (call == NULL)
continue;
callee = get_callee_fndecl (call);
if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
return NULL_TREE;
if (DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE)
break;
}
if (bsi_end_p (i)
&& (! single_succ_p (bb)
|| single_succ_edge (bb)->dest != EXIT_BLOCK_PTR))
return NULL_TREE;
stack_save = SSA_NAME_DEF_STMT (CALL_EXPR_ARG (call, 0));
if (TREE_CODE (stack_save) != GIMPLE_MODIFY_STMT
|| GIMPLE_STMT_OPERAND (stack_save, 0) != CALL_EXPR_ARG (call, 0)
|| TREE_CODE (GIMPLE_STMT_OPERAND (stack_save, 1)) != CALL_EXPR
|| tree_could_throw_p (stack_save)
|| !has_single_use (CALL_EXPR_ARG (call, 0)))
return NULL_TREE;
callee = get_callee_fndecl (GIMPLE_STMT_OPERAND (stack_save, 1));
if (!callee
|| DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
|| DECL_FUNCTION_CODE (callee) != BUILT_IN_STACK_SAVE
|| call_expr_nargs (GIMPLE_STMT_OPERAND (stack_save, 1)) != 0)
return NULL_TREE;
stmt = stack_save;
push_stmt_changes (&stmt);
if (!set_rhs (&stmt,
build_int_cst (TREE_TYPE (CALL_EXPR_ARG (call, 0)), 0)))
{
discard_stmt_changes (&stmt);
return NULL_TREE;
}
gcc_assert (stmt == stack_save);
pop_stmt_changes (&stmt);
return integer_zero_node;
}
/* Convert EXPR into a GIMPLE value suitable for substitution on the
RHS of an assignment. Insert the necessary statements before
iterator *SI_P.
@ -2685,6 +2755,12 @@ execute_fold_all_builtins (void)
result = integer_zero_node;
break;
case BUILT_IN_STACK_RESTORE:
result = optimize_stack_restore (bb, *stmtp, i);
if (result)
break;
/* FALLTHRU */
default:
bsi_next (&i);
continue;