gcc/gcc41-pr23848.patch

226 lines
6.4 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.
* 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.
--- gcc/tree-ssa-ccp.c (revision 130205)
+++ gcc/tree-ssa-ccp.c (revision 130206)
@@ -2394,6 +2394,75 @@ 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
+ || TREE_OPERAND (call, 1) == NULL_TREE
+ || TREE_CHAIN (TREE_OPERAND (call, 1)) != NULL_TREE
+ || TREE_CODE (TREE_VALUE (TREE_OPERAND (call, 1))) != SSA_NAME
+ || !POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (TREE_OPERAND (call, 1)))))
+ 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 (TREE_VALUE (TREE_OPERAND (call, 1)));
+ if (TREE_CODE (stack_save) != MODIFY_EXPR
+ || TREE_OPERAND (stack_save, 0)
+ != TREE_VALUE (TREE_OPERAND (call, 1))
+ || TREE_CODE (TREE_OPERAND (stack_save, 1)) != CALL_EXPR
+ || tree_could_throw_p (stack_save)
+ || !has_single_use (TREE_VALUE (TREE_OPERAND (call, 1))))
+ return NULL_TREE;
+
+ callee = get_callee_fndecl (TREE_OPERAND (stack_save, 1));
+ if (!callee
+ || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
+ || DECL_FUNCTION_CODE (callee) != BUILT_IN_STACK_SAVE
+ || TREE_OPERAND (TREE_OPERAND (stack_save, 1), 1) != NULL_TREE)
+ return NULL_TREE;
+
+ stmt = stack_save;
+ if (!set_rhs (&stmt,
+ build_int_cst (TREE_TYPE (TREE_VALUE (TREE_OPERAND (call,
+ 1))), 0)))
+ return NULL_TREE;
+ gcc_assert (stmt == stack_save);
+ mark_new_vars_to_rename (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. */
@@ -2469,6 +2538,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;
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c (revision 130206)
@@ -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" } } */
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c (revision 130206)
@@ -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" } } */
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c (revision 130206)
@@ -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" } } */
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c (revision 130206)
@@ -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" } } */