/* Natural loop functions
- Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007Free Software Foundation, Inc.
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef GCC_CFGLOOP_H
#define GCC_CFGLOOP_H
#include "basic-block.h"
/* For rtx_code. */
#include "rtl.h"
+#include "vecprim.h"
+#include "double-int.h"
/* Structure to hold decision about unrolling/peeling. */
enum lpt_dec
LPT_UNROLL_STUPID
};
-struct lpt_decision
+struct lpt_decision GTY (())
{
enum lpt_dec decision;
unsigned times;
};
+/* The structure describing a bound on number of iterations of a loop. */
+
+struct nb_iter_bound GTY ((chain_next ("%h.next")))
+{
+ /* The statement STMT is executed at most ... */
+ tree stmt;
+
+ /* ... BOUND + 1 times (BOUND must be an unsigned constant).
+ The + 1 is added for the following reasons:
+
+ a) 0 would otherwise be unused, while we would need to care more about
+ overflows (as MAX + 1 is sometimes produced as the estimate on number
+ of executions of STMT).
+ b) it is consistent with the result of number_of_iterations_exit. */
+ double_int bound;
+
+ /* True if the statement will cause the loop to be leaved the (at most)
+ BOUND + 1-st time it is executed, that is, all the statements after it
+ are executed at most BOUND times. */
+ bool is_exit;
+
+ /* The next bound in the list. */
+ struct nb_iter_bound *next;
+};
+
+/* Description of the loop exit. */
+
+struct loop_exit GTY (())
+{
+ /* The exit edge. */
+ struct edge_def *e;
+
+ /* Previous and next exit in the list of the exits of the loop. */
+ struct loop_exit *prev;
+ struct loop_exit *next;
+
+ /* Next element in the list of loops from that E exits. */
+ struct loop_exit *next_e;
+};
+
+typedef struct loop *loop_p;
+DEF_VEC_P (loop_p);
+DEF_VEC_ALLOC_P (loop_p, heap);
+DEF_VEC_ALLOC_P (loop_p, gc);
+
+/* An integer estimation of the number of iterations. Estimate_state
+ describes what is the state of the estimation. */
+enum loop_estimation
+{
+ /* Estimate was not computed yet. */
+ EST_NOT_COMPUTED,
+ /* Estimate is ready. */
+ EST_AVAILABLE
+};
+
/* Structure to hold information for each natural loop. */
-struct loop
+struct loop GTY ((chain_next ("%h.next")))
{
/* Index into loops array. */
int num;
/* Basic block of loop header. */
- basic_block header;
+ struct basic_block_def *header;
/* Basic block of loop latch. */
- basic_block latch;
-
- /* Basic block of loop preheader or NULL if it does not exist. */
- basic_block pre_header;
+ struct basic_block_def *latch;
/* For loop unrolling/peeling decision. */
struct lpt_decision lpt_decision;
/* Average number of executed insns per iteration. */
unsigned av_ninsns;
- /* Array of edges along the preheader extended basic block trace.
- The source of the first edge is the root node of preheader
- extended basic block, if it exists. */
- edge *pre_header_edges;
-
- /* Number of edges along the pre_header extended basic block trace. */
- int num_pre_header_edges;
-
- /* The first block in the loop. This is not necessarily the same as
- the loop header. */
- basic_block first;
-
- /* The last block in the loop. This is not necessarily the same as
- the loop latch. */
- basic_block last;
-
- /* Bitmap of blocks contained within the loop. */
- sbitmap nodes;
-
/* Number of blocks contained within the loop. */
unsigned num_nodes;
- /* Array of edges that enter the loop. */
- edge *entry_edges;
-
- /* Number of edges that enter the loop. */
- int num_entries;
-
- /* Array of edges that exit the loop. */
- edge *exit_edges;
-
- /* Number of edges that exit the loop. */
- int num_exits;
-
- /* Bitmap of blocks that dominate all exits of the loop. */
- sbitmap exits_doms;
-
- /* The loop nesting depth. */
- int depth;
-
- /* Superloops of the loop. */
- struct loop **pred;
-
- /* The height of the loop (enclosed loop levels) within the loop
- hierarchy tree. */
- int level;
-
- /* The outer (parent) loop or NULL if outermost loop. */
- struct loop *outer;
+ /* Superloops of the loop, starting with the outermost loop. */
+ VEC (loop_p, gc) *superloops;
/* The first inner (child) loop or NULL if innermost loop. */
struct loop *inner;
/* Link to the next (sibling) loop. */
struct loop *next;
- /* Loop that is copy of this loop. */
- struct loop *copy;
-
- /* Nonzero if the loop is invalid (e.g., contains setjmp.). */
- int invalid;
-
/* Auxiliary info specific to a pass. */
- void *aux;
-
- /* The following are currently used by loop.c but they are likely to
- disappear as loop.c is converted to use the CFG. */
-
- /* Nonzero if the loop has a NOTE_INSN_LOOP_VTOP. */
- rtx vtop;
-
- /* Nonzero if the loop has a NOTE_INSN_LOOP_CONT.
- A continue statement will generate a branch to NEXT_INSN (cont). */
- rtx cont;
-
- /* The dominator of cont. */
- rtx cont_dominator;
-
- /* The NOTE_INSN_LOOP_BEG. */
- rtx start;
+ PTR GTY ((skip (""))) aux;
- /* The NOTE_INSN_LOOP_END. */
- rtx end;
+ /* The number of times the latch of the loop is executed.
+ This is an INTEGER_CST or an expression containing symbolic
+ names. Don't access this field directly:
+ number_of_latch_executions computes and caches the computed
+ information in this field. */
+ tree nb_iterations;
- /* For a rotated loop that is entered near the bottom,
- this is the label at the top. Otherwise it is zero. */
- rtx top;
+ /* An integer estimation of the number of iterations. Estimate_state
+ describes what is the state of the estimation. */
+ enum loop_estimation estimate_state;
- /* Place in the loop where control enters. */
- rtx scan_start;
+ /* An integer guaranteed to bound the number of iterations of the loop
+ from above. */
+ bool any_upper_bound;
+ double_int nb_iterations_upper_bound;
- /* The position where to sink insns out of the loop. */
- rtx sink;
-
- /* List of all LABEL_REFs which refer to code labels outside the
- loop. Used by routines that need to know all loop exits, such as
- final_biv_value and final_giv_value.
-
- This does not include loop exits due to return instructions.
- This is because all bivs and givs are pseudos, and hence must be
- dead after a return, so the presence of a return does not affect
- any of the optimizations that use this info. It is simpler to
- just not include return instructions on this list. */
- rtx exit_labels;
-
- /* The number of LABEL_REFs on exit_labels for this loop and all
- loops nested inside it. */
- int exit_count;
+ /* An integer giving the expected number of iterations of the loop. */
+ bool any_estimate;
+ double_int nb_iterations_estimate;
/* Upper bound on number of iterations of a loop. */
struct nb_iter_bound *bounds;
+
+ /* Head of the cyclic list of the exits of the loop. */
+ struct loop_exit *exits;
};
/* Flags for state of loop structure. */
{
LOOPS_HAVE_PREHEADERS = 1,
LOOPS_HAVE_SIMPLE_LATCHES = 2,
- LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS = 4
+ LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS = 4,
+ LOOPS_HAVE_RECORDED_EXITS = 8,
+ LOOPS_MAY_HAVE_MULTIPLE_LATCHES = 16,
+ LOOP_CLOSED_SSA = 32
};
+#define LOOPS_NORMAL (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES \
+ | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+#define AVOID_CFG_MODIFICATIONS (LOOPS_MAY_HAVE_MULTIPLE_LATCHES)
+
/* Structure to hold CFG information about natural loops within a function. */
-struct loops
+struct loops GTY (())
{
- /* Number of natural loops in the function. */
- unsigned num;
-
- /* Maximum nested loop level in the function. */
- unsigned levels;
+ /* State of loops. */
+ int state;
- /* Array of natural loop descriptors (scanning this array in reverse order
- will find the inner loops before their enclosing outer loops). */
- struct loop *array;
+ /* Array of the loops. */
+ VEC (loop_p, gc) *larray;
- /* The above array is unused in new loop infrastructure and is kept only for
- purposes of the old loop optimizer. Instead we store just pointers to
- loops here. */
- struct loop **parray;
+ /* Maps edges to the list of their descriptions as loop exits. Edges
+ whose sources or destinations have loop_father == NULL (which may
+ happen during the cfg manipulations) should not appear in EXITS. */
+ htab_t GTY((param_is (struct loop_exit))) exits;
/* Pointer to root of loop hierarchy tree. */
struct loop *tree_root;
-
- /* Information derived from the CFG. */
- struct cfg
- {
- /* The ordering of the basic blocks in a depth first search. */
- int *dfs_order;
-
- /* The reverse completion ordering of the basic blocks found in a
- depth first search. */
- int *rc_order;
- } cfg;
-
- /* Headers shared by multiple loops that should be merged. */
- sbitmap shared_headers;
-
- /* State of loops. */
- int state;
};
-/* Flags for loop discovery. */
-
-#define LOOP_TREE 1 /* Build loop hierarchy tree. */
-#define LOOP_PRE_HEADER 2 /* Analyze loop preheader. */
-#define LOOP_ENTRY_EDGES 4 /* Find entry edges. */
-#define LOOP_EXIT_EDGES 8 /* Find exit edges. */
-#define LOOP_EDGES (LOOP_ENTRY_EDGES | LOOP_EXIT_EDGES)
-#define LOOP_ALL 15 /* All of the above */
-
/* Loop recognition. */
-extern int flow_loops_find (struct loops *, int flags);
-extern int flow_loops_update (struct loops *, int flags);
+extern int flow_loops_find (struct loops *);
+extern void disambiguate_loops_with_multiple_latches (void);
extern void flow_loops_free (struct loops *);
-extern void flow_loops_dump (const struct loops *, FILE *,
+extern void flow_loops_dump (FILE *,
void (*)(const struct loop *, FILE *, int), int);
extern void flow_loop_dump (const struct loop *, FILE *,
void (*)(const struct loop *, FILE *, int), int);
-extern int flow_loop_scan (struct loop *, int);
+struct loop *alloc_loop (void);
extern void flow_loop_free (struct loop *);
-void mark_irreducible_loops (struct loops *);
-extern void create_loop_notes (void);
+int flow_loop_nodes_find (basic_block, struct loop *);
+void fix_loop_structure (bitmap changed_bbs);
+void mark_irreducible_loops (void);
+void release_recorded_exits (void);
+void record_loop_exits (void);
+void rescan_loop_exit (edge, bool, bool);
/* Loop data structure manipulation/querying. */
extern void flow_loop_tree_node_add (struct loop *, struct loop *);
extern void flow_loop_tree_node_remove (struct loop *);
-extern bool flow_loop_outside_edge_p (const struct loop *, edge);
+extern void add_loop (struct loop *, struct loop *);
extern bool flow_loop_nested_p (const struct loop *, const struct loop *);
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 (struct loop *);
extern int average_num_loop_insns (struct loop *);
extern unsigned get_loop_level (const struct loop *);
+extern bool loop_exit_edge_p (const struct loop *, edge);
+extern void mark_loop_exit_edges (void);
/* Loops & cfg manipulation. */
extern basic_block *get_loop_body (const struct loop *);
+extern unsigned get_loop_body_with_size (const struct loop *, basic_block *,
+ unsigned);
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
-extern edge *get_loop_exit_edges (const struct loop *, unsigned *);
+extern basic_block *get_loop_body_in_bfs_order (const struct loop *);
+extern VEC (edge, heap) *get_loop_exit_edges (const struct loop *);
+edge single_exit (const struct loop *);
extern unsigned num_loop_branches (const struct loop *);
extern edge loop_preheader_edge (const struct loop *);
extern void add_bb_to_loop (basic_block, struct loop *);
extern void remove_bb_from_loops (basic_block);
-extern void cancel_loop (struct loops *, struct loop *);
-extern void cancel_loop_tree (struct loops *, struct loop *);
-
-extern basic_block loop_split_edge_with (edge, rtx);
-extern int fix_loop_placement (struct loop *);
+extern void cancel_loop_tree (struct loop *);
+extern void delete_loop (struct loop *);
enum
{
CP_SIMPLE_PREHEADERS = 1
};
-extern void create_preheaders (struct loops *, int);
-extern void force_single_succ_latches (struct loops *);
+basic_block create_preheader (struct loop *, int);
+extern void create_preheaders (int);
+extern void force_single_succ_latches (void);
-extern void verify_loop_structure (struct loops *);
+extern void verify_loop_structure (void);
/* Loop analysis. */
-extern bool just_once_each_iteration_p (struct loop *, basic_block);
+extern bool just_once_each_iteration_p (const struct loop *, basic_block);
+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 *);
+HOST_WIDE_INT estimated_loop_iterations_int (struct loop *, bool);
+bool estimated_loop_iterations (struct loop *, bool, double_int *);
/* Loop manipulation. */
extern bool can_duplicate_loop_p (struct loop *loop);
#define DLTHE_FLAG_UPDATE_FREQ 1 /* Update frequencies in
duplicate_loop_to_header_edge. */
-
-extern int duplicate_loop_to_header_edge (struct loop *, edge, struct loops *,
- unsigned, sbitmap, edge, edge *,
- unsigned *, int);
-extern struct loop *loopify (struct loops *, edge, edge, basic_block);
-extern void unloop (struct loops *, struct loop *);
-extern bool remove_path (struct loops *, edge);
-extern edge split_loop_bb (basic_block, rtx);
+#define DLTHE_RECORD_COPY_NUMBER 2 /* Record copy number in the aux
+ field of newly create BB. */
+#define DLTHE_FLAG_COMPLETTE_PEEL 4 /* Update frequencies expecting
+ a complete peeling. */
+
+extern struct loop * duplicate_loop (struct loop *, struct loop *);
+extern bool duplicate_loop_to_header_edge (struct loop *, edge,
+ unsigned, sbitmap, edge,
+ VEC (edge, heap) **, int);
+extern struct loop *loopify (edge, edge,
+ basic_block, edge, edge, bool,
+ unsigned, unsigned);
+struct loop * loop_version (struct loop *, void *,
+ basic_block *, unsigned, unsigned, unsigned, bool);
+extern bool remove_path (edge);
+void scale_loop_frequencies (struct loop *, int, int);
/* Induction variable analysis. */
If first_special is true, the value in the first iteration is
delta + mult * base
-
- If extend = NIL, first_special must be false, delta 0, mult 1 and value is
+
+ If extend = UNKNOWN, first_special must be false, delta 0, mult 1 and value is
subreg_{mode} (base + i * step)
The get_iv_value function can be used to obtain these expressions.
see the description above). */
rtx base, step;
- /* The type of extend applied to it (SIGN_EXTEND, ZERO_EXTEND or NIL). */
+ /* The type of extend applied to it (SIGN_EXTEND, ZERO_EXTEND or UNKNOWN). */
enum rtx_code extend;
/* Operations applied in the extended mode. */
/* The mode the variable iterates in. */
enum machine_mode mode;
- /* Whether we have already filled the remaining fields. */
- unsigned analysed : 1;
-
/* Whether the first iteration needs to be handled specially. */
unsigned first_special : 1;
};
};
extern void iv_analysis_loop_init (struct loop *);
-extern rtx iv_get_reaching_def (rtx, rtx);
extern bool iv_analyze (rtx, rtx, struct rtx_iv *);
+extern bool iv_analyze_result (rtx, rtx, struct rtx_iv *);
+extern bool iv_analyze_expr (rtx, rtx, enum machine_mode, struct rtx_iv *);
extern rtx get_iv_value (struct rtx_iv *, rtx);
+extern bool biv_p (rtx, rtx);
extern void find_simple_exit (struct loop *, struct niter_desc *);
-extern void iv_number_of_iterations (struct loop *, rtx, rtx,
- struct niter_desc *);
extern void iv_analysis_done (void);
extern struct niter_desc *get_simple_loop_desc (struct loop *loop);
static inline struct niter_desc *
simple_loop_desc (struct loop *loop)
{
- return loop->aux;
+ return (struct niter_desc *) loop->aux;
+}
+
+/* Accessors for the loop structures. */
+
+/* Returns the loop with index NUM from current_loops. */
+
+static inline struct loop *
+get_loop (unsigned num)
+{
+ return VEC_index (loop_p, current_loops->larray, num);
+}
+
+/* Returns the number of superloops of LOOP. */
+
+static inline unsigned
+loop_depth (const struct loop *loop)
+{
+ return VEC_length (loop_p, loop->superloops);
+}
+
+/* Returns the immediate superloop of LOOP, or NULL if LOOP is the outermost
+ loop. */
+
+static inline struct loop *
+loop_outer (const struct loop *loop)
+{
+ unsigned n = VEC_length (loop_p, loop->superloops);
+
+ if (n == 0)
+ return NULL;
+
+ return VEC_index (loop_p, loop->superloops, n - 1);
+}
+
+/* Returns the list of loops in current_loops. */
+
+static inline VEC (loop_p, gc) *
+get_loops (void)
+{
+ if (!current_loops)
+ return NULL;
+
+ return current_loops->larray;
+}
+
+/* Returns the number of loops in current_loops (including the removed
+ ones and the fake loop that forms the root of the loop tree). */
+
+static inline unsigned
+number_of_loops (void)
+{
+ if (!current_loops)
+ return 0;
+
+ return VEC_length (loop_p, current_loops->larray);
+}
+
+/* Loop iterators. */
+
+/* Flags for loop iteration. */
+
+enum li_flags
+{
+ LI_INCLUDE_ROOT = 1, /* Include the fake root of the loop tree. */
+ LI_FROM_INNERMOST = 2, /* Iterate over the loops in the reverse order,
+ starting from innermost ones. */
+ LI_ONLY_INNERMOST = 4 /* Iterate only over innermost loops. */
+};
+
+/* The iterator for loops. */
+
+typedef struct
+{
+ /* The list of loops to visit. */
+ VEC(int,heap) *to_visit;
+
+ /* The index of the actual loop. */
+ unsigned idx;
+} loop_iterator;
+
+static inline void
+fel_next (loop_iterator *li, loop_p *loop)
+{
+ int anum;
+
+ while (VEC_iterate (int, li->to_visit, li->idx, anum))
+ {
+ li->idx++;
+ *loop = get_loop (anum);
+ if (*loop)
+ return;
+ }
+
+ VEC_free (int, heap, li->to_visit);
+ *loop = NULL;
}
+static inline void
+fel_init (loop_iterator *li, loop_p *loop, unsigned flags)
+{
+ struct loop *aloop;
+ unsigned i;
+ int mn;
+
+ li->idx = 0;
+ if (!current_loops)
+ {
+ li->to_visit = NULL;
+ *loop = NULL;
+ return;
+ }
+
+ li->to_visit = VEC_alloc (int, heap, number_of_loops ());
+ mn = (flags & LI_INCLUDE_ROOT) ? 0 : 1;
+
+ if (flags & LI_ONLY_INNERMOST)
+ {
+ for (i = 0; VEC_iterate (loop_p, current_loops->larray, i, aloop); i++)
+ if (aloop != NULL
+ && aloop->inner == NULL
+ && aloop->num >= mn)
+ VEC_quick_push (int, li->to_visit, aloop->num);
+ }
+ else if (flags & LI_FROM_INNERMOST)
+ {
+ /* Push the loops to LI->TO_VISIT in postorder. */
+ for (aloop = current_loops->tree_root;
+ aloop->inner != NULL;
+ aloop = aloop->inner)
+ continue;
+
+ while (1)
+ {
+ if (aloop->num >= mn)
+ VEC_quick_push (int, li->to_visit, aloop->num);
+
+ if (aloop->next)
+ {
+ for (aloop = aloop->next;
+ aloop->inner != NULL;
+ aloop = aloop->inner)
+ continue;
+ }
+ else if (!loop_outer (aloop))
+ break;
+ else
+ aloop = loop_outer (aloop);
+ }
+ }
+ else
+ {
+ /* Push the loops to LI->TO_VISIT in preorder. */
+ aloop = current_loops->tree_root;
+ while (1)
+ {
+ if (aloop->num >= mn)
+ VEC_quick_push (int, li->to_visit, aloop->num);
+
+ if (aloop->inner != NULL)
+ aloop = aloop->inner;
+ else
+ {
+ while (aloop != NULL && aloop->next == NULL)
+ aloop = loop_outer (aloop);
+ if (aloop == NULL)
+ break;
+ aloop = aloop->next;
+ }
+ }
+ }
+
+ fel_next (li, loop);
+}
+
+#define FOR_EACH_LOOP(LI, LOOP, FLAGS) \
+ for (fel_init (&(LI), &(LOOP), FLAGS); \
+ (LOOP); \
+ fel_next (&(LI), &(LOOP)))
+
+#define FOR_EACH_LOOP_BREAK(LI) \
+ { \
+ VEC_free (int, heap, (LI)->to_visit); \
+ break; \
+ }
+
+/* The properties of the target. */
+
+extern unsigned target_avail_regs;
+extern unsigned target_res_regs;
+extern unsigned target_reg_cost;
+extern unsigned target_spill_cost;
+
/* Register pressure estimation for induction variable optimizations & loop
invariant motion. */
-extern unsigned global_cost_for_size (unsigned, unsigned, unsigned);
+extern unsigned estimate_reg_pressure_cost (unsigned, unsigned);
extern void init_set_costs (void);
/* Loop optimizer initialization. */
-extern struct loops *loop_optimizer_init (FILE *);
-extern void loop_optimizer_finalize (struct loops *, FILE *);
+extern void loop_optimizer_init (unsigned);
+extern void loop_optimizer_finalize (void);
/* Optimization passes. */
-extern void unswitch_loops (struct loops *);
+extern void unswitch_loops (void);
enum
{
UAP_PEEL = 1, /* Enables loop peeling. */
- UAP_UNROLL = 2, /* Enables peeling of loops if it seems profitable. */
- UAP_UNROLL_ALL = 4 /* Enables peeling of all loops. */
+ UAP_UNROLL = 2, /* Enables unrolling of loops if it seems profitable. */
+ UAP_UNROLL_ALL = 4 /* Enables unrolling of all loops. */
};
-extern void unroll_and_peel_loops (struct loops *, int);
-extern void doloop_optimize_loops (struct loops *);
-extern void move_loop_invariants (struct loops *);
+extern void unroll_and_peel_loops (int);
+extern void doloop_optimize_loops (void);
+extern void move_loop_invariants (void);
#endif /* GCC_CFGLOOP_H */