tstellar / rpms / gcc

Forked from rpms/gcc 4 years ago
Clone
0d16b69
2007-11-15  Jakub Jelinek  <jakub@redhat.com>
0d16b69
0d16b69
	PR middle-end/23848
0d16b69
	* tree-ssa-ccp.c (optimize_stack_restore): New function.
0d16b69
	(execute_fold_all_builtins): Call optimize_stack_restore for
0d16b69
	BUILT_IN_STACK_RESTORE.
0d16b69
0d16b69
	* gcc.dg/tree-ssa/pr23848-1.c: New test.
0d16b69
	* gcc.dg/tree-ssa/pr23848-2.c: New test.
0d16b69
	* gcc.dg/tree-ssa/pr23848-3.c: New test.
0d16b69
	* gcc.dg/tree-ssa/pr23848-4.c: New test.
0d16b69
0d16b69
--- gcc/tree-ssa-ccp.c	(revision 130205)
0d16b69
+++ gcc/tree-ssa-ccp.c	(revision 130206)
0d16b69
@@ -2394,6 +2394,75 @@ fold_stmt_inplace (tree stmt)
0d16b69
   return changed;
0d16b69
 }
0d16b69
 
0d16b69
+/* Try to optimize out __builtin_stack_restore.  Optimize it out
0d16b69
+   if there is another __builtin_stack_restore in the same basic
0d16b69
+   block and no calls or ASM_EXPRs are in between, or if this block's
0d16b69
+   only outgoing edge is to EXIT_BLOCK and there are no calls or
0d16b69
+   ASM_EXPRs after this __builtin_stack_restore.  */
0d16b69
+
0d16b69
+static tree
0d16b69
+optimize_stack_restore (basic_block bb, tree call, block_stmt_iterator i)
0d16b69
+{
0d16b69
+  tree stack_save, stmt, callee;
0d16b69
+
0d16b69
+  if (TREE_CODE (call) != CALL_EXPR
0d16b69
+      || TREE_OPERAND (call, 1) == NULL_TREE
0d16b69
+      || TREE_CHAIN (TREE_OPERAND (call, 1)) != NULL_TREE
0d16b69
+      || TREE_CODE (TREE_VALUE (TREE_OPERAND (call, 1))) != SSA_NAME
0d16b69
+      || !POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (TREE_OPERAND (call, 1)))))
0d16b69
+    return NULL_TREE;
0d16b69
+
0d16b69
+  for (bsi_next (&i); !bsi_end_p (i); bsi_next (&i))
0d16b69
+    {
0d16b69
+      tree call;
0d16b69
+
0d16b69
+      stmt = bsi_stmt (i);
0d16b69
+      if (TREE_CODE (stmt) == ASM_EXPR)
0d16b69
+	return NULL_TREE;
0d16b69
+      call = get_call_expr_in (stmt);
0d16b69
+      if (call == NULL)
0d16b69
+	continue;
0d16b69
+
0d16b69
+      callee = get_callee_fndecl (call);
0d16b69
+      if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
0d16b69
+	return NULL_TREE;
0d16b69
+
0d16b69
+      if (DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE)
0d16b69
+	break;
0d16b69
+    }
0d16b69
+
0d16b69
+  if (bsi_end_p (i)
0d16b69
+      && (! single_succ_p (bb)
0d16b69
+	  || single_succ_edge (bb)->dest != EXIT_BLOCK_PTR))
0d16b69
+    return NULL_TREE;
0d16b69
+
0d16b69
+  stack_save = SSA_NAME_DEF_STMT (TREE_VALUE (TREE_OPERAND (call, 1)));
0d16b69
+  if (TREE_CODE (stack_save) != MODIFY_EXPR
0d16b69
+      || TREE_OPERAND (stack_save, 0)
0d16b69
+	 != TREE_VALUE (TREE_OPERAND (call, 1))
0d16b69
+      || TREE_CODE (TREE_OPERAND (stack_save, 1)) != CALL_EXPR
0d16b69
+      || tree_could_throw_p (stack_save)
0d16b69
+      || !has_single_use (TREE_VALUE (TREE_OPERAND (call, 1))))
0d16b69
+    return NULL_TREE;
0d16b69
+
0d16b69
+  callee = get_callee_fndecl (TREE_OPERAND (stack_save, 1));
0d16b69
+  if (!callee
0d16b69
+      || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
0d16b69
+      || DECL_FUNCTION_CODE (callee) != BUILT_IN_STACK_SAVE
0d16b69
+      || TREE_OPERAND (TREE_OPERAND (stack_save, 1), 1) != NULL_TREE)
0d16b69
+    return NULL_TREE;
0d16b69
+
0d16b69
+  stmt = stack_save;
0d16b69
+  if (!set_rhs (&stmt,
0d16b69
+		build_int_cst (TREE_TYPE (TREE_VALUE (TREE_OPERAND (call,
0d16b69
+								    1))), 0)))
0d16b69
+    return NULL_TREE;
0d16b69
+  gcc_assert (stmt == stack_save);
0d16b69
+  mark_new_vars_to_rename (stmt);
0d16b69
+
0d16b69
+  return integer_zero_node;
0d16b69
+}
0d16b69
+
0d16b69
 /* Convert EXPR into a GIMPLE value suitable for substitution on the
0d16b69
    RHS of an assignment.  Insert the necessary statements before
0d16b69
    iterator *SI_P.  */
0d16b69
@@ -2469,6 +2538,12 @@ execute_fold_all_builtins (void)
0d16b69
 		result = integer_zero_node;
0d16b69
 		break;
0d16b69
 
0d16b69
+	      case BUILT_IN_STACK_RESTORE:
0d16b69
+		result = optimize_stack_restore (bb, *stmtp, i);
0d16b69
+		if (result)
0d16b69
+		  break;
0d16b69
+		/* FALLTHRU */
0d16b69
+
0d16b69
 	      default:
0d16b69
 		bsi_next (&i);
0d16b69
 		continue;
0d16b69
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c	(revision 0)
0d16b69
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c	(revision 130206)
0d16b69
@@ -0,0 +1,32 @@
0d16b69
+/* PR middle-end/23848 */
0d16b69
+/* { dg-do compile } */
0d16b69
+/* { dg-options "-O2 -fdump-tree-optimized" } */
0d16b69
+
0d16b69
+void bar1 (char *, int);
0d16b69
+void foo1 (int size)
0d16b69
+{
0d16b69
+  char temp[size];
0d16b69
+  temp[size-1] = '\0';
0d16b69
+  bar1 (temp, size);
0d16b69
+}
0d16b69
+
0d16b69
+void bar2 (char *, char *, char *, char *, int);
0d16b69
+void foo2 (int size)
0d16b69
+{
0d16b69
+  char temp[size];
0d16b69
+  temp[size-1] = '\0';
0d16b69
+  {
0d16b69
+    char temp2[size];
0d16b69
+    {
0d16b69
+      char temp3[size];
0d16b69
+      {
0d16b69
+	char temp4[size];
0d16b69
+	bar2 (temp, temp2, temp3, temp4, size);
0d16b69
+      }
0d16b69
+    }
0d16b69
+  }
0d16b69
+}
0d16b69
+
0d16b69
+/* { dg-final { scan-tree-dump-not "__builtin_stack_save" "optimized"} } */
0d16b69
+/* { dg-final { scan-tree-dump-not "__builtin_stack_restore" "optimized"} } */
0d16b69
+/* { dg-final { cleanup-tree-dump "optimized" } } */
0d16b69
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c	(revision 0)
0d16b69
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c	(revision 130206)
0d16b69
@@ -0,0 +1,25 @@
0d16b69
+/* PR middle-end/23848 */
0d16b69
+/* { dg-do compile } */
0d16b69
+/* { dg-options "-O2 -fdump-tree-optimized" } */
0d16b69
+
0d16b69
+void bar (char *, char *, char *, char *, int);
0d16b69
+void foo (int size)
0d16b69
+{
0d16b69
+  char temp[size];
0d16b69
+  temp[size-1] = '\0';
0d16b69
+  {
0d16b69
+    char temp2[size];
0d16b69
+    {
0d16b69
+      char temp3[size];
0d16b69
+      {
0d16b69
+	char temp4[size];
0d16b69
+	bar (temp, temp2, temp3, temp4, size);
0d16b69
+      }
0d16b69
+    }
0d16b69
+    bar (temp, temp2, (char *) 0, (char *) 0, size);
0d16b69
+  }
0d16b69
+}
0d16b69
+
0d16b69
+/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */
0d16b69
+/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */
0d16b69
+/* { dg-final { cleanup-tree-dump "optimized" } } */
0d16b69
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c	(revision 0)
0d16b69
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c	(revision 130206)
0d16b69
@@ -0,0 +1,28 @@
0d16b69
+/* PR middle-end/23848 */
0d16b69
+/* { dg-do compile } */
0d16b69
+/* { dg-options "-O2 -fdump-tree-optimized" } */
0d16b69
+
0d16b69
+void bar (int, char *, char *, char *, char *, int);
0d16b69
+void foo (int size)
0d16b69
+{
0d16b69
+  int i;
0d16b69
+  for (i = 0; i < size; i++)
0d16b69
+    {
0d16b69
+      char temp[size];
0d16b69
+      temp[size-1] = '\0';
0d16b69
+      {
0d16b69
+	char temp2[size];
0d16b69
+	{
0d16b69
+	  char temp3[size];
0d16b69
+	  {
0d16b69
+	    char temp4[size];
0d16b69
+	    bar (i, temp, temp2, temp3, temp4, size);
0d16b69
+	  }
0d16b69
+	}
0d16b69
+      }
0d16b69
+    }
0d16b69
+}
0d16b69
+
0d16b69
+/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */
0d16b69
+/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */
0d16b69
+/* { dg-final { cleanup-tree-dump "optimized" } } */
0d16b69
--- gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c	(revision 0)
0d16b69
+++ gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c	(revision 130206)
0d16b69
@@ -0,0 +1,25 @@
0d16b69
+/* PR middle-end/23848 */
0d16b69
+/* { dg-do compile } */
0d16b69
+/* { dg-options "-O2 -fdump-tree-optimized" } */
0d16b69
+
0d16b69
+void bar (char *, char *, char *, char *, int);
0d16b69
+void foo (int size)
0d16b69
+{
0d16b69
+  char temp[size];
0d16b69
+  temp[size-1] = '\0';
0d16b69
+  {
0d16b69
+    char temp2[size];
0d16b69
+    {
0d16b69
+      char temp3[size];
0d16b69
+      {
0d16b69
+	char temp4[size];
0d16b69
+	bar (temp, temp2, temp3, temp4, size);
0d16b69
+      }
0d16b69
+    }
0d16b69
+    __asm __volatile ("" : : "r" (&temp[0]), "r" (&temp2[0]) : "memory");
0d16b69
+  }
0d16b69
+}
0d16b69
+
0d16b69
+/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */
0d16b69
+/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */
0d16b69
+/* { dg-final { cleanup-tree-dump "optimized" } } */