* 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.
* 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 (double_int_cmp, bound_index,
estimate_numbers_of_iterations_loop): Make static.
* 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.
* loop-iv.c: Include tree-ssa-loop-niter.h.
* loop-unroll.c: Include tree-ssa-loop-niter.h.
* loop-unswitch.c: Include tree-ssa-loop-niter.h.
===================================================================
*************** along with GCC; see the file COPYING3.
#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. */
*************** extern basic_block move_sese_region_to_f
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);
*************** extern void thread_across_edge (gimple,
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-flow-inline.h */
static inline bool unmodifiable_var_p (const_tree);
static inline bool ref_contains_array_ref (const_tree);
*************** extern void graphite_transform_loops (vo
/* 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);
===================================================================
*************** extern bool flow_bb_inside_loop_p (const
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 *);
*************** gcov_type expected_loop_iterations_unbou
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);
*************** 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);
===================================================================
*************** 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
===================================================================
***************
+ /* 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 */
===================================================================
*************** along with GCC; see the file COPYING3.
#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
*************** should_duplicate_loop_header_p (basic_bl
/* Checks whether LOOP is a do-while style loop. */
! bool
do_while_loop_p (struct loop *loop)
{
gimple stmt = last_stmt (loop->latch);
/* Checks whether LOOP is a do-while style loop. */
! static bool
do_while_loop_p (struct loop *loop)
{
gimple stmt = last_stmt (loop->latch);
===================================================================
*************** 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;
!
! 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.
*p = NULL;
}
! /* 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. */
! };
/* If it is possible to hoist the statement STMT unconditionally,
returns MOVE_POSSIBLE.
*************** first_mem_ref_loc (struct loop *loop, me
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;
*************** 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");
flag = create_tmp_reg (boolean_type_node, str);
for_all_locs_in_loop (loop, ref, sm_set_flag_if_changed (flag));
return flag;
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, "_flag");
flag = create_tmp_reg (boolean_type_node, str);
for_all_locs_in_loop (loop, ref, sm_set_flag_if_changed (flag));
return flag;
*************** 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);
+ }
+
+
===================================================================
*************** create_canonical_iv (struct loop *loop,
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
{
*************** estimated_unrolled_size (struct loop_siz
loop-niter identified as having undefined effect in the last iteration.
The other cases are hopefully rare and will be cleaned up later. */
! edge
loop_edge_to_cancel (struct loop *loop)
{
vec<edge> exits;
loop-niter identified as having undefined effect in the last iteration.
The other cases are hopefully rare and will be cleaned up later. */
! static edge
loop_edge_to_cancel (struct loop *loop)
{
vec<edge> exits;
*************** 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
unloop_loops (bitmap loop_closed_ssa_invalidated,
bool *irred_invalidated)
{
LOOP_CLOSED_SSA_INVALIDATED is used to bookkepp the case
when we need to go into loop closed SSA form. */
! static void
unloop_loops (bitmap loop_closed_ssa_invalidated,
bool *irred_invalidated)
{
*************** tree_unroll_loops_completely (bool may_i
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);
+ }
+
+
===================================================================
*************** 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)
{
*************** 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)
{
*************** 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)
{
*************** dump_uses (FILE *file, struct ivopts_dat
/* 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)
{
*************** expr_invariant_in_loop_p (struct loop *l
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. */
===================================================================
***************
+ /* 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 */
===================================================================
***************
+ /* 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 */
===================================================================
*************** gcov_type_to_double_int (gcov_type val)
/* Compare double ints, callback for qsort. */
! int
double_int_cmp (const void *p1, const void *p2)
{
const double_int *d1 = (const double_int *)p1;
/* Compare double ints, callback for qsort. */
! static int
double_int_cmp (const void *p1, const void *p2)
{
const double_int *d1 = (const double_int *)p1;
*************** double_int_cmp (const void *p1, const vo
/* Return index of BOUND in BOUNDS array sorted in increasing order.
Lookup by binary search. */
! int
bound_index (vec<double_int> bounds, double_int bound)
{
unsigned int end = bounds.length ();
/* Return index of BOUND in BOUNDS array sorted in increasing order.
Lookup by binary search. */
! static int
bound_index (vec<double_int> bounds, double_int bound)
{
unsigned int end = bounds.length ();
*************** maybe_lower_iteration_bound (struct loop
/* Records estimates on numbers of iterations of LOOP. If USE_UNDEFINED_P
is true also use estimates derived from undefined behavior. */
! void
estimate_numbers_of_iterations_loop (struct loop *loop)
{
vec<edge> exits;
/* Records estimates on numbers of iterations of LOOP. If USE_UNDEFINED_P
is true also use estimates derived from undefined behavior. */
! static void
estimate_numbers_of_iterations_loop (struct loop *loop)
{
vec<edge> exits;
===================================================================
***************
+ /* 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 void record_niter_bound (struct loop *, double_int, bool, bool);
+ extern bool estimated_loop_iterations (struct loop *, double_int *);
+ extern bool max_loop_iterations (struct loop *, double_int *);
+ extern HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
+ extern HOST_WIDE_INT max_loop_iterations_int (struct loop *);
+ 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 */
===================================================================
*************** 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);
+ }
+
+
===================================================================
*************** 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);
+ }
+
+
===================================================================
*************** make_pass_tree_loop_init (gcc::context *
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
*************** make_pass_check_data_deps (gcc::context
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
*************** make_pass_record_bounds (gcc::context *c
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
*************** make_pass_parallelize_loops (gcc::contex
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
*************** make_pass_tree_loop_done (gcc::context *
{
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;
+ }
+
+
+
===================================================================
*************** extern tree resolve_mixers (struct loop
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 tree compute_overall_effect_of_inner_loop (struct loop *, tree);
/* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the
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, 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
===================================================================
*************** along with GCC; see the file COPYING3.
#include "df.h"
#include "hash-table.h"
#include "dumpfile.h"
+ #include "tree-ssa-loop-niter.h"
/* Possible return values of iv_get_reaching_def. */
===================================================================
*************** along with GCC; see the file COPYING3.
#include "recog.h"
#include "target.h"
#include "dumpfile.h"
+ #include "tree-ssa-loop-niter.h"
/* This pass performs loop unrolling and peeling. We only perform these
optimizations on innermost loops (with single exception) because
===================================================================
*************** along with GCC; see the file COPYING3.
#include "params.h"
#include "expr.h"
#include "dumpfile.h"
+ #include "tree-ssa-loop-niter.h"
/* This pass moves constant conditions out of loops, duplicating the loop
in progress, i.e. this code: