#include "toplev.h"
#include "cfgloop.h"
#include "flags.h"
+#include "tree.h"
+#include "tree-flow.h"
/* Ratio of frequencies of edges so that one of more latch edges is
considered to belong to inner loop with same header. */
bool
flow_loop_nested_p (const struct loop *outer, const struct loop *loop)
{
- return loop->depth > outer->depth
- && loop->pred[outer->depth] == outer;
+ return (loop->depth > outer->depth
+ && loop->pred[outer->depth] == outer);
+}
+
+/* Returns the loop such that LOOP is nested DEPTH (indexed from zero)
+ loops within LOOP. */
+
+struct loop *
+superloop_at_depth (struct loop *loop, unsigned depth)
+{
+ if (depth > (unsigned) loop->depth)
+ abort ();
+
+ if (depth == (unsigned) loop->depth)
+ return loop;
+
+ return loop->pred[depth];
}
/* Dump the loop information specified by LOOP to the stream FILE
HEADER_BLOCK (jump) = 0;
alloc_aux_for_edge (jump->pred, sizeof (int));
LATCH_EDGE (jump->pred) = 0;
+ set_immediate_dominator (CDI_DOMINATORS, jump, jump->pred->src);
}
/* A callback for make_forwarder block, to redirect all edges except for
basic_block header;
edge e;
- /* Compute the dominators. */
- calculate_dominance_info (CDI_DOMINATORS);
-
alloc_aux_for_blocks (sizeof (int));
alloc_aux_for_edges (sizeof (int));
HEADER_BLOCK (header) = num_latches;
}
- free_dominance_info (CDI_DOMINATORS);
-
if (HEADER_BLOCK (ENTRY_BLOCK_PTR->succ->dest))
{
basic_block bb;
free_aux_for_blocks ();
free_aux_for_edges ();
+
+#ifdef ENABLE_CHECKING
+ verify_dominators (CDI_DOMINATORS);
+#endif
}
/* Find all the natural loops in the function and save in LOOPS structure and
dfs_order = NULL;
rc_order = NULL;
+ /* Ensure that the dominators are computed. */
+ calculate_dominance_info (CDI_DOMINATORS);
+
/* Join loops with shared headers. */
canonicalize_loop_headers ();
- /* Compute the dominators. */
- calculate_dominance_info (CDI_DOMINATORS);
-
/* Count the number of loop headers. This should be the
same as the number of natural loops. */
headers = sbitmap_alloc (last_basic_block);
loops->num = num_loops;
}
- else
- {
- free_dominance_info (CDI_DOMINATORS);
- }
sbitmap_free (headers);
return tovisit;
}
+/* Fills dominance descendants inside LOOP of the basic block BB into
+ array TOVISIT from index *TV. */
+
+static void
+fill_sons_in_loop (const struct loop *loop, basic_block bb,
+ basic_block *tovisit, int *tv)
+{
+ basic_block son, postpone = NULL;
+
+ tovisit[(*tv)++] = bb;
+ for (son = first_dom_son (CDI_DOMINATORS, bb);
+ son;
+ son = next_dom_son (CDI_DOMINATORS, son))
+ {
+ if (!flow_bb_inside_loop_p (loop, son))
+ continue;
+
+ if (dominated_by_p (CDI_DOMINATORS, loop->latch, son))
+ {
+ postpone = son;
+ continue;
+ }
+ fill_sons_in_loop (loop, son, tovisit, tv);
+ }
+
+ if (postpone)
+ fill_sons_in_loop (loop, postpone, tovisit, tv);
+}
+
+/* Gets body of a LOOP (that must be different from the outermost loop)
+ sorted by dominance relation. Additionally, if a basic block s dominates
+ the latch, then only blocks dominated by s are be after it. */
+
+basic_block *
+get_loop_body_in_dom_order (const struct loop *loop)
+{
+ basic_block *tovisit;
+ int tv;
+
+ if (!loop->num_nodes)
+ abort ();
+
+ tovisit = xcalloc (loop->num_nodes, sizeof (basic_block));
+
+ if (loop->latch == EXIT_BLOCK_PTR)
+ abort ();
+
+ tv = 0;
+ fill_sons_in_loop (loop, loop->header, tovisit, &tv);
+
+ if (tv != (int) loop->num_nodes)
+ abort ();
+
+ return tovisit;
+}
+
/* Gets exit edges of a LOOP, returning their number in N_EDGES. */
edge *
get_loop_exit_edges (const struct loop *loop, unsigned int *n_edges)
return edges;
}
+/* Counts the number of conditional branches inside LOOP. */
+
+unsigned
+num_loop_branches (const struct loop *loop)
+{
+ unsigned i, n;
+ basic_block * body;
+
+ if (loop->latch == EXIT_BLOCK_PTR)
+ abort ();
+
+ body = get_loop_body (loop);
+ n = 0;
+ for (i = 0; i < loop->num_nodes; i++)
+ if (body[i]->succ && body[i]->succ->succ_next)
+ n++;
+ free (body);
+
+ return n;
+}
+
/* Adds basic block BB to LOOP. */
void
add_bb_to_loop (basic_block bb, struct loop *loop)