/* Natural loop analysis code for GNU compiler.
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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 2, or (at your option) any later
+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
for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "cfgloop.h"
#include "expr.h"
#include "output.h"
+#include "graphds.h"
/* Checks whether BB is executed exactly once in each LOOP iteration. */
bool
-just_once_each_iteration_p (const struct loop *loop, basic_block bb)
+just_once_each_iteration_p (const struct loop *loop, const_basic_block bb)
{
/* It must be executed at least once each iteration. */
if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
return true;
}
-/* Structure representing edge of a graph. */
-
-struct edge
-{
- int src, dest; /* Source and destination. */
- struct edge *pred_next, *succ_next;
- /* Next edge in predecessor and successor lists. */
- void *data; /* Data attached to the edge. */
-};
-
-/* Structure representing vertex of a graph. */
-
-struct vertex
-{
- struct edge *pred, *succ;
- /* Lists of predecessors and successors. */
- int component; /* Number of dfs restarts before reaching the
- vertex. */
- int post; /* Postorder number. */
-};
-
-/* Structure representing a graph. */
-
-struct graph
-{
- int n_vertices; /* Number of vertices. */
- struct vertex *vertices;
- /* The vertices. */
-};
-
-/* Dumps graph G into F. */
-
-extern void dump_graph (FILE *, struct graph *);
-
-void
-dump_graph (FILE *f, struct graph *g)
-{
- int i;
- struct edge *e;
-
- for (i = 0; i < g->n_vertices; i++)
- {
- if (!g->vertices[i].pred
- && !g->vertices[i].succ)
- continue;
-
- fprintf (f, "%d (%d)\t<-", i, g->vertices[i].component);
- for (e = g->vertices[i].pred; e; e = e->pred_next)
- fprintf (f, " %d", e->src);
- fprintf (f, "\n");
-
- fprintf (f, "\t->");
- for (e = g->vertices[i].succ; e; e = e->succ_next)
- fprintf (f, " %d", e->dest);
- fprintf (f, "\n");
- }
-}
-
-/* Creates a new graph with N_VERTICES vertices. */
-
-static struct graph *
-new_graph (int n_vertices)
-{
- struct graph *g = XNEW (struct graph);
-
- g->n_vertices = n_vertices;
- g->vertices = XCNEWVEC (struct vertex, n_vertices);
-
- return g;
-}
-
-/* Adds an edge from F to T to graph G, with DATA attached. */
-
-static void
-add_edge (struct graph *g, int f, int t, void *data)
-{
- struct edge *e = xmalloc (sizeof (struct edge));
-
- e->src = f;
- e->dest = t;
- e->data = data;
-
- e->pred_next = g->vertices[t].pred;
- g->vertices[t].pred = e;
-
- e->succ_next = g->vertices[f].succ;
- g->vertices[f].succ = e;
-}
-
-/* Runs dfs search over vertices of G, from NQ vertices in queue QS.
- The vertices in postorder are stored into QT. If FORWARD is false,
- backward dfs is run. */
-
-static void
-dfs (struct graph *g, int *qs, int nq, int *qt, bool forward)
-{
- int i, tick = 0, v, comp = 0, top;
- struct edge *e;
- struct edge **stack = xmalloc (sizeof (struct edge *) * g->n_vertices);
-
- for (i = 0; i < g->n_vertices; i++)
- {
- g->vertices[i].component = -1;
- g->vertices[i].post = -1;
- }
-
-#define FST_EDGE(V) (forward ? g->vertices[(V)].succ : g->vertices[(V)].pred)
-#define NEXT_EDGE(E) (forward ? (E)->succ_next : (E)->pred_next)
-#define EDGE_SRC(E) (forward ? (E)->src : (E)->dest)
-#define EDGE_DEST(E) (forward ? (E)->dest : (E)->src)
-
- for (i = 0; i < nq; i++)
- {
- v = qs[i];
- if (g->vertices[v].post != -1)
- continue;
-
- g->vertices[v].component = comp++;
- e = FST_EDGE (v);
- top = 0;
-
- while (1)
- {
- while (e && g->vertices[EDGE_DEST (e)].component != -1)
- e = NEXT_EDGE (e);
-
- if (!e)
- {
- if (qt)
- qt[tick] = v;
- g->vertices[v].post = tick++;
-
- if (!top)
- break;
-
- e = stack[--top];
- v = EDGE_SRC (e);
- e = NEXT_EDGE (e);
- continue;
- }
-
- stack[top++] = e;
- v = EDGE_DEST (e);
- e = FST_EDGE (v);
- g->vertices[v].component = comp - 1;
- }
- }
-
- free (stack);
-}
-
/* Marks the edge E in graph G irreducible if it connects two vertices in the
same scc. */
static void
-check_irred (struct graph *g, struct edge *e)
+check_irred (struct graph *g, struct graph_edge *e)
{
- edge real = e->data;
+ edge real = (edge) e->data;
/* All edges should lead from a component with higher number to the
one with lower one. */
real->src->flags |= BB_IRREDUCIBLE_LOOP;
}
-/* Runs CALLBACK for all edges in G. */
-
-static void
-for_each_edge (struct graph *g,
- void (callback) (struct graph *, struct edge *))
-{
- struct edge *e;
- int i;
-
- for (i = 0; i < g->n_vertices; i++)
- for (e = g->vertices[i].succ; e; e = e->succ_next)
- callback (g, e);
-}
-
-/* Releases the memory occupied by G. */
-
-static void
-free_graph (struct graph *g)
-{
- struct edge *e, *n;
- int i;
-
- for (i = 0; i < g->n_vertices; i++)
- for (e = g->vertices[i].succ; e; e = n)
- {
- n = e->succ_next;
- free (e);
- }
- free (g->vertices);
- free (g);
-}
-
/* Marks blocks and edges that are part of non-recognized loops; i.e. we
throw away all latch edges and mark blocks inside any remaining cycle.
Everything is a bit complicated due to fact we do not want to do this
basic_block act;
edge e;
edge_iterator ei;
- int i, src, dest;
+ int src, dest;
+ unsigned depth;
struct graph *g;
int num = number_of_loops ();
- int *queue1 = XNEWVEC (int, last_basic_block + num);
- int *queue2 = XNEWVEC (int, last_basic_block + num);
- int nq;
- unsigned depth;
- struct loop *cloop, *loop;
- loop_iterator li;
+ struct loop *cloop;
gcc_assert (current_loops != NULL);
src = LOOP_REPR (cloop);
}
- add_edge (g, src, dest, e);
+ add_edge (g, src, dest)->data = e;
}
- /* Find the strongly connected components. Use the algorithm of Tarjan --
- first determine the postorder dfs numbering in reversed graph, then
- run the dfs on the original graph in the order given by decreasing
- numbers assigned by the previous pass. */
- nq = 0;
- FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
- {
- queue1[nq++] = BB_REPR (act);
- }
-
- FOR_EACH_LOOP (li, loop, 0)
- {
- queue1[nq++] = LOOP_REPR (loop);
- }
- dfs (g, queue1, nq, queue2, false);
- for (i = 0; i < nq; i++)
- queue1[i] = queue2[nq - i - 1];
- dfs (g, queue1, nq, NULL, true);
+ /* Find the strongly connected components. */
+ graphds_scc (g, NULL);
/* Mark the irreducible loops. */
for_each_edge (g, check_irred);
free_graph (g);
- free (queue1);
- free (queue2);
- current_loops->state |= LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
+ loops_state_set (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS);
}
/* Counts number of insns inside LOOP. */
int
-num_loop_insns (struct loop *loop)
+num_loop_insns (const struct loop *loop)
{
basic_block *bbs, bb;
unsigned i, ninsns = 0;
/* Counts number of insns executed on average per iteration LOOP. */
int
-average_num_loop_insns (struct loop *loop)
+average_num_loop_insns (const struct loop *loop)
{
basic_block *bbs, bb;
unsigned i, binsns, ninsns, ratio;
/* Returns estimate on cost of computing SEQ. */
static unsigned
-seq_cost (rtx seq)
+seq_cost (const_rtx seq)
{
unsigned cost = 0;
rtx set;
rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
unsigned i;
+ target_avail_regs = 0;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
&& !fixed_regs[i])