tree-flow.h: Move some protoypes.
authorAndrew MacLeod <amacleod@redhat.com>
Wed, 9 Oct 2013 13:09:23 +0000 (13:09 +0000)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Wed, 9 Oct 2013 13:09:23 +0000 (13:09 +0000)
* tree-flow.h: Move some protoypes.  Include new tree-ssa-loop.h.
(struct affine_iv, struct tree_niter_desc): Move to tree-ssa-loop.h.
(enum move_pos): Move to tree-ssa-loop-im.h
* cfgloop.h: Move some prototypes.
(gcov_type_to_double_int): relocate from tree-ssa-loop.niter.c.
* tree-flow-inline.h (loop_containing_stmt): Move to tree-ssa-loop.h.
* tree-ssa-loop.h: New File.  Include other tree-ssa-loop-*.h files.
(struct affine_iv, struct tree_niter_desc): Relocate from tree-flow.h.
(loop_containing_stmt): Relocate from tree-flow-inline.h.
* tree-ssa-loop-ch.c: (do_while_loop_p): Make static.
* tree-ssa-loop-im.c (for_each_index): Move to tree-ssa-loop.c.
(enum move_pos): Relocate here.
(lsm_tmp_name_add, gen_lsm_tmp_name, get_lsm_tmp_name): Move to
tree-ssa-loop.c.
(execute_sm_if_changed_flag_set): Change get_lsm_tmp_name call.
(tree_ssa_loop_im, gate_tree_ssa_loop_im, pass_data_lim, make_pass_lim):
Relocate here from tree-ssa-loop.c.
* tree-ssa-loop-ivcanon.c (tree_num_loop_insns): Move to
tree-ssa-loop.c.
(loop_edge_to_cancel, unloop_loops): Make static.
(tree_ssa_loop_ivcanon, gate_tree_ssa_loop_ivcanon, pass_data_iv_canon,
make_pass_iv_canon): Relocate from tree-ssa-loop.c.
(tree_complete_unroll, gate_tree_complete_unroll,
pass_data_complete_unroll, make_pass_complete_unroll): Relocate here.
(tree_complete_unroll_inner, gate_tree_complete_unroll_inner,
pass_data_complete_unrolli, make_pass_complete_unrolli): Relocate here.
* tree-ssa-loop-ivopts.c: Remove local prototypes.
(stmt_invariant_in_loop_p): Remove unused function.
* tree-ssa-loop-ivopts.h: New file.  Add prototypes.
* tree-ssa-loop-manip.h: New file.  Add prototypes.
* tree-ssa-loop-niter.c (record_niter_bound): Move to cfgloop.c.
(gcov_type_to_double_int): Move to cfgloop.h.
(double_int_cmp, bound_index,
estimate_numbers_of_iterations_loop): Make static.
(estimated_loop_iterations): Factor out get_estimated_loop_iterations.
(max_loop_iterations): Factor out get_max_loop_iterations.
(estimated_loop_iterations_int, max_stmt_executions_int): Move to
cfgloop.c.
* tree-ssa-loop-niter.h: New file.  Add prototypes.
* tree-ssa-loop-prefetch.c (tree_ssa_loop_prefetch,
gate_tree_ssa_loop_prefetch, pass_data_loop_prefetch,
make_pass_loop_prefetch): Relocate from tree-ssa-loop.c.
* tree-ssa-loop-unswitch.c (tree_ssa_loop_unswitch,
gate_tree_ssa_loop_unswitch, pass_data_tree_unswitch,
make_pass_tree_unswitch): Relocate from tree-ssa-loop.c.
* tree-ssa-loop.c (tree_ssa_loop_im, gate_tree_ssa_loop_im,
pass_data_lim, make_pass_lim): Move to tree-ssa-loop-im.c.
(tree_ssa_loop_unswitch, gate_tree_ssa_loop_unswitch,
pass_data_tree_unswitch, make_pass_tree_unswitch): Move.
(tree_ssa_loop_ivcanon, gate_tree_ssa_loop_ivcanon, pass_data_iv_canon,
make_pass_iv_canon, tree_complete_unroll, gate_tree_complete_unroll,
pass_data_complete_unroll, make_pass_complete_unroll,
tree_complete_unroll_inner, gate_tree_complete_unroll_inner,
pass_data_complete_unrolli, make_pass_complete_unrolli): Move to
tree-ssa-loop-ivcanon.c.
(tree_ssa_loop_prefetch, gate_tree_ssa_loop_prefetch,
pass_data_loop_prefetch, make_pass_loop_prefetch): Move to
tree-ssa-loop-prefetch.c.
(for_each_index, lsm_tmp_name_add, gen_lsm_tmp_name): Relocate from
tree-ssa-loop-im.c.
(get_lsm_tmp_name): Relocate and add suffix parameter.
(tree_num_loop_insns): Relocate from tree-ssa-ivcanon.c.
* tree-scalar-evolution.h (simple_iv): Don't use affive_iv typedef.
* cfgloop.c (record_niter_bound, estimated_loop_iterations_int,
max_stmt_executions_int): Move from tree-ssa-loop-niter.c.
(get_estimated_loop_iterations): Factor out accessor from
estimated_loop_iterations in tree-ssa-loop-niter.c.
(get_max_loop_iterations): Factor out accessor from _max_loop_iterations
in tree-ssa-niter.c.
* loop-unroll.c (decide_unroll_constant_iterations,
decide_unroll_runtime_iterations, decide_peel_simple,
decide_unroll_stupid): Use new get_* accessors.

From-SVN: r203317

19 files changed:
gcc/ChangeLog
gcc/cfgloop.c
gcc/cfgloop.h
gcc/loop-unroll.c
gcc/tree-flow-inline.h
gcc/tree-flow.h
gcc/tree-scalar-evolution.h
gcc/tree-ssa-loop-ch.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-loop-ivcanon.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-ivopts.h [new file with mode: 0644]
gcc/tree-ssa-loop-manip.h [new file with mode: 0644]
gcc/tree-ssa-loop-niter.c
gcc/tree-ssa-loop-niter.h [new file with mode: 0644]
gcc/tree-ssa-loop-prefetch.c
gcc/tree-ssa-loop-unswitch.c
gcc/tree-ssa-loop.c
gcc/tree-ssa-loop.h [new file with mode: 0644]

index 95c490bcd360299bc4fb3c3505765950b34a2f28..92fc367e69a77eef141bf2a066b2b0694d5264c2 100644 (file)
@@ -1,3 +1,78 @@
+2013-10-09  Andrew MacLeod  <amacleod@redhat.com>
+
+       * tree-flow.h: Move some protoypes.  Include new tree-ssa-loop.h.
+       (struct affine_iv, struct tree_niter_desc): Move to tree-ssa-loop.h.
+       (enum move_pos): Move to tree-ssa-loop-im.h
+       * cfgloop.h: Move some prototypes.
+       (gcov_type_to_double_int): relocate from tree-ssa-loop.niter.c.
+       * tree-flow-inline.h (loop_containing_stmt): Move to tree-ssa-loop.h.
+       * tree-ssa-loop.h: New File.  Include other tree-ssa-loop-*.h files.
+       (struct affine_iv, struct tree_niter_desc): Relocate from tree-flow.h.
+       (loop_containing_stmt): Relocate from tree-flow-inline.h.
+       * tree-ssa-loop-ch.c: (do_while_loop_p): Make static.
+       * tree-ssa-loop-im.c (for_each_index): Move to tree-ssa-loop.c.
+       (enum move_pos): Relocate here.
+       (lsm_tmp_name_add, gen_lsm_tmp_name, get_lsm_tmp_name): Move to
+       tree-ssa-loop.c.
+       (execute_sm_if_changed_flag_set): Change get_lsm_tmp_name call.
+       (tree_ssa_loop_im, gate_tree_ssa_loop_im, pass_data_lim, make_pass_lim):
+       Relocate here from tree-ssa-loop.c.
+       * tree-ssa-loop-ivcanon.c (tree_num_loop_insns): Move to 
+       tree-ssa-loop.c.
+       (loop_edge_to_cancel, unloop_loops): Make static.
+       (tree_ssa_loop_ivcanon, gate_tree_ssa_loop_ivcanon, pass_data_iv_canon,
+       make_pass_iv_canon): Relocate from tree-ssa-loop.c.
+       (tree_complete_unroll, gate_tree_complete_unroll,
+       pass_data_complete_unroll, make_pass_complete_unroll): Relocate here.
+       (tree_complete_unroll_inner, gate_tree_complete_unroll_inner,
+       pass_data_complete_unrolli, make_pass_complete_unrolli): Relocate here.
+       * tree-ssa-loop-ivopts.c: Remove local prototypes.
+       (stmt_invariant_in_loop_p): Remove unused function.
+       * tree-ssa-loop-ivopts.h: New file.  Add prototypes.
+       * tree-ssa-loop-manip.h: New file.  Add prototypes.
+       * tree-ssa-loop-niter.c (record_niter_bound): Move to cfgloop.c.
+       (gcov_type_to_double_int): Move to cfgloop.h.
+       (double_int_cmp, bound_index,
+       estimate_numbers_of_iterations_loop): Make static.
+       (estimated_loop_iterations): Factor out get_estimated_loop_iterations.
+       (max_loop_iterations): Factor out get_max_loop_iterations.
+       (estimated_loop_iterations_int, max_stmt_executions_int): Move to
+       cfgloop.c.
+       * tree-ssa-loop-niter.h: New file.  Add prototypes.
+       * tree-ssa-loop-prefetch.c (tree_ssa_loop_prefetch,
+       gate_tree_ssa_loop_prefetch, pass_data_loop_prefetch,
+       make_pass_loop_prefetch): Relocate from tree-ssa-loop.c.
+       * tree-ssa-loop-unswitch.c (tree_ssa_loop_unswitch,
+       gate_tree_ssa_loop_unswitch, pass_data_tree_unswitch,
+       make_pass_tree_unswitch): Relocate from tree-ssa-loop.c.
+       * tree-ssa-loop.c (tree_ssa_loop_im, gate_tree_ssa_loop_im,
+       pass_data_lim, make_pass_lim): Move to tree-ssa-loop-im.c.
+       (tree_ssa_loop_unswitch, gate_tree_ssa_loop_unswitch,
+       pass_data_tree_unswitch, make_pass_tree_unswitch): Move.
+       (tree_ssa_loop_ivcanon, gate_tree_ssa_loop_ivcanon, pass_data_iv_canon,
+       make_pass_iv_canon, tree_complete_unroll, gate_tree_complete_unroll,
+       pass_data_complete_unroll, make_pass_complete_unroll,
+       tree_complete_unroll_inner, gate_tree_complete_unroll_inner,
+       pass_data_complete_unrolli, make_pass_complete_unrolli): Move to
+       tree-ssa-loop-ivcanon.c.
+       (tree_ssa_loop_prefetch, gate_tree_ssa_loop_prefetch,
+       pass_data_loop_prefetch, make_pass_loop_prefetch): Move to
+       tree-ssa-loop-prefetch.c.
+       (for_each_index, lsm_tmp_name_add, gen_lsm_tmp_name): Relocate from
+       tree-ssa-loop-im.c.
+       (get_lsm_tmp_name): Relocate and add suffix parameter.
+       (tree_num_loop_insns): Relocate from tree-ssa-ivcanon.c.
+       * tree-scalar-evolution.h (simple_iv): Don't use affive_iv typedef.
+       * cfgloop.c (record_niter_bound, estimated_loop_iterations_int,
+       max_stmt_executions_int): Move from tree-ssa-loop-niter.c.
+       (get_estimated_loop_iterations): Factor out accessor from 
+       estimated_loop_iterations in tree-ssa-loop-niter.c.
+       (get_max_loop_iterations): Factor out accessor from _max_loop_iterations
+       in tree-ssa-niter.c.
+       * loop-unroll.c (decide_unroll_constant_iterations,
+       decide_unroll_runtime_iterations, decide_peel_simple,
+       decide_unroll_stupid): Use new get_* accessors.
+
 2013-10-09  Marc Glisse  <marc.glisse@inria.fr>
 
        PR tree-optimization/20318
index f39b1944ab690b1d3428540daf673032f8c47ceb..272a675ab7dc8d7c909acb579966c8ca8c27d54e 100644 (file)
@@ -1781,3 +1781,113 @@ get_loop_location (struct loop *loop)
   return DECL_SOURCE_LOCATION (current_function_decl);
 }
 
+/* Records that every statement in LOOP is executed I_BOUND times.
+   REALISTIC is true if I_BOUND is expected to be close to the real number
+   of iterations.  UPPER is true if we are sure the loop iterates at most
+   I_BOUND times.  */
+
+void
+record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
+                   bool upper)
+{
+  /* Update the bounds only when there is no previous estimation, or when the
+     current estimation is smaller.  */
+  if (upper
+      && (!loop->any_upper_bound
+         || i_bound.ult (loop->nb_iterations_upper_bound)))
+    {
+      loop->any_upper_bound = true;
+      loop->nb_iterations_upper_bound = i_bound;
+    }
+  if (realistic
+      && (!loop->any_estimate
+         || i_bound.ult (loop->nb_iterations_estimate)))
+    {
+      loop->any_estimate = true;
+      loop->nb_iterations_estimate = i_bound;
+    }
+
+  /* If an upper bound is smaller than the realistic estimate of the
+     number of iterations, use the upper bound instead.  */
+  if (loop->any_upper_bound
+      && loop->any_estimate
+      && loop->nb_iterations_upper_bound.ult (loop->nb_iterations_estimate))
+    loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
+}
+
+/* Similar to estimated_loop_iterations, but returns the estimate only
+   if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
+   on the number of iterations of LOOP could not be derived, returns -1.  */
+
+HOST_WIDE_INT
+estimated_loop_iterations_int (struct loop *loop)
+{
+  double_int nit;
+  HOST_WIDE_INT hwi_nit;
+
+  if (!get_estimated_loop_iterations (loop, &nit))
+    return -1;
+
+  if (!nit.fits_shwi ())
+    return -1;
+  hwi_nit = nit.to_shwi ();
+
+  return hwi_nit < 0 ? -1 : hwi_nit;
+}
+
+/* Returns an upper bound on the number of executions of statements
+   in the LOOP.  For statements before the loop exit, this exceeds
+   the number of execution of the latch by one.  */
+
+HOST_WIDE_INT
+max_stmt_executions_int (struct loop *loop)
+{
+  HOST_WIDE_INT nit = max_loop_iterations_int (loop);
+  HOST_WIDE_INT snit;
+
+  if (nit == -1)
+    return -1;
+
+  snit = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) nit + 1);
+
+  /* If the computation overflows, return -1.  */
+  return snit < 0 ? -1 : snit;
+}
+
+/* Sets NIT to the estimated number of executions of the latch of the
+   LOOP.  If we have no reliable estimate, the function returns false, otherwise
+   returns true.  */
+
+bool
+get_estimated_loop_iterations (struct loop *loop, double_int *nit)
+{
+  /* Even if the bound is not recorded, possibly we can derrive one from
+     profile.  */
+  if (!loop->any_estimate)
+    {
+      if (loop->header->count)
+       {
+          *nit = gcov_type_to_double_int
+                  (expected_loop_iterations_unbounded (loop) + 1);
+         return true;
+       }
+      return false;
+    }
+
+  *nit = loop->nb_iterations_estimate;
+  return true;
+}
+
+/* Sets NIT to an upper bound for the maximum number of executions of the
+   latch of the LOOP.  If we have no reliable estimate, the function returns
+   false, otherwise returns true.  */
+
+bool
+get_max_loop_iterations (struct loop *loop, double_int *nit)
+{
+  if (!loop->any_upper_bound)
+    return false;
+
+  *nit = loop->nb_iterations_upper_bound;
+  return true;
+}
index 33d96fe5263b31d9fa03824001d6104154e34faa..9048e0226077ffd1d4c6dbf7442b52f4f0229711 100644 (file)
@@ -255,7 +255,6 @@ extern bool flow_bb_inside_loop_p (const struct loop *, const_basic_block);
 extern struct loop * find_common_loop (struct loop *, struct loop *);
 struct loop *superloop_at_depth (struct loop *, unsigned);
 struct eni_weights_d;
-extern unsigned tree_num_loop_insns (struct loop *, struct eni_weights_d *);
 extern int num_loop_insns (const struct loop *);
 extern int average_num_loop_insns (const struct loop *);
 extern unsigned get_loop_level (const struct loop *);
@@ -306,16 +305,6 @@ gcov_type expected_loop_iterations_unbounded (const struct loop *);
 extern unsigned expected_loop_iterations (const struct loop *);
 extern rtx doloop_condition_get (rtx);
 
-void estimate_numbers_of_iterations_loop (struct loop *);
-void record_niter_bound (struct loop *, double_int, bool, bool);
-bool estimated_loop_iterations (struct loop *, double_int *);
-bool max_loop_iterations (struct loop *, double_int *);
-HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
-HOST_WIDE_INT max_loop_iterations_int (struct loop *);
-bool max_stmt_executions (struct loop *, double_int *);
-bool estimated_stmt_executions (struct loop *, double_int *);
-HOST_WIDE_INT max_stmt_executions_int (struct loop *);
-HOST_WIDE_INT estimated_stmt_executions_int (struct loop *);
 
 /* Loop manipulation.  */
 extern bool can_duplicate_loop_p (const struct loop *loop);
@@ -735,7 +724,6 @@ enum
 extern void unroll_and_peel_loops (int);
 extern void doloop_optimize_loops (void);
 extern void move_loop_invariants (void);
-extern bool finite_loop_p (struct loop *);
 extern void scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound);
 extern vec<basic_block> get_loop_hot_path (const struct loop *loop);
 
@@ -751,5 +739,26 @@ loop_outermost (struct loop *loop)
   return (*loop->superloops)[1];
 }
 
+extern void record_niter_bound (struct loop *, double_int, bool, bool);
+extern HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
+extern HOST_WIDE_INT max_loop_iterations_int (struct loop *);
+extern bool get_estimated_loop_iterations (struct loop *loop, double_int *nit);
+extern bool get_max_loop_iterations (struct loop *loop, double_int *nit);
 
+/* Converts VAL to double_int.  */
+
+static inline double_int
+gcov_type_to_double_int (gcov_type val)
+{
+  double_int ret;
+
+  ret.low = (unsigned HOST_WIDE_INT) val;
+  /* If HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_WIDEST_INT, avoid shifting by
+     the size of type.  */
+  val >>= HOST_BITS_PER_WIDE_INT - 1;
+  val >>= 1;
+  ret.high = (unsigned HOST_WIDE_INT) val;
+
+  return ret;
+}
 #endif /* GCC_CFGLOOP_H */
index 95d58209224f6fd69567c2f66a6758c83a5d11b4..7fd317713fba3817d1487e0849b37d39f1e8e826 100644 (file)
@@ -694,8 +694,8 @@ decide_unroll_constant_iterations (struct loop *loop, int flags)
      than one exit it may well loop less than determined maximal number
      of iterations.  */
   if (desc->niter < 2 * nunroll
-      || ((estimated_loop_iterations (loop, &iterations)
-          || max_loop_iterations (loop, &iterations))
+      || ((get_estimated_loop_iterations (loop, &iterations)
+          || get_max_loop_iterations (loop, &iterations))
          && iterations.ult (double_int::from_shwi (2 * nunroll))))
     {
       if (dump_file)
@@ -999,8 +999,8 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags)
     }
 
   /* Check whether the loop rolls.  */
-  if ((estimated_loop_iterations (loop, &iterations)
-       || max_loop_iterations (loop, &iterations))
+  if ((get_estimated_loop_iterations (loop, &iterations)
+       || get_max_loop_iterations (loop, &iterations))
       && iterations.ult (double_int::from_shwi (2 * nunroll)))
     {
       if (dump_file)
@@ -1388,7 +1388,7 @@ decide_peel_simple (struct loop *loop, int flags)
     }
 
   /* If we have realistic estimate on number of iterations, use it.  */
-  if (estimated_loop_iterations (loop, &iterations))
+  if (get_estimated_loop_iterations (loop, &iterations))
     {
       if (double_int::from_shwi (npeel).ule (iterations))
        {
@@ -1406,7 +1406,7 @@ decide_peel_simple (struct loop *loop, int flags)
     }
   /* If we have small enough bound on iterations, we can still peel (completely
      unroll).  */
-  else if (max_loop_iterations (loop, &iterations)
+  else if (get_max_loop_iterations (loop, &iterations)
            && iterations.ult (double_int::from_shwi (npeel)))
     npeel = iterations.to_shwi () + 1;
   else
@@ -1556,8 +1556,8 @@ decide_unroll_stupid (struct loop *loop, int flags)
     }
 
   /* Check whether the loop rolls.  */
-  if ((estimated_loop_iterations (loop, &iterations)
-       || max_loop_iterations (loop, &iterations))
+  if ((get_estimated_loop_iterations (loop, &iterations)
+       || get_max_loop_iterations (loop, &iterations))
       && iterations.ult (double_int::from_shwi (2 * nunroll)))
     {
       if (dump_file)
index 164df957315e0b380e5e364c000f6e472654d9e7..8243f29774748a2067669cc71d1fd819989644cd 100644 (file)
@@ -107,21 +107,6 @@ may_be_aliased (const_tree var)
              || TREE_ADDRESSABLE (var)));
 }
 
-
-/* Returns the loop of the statement STMT.  */
-
-static inline struct loop *
-loop_containing_stmt (gimple stmt)
-{
-  basic_block bb = gimple_bb (stmt);
-  if (!bb)
-    return NULL;
-
-  return bb->loop_father;
-}
-
-
-
 /* Return true if VAR cannot be modified by the program.  */
 
 static inline bool
index 54ba51aa68bacbfa2b4b326f1e87f2b1513d85fb..2aed9ddfee1c59481bf046fb7909ad662230f89a 100644 (file)
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "gimple-low.h"
 #include "tree-into-ssa.h"
+#include "tree-ssa-loop.h"
 
 /* This structure is used to map a gimple statement to a label,
    or list of labels to represent transaction restart.  */
@@ -244,109 +245,19 @@ extern basic_block move_sese_region_to_fn (struct function *, basic_block,
 void remove_edge_and_dominated_blocks (edge);
 bool tree_node_can_be_shared (tree);
 
-/* In tree-ssa-loop-ch.c  */
-bool do_while_loop_p (struct loop *);
-
-/* Affine iv.  */
-
-typedef struct
-{
-  /* Iv = BASE + STEP * i.  */
-  tree base, step;
-
-  /* True if this iv does not overflow.  */
-  bool no_overflow;
-} affine_iv;
-
-/* Description of number of iterations of a loop.  All the expressions inside
-   the structure can be evaluated at the end of the loop's preheader
-   (and due to ssa form, also anywhere inside the body of the loop).  */
-
-struct tree_niter_desc
-{
-  tree assumptions;    /* The boolean expression.  If this expression evaluates
-                          to false, then the other fields in this structure
-                          should not be used; there is no guarantee that they
-                          will be correct.  */
-  tree may_be_zero;    /* The boolean expression.  If it evaluates to true,
-                          the loop will exit in the first iteration (i.e.
-                          its latch will not be executed), even if the niter
-                          field says otherwise.  */
-  tree niter;          /* The expression giving the number of iterations of
-                          a loop (provided that assumptions == true and
-                          may_be_zero == false), more precisely the number
-                          of executions of the latch of the loop.  */
-  double_int max;      /* The upper bound on the number of iterations of
-                          the loop.  */
-
-  /* The simplified shape of the exit condition.  The loop exits if
-     CONTROL CMP BOUND is false, where CMP is one of NE_EXPR,
-     LT_EXPR, or GT_EXPR, and step of CONTROL is positive if CMP is
-     LE_EXPR and negative if CMP is GE_EXPR.  This information is used
-     by loop unrolling.  */
-  affine_iv control;
-  tree bound;
-  enum tree_code cmp;
-};
 
 
 /* In tree-ssa-loop*.c  */
 
-unsigned int tree_ssa_lim (void);
-unsigned int tree_ssa_unswitch_loops (void);
-unsigned int canonicalize_induction_variables (void);
-unsigned int tree_unroll_loops_completely (bool, bool);
-unsigned int tree_ssa_prefetch_arrays (void);
-void tree_ssa_iv_optimize (void);
 unsigned tree_predictive_commoning (void);
-tree canonicalize_loop_ivs (struct loop *, tree *, bool);
 bool parallelize_loops (void);
 
-bool loop_only_exit_p (const struct loop *, const_edge);
-bool number_of_iterations_exit (struct loop *, edge,
-                               struct tree_niter_desc *niter, bool,
-                               bool every_iteration = true);
-tree find_loop_niter (struct loop *, edge *);
-tree loop_niter_by_eval (struct loop *, edge);
-tree find_loop_niter_by_eval (struct loop *, edge *);
-void estimate_numbers_of_iterations (void);
-bool scev_probably_wraps_p (tree, tree, gimple, struct loop *, bool);
 bool convert_affine_scev (struct loop *, tree, tree *, tree *, gimple, bool);
 
-bool nowrap_type_p (tree);
 enum ev_direction {EV_DIR_GROWS, EV_DIR_DECREASES, EV_DIR_UNKNOWN};
 enum ev_direction scev_direction (const_tree);
 
-void free_numbers_of_iterations_estimates (void);
-void free_numbers_of_iterations_estimates_loop (struct loop *);
-void rewrite_into_loop_closed_ssa (bitmap, unsigned);
-void verify_loop_closed_ssa (bool);
-bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
-void create_iv (tree, tree, tree, struct loop *, gimple_stmt_iterator *, bool,
-               tree *, tree *);
-basic_block split_loop_exit_edge (edge);
-void standard_iv_increment_position (struct loop *, gimple_stmt_iterator *,
-                                    bool *);
-basic_block ip_end_pos (struct loop *);
-basic_block ip_normal_pos (struct loop *);
-bool gimple_duplicate_loop_to_header_edge (struct loop *, edge,
-                                        unsigned int, sbitmap,
-                                        edge, vec<edge> *,
-                                        int);
 struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *, edge);
-tree expand_simple_operations (tree);
-void substitute_in_loop_info (struct loop *, tree, tree);
-edge single_dom_exit (struct loop *);
-bool can_unroll_loop_p (struct loop *loop, unsigned factor,
-                       struct tree_niter_desc *niter);
-void tree_unroll_loop (struct loop *, unsigned,
-                      edge, struct tree_niter_desc *);
-typedef void (*transform_callback)(struct loop *, void *);
-void tree_transform_and_unroll_loop (struct loop *, unsigned,
-                                    edge, struct tree_niter_desc *,
-                                    transform_callback, void *);
-bool contains_abnormal_ssa_name_p (tree);
-bool stmt_dominates_stmt_p (gimple, gimple);
 
 /* In tree-ssa-threadedge.c */
 extern void threadedge_initialize_values (void);
@@ -362,19 +273,6 @@ extern void thread_across_edge (gimple, edge, bool,
                                vec<tree> *, tree (*) (gimple, gimple));
 extern void propagate_threaded_block_debug_into (basic_block, basic_block);
 
-/* In tree-ssa-loop-im.c  */
-/* The possibilities of statement movement.  */
-
-enum move_pos
-  {
-    MOVE_IMPOSSIBLE,           /* No movement -- side effect expression.  */
-    MOVE_PRESERVE_EXECUTION,   /* Must not cause the non-executed statement
-                                  become executed -- memory accesses, ... */
-    MOVE_POSSIBLE              /* Unlimited movement.  */
-  };
-extern enum move_pos movement_possibility (gimple);
-char *get_lsm_tmp_name (tree, unsigned);
-
 /* In tree-loop-linear.c  */
 extern void linear_transform_loops (void);
 extern unsigned perfect_loop_nest_depth (struct loop *);
@@ -385,14 +283,6 @@ extern void graphite_transform_loops (void);
 /* In tree-data-ref.c  */
 extern void tree_check_data_deps (void);
 
-/* In tree-ssa-loop-ivopts.c  */
-bool expr_invariant_in_loop_p (struct loop *, tree);
-bool stmt_invariant_in_loop_p (struct loop *, gimple);
-struct loop *outermost_invariant_loop_for_expr (struct loop *, tree);
-bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode,
-                                     addr_space_t);
-bool may_be_nonaddressable_p (tree expr);
-
 /* In gimplify.c  */
 tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree);
 tree force_gimple_operand (tree, gimple_seq *, bool, tree);
index 55ba82c5dbd5a1b574b33c603a00ee936ee033b7..db7ac4c66f046ae4834d6fe8e2f8d3aa4fc04663 100644 (file)
@@ -36,7 +36,8 @@ extern tree resolve_mixers (struct loop *, tree);
 extern void gather_stats_on_scev_database (void);
 extern unsigned int scev_const_prop (void);
 extern bool expression_expensive_p (tree);
-extern bool simple_iv (struct loop *, struct loop *, tree, affine_iv *, bool);
+extern bool simple_iv (struct loop *, struct loop *, tree, struct affine_iv_d *,
+                      bool);
 extern tree compute_overall_effect_of_inner_loop (struct loop *, tree);
 
 /* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the
index faa6bbcc58531e80f098f973a8c90e04bd0eec02..b74855e62de830fdf7163693a65dc7f14ba6c127 100644 (file)
@@ -29,7 +29,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "tree-inline.h"
 #include "flags.h"
-#include "tree-inline.h"
 
 /* Duplicates headers of loops if they are small enough, so that the statements
    in the loop body are always executed when the loop is entered.  This
@@ -100,7 +99,7 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
 
 /* Checks whether LOOP is a do-while style loop.  */
 
-bool
+static bool
 do_while_loop_p (struct loop *loop)
 {
   gimple stmt = last_stmt (loop->latch);
index fc255289f24ba7fce8d310d6cc9825a273c624f2..84f50cdb92d357e4e91781c34ca69ebf0d2cc10e 100644 (file)
@@ -242,98 +242,16 @@ clear_lim_data (gimple stmt)
   *p = NULL;
 }
 
-/* Calls CBCK for each index in memory reference ADDR_P.  There are two
-   kinds situations handled; in each of these cases, the memory reference
-   and DATA are passed to the callback:
 
-   Access to an array: ARRAY_{RANGE_}REF (base, index).  In this case we also
-   pass the pointer to the index to the callback.
-
-   Pointer dereference: INDIRECT_REF (addr).  In this case we also pass the
-   pointer to addr to the callback.
-
-   If the callback returns false, the whole search stops and false is returned.
-   Otherwise the function returns true after traversing through the whole
-   reference *ADDR_P.  */
-
-bool
-for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
-{
-  tree *nxt, *idx;
-
-  for (; ; addr_p = nxt)
-    {
-      switch (TREE_CODE (*addr_p))
-       {
-       case SSA_NAME:
-         return cbck (*addr_p, addr_p, data);
-
-       case MEM_REF:
-         nxt = &TREE_OPERAND (*addr_p, 0);
-         return cbck (*addr_p, nxt, data);
-
-       case BIT_FIELD_REF:
-       case VIEW_CONVERT_EXPR:
-       case REALPART_EXPR:
-       case IMAGPART_EXPR:
-         nxt = &TREE_OPERAND (*addr_p, 0);
-         break;
-
-       case COMPONENT_REF:
-         /* If the component has varying offset, it behaves like index
-            as well.  */
-         idx = &TREE_OPERAND (*addr_p, 2);
-         if (*idx
-             && !cbck (*addr_p, idx, data))
-           return false;
-
-         nxt = &TREE_OPERAND (*addr_p, 0);
-         break;
+/* The possibilities of statement movement.  */
+enum move_pos
+  {
+    MOVE_IMPOSSIBLE,           /* No movement -- side effect expression.  */
+    MOVE_PRESERVE_EXECUTION,   /* Must not cause the non-executed statement
+                                  become executed -- memory accesses, ... */
+    MOVE_POSSIBLE              /* Unlimited movement.  */
+  };
 
-       case ARRAY_REF:
-       case ARRAY_RANGE_REF:
-         nxt = &TREE_OPERAND (*addr_p, 0);
-         if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
-           return false;
-         break;
-
-       case VAR_DECL:
-       case PARM_DECL:
-       case CONST_DECL:
-       case STRING_CST:
-       case RESULT_DECL:
-       case VECTOR_CST:
-       case COMPLEX_CST:
-       case INTEGER_CST:
-       case REAL_CST:
-       case FIXED_CST:
-       case CONSTRUCTOR:
-         return true;
-
-       case ADDR_EXPR:
-         gcc_assert (is_gimple_min_invariant (*addr_p));
-         return true;
-
-       case TARGET_MEM_REF:
-         idx = &TMR_BASE (*addr_p);
-         if (*idx
-             && !cbck (*addr_p, idx, data))
-           return false;
-         idx = &TMR_INDEX (*addr_p);
-         if (*idx
-             && !cbck (*addr_p, idx, data))
-           return false;
-         idx = &TMR_INDEX2 (*addr_p);
-         if (*idx
-             && !cbck (*addr_p, idx, data))
-           return false;
-         return true;
-
-       default:
-         gcc_unreachable ();
-       }
-    }
-}
 
 /* If it is possible to hoist the statement STMT unconditionally,
    returns MOVE_POSSIBLE.
@@ -1741,122 +1659,6 @@ first_mem_ref_loc (struct loop *loop, mem_ref_p ref)
   return locp;
 }
 
-/* The name and the length of the currently generated variable
-   for lsm.  */
-#define MAX_LSM_NAME_LENGTH 40
-static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
-static int lsm_tmp_name_length;
-
-/* Adds S to lsm_tmp_name.  */
-
-static void
-lsm_tmp_name_add (const char *s)
-{
-  int l = strlen (s) + lsm_tmp_name_length;
-  if (l > MAX_LSM_NAME_LENGTH)
-    return;
-
-  strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
-  lsm_tmp_name_length = l;
-}
-
-/* Stores the name for temporary variable that replaces REF to
-   lsm_tmp_name.  */
-
-static void
-gen_lsm_tmp_name (tree ref)
-{
-  const char *name;
-
-  switch (TREE_CODE (ref))
-    {
-    case MEM_REF:
-    case TARGET_MEM_REF:
-      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
-      lsm_tmp_name_add ("_");
-      break;
-
-    case ADDR_EXPR:
-      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
-      break;
-
-    case BIT_FIELD_REF:
-    case VIEW_CONVERT_EXPR:
-    case ARRAY_RANGE_REF:
-      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
-      break;
-
-    case REALPART_EXPR:
-      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
-      lsm_tmp_name_add ("_RE");
-      break;
-
-    case IMAGPART_EXPR:
-      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
-      lsm_tmp_name_add ("_IM");
-      break;
-
-    case COMPONENT_REF:
-      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
-      lsm_tmp_name_add ("_");
-      name = get_name (TREE_OPERAND (ref, 1));
-      if (!name)
-       name = "F";
-      lsm_tmp_name_add (name);
-      break;
-
-    case ARRAY_REF:
-      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
-      lsm_tmp_name_add ("_I");
-      break;
-
-    case SSA_NAME:
-    case VAR_DECL:
-    case PARM_DECL:
-      name = get_name (ref);
-      if (!name)
-       name = "D";
-      lsm_tmp_name_add (name);
-      break;
-
-    case STRING_CST:
-      lsm_tmp_name_add ("S");
-      break;
-
-    case RESULT_DECL:
-      lsm_tmp_name_add ("R");
-      break;
-
-    case INTEGER_CST:
-      /* Nothing.  */
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Determines name for temporary variable that replaces REF.
-   The name is accumulated into the lsm_tmp_name variable.
-   N is added to the name of the temporary.  */
-
-char *
-get_lsm_tmp_name (tree ref, unsigned n)
-{
-  char ns[2];
-
-  lsm_tmp_name_length = 0;
-  gen_lsm_tmp_name (ref);
-  lsm_tmp_name_add ("_lsm");
-  if (n < 10)
-    {
-      ns[0] = '0' + n;
-      ns[1] = 0;
-      lsm_tmp_name_add (ns);
-    }
-  return lsm_tmp_name;
-}
-
 struct prev_flag_edges {
   /* Edge to insert new flag comparison code.  */
   edge append_cond_position;
@@ -2026,8 +1828,7 @@ static tree
 execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref)
 {
   tree flag;
-  char *str = get_lsm_tmp_name (ref->mem.ref, ~0);
-  lsm_tmp_name_add ("_flag");
+  char *str = get_lsm_tmp_name (ref->mem.ref, ~0, "_flag");
   flag = create_tmp_reg (boolean_type_node, str);
   for_all_locs_in_loop (loop, ref, sm_set_flag_if_changed (flag));
   return flag;
@@ -2639,3 +2440,61 @@ tree_ssa_lim (void)
 
   return todo;
 }
+
+/* Loop invariant motion pass.  */
+
+static unsigned int
+tree_ssa_loop_im (void)
+{
+  if (number_of_loops (cfun) <= 1)
+    return 0;
+
+  return tree_ssa_lim ();
+}
+
+static bool
+gate_tree_ssa_loop_im (void)
+{
+  return flag_tree_loop_im != 0;
+}
+
+namespace {
+
+const pass_data pass_data_lim =
+{
+  GIMPLE_PASS, /* type */
+  "lim", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_LIM, /* tv_id */
+  PROP_cfg, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_lim : public gimple_opt_pass
+{
+public:
+  pass_lim (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_lim, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  opt_pass * clone () { return new pass_lim (m_ctxt); }
+  bool gate () { return gate_tree_ssa_loop_im (); }
+  unsigned int execute () { return tree_ssa_loop_im (); }
+
+}; // class pass_lim
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_lim (gcc::context *ctxt)
+{
+  return new pass_lim (ctxt);
+}
+
+
index d5249baeab0f090c0a98558e17483a317b32f13b..8db5b9ede7e79834a0d8da6c40a6d7fa1ecd1700 100644 (file)
@@ -107,23 +107,6 @@ create_canonical_iv (struct loop *loop, edge exit, tree niter)
   update_stmt (cond);
 }
 
-/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS.  */
-
-unsigned
-tree_num_loop_insns (struct loop *loop, eni_weights *weights)
-{
-  basic_block *body = get_loop_body (loop);
-  gimple_stmt_iterator gsi;
-  unsigned size = 0, i;
-
-  for (i = 0; i < loop->num_nodes; i++)
-    for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
-      size += estimate_num_insns (gsi_stmt (gsi), weights);
-  free (body);
-
-  return size;
-}
-
 /* Describe size of loop as detected by tree_estimate_loop_size.  */
 struct loop_size
 {
@@ -422,7 +405,7 @@ estimated_unrolled_size (struct loop_size *size,
    loop-niter identified as having undefined effect in the last iteration.
    The other cases are hopefully rare and will be cleaned up later.  */
 
-edge
+static edge
 loop_edge_to_cancel (struct loop *loop)
 {
   vec<edge> exits;
@@ -598,7 +581,7 @@ static vec<int> loops_to_unloop_nunroll;
    LOOP_CLOSED_SSA_INVALIDATED is used to bookkepp the case
    when we need to go into loop closed SSA form.  */
 
-void
+static void
 unloop_loops (bitmap loop_closed_ssa_invalidated,
              bool *irred_invalidated)
 {
@@ -1253,3 +1236,182 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
 
   return 0;
 }
+
+/* Canonical induction variable creation pass.  */
+
+static unsigned int
+tree_ssa_loop_ivcanon (void)
+{
+  if (number_of_loops (cfun) <= 1)
+    return 0;
+
+  return canonicalize_induction_variables ();
+}
+
+static bool
+gate_tree_ssa_loop_ivcanon (void)
+{
+  return flag_tree_loop_ivcanon != 0;
+}
+
+namespace {
+
+const pass_data pass_data_iv_canon =
+{
+  GIMPLE_PASS, /* type */
+  "ivcanon", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_TREE_LOOP_IVCANON, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_iv_canon : public gimple_opt_pass
+{
+public:
+  pass_iv_canon (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_iv_canon, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_tree_ssa_loop_ivcanon (); }
+  unsigned int execute () { return tree_ssa_loop_ivcanon (); }
+
+}; // class pass_iv_canon
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_iv_canon (gcc::context *ctxt)
+{
+  return new pass_iv_canon (ctxt);
+}
+
+/* Complete unrolling of loops.  */
+
+static unsigned int
+tree_complete_unroll (void)
+{
+  if (number_of_loops (cfun) <= 1)
+    return 0;
+
+  return tree_unroll_loops_completely (flag_unroll_loops
+                                      || flag_peel_loops
+                                      || optimize >= 3, true);
+}
+
+static bool
+gate_tree_complete_unroll (void)
+{
+  return true;
+}
+
+namespace {
+
+const pass_data pass_data_complete_unroll =
+{
+  GIMPLE_PASS, /* type */
+  "cunroll", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_COMPLETE_UNROLL, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_complete_unroll : public gimple_opt_pass
+{
+public:
+  pass_complete_unroll (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_complete_unroll, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_tree_complete_unroll (); }
+  unsigned int execute () { return tree_complete_unroll (); }
+
+}; // class pass_complete_unroll
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_complete_unroll (gcc::context *ctxt)
+{
+  return new pass_complete_unroll (ctxt);
+}
+
+/* Complete unrolling of inner loops.  */
+
+static unsigned int
+tree_complete_unroll_inner (void)
+{
+  unsigned ret = 0;
+
+  loop_optimizer_init (LOOPS_NORMAL
+                      | LOOPS_HAVE_RECORDED_EXITS);
+  if (number_of_loops (cfun) > 1)
+    {
+      scev_initialize ();
+      ret = tree_unroll_loops_completely (optimize >= 3, false);
+      free_numbers_of_iterations_estimates ();
+      scev_finalize ();
+    }
+  loop_optimizer_finalize ();
+
+  return ret;
+}
+
+static bool
+gate_tree_complete_unroll_inner (void)
+{
+  return optimize >= 2;
+}
+
+namespace {
+
+const pass_data pass_data_complete_unrolli =
+{
+  GIMPLE_PASS, /* type */
+  "cunrolli", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_COMPLETE_UNROLL, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_verify_flow, /* todo_flags_finish */
+};
+
+class pass_complete_unrolli : public gimple_opt_pass
+{
+public:
+  pass_complete_unrolli (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_complete_unrolli, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_tree_complete_unroll_inner (); }
+  unsigned int execute () { return tree_complete_unroll_inner (); }
+
+}; // class pass_complete_unrolli
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_complete_unrolli (gcc::context *ctxt)
+{
+  return new pass_complete_unrolli (ctxt);
+}
+
+
index 7b684a6281908000f5ac0fa84deecd9c36adb961..5e8fa36f39494772c6a1ca2f80512a77c9439964 100644 (file)
@@ -452,7 +452,6 @@ single_dom_exit (struct loop *loop)
 
 /* Dumps information about the induction variable IV to FILE.  */
 
-extern void dump_iv (FILE *, struct iv *);
 void
 dump_iv (FILE *file, struct iv *iv)
 {
@@ -497,7 +496,6 @@ dump_iv (FILE *file, struct iv *iv)
 
 /* Dumps information about the USE to FILE.  */
 
-extern void dump_use (FILE *, struct iv_use *);
 void
 dump_use (FILE *file, struct iv_use *use)
 {
@@ -541,7 +539,6 @@ dump_use (FILE *file, struct iv_use *use)
 
 /* Dumps information about the uses to FILE.  */
 
-extern void dump_uses (FILE *, struct ivopts_data *);
 void
 dump_uses (FILE *file, struct ivopts_data *data)
 {
@@ -559,7 +556,6 @@ dump_uses (FILE *file, struct ivopts_data *data)
 
 /* Dumps information about induction variable candidate CAND to FILE.  */
 
-extern void dump_cand (FILE *, struct iv_cand *);
 void
 dump_cand (FILE *file, struct iv_cand *cand)
 {
@@ -1454,29 +1450,6 @@ expr_invariant_in_loop_p (struct loop *loop, tree expr)
   return true;
 }
 
-/* Returns true if statement STMT is obviously invariant in LOOP,
-   i.e. if all its operands on the RHS are defined outside of the LOOP.
-   LOOP should not be the function body.  */
-
-bool
-stmt_invariant_in_loop_p (struct loop *loop, gimple stmt)
-{
-  unsigned i;
-  tree lhs;
-
-  gcc_assert (loop_depth (loop) > 0);
-
-  lhs = gimple_get_lhs (stmt);
-  for (i = 0; i < gimple_num_ops (stmt); i++)
-    {
-      tree op = gimple_op (stmt, i);
-      if (op != lhs && !expr_invariant_in_loop_p (loop, op))
-       return false;
-    }
-
-  return true;
-}
-
 /* Cumulates the steps of indices into DATA and replaces their values with the
    initial ones.  Returns false when the value of the index cannot be determined.
    Callback for for_each_index.  */
diff --git a/gcc/tree-ssa-loop-ivopts.h b/gcc/tree-ssa-loop-ivopts.h
new file mode 100644 (file)
index 0000000..1af92be
--- /dev/null
@@ -0,0 +1,36 @@
+/* Header file for Induction variable optimizations.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_TREE_SSA_LOOP_IVOPTS_H
+#define GCC_TREE_SSA_LOOP_IVOPTS_H
+
+extern edge single_dom_exit (struct loop *);
+extern void dump_iv (FILE *, struct iv *);
+extern void dump_use (FILE *, struct iv_use *);
+extern void dump_uses (FILE *, struct ivopts_data *);
+extern void dump_cand (FILE *, struct iv_cand *);
+extern bool contains_abnormal_ssa_name_p (tree);
+extern struct loop *outermost_invariant_loop_for_expr (struct loop *, tree);
+extern bool expr_invariant_in_loop_p (struct loop *, tree);
+bool may_be_nonaddressable_p (tree expr);
+bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode,
+                                     addr_space_t);
+void tree_ssa_iv_optimize (void);
+
+#endif /* GCC_TREE_SSA_LOOP_IVOPTS_H */
diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h
new file mode 100644 (file)
index 0000000..a1dcd22
--- /dev/null
@@ -0,0 +1,49 @@
+/* Header file for High-level loop manipulation functions.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_TREE_SSA_LOOP_MANIP_H
+#define GCC_TREE_SSA_LOOP_MANIP_H
+
+typedef void (*transform_callback)(struct loop *, void *);
+
+extern void create_iv (tree, tree, tree, struct loop *, gimple_stmt_iterator *,
+                      bool, tree *, tree *);
+extern void rewrite_into_loop_closed_ssa (bitmap, unsigned);
+extern void verify_loop_closed_ssa (bool);
+extern basic_block split_loop_exit_edge (edge);
+extern basic_block ip_end_pos (struct loop *);
+extern basic_block ip_normal_pos (struct loop *);
+extern void standard_iv_increment_position (struct loop *,
+                                           gimple_stmt_iterator *, bool *);
+extern bool gimple_duplicate_loop_to_header_edge (struct loop *, edge,
+                                                 unsigned int, sbitmap,
+                                                 edge, vec<edge> *,
+                                                 int);
+extern bool can_unroll_loop_p (struct loop *loop, unsigned factor,
+                              struct tree_niter_desc *niter);
+extern void tree_transform_and_unroll_loop (struct loop *, unsigned,
+                                           edge, struct tree_niter_desc *,
+                                           transform_callback, void *);
+extern void tree_unroll_loop (struct loop *, unsigned,
+                             edge, struct tree_niter_desc *);
+extern tree canonicalize_loop_ivs (struct loop *, tree *, bool);
+
+
+
+#endif /* GCC_TREE_SSA_LOOP_MANIP_H */
index adbfe8e8c21a86ec8e1f5208769dd6bf0b39fc0b..8bcb1c6b26e23bb85c5b41369560b3ab6cc1536f 100644 (file)
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-inline.h"
 #include "tree-pass.h"
 
+
 #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
 
 /* The maximum number of dominator BBs we search for conditions
@@ -2507,40 +2508,6 @@ derive_constant_upper_bound_ops (tree type, tree op0,
     }
 }
 
-/* Records that every statement in LOOP is executed I_BOUND times.
-   REALISTIC is true if I_BOUND is expected to be close to the real number
-   of iterations.  UPPER is true if we are sure the loop iterates at most
-   I_BOUND times.  */
-
-void
-record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
-                   bool upper)
-{
-  /* Update the bounds only when there is no previous estimation, or when the
-     current estimation is smaller.  */
-  if (upper
-      && (!loop->any_upper_bound
-         || i_bound.ult (loop->nb_iterations_upper_bound)))
-    {
-      loop->any_upper_bound = true;
-      loop->nb_iterations_upper_bound = i_bound;
-    }
-  if (realistic
-      && (!loop->any_estimate
-         || i_bound.ult (loop->nb_iterations_estimate)))
-    {
-      loop->any_estimate = true;
-      loop->nb_iterations_estimate = i_bound;
-    }
-
-  /* If an upper bound is smaller than the realistic estimate of the
-     number of iterations, use the upper bound instead.  */
-  if (loop->any_upper_bound
-      && loop->any_estimate
-      && loop->nb_iterations_upper_bound.ult (loop->nb_iterations_estimate))
-    loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
-}
-
 /* Emit a -Waggressive-loop-optimizations warning if needed.  */
 
 static void
@@ -3008,26 +2975,11 @@ infer_loop_bounds_from_undefined (struct loop *loop)
   free (bbs);
 }
 
-/* Converts VAL to double_int.  */
 
-static double_int
-gcov_type_to_double_int (gcov_type val)
-{
-  double_int ret;
-
-  ret.low = (unsigned HOST_WIDE_INT) val;
-  /* If HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_WIDEST_INT, avoid shifting by
-     the size of type.  */
-  val >>= HOST_BITS_PER_WIDE_INT - 1;
-  val >>= 1;
-  ret.high = (unsigned HOST_WIDE_INT) val;
-
-  return ret;
-}
 
 /* Compare double ints, callback for qsort.  */
 
-int
+static int
 double_int_cmp (const void *p1, const void *p2)
 {
   const double_int *d1 = (const double_int *)p1;
@@ -3042,7 +2994,7 @@ double_int_cmp (const void *p1, const void *p2)
 /* Return index of BOUND in BOUNDS array sorted in increasing order.
    Lookup by binary search.  */
 
-int
+static int
 bound_index (vec<double_int> bounds, double_int bound)
 {
   unsigned int end = bounds.length ();
@@ -3349,7 +3301,7 @@ maybe_lower_iteration_bound (struct loop *loop)
 /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
    is true also use estimates derived from undefined behavior.  */
 
-void
+static void
 estimate_numbers_of_iterations_loop (struct loop *loop)
 {
   vec<edge> exits;
@@ -3433,21 +3385,7 @@ estimated_loop_iterations (struct loop *loop, double_int *nit)
   if (scev_initialized_p ())
     estimate_numbers_of_iterations_loop (loop);
 
-  /* Even if the bound is not recorded, possibly we can derrive one from
-     profile.  */
-  if (!loop->any_estimate)
-    {
-      if (loop->header->count)
-       {
-          *nit = gcov_type_to_double_int
-                  (expected_loop_iterations_unbounded (loop) + 1);
-         return true;
-       }
-      return false;
-    }
-
-  *nit = loop->nb_iterations_estimate;
-  return true;
+  return (get_estimated_loop_iterations (loop, nit));
 }
 
 /* Sets NIT to an upper bound for the maximum number of executions of the
@@ -3461,31 +3399,8 @@ max_loop_iterations (struct loop *loop, double_int *nit)
      estimate.  Otherwise just return whatever we recorded earlier.  */
   if (scev_initialized_p ())
     estimate_numbers_of_iterations_loop (loop);
-  if (!loop->any_upper_bound)
-    return false;
-
-  *nit = loop->nb_iterations_upper_bound;
-  return true;
-}
-
-/* Similar to estimated_loop_iterations, but returns the estimate only
-   if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
-   on the number of iterations of LOOP could not be derived, returns -1.  */
 
-HOST_WIDE_INT
-estimated_loop_iterations_int (struct loop *loop)
-{
-  double_int nit;
-  HOST_WIDE_INT hwi_nit;
-
-  if (!estimated_loop_iterations (loop, &nit))
-    return -1;
-
-  if (!nit.fits_shwi ())
-    return -1;
-  hwi_nit = nit.to_shwi ();
-
-  return hwi_nit < 0 ? -1 : hwi_nit;
+  return get_max_loop_iterations (loop, nit);
 }
 
 /* Similar to max_loop_iterations, but returns the estimate only
@@ -3508,25 +3423,6 @@ max_loop_iterations_int (struct loop *loop)
   return hwi_nit < 0 ? -1 : hwi_nit;
 }
 
-/* Returns an upper bound on the number of executions of statements
-   in the LOOP.  For statements before the loop exit, this exceeds
-   the number of execution of the latch by one.  */
-
-HOST_WIDE_INT
-max_stmt_executions_int (struct loop *loop)
-{
-  HOST_WIDE_INT nit = max_loop_iterations_int (loop);
-  HOST_WIDE_INT snit;
-
-  if (nit == -1)
-    return -1;
-
-  snit = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) nit + 1);
-
-  /* If the computation overflows, return -1.  */
-  return snit < 0 ? -1 : snit;
-}
-
 /* Returns an estimate for the number of executions of statements
    in the LOOP.  For statements before the loop exit, this exceeds
    the number of execution of the latch by one.  */
diff --git a/gcc/tree-ssa-loop-niter.h b/gcc/tree-ssa-loop-niter.h
new file mode 100644 (file)
index 0000000..aa05282
--- /dev/null
@@ -0,0 +1,46 @@
+/* Header file for loop interation estimates.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_TREE_SSA_LOOP_NITER_H
+#define GCC_TREE_SSA_LOOP_NITER_H
+
+extern tree expand_simple_operations (tree);
+extern bool loop_only_exit_p (const struct loop *, const_edge);
+extern bool number_of_iterations_exit (struct loop *, edge,
+                                      struct tree_niter_desc *niter, bool,
+                                      bool every_iteration = true);
+extern tree find_loop_niter (struct loop *, edge *);
+extern bool finite_loop_p (struct loop *);
+extern tree loop_niter_by_eval (struct loop *, edge);
+extern tree find_loop_niter_by_eval (struct loop *, edge *);
+extern bool estimated_loop_iterations (struct loop *, double_int *);
+extern bool max_loop_iterations (struct loop *, double_int *);
+extern HOST_WIDE_INT max_stmt_executions_int (struct loop *);
+extern HOST_WIDE_INT estimated_stmt_executions_int (struct loop *);
+extern bool max_stmt_executions (struct loop *, double_int *);
+extern bool estimated_stmt_executions (struct loop *, double_int *);
+extern void estimate_numbers_of_iterations (void);
+extern bool stmt_dominates_stmt_p (gimple, gimple);
+extern bool nowrap_type_p (tree);
+extern bool scev_probably_wraps_p (tree, tree, gimple, struct loop *, bool);
+extern void free_numbers_of_iterations_estimates_loop (struct loop *);
+extern void free_numbers_of_iterations_estimates (void);
+extern void substitute_in_loop_info (struct loop *, tree, tree);
+
+#endif /* GCC_TREE_SSA_LOOP_NITER_H */
index d75155d15d6e2585077ba95bd1c833d98d1175b1..5a51ba66c490c5453ec3716dab00952357fdf5ab 100644 (file)
@@ -1988,3 +1988,60 @@ tree_ssa_prefetch_arrays (void)
   free_original_copy_tables ();
   return todo_flags;
 }
+
+/* Prefetching.  */
+
+static unsigned int
+tree_ssa_loop_prefetch (void)
+{
+  if (number_of_loops (cfun) <= 1)
+    return 0;
+
+  return tree_ssa_prefetch_arrays ();
+}
+
+static bool
+gate_tree_ssa_loop_prefetch (void)
+{
+  return flag_prefetch_loop_arrays > 0;
+}
+
+namespace {
+
+const pass_data pass_data_loop_prefetch =
+{
+  GIMPLE_PASS, /* type */
+  "aprefetch", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_TREE_PREFETCH, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_loop_prefetch : public gimple_opt_pass
+{
+public:
+  pass_loop_prefetch (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_loop_prefetch, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_tree_ssa_loop_prefetch (); }
+  unsigned int execute () { return tree_ssa_loop_prefetch (); }
+
+}; // class pass_loop_prefetch
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_loop_prefetch (gcc::context *ctxt)
+{
+  return new pass_loop_prefetch (ctxt);
+}
+
+
index 6ce06c1326cc8a903ea4c5bcddb6d542c73767b0..74af9758b1adad31917d3c3ae3c849b90f806076 100644 (file)
@@ -388,3 +388,60 @@ tree_unswitch_loop (struct loop *loop,
                       NULL, prob_true, prob_true,
                       REG_BR_PROB_BASE - prob_true, false);
 }
+
+/* Loop unswitching pass.  */
+
+static unsigned int
+tree_ssa_loop_unswitch (void)
+{
+  if (number_of_loops (cfun) <= 1)
+    return 0;
+
+  return tree_ssa_unswitch_loops ();
+}
+
+static bool
+gate_tree_ssa_loop_unswitch (void)
+{
+  return flag_unswitch_loops != 0;
+}
+
+namespace {
+
+const pass_data pass_data_tree_unswitch =
+{
+  GIMPLE_PASS, /* type */
+  "unswitch", /* name */
+  OPTGROUP_LOOP, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_TREE_LOOP_UNSWITCH, /* tv_id */
+  PROP_cfg, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_tree_unswitch : public gimple_opt_pass
+{
+public:
+  pass_tree_unswitch (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_tree_ssa_loop_unswitch (); }
+  unsigned int execute () { return tree_ssa_loop_unswitch (); }
+
+}; // class pass_tree_unswitch
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_tree_unswitch (gcc::context *ctxt)
+{
+  return new pass_tree_unswitch (ctxt);
+}
+
+
index 3952029d0ea8c28d870fc943191db5979cd02aa1..bf2fbc885d678abf5a8af3b26df3a3db13059234 100644 (file)
@@ -134,117 +134,6 @@ make_pass_tree_loop_init (gcc::context *ctxt)
   return new pass_tree_loop_init (ctxt);
 }
 
-/* Loop invariant motion pass.  */
-
-static unsigned int
-tree_ssa_loop_im (void)
-{
-  if (number_of_loops (cfun) <= 1)
-    return 0;
-
-  return tree_ssa_lim ();
-}
-
-static bool
-gate_tree_ssa_loop_im (void)
-{
-  return flag_tree_loop_im != 0;
-}
-
-namespace {
-
-const pass_data pass_data_lim =
-{
-  GIMPLE_PASS, /* type */
-  "lim", /* name */
-  OPTGROUP_LOOP, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
-  TV_LIM, /* tv_id */
-  PROP_cfg, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_lim : public gimple_opt_pass
-{
-public:
-  pass_lim (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_lim, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  opt_pass * clone () { return new pass_lim (m_ctxt); }
-  bool gate () { return gate_tree_ssa_loop_im (); }
-  unsigned int execute () { return tree_ssa_loop_im (); }
-
-}; // class pass_lim
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_lim (gcc::context *ctxt)
-{
-  return new pass_lim (ctxt);
-}
-
-/* Loop unswitching pass.  */
-
-static unsigned int
-tree_ssa_loop_unswitch (void)
-{
-  if (number_of_loops (cfun) <= 1)
-    return 0;
-
-  return tree_ssa_unswitch_loops ();
-}
-
-static bool
-gate_tree_ssa_loop_unswitch (void)
-{
-  return flag_unswitch_loops != 0;
-}
-
-namespace {
-
-const pass_data pass_data_tree_unswitch =
-{
-  GIMPLE_PASS, /* type */
-  "unswitch", /* name */
-  OPTGROUP_LOOP, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
-  TV_TREE_LOOP_UNSWITCH, /* tv_id */
-  PROP_cfg, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_tree_unswitch : public gimple_opt_pass
-{
-public:
-  pass_tree_unswitch (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  bool gate () { return gate_tree_ssa_loop_unswitch (); }
-  unsigned int execute () { return tree_ssa_loop_unswitch (); }
-
-}; // class pass_tree_unswitch
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_tree_unswitch (gcc::context *ctxt)
-{
-  return new pass_tree_unswitch (ctxt);
-}
-
 /* Predictive commoning.  */
 
 static unsigned
@@ -515,61 +404,6 @@ make_pass_check_data_deps (gcc::context *ctxt)
   return new pass_check_data_deps (ctxt);
 }
 
-/* Canonical induction variable creation pass.  */
-
-static unsigned int
-tree_ssa_loop_ivcanon (void)
-{
-  if (number_of_loops (cfun) <= 1)
-    return 0;
-
-  return canonicalize_induction_variables ();
-}
-
-static bool
-gate_tree_ssa_loop_ivcanon (void)
-{
-  return flag_tree_loop_ivcanon != 0;
-}
-
-namespace {
-
-const pass_data pass_data_iv_canon =
-{
-  GIMPLE_PASS, /* type */
-  "ivcanon", /* name */
-  OPTGROUP_LOOP, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
-  TV_TREE_LOOP_IVCANON, /* tv_id */
-  ( PROP_cfg | PROP_ssa ), /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_iv_canon : public gimple_opt_pass
-{
-public:
-  pass_iv_canon (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_iv_canon, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  bool gate () { return gate_tree_ssa_loop_ivcanon (); }
-  unsigned int execute () { return tree_ssa_loop_ivcanon (); }
-
-}; // class pass_iv_canon
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_iv_canon (gcc::context *ctxt)
-{
-  return new pass_iv_canon (ctxt);
-}
-
 /* Propagation of constants using scev.  */
 
 static bool
@@ -667,128 +501,6 @@ make_pass_record_bounds (gcc::context *ctxt)
   return new pass_record_bounds (ctxt);
 }
 
-/* Complete unrolling of loops.  */
-
-static unsigned int
-tree_complete_unroll (void)
-{
-  if (number_of_loops (cfun) <= 1)
-    return 0;
-
-  return tree_unroll_loops_completely (flag_unroll_loops
-                                      || flag_peel_loops
-                                      || optimize >= 3, true);
-}
-
-static bool
-gate_tree_complete_unroll (void)
-{
-  return true;
-}
-
-namespace {
-
-const pass_data pass_data_complete_unroll =
-{
-  GIMPLE_PASS, /* type */
-  "cunroll", /* name */
-  OPTGROUP_LOOP, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
-  TV_COMPLETE_UNROLL, /* tv_id */
-  ( PROP_cfg | PROP_ssa ), /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_complete_unroll : public gimple_opt_pass
-{
-public:
-  pass_complete_unroll (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_complete_unroll, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  bool gate () { return gate_tree_complete_unroll (); }
-  unsigned int execute () { return tree_complete_unroll (); }
-
-}; // class pass_complete_unroll
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_complete_unroll (gcc::context *ctxt)
-{
-  return new pass_complete_unroll (ctxt);
-}
-
-/* Complete unrolling of inner loops.  */
-
-static unsigned int
-tree_complete_unroll_inner (void)
-{
-  unsigned ret = 0;
-
-  loop_optimizer_init (LOOPS_NORMAL
-                      | LOOPS_HAVE_RECORDED_EXITS);
-  if (number_of_loops (cfun) > 1)
-    {
-      scev_initialize ();
-      ret = tree_unroll_loops_completely (optimize >= 3, false);
-      free_numbers_of_iterations_estimates ();
-      scev_finalize ();
-    }
-  loop_optimizer_finalize ();
-
-  return ret;
-}
-
-static bool
-gate_tree_complete_unroll_inner (void)
-{
-  return optimize >= 2;
-}
-
-namespace {
-
-const pass_data pass_data_complete_unrolli =
-{
-  GIMPLE_PASS, /* type */
-  "cunrolli", /* name */
-  OPTGROUP_LOOP, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
-  TV_COMPLETE_UNROLL, /* tv_id */
-  ( PROP_cfg | PROP_ssa ), /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  TODO_verify_flow, /* todo_flags_finish */
-};
-
-class pass_complete_unrolli : public gimple_opt_pass
-{
-public:
-  pass_complete_unrolli (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_complete_unrolli, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  bool gate () { return gate_tree_complete_unroll_inner (); }
-  unsigned int execute () { return tree_complete_unroll_inner (); }
-
-}; // class pass_complete_unrolli
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_complete_unrolli (gcc::context *ctxt)
-{
-  return new pass_complete_unrolli (ctxt);
-}
-
 /* Parallelization.  */
 
 static bool
@@ -846,61 +558,6 @@ make_pass_parallelize_loops (gcc::context *ctxt)
   return new pass_parallelize_loops (ctxt);
 }
 
-/* Prefetching.  */
-
-static unsigned int
-tree_ssa_loop_prefetch (void)
-{
-  if (number_of_loops (cfun) <= 1)
-    return 0;
-
-  return tree_ssa_prefetch_arrays ();
-}
-
-static bool
-gate_tree_ssa_loop_prefetch (void)
-{
-  return flag_prefetch_loop_arrays > 0;
-}
-
-namespace {
-
-const pass_data pass_data_loop_prefetch =
-{
-  GIMPLE_PASS, /* type */
-  "aprefetch", /* name */
-  OPTGROUP_LOOP, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
-  TV_TREE_PREFETCH, /* tv_id */
-  ( PROP_cfg | PROP_ssa ), /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_loop_prefetch : public gimple_opt_pass
-{
-public:
-  pass_loop_prefetch (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_loop_prefetch, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  bool gate () { return gate_tree_ssa_loop_prefetch (); }
-  unsigned int execute () { return tree_ssa_loop_prefetch (); }
-
-}; // class pass_loop_prefetch
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_loop_prefetch (gcc::context *ctxt)
-{
-  return new pass_loop_prefetch (ctxt);
-}
-
 /* Induction variable optimizations.  */
 
 static unsigned int
@@ -1004,3 +661,235 @@ make_pass_tree_loop_done (gcc::context *ctxt)
 {
   return new pass_tree_loop_done (ctxt);
 }
+
+/* Calls CBCK for each index in memory reference ADDR_P.  There are two
+   kinds situations handled; in each of these cases, the memory reference
+   and DATA are passed to the callback:
+
+   Access to an array: ARRAY_{RANGE_}REF (base, index).  In this case we also
+   pass the pointer to the index to the callback.
+
+   Pointer dereference: INDIRECT_REF (addr).  In this case we also pass the
+   pointer to addr to the callback.
+
+   If the callback returns false, the whole search stops and false is returned.
+   Otherwise the function returns true after traversing through the whole
+   reference *ADDR_P.  */
+
+bool
+for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
+{
+  tree *nxt, *idx;
+
+  for (; ; addr_p = nxt)
+    {
+      switch (TREE_CODE (*addr_p))
+       {
+       case SSA_NAME:
+         return cbck (*addr_p, addr_p, data);
+
+       case MEM_REF:
+         nxt = &TREE_OPERAND (*addr_p, 0);
+         return cbck (*addr_p, nxt, data);
+
+       case BIT_FIELD_REF:
+       case VIEW_CONVERT_EXPR:
+       case REALPART_EXPR:
+       case IMAGPART_EXPR:
+         nxt = &TREE_OPERAND (*addr_p, 0);
+         break;
+
+       case COMPONENT_REF:
+         /* If the component has varying offset, it behaves like index
+            as well.  */
+         idx = &TREE_OPERAND (*addr_p, 2);
+         if (*idx
+             && !cbck (*addr_p, idx, data))
+           return false;
+
+         nxt = &TREE_OPERAND (*addr_p, 0);
+         break;
+
+       case ARRAY_REF:
+       case ARRAY_RANGE_REF:
+         nxt = &TREE_OPERAND (*addr_p, 0);
+         if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
+           return false;
+         break;
+
+       case VAR_DECL:
+       case PARM_DECL:
+       case CONST_DECL:
+       case STRING_CST:
+       case RESULT_DECL:
+       case VECTOR_CST:
+       case COMPLEX_CST:
+       case INTEGER_CST:
+       case REAL_CST:
+       case FIXED_CST:
+       case CONSTRUCTOR:
+         return true;
+
+       case ADDR_EXPR:
+         gcc_assert (is_gimple_min_invariant (*addr_p));
+         return true;
+
+       case TARGET_MEM_REF:
+         idx = &TMR_BASE (*addr_p);
+         if (*idx
+             && !cbck (*addr_p, idx, data))
+           return false;
+         idx = &TMR_INDEX (*addr_p);
+         if (*idx
+             && !cbck (*addr_p, idx, data))
+           return false;
+         idx = &TMR_INDEX2 (*addr_p);
+         if (*idx
+             && !cbck (*addr_p, idx, data))
+           return false;
+         return true;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+}
+
+
+/* The name and the length of the currently generated variable
+   for lsm.  */
+#define MAX_LSM_NAME_LENGTH 40
+static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
+static int lsm_tmp_name_length;
+
+/* Adds S to lsm_tmp_name.  */
+
+static void
+lsm_tmp_name_add (const char *s)
+{
+  int l = strlen (s) + lsm_tmp_name_length;
+  if (l > MAX_LSM_NAME_LENGTH)
+    return;
+
+  strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
+  lsm_tmp_name_length = l;
+}
+
+/* Stores the name for temporary variable that replaces REF to
+   lsm_tmp_name.  */
+
+static void
+gen_lsm_tmp_name (tree ref)
+{
+  const char *name;
+
+  switch (TREE_CODE (ref))
+    {
+    case MEM_REF:
+    case TARGET_MEM_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_");
+      break;
+
+    case ADDR_EXPR:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      break;
+
+    case BIT_FIELD_REF:
+    case VIEW_CONVERT_EXPR:
+    case ARRAY_RANGE_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      break;
+
+    case REALPART_EXPR:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_RE");
+      break;
+
+    case IMAGPART_EXPR:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_IM");
+      break;
+
+    case COMPONENT_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_");
+      name = get_name (TREE_OPERAND (ref, 1));
+      if (!name)
+       name = "F";
+      lsm_tmp_name_add (name);
+      break;
+
+    case ARRAY_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_I");
+      break;
+
+    case SSA_NAME:
+    case VAR_DECL:
+    case PARM_DECL:
+      name = get_name (ref);
+      if (!name)
+       name = "D";
+      lsm_tmp_name_add (name);
+      break;
+
+    case STRING_CST:
+      lsm_tmp_name_add ("S");
+      break;
+
+    case RESULT_DECL:
+      lsm_tmp_name_add ("R");
+      break;
+
+    case INTEGER_CST:
+      /* Nothing.  */
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Determines name for temporary variable that replaces REF.
+   The name is accumulated into the lsm_tmp_name variable.
+   N is added to the name of the temporary.  */
+
+char *
+get_lsm_tmp_name (tree ref, unsigned n, const char *suffix)
+{
+  char ns[2];
+
+  lsm_tmp_name_length = 0;
+  gen_lsm_tmp_name (ref);
+  lsm_tmp_name_add ("_lsm");
+  if (n < 10)
+    {
+      ns[0] = '0' + n;
+      ns[1] = 0;
+      lsm_tmp_name_add (ns);
+    }
+  return lsm_tmp_name;
+  if (suffix != NULL)
+    lsm_tmp_name_add (suffix);
+}
+
+/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS.  */
+
+unsigned
+tree_num_loop_insns (struct loop *loop, eni_weights *weights)
+{
+  basic_block *body = get_loop_body (loop);
+  gimple_stmt_iterator gsi;
+  unsigned size = 0, i;
+
+  for (i = 0; i < loop->num_nodes; i++)
+    for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
+      size += estimate_num_insns (gsi_stmt (gsi), weights);
+  free (body);
+
+  return size;
+}
+
+
+
diff --git a/gcc/tree-ssa-loop.h b/gcc/tree-ssa-loop.h
new file mode 100644 (file)
index 0000000..1c96d9c
--- /dev/null
@@ -0,0 +1,85 @@
+/* Header file for SSA loop optimizations.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_TREE_SSA_LOOP_H
+#define GCC_TREE_SSA_LOOP_H
+
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+
+/* Affine iv.  */
+
+typedef struct affine_iv_d
+{
+  /* Iv = BASE + STEP * i.  */
+  tree base, step;
+
+  /* True if this iv does not overflow.  */
+  bool no_overflow;
+} affine_iv;
+
+/* Description of number of iterations of a loop.  All the expressions inside
+   the structure can be evaluated at the end of the loop's preheader
+   (and due to ssa form, also anywhere inside the body of the loop).  */
+
+struct tree_niter_desc
+{
+  tree assumptions;    /* The boolean expression.  If this expression evaluates
+                          to false, then the other fields in this structure
+                          should not be used; there is no guarantee that they
+                          will be correct.  */
+  tree may_be_zero;    /* The boolean expression.  If it evaluates to true,
+                          the loop will exit in the first iteration (i.e.
+                          its latch will not be executed), even if the niter
+                          field says otherwise.  */
+  tree niter;          /* The expression giving the number of iterations of
+                          a loop (provided that assumptions == true and
+                          may_be_zero == false), more precisely the number
+                          of executions of the latch of the loop.  */
+  double_int max;      /* The upper bound on the number of iterations of
+                          the loop.  */
+
+  /* The simplified shape of the exit condition.  The loop exits if
+     CONTROL CMP BOUND is false, where CMP is one of NE_EXPR,
+     LT_EXPR, or GT_EXPR, and step of CONTROL is positive if CMP is
+     LE_EXPR and negative if CMP is GE_EXPR.  This information is used
+     by loop unrolling.  */
+  affine_iv control;
+  tree bound;
+  enum tree_code cmp;
+};
+
+extern bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
+extern char *get_lsm_tmp_name (tree ref, unsigned n, const char *suffix = NULL);
+extern unsigned tree_num_loop_insns (struct loop *, struct eni_weights_d *);
+
+/* Returns the loop of the statement STMT.  */
+
+static inline struct loop *
+loop_containing_stmt (gimple stmt)
+{
+  basic_block bb = gimple_bb (stmt);
+  if (!bb)
+    return NULL;
+
+  return bb->loop_father;
+}
+
+#endif /* GCC_TREE_SSA_LOOP_H */