From 925196ed525e3f05b74d54391edd3a198986e035 Mon Sep 17 00:00:00 2001
From: Zdenek Dvorak <dvorakz@suse.cz>
Date: Fri, 18 Nov 2005 11:27:50 +0100
Subject: [PATCH] tree-scalar-evolution.c (expression_expensive_p): New
 function.

	* tree-scalar-evolution.c (expression_expensive_p): New function.
	(scev_const_prop): Use compute_overall_effect_of_inner_loop.

	* gcc.dg/tree-ssa/loop-14.c: New test.

From-SVN: r107170
---
 gcc/ChangeLog                           |  5 ++
 gcc/testsuite/ChangeLog                 |  4 ++
 gcc/testsuite/gcc.dg/tree-ssa/loop-14.c | 19 ++++++++
 gcc/tree-scalar-evolution.c             | 63 +++++++++++++++----------
 4 files changed, 66 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-14.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fc9df6a50c10..7774bdaeaa83 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2005-11-18  Zdenek Dvorak  <dvorakz@suse.cz>
+
+	* tree-scalar-evolution.c (expression_expensive_p): New function.
+	(scev_const_prop): Use compute_overall_effect_of_inner_loop.
+
 2005-11-18  Bernd Schmidt  <bernd.schmidt@analog.com>
 
 	* config/bfin/crtlibid.s: New file.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9eafe7ee9cdf..dc1c727a80cf 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2005-11-18  Zdenek Dvorak  <dvorakz@suse.cz>
+
+	* gcc.dg/tree-ssa/loop-14.c: New test.
+
 2005-11-17  James A. Morrison  <phython@gcc.gnu.org>
             Michael Chamberlain <michael@chamberlain.net.au>
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-14.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-14.c
new file mode 100644
index 000000000000..ff96e128bebe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-14.c
@@ -0,0 +1,19 @@
+/* A test for final value replacement.  */
+
+/* { dg-options "-O2 -fdump-tree-vars" } */
+
+int foo(void);
+
+int bla(void)
+{
+  int i, j = foo ();
+
+  for (i = 0; i < 100; i++, j++)
+    foo ();
+
+  /* Should be replaced with return j0 + 100;  */
+  return j;
+}
+
+/* { dg-final { scan-tree-dump-times "\\+ 100" 1 "vars" } } */
+/* { dg-final { cleanup-tree-dump "vars" } } */
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index c2fa2ef995d6..c35298e9d09b 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -2700,6 +2700,14 @@ scev_finalize (void)
   BITMAP_FREE (already_instantiated);
 }
 
+/* Returns true if EXPR looks expensive.  */
+
+static bool
+expression_expensive_p (tree expr)
+{
+  return force_expr_to_var_cost (expr) >= target_spill_cost;
+}
+
 /* Replace ssa names for that scev can prove they are constant by the
    appropriate constants.  Also perform final value replacement in loops,
    in case the replacement expressions are cheap.
@@ -2775,7 +2783,8 @@ scev_const_prop (void)
   for (i = current_loops->num - 1; i > 0; i--)
     {
       edge exit;
-      tree def, stmts;
+      tree def, rslt, ass;
+      block_stmt_iterator bsi;
 
       loop = current_loops->parray[i];
       if (!loop)
@@ -2787,46 +2796,50 @@ scev_const_prop (void)
       if (!exit
 	  || number_of_iterations_in_loop (loop) == chrec_dont_know)
 	continue;
-      ex_loop = exit->dest->loop_father;
+
+      /* Ensure that it is possible to insert new statements somewhere.  */
+      if (!single_pred_p (exit->dest))
+	split_loop_exit_edge (exit);
+      tree_block_label (exit->dest);
+      bsi = bsi_after_labels (exit->dest);
+
+      ex_loop = superloop_at_depth (loop, exit->dest->loop_father->depth + 1);
 
       for (phi = phi_nodes (exit->dest); phi; phi = next_phi)
 	{
 	  next_phi = PHI_CHAIN (phi);
+	  rslt = PHI_RESULT (phi);
 	  def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
-	  if (!is_gimple_reg (def)
-	      || expr_invariant_in_loop_p (loop, def))
+	  if (!is_gimple_reg (def))
 	    continue;
 
 	  if (!POINTER_TYPE_P (TREE_TYPE (def))
 	      && !INTEGRAL_TYPE_P (TREE_TYPE (def)))
 	    continue;
 
-	  def = analyze_scalar_evolution_in_loop (ex_loop, ex_loop, def);
+	  def = analyze_scalar_evolution_in_loop (ex_loop, loop, def);
+	  def = compute_overall_effect_of_inner_loop (ex_loop, def);
 	  if (!tree_does_not_contain_chrecs (def)
-	      || chrec_contains_symbols_defined_in_loop (def, loop->num)
-	      || def == PHI_RESULT (phi)
-	      || (TREE_CODE (def) == SSA_NAME
-		  && loop_containing_stmt (SSA_NAME_DEF_STMT (def))
-		  && loop_containing_stmt (phi)
-		  && loop_containing_stmt (SSA_NAME_DEF_STMT (def))
-		  == loop_containing_stmt (phi)))
+	      || chrec_contains_symbols_defined_in_loop (def, ex_loop->num))
 	    continue;
 
-	  /* If computing the expression is expensive, let it remain in
-	     loop.  TODO -- we should take the cost of computing the expression
-	     in loop into account.  */
-	  if (force_expr_to_var_cost (def) >= target_spill_cost)
+	  /* If computing the expression is expensive, let it remain in the
+	     loop.  */
+	  if (expression_expensive_p (def))
 	    continue;
-	  def = unshare_expr (def);
 
-	  if (is_gimple_val (def))
-	    stmts = NULL_TREE;
-	  else
-	    def = force_gimple_operand (def, &stmts, true,
-					SSA_NAME_VAR (PHI_RESULT (phi)));
-	  SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, exit), def);
-	  if (stmts)
-	    compute_phi_arg_on_exit (exit, stmts, def);
+	  /* Eliminate the phi node and replace it by a computation outside
+	     the loop.  */
+	  def = unshare_expr (def);
+	  SET_PHI_RESULT (phi, NULL_TREE);
+	  remove_phi_node (phi, NULL_TREE);
+
+	  ass = build2 (MODIFY_EXPR, void_type_node, rslt, NULL_TREE);
+	  SSA_NAME_DEF_STMT (rslt) = ass;
+	  bsi_insert_after (&bsi, ass, BSI_NEW_STMT);
+	  def = force_gimple_operand_bsi (&bsi, def, false, NULL_TREE);
+	  TREE_OPERAND (ass, 1) = def;
+	  update_stmt (ass);
 	}
     }
 }
-- 
GitLab