re PR tree-optimization/22325 (missed optimization in loop)
authorZdenek Dvorak <dvorakz@suse.cz>
Wed, 27 Jul 2005 13:26:55 +0000 (15:26 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Wed, 27 Jul 2005 13:26:55 +0000 (13:26 +0000)
PR tree-optimization/22325
* tree-flow.h (compute_phi_arg_on_exit, force_expr_to_var_cost):
Declare.
* tree-scalar-evolution.c (scev_const_prop): Add generic final
value replacement.
* tree-ssa-loop-ivopts.c (force_expr_to_var_cost): Split from ...
(force_var_cost): ... this function.
(compute_phi_arg_on_exit): Export.

From-SVN: r102426

gcc/ChangeLog
gcc/tree-flow.h
gcc/tree-scalar-evolution.c
gcc/tree-ssa-loop-ivopts.c

index 10f3d12..13c7a17 100644 (file)
@@ -1,5 +1,16 @@
 2005-07-27  Zdenek Dvorak  <dvorakz@suse.cz>
 
+       PR tree-optimization/22325
+       * tree-flow.h (compute_phi_arg_on_exit, force_expr_to_var_cost):
+       Declare.
+       * tree-scalar-evolution.c (scev_const_prop): Add generic final
+       value replacement.
+       * tree-ssa-loop-ivopts.c (force_expr_to_var_cost): Split from ...
+       (force_var_cost): ... this function.
+       (compute_phi_arg_on_exit): Export.
+
+2005-07-27  Zdenek Dvorak  <dvorakz@suse.cz>
+
        PR tree-optimization/20773
        * tree-ssa-loop-ch.c (copy_loop_headers): Select the correct latch
        edge.
index 4a0b480..bfbceba 100644 (file)
@@ -738,6 +738,8 @@ bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
 void create_iv (tree, tree, tree, struct loop *, block_stmt_iterator *, bool,
                tree *, tree *);
 void split_loop_exit_edge (edge);
+void compute_phi_arg_on_exit (edge, tree, tree);
+unsigned force_expr_to_var_cost (tree);
 basic_block bsi_insert_on_edge_immediate_loop (edge, tree);
 void standard_iv_increment_position (struct loop *, block_stmt_iterator *,
                                     bool *);
index f12ec09..52a2d1a 100644 (file)
@@ -2608,8 +2608,8 @@ scev_finalize (void)
 }
 
 /* Replace ssa names for that scev can prove they are constant by the
-   appropriate constants.  Most importantly, this takes care of final
-   value replacement.
+   appropriate constants.  Also perform final value replacement in loops,
+   in case the replacement expressions are cheap.
    
    We only consider SSA names defined by phi nodes; rest is left to the
    ordinary constant propagation pass.  */
@@ -2618,9 +2618,10 @@ void
 scev_const_prop (void)
 {
   basic_block bb;
-  tree name, phi, type, ev;
-  struct loop *loop;
+  tree name, phi, next_phi, type, ev;
+  struct loop *loop, *ex_loop;
   bitmap ssa_names_to_remove = NULL;
+  unsigned i;
 
   if (!current_loops)
     return;
@@ -2675,4 +2676,56 @@ scev_const_prop (void)
       BITMAP_FREE (ssa_names_to_remove);
       scev_reset ();
     }
+
+  /* Now the regular final value replacement.  */
+  for (i = current_loops->num - 1; i > 0; i--)
+    {
+      edge exit;
+      tree def, stmts;
+
+      loop = current_loops->parray[i];
+      if (!loop)
+       continue;
+
+      /* If we do not know exact number of iterations of the loop, we cannot
+        replace the final value.  */
+      exit = loop->single_exit;
+      if (!exit
+         || number_of_iterations_in_loop (loop) == chrec_dont_know)
+       continue;
+      ex_loop = exit->dest->loop_father;
+
+      for (phi = phi_nodes (exit->dest); phi; phi = next_phi)
+       {
+         next_phi = PHI_CHAIN (phi);
+         def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
+         if (!is_gimple_reg (def)
+             || expr_invariant_in_loop_p (loop, 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);
+         if (!tree_does_not_contain_chrecs (def)
+             || chrec_contains_symbols_defined_in_loop (def, 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)
+           continue;
+
+         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);
+       }
+    }
 }
index fda17f9..e5a8d85 100644 (file)
@@ -3415,12 +3415,11 @@ get_address_cost (bool symbol_present, bool var_present,
 
   return cost + acost;
 }
-/* Estimates cost of forcing EXPR into a variable.  DEPENDS_ON is a set of the
-   invariants the computation depends on.  */
 
-static unsigned
-force_var_cost (struct ivopts_data *data,
-               tree expr, bitmap *depends_on)
+/* Estimates cost of forcing expression EXPR into a variable.  */
+
+unsigned
+force_expr_to_var_cost (tree expr)
 {
   static bool costs_initialized = false;
   static unsigned integer_cost;
@@ -3452,7 +3451,7 @@ force_var_cost (struct ivopts_data *data,
                                    build_int_cst_type (type, 2000))) + 1;
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
-         fprintf (dump_file, "force_var_cost:\n");
+         fprintf (dump_file, "force_expr_to_var_cost:\n");
          fprintf (dump_file, "  integer %d\n", (int) integer_cost);
          fprintf (dump_file, "  symbol %d\n", (int) symbol_cost);
          fprintf (dump_file, "  address %d\n", (int) address_cost);
@@ -3465,12 +3464,6 @@ force_var_cost (struct ivopts_data *data,
 
   STRIP_NOPS (expr);
 
-  if (depends_on)
-    {
-      fd_ivopts_data = data;
-      walk_tree (&expr, find_depends, depends_on, NULL);
-    }
-
   if (SSA_VAR_P (expr))
     return 0;
 
@@ -3505,12 +3498,12 @@ force_var_cost (struct ivopts_data *data,
       if (is_gimple_val (op0))
        cost0 = 0;
       else
-       cost0 = force_var_cost (data, op0, NULL);
+       cost0 = force_expr_to_var_cost (op0);
 
       if (is_gimple_val (op1))
        cost1 = 0;
       else
-       cost1 = force_var_cost (data, op1, NULL);
+       cost1 = force_expr_to_var_cost (op1);
 
       break;
 
@@ -3550,6 +3543,22 @@ force_var_cost (struct ivopts_data *data,
   return cost < target_spill_cost ? cost : target_spill_cost;
 }
 
+/* Estimates cost of forcing EXPR into a variable.  DEPENDS_ON is a set of the
+   invariants the computation depends on.  */
+
+static unsigned
+force_var_cost (struct ivopts_data *data,
+               tree expr, bitmap *depends_on)
+{
+  if (depends_on)
+    {
+      fd_ivopts_data = data;
+      walk_tree (&expr, find_depends, depends_on, NULL);
+    }
+
+  return force_expr_to_var_cost (expr);
+}
+
 /* Estimates cost of expressing address ADDR  as var + symbol + offset.  The
    value of offset is added to OFFSET, SYMBOL_PRESENT and VAR_PRESENT are set
    to false if the corresponding part is missing.  DEPENDS_ON is a set of the
@@ -5600,7 +5609,7 @@ protect_loop_closed_ssa_form (edge exit, tree stmt)
    so that they are emitted on the correct place, and so that the loop closed
    ssa form is preserved.  */
 
-static void
+void
 compute_phi_arg_on_exit (edge exit, tree stmts, tree op)
 {
   tree_stmt_iterator tsi;