cfgloopmanip.c (remove_path, [...]): Change dom_bbs to vector.

* cfgloopmanip.c (remove_path, loopify, duplicate_loop_to_header_edge):
	Change dom_bbs to vector.  Add argument to iterate_fix_dominators call.
	* loop-unroll.c (unroll_loop_runtime_iterations): Ditto.
	* tree-cfg.c (tree_duplicate_sese_region): Change doms to vector.
	Add argument to iterate_fix_dominators call.
	(remove_edge_and_dominated_blocks): Pass vector to bbs_to_fix_dom.
	* gcse.c (hoist_code): Change domby to vector.
	* cfghooks.c (make_forwarder_block): Change doms_to_fix to vector.
	Add argument to iterate_fix_dominators call.
	* loop-doloop.c (doloop_modify): Changed recount_dominator to
	recompute_dominator.
	* lambda-code.c (perfect_nestify): Ditto.
	* cfgloopanal.c: Include graphds.h.
	(struct edge, struct vertex, struct graph, dump_graph, new_graph,
	add_edge, dfs, for_each_edge, free_graph): Moved to graphds.c.
	(mark_irreducible_loops): Use graphds_scc.  Remove argument from
	add_edge call.
	* graphds.c: New file.
	* graphds.h: New file.
	* dominance.c: Include vecprim.h, pointer-set.h and graphds.h.
	(get_dominated_by, get_dominated_by_region): Change return type to
	vector.
	(verify_dominators): Recompute all dominators and compare the results.
	(recount_dominator): Renamed to ...
	(recompute_dominator): ... this.  Do not check that the block is
	dominated by entry.
	(iterate_fix_dominators): Reimplemented.
	(prune_bbs_to_update_dominators, root_of_dom_tree,
	determine_dominators_for_sons): New functions.
	* et-forest.c (et_root): New function.
	* et-forest.h (et_root): Declare.
	* Makefile.in (graphds.o): Add.
	(cfgloopanal.o): Add graphds.h dependency.
	(dominance.o): Add graphds.h, vecprim.h and pointer-set.h dependency.
	* basic-block.h (get_dominated_by, get_dominated_by_region,
	iterate_fix_dominators): Declaration changed.
	(recount_dominator): Renamed to ...
	(recompute_dominator): ... this.
	* tree-ssa-threadupdate.c (thread_block): Free dominance info.
	(thread_through_all_blocks): Do not free dominance info.

From-SVN: r125297
This commit is contained in:
Zdenek Dvorak 2007-06-03 21:10:44 +02:00 committed by Zdenek Dvorak
parent b6a9c30c80
commit 66f97d31f2
17 changed files with 1026 additions and 357 deletions

View File

@ -1,3 +1,46 @@
2007-06-03 Zdenek Dvorak <dvorakz@suse.cz>
* cfgloopmanip.c (remove_path, loopify, duplicate_loop_to_header_edge):
Change dom_bbs to vector. Add argument to iterate_fix_dominators call.
* loop-unroll.c (unroll_loop_runtime_iterations): Ditto.
* tree-cfg.c (tree_duplicate_sese_region): Change doms to vector.
Add argument to iterate_fix_dominators call.
(remove_edge_and_dominated_blocks): Pass vector to bbs_to_fix_dom.
* gcse.c (hoist_code): Change domby to vector.
* cfghooks.c (make_forwarder_block): Change doms_to_fix to vector.
Add argument to iterate_fix_dominators call.
* loop-doloop.c (doloop_modify): Changed recount_dominator to
recompute_dominator.
* lambda-code.c (perfect_nestify): Ditto.
* cfgloopanal.c: Include graphds.h.
(struct edge, struct vertex, struct graph, dump_graph, new_graph,
add_edge, dfs, for_each_edge, free_graph): Moved to graphds.c.
(mark_irreducible_loops): Use graphds_scc. Remove argument from
add_edge call.
* graphds.c: New file.
* graphds.h: New file.
* dominance.c: Include vecprim.h, pointer-set.h and graphds.h.
(get_dominated_by, get_dominated_by_region): Change return type to
vector.
(verify_dominators): Recompute all dominators and compare the results.
(recount_dominator): Renamed to ...
(recompute_dominator): ... this. Do not check that the block is
dominated by entry.
(iterate_fix_dominators): Reimplemented.
(prune_bbs_to_update_dominators, root_of_dom_tree,
determine_dominators_for_sons): New functions.
* et-forest.c (et_root): New function.
* et-forest.h (et_root): Declare.
* Makefile.in (graphds.o): Add.
(cfgloopanal.o): Add graphds.h dependency.
(dominance.o): Add graphds.h, vecprim.h and pointer-set.h dependency.
* basic-block.h (get_dominated_by, get_dominated_by_region,
iterate_fix_dominators): Declaration changed.
(recount_dominator): Renamed to ...
(recompute_dominator): ... this.
* tree-ssa-threadupdate.c (thread_block): Free dominance info.
(thread_through_all_blocks): Do not free dominance info.
2007-06-03 Andreas Schwab <schwab@suse.de>
* config/m68k/m68k.c (override_options): Don't override

View File

@ -1009,6 +1009,7 @@ OBJS-common = \
gimplify.o \
global.o \
graph.o \
graphds.o \
gtype-desc.o \
haifa-sched.o \
hooks.o \
@ -2556,7 +2557,9 @@ cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h $(TM_H) \
$(GGC_H)
cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) \
$(OBSTACK_H) output.h
$(OBSTACK_H) output.h graphds.h
graphds.o : graphds.c graphds.h $(CONFIG_H) $(SYSTEM_H) bitmap.h $(OBSTACK_H) \
coretypes.h vec.h vecprim.h
struct-equiv.o : struct-equiv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) hard-reg-set.h output.h $(FLAGS_H) $(RECOG_H) \
insn-config.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \
@ -2582,7 +2585,8 @@ loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
output.h $(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) \
$(OBSTACK_H)
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) toplev.h $(TIMEVAR_H)
hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) toplev.h \
$(TIMEVAR_H) graphds.h vecprim.h pointer-set.h
et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
et-forest.h alloc-pool.h $(BASIC_BLOCK_H)
combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \

View File

@ -959,15 +959,17 @@ extern void set_immediate_dominator (enum cdi_direction, basic_block,
basic_block);
extern basic_block get_immediate_dominator (enum cdi_direction, basic_block);
extern bool dominated_by_p (enum cdi_direction, basic_block, basic_block);
extern int get_dominated_by (enum cdi_direction, basic_block, basic_block **);
extern unsigned get_dominated_by_region (enum cdi_direction, basic_block *,
unsigned, basic_block *);
extern VEC (basic_block, heap) *get_dominated_by (enum cdi_direction, basic_block);
extern VEC (basic_block, heap) *get_dominated_by_region (enum cdi_direction,
basic_block *,
unsigned);
extern void add_to_dominance_info (enum cdi_direction, basic_block);
extern void delete_from_dominance_info (enum cdi_direction, basic_block);
basic_block recount_dominator (enum cdi_direction, basic_block);
basic_block recompute_dominator (enum cdi_direction, basic_block);
extern void redirect_immediate_dominators (enum cdi_direction, basic_block,
basic_block);
extern void iterate_fix_dominators (enum cdi_direction, basic_block *, int);
extern void iterate_fix_dominators (enum cdi_direction,
VEC (basic_block, heap) *, bool);
extern void verify_dominators (enum cdi_direction);
extern basic_block first_dom_son (enum cdi_direction, basic_block);
extern basic_block next_dom_son (enum cdi_direction, basic_block);

View File

@ -735,11 +735,11 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
if (dom_info_available_p (CDI_DOMINATORS))
{
basic_block doms_to_fix[2];
doms_to_fix[0] = dummy;
doms_to_fix[1] = bb;
iterate_fix_dominators (CDI_DOMINATORS, doms_to_fix, 2);
VEC (basic_block, heap) *doms_to_fix = VEC_alloc (basic_block, heap, 2);
VEC_quick_push (basic_block, doms_to_fix, dummy);
VEC_quick_push (basic_block, doms_to_fix, bb);
iterate_fix_dominators (CDI_DOMINATORS, doms_to_fix, false);
VEC_free (basic_block, heap, doms_to_fix);
}
if (current_loops != NULL)

View File

@ -29,6 +29,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "cfgloop.h"
#include "expr.h"
#include "output.h"
#include "graphds.h"
/* Checks whether BB is executed exactly once in each LOOP iteration. */
@ -50,157 +51,6 @@ just_once_each_iteration_p (const struct loop *loop, basic_block 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. */
@ -221,38 +71,6 @@ check_irred (struct graph *g, struct edge *e)
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
@ -271,15 +89,11 @@ mark_irreducible_loops (void)
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);
@ -332,34 +146,16 @@ mark_irreducible_loops (void)
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;
}

View File

@ -276,8 +276,9 @@ bool
remove_path (edge e)
{
edge ae;
basic_block *rem_bbs, *bord_bbs, *dom_bbs, from, bb;
int i, nrem, n_bord_bbs, n_dom_bbs, nreml;
basic_block *rem_bbs, *bord_bbs, from, bb;
VEC (basic_block, heap) *dom_bbs;
int i, nrem, n_bord_bbs, nreml;
sbitmap seen;
bool irred_invalidated = false;
struct loop **deleted_loop;
@ -338,7 +339,7 @@ remove_path (edge e)
/* Remove the path. */
from = e->src;
remove_branch (e);
dom_bbs = XCNEWVEC (basic_block, n_basic_blocks);
dom_bbs = NULL;
/* Cancel loops contained in the path. */
deleted_loop = XNEWVEC (struct loop *, nrem);
@ -355,7 +356,6 @@ remove_path (edge e)
free (deleted_loop);
/* Find blocks whose dominators may be affected. */
n_dom_bbs = 0;
sbitmap_zero (seen);
for (i = 0; i < n_bord_bbs; i++)
{
@ -370,14 +370,14 @@ remove_path (edge e)
ldom;
ldom = next_dom_son (CDI_DOMINATORS, ldom))
if (!dominated_by_p (CDI_DOMINATORS, from, ldom))
dom_bbs[n_dom_bbs++] = ldom;
VEC_safe_push (basic_block, heap, dom_bbs, ldom);
}
free (seen);
/* Recount dominators. */
iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, n_dom_bbs);
free (dom_bbs);
iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, true);
VEC_free (basic_block, heap, dom_bbs);
free (bord_bbs);
/* Fix placements of basic blocks inside loops and the placement of
@ -472,8 +472,9 @@ loopify (edge latch_edge, edge header_edge,
{
basic_block succ_bb = latch_edge->dest;
basic_block pred_bb = header_edge->src;
basic_block *dom_bbs, *body;
unsigned n_dom_bbs, i;
basic_block *body;
VEC (basic_block, heap) *dom_bbs;
unsigned i;
sbitmap seen;
struct loop *loop = alloc_loop ();
struct loop *outer = loop_outer (succ_bb->loop_father);
@ -528,8 +529,7 @@ loopify (edge latch_edge, edge header_edge,
scale_loop_frequencies (succ_bb->loop_father, true_scale, REG_BR_PROB_BASE);
/* Update dominators of blocks outside of LOOP. */
dom_bbs = XCNEWVEC (basic_block, n_basic_blocks);
n_dom_bbs = 0;
dom_bbs = NULL;
seen = sbitmap_alloc (last_basic_block);
sbitmap_zero (seen);
body = get_loop_body (loop);
@ -547,15 +547,15 @@ loopify (edge latch_edge, edge header_edge,
if (!TEST_BIT (seen, ldom->index))
{
SET_BIT (seen, ldom->index);
dom_bbs[n_dom_bbs++] = ldom;
VEC_safe_push (basic_block, heap, dom_bbs, ldom);
}
}
iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, n_dom_bbs);
iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, false);
free (body);
free (seen);
free (dom_bbs);
VEC_free (basic_block, heap, dom_bbs);
return loop;
}
@ -1054,23 +1054,23 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e,
/* Update dominators of outer blocks if affected. */
for (i = 0; i < n; i++)
{
basic_block dominated, dom_bb, *dom_bbs;
int n_dom_bbs,j;
basic_block dominated, dom_bb;
VEC (basic_block, heap) *dom_bbs;
unsigned j;
bb = bbs[i];
bb->aux = 0;
n_dom_bbs = get_dominated_by (CDI_DOMINATORS, bb, &dom_bbs);
for (j = 0; j < n_dom_bbs; j++)
dom_bbs = get_dominated_by (CDI_DOMINATORS, bb);
for (j = 0; VEC_iterate (basic_block, dom_bbs, j, dominated); j++)
{
dominated = dom_bbs[j];
if (flow_bb_inside_loop_p (loop, dominated))
continue;
dom_bb = nearest_common_dominator (
CDI_DOMINATORS, first_active[i], first_active_latch);
set_immediate_dominator (CDI_DOMINATORS, dominated, dom_bb);
}
free (dom_bbs);
VEC_free (basic_block, heap, dom_bbs);
}
free (first_active);

View File

@ -44,6 +44,9 @@
#include "toplev.h"
#include "et-forest.h"
#include "timevar.h"
#include "vecprim.h"
#include "pointer-set.h"
#include "graphds.h"
/* Whether the dominators and the postdominators are available. */
static enum dom_state dom_computed[2];
@ -735,45 +738,39 @@ set_immediate_dominator (enum cdi_direction dir, basic_block bb,
dom_computed[dir_index] = DOM_NO_FAST_QUERY;
}
/* Store all basic blocks immediately dominated by BB into BBS and return
their number. */
int
get_dominated_by (enum cdi_direction dir, basic_block bb, basic_block **bbs)
/* Returns the list of basic blocks immediately dominated by BB, in the
direction DIR. */
VEC (basic_block, heap) *
get_dominated_by (enum cdi_direction dir, basic_block bb)
{
unsigned int dir_index = dom_convert_dir_to_idx (dir);
int n;
unsigned int dir_index = dom_convert_dir_to_idx (dir);
struct et_node *node = bb->dom[dir_index], *son = node->son, *ason;
VEC (basic_block, heap) *bbs = NULL;
gcc_assert (dom_computed[dir_index]);
if (!son)
{
*bbs = NULL;
return 0;
}
return NULL;
VEC_safe_push (basic_block, heap, bbs, son->data);
for (ason = son->right, n = 1; ason != son; ason = ason->right)
n++;
VEC_safe_push (basic_block, heap, bbs, ason->data);
*bbs = XNEWVEC (basic_block, n);
(*bbs)[0] = son->data;
for (ason = son->right, n = 1; ason != son; ason = ason->right)
(*bbs)[n++] = ason->data;
return n;
return bbs;
}
/* Find all basic blocks that are immediately dominated (in direction DIR)
by some block between N_REGION ones stored in REGION, except for blocks
in the REGION itself. The found blocks are stored to DOMS and their number
is returned. */
unsigned
/* Returns the list of basic blocks that are immediately dominated (in
direction DIR) by some block between N_REGION ones stored in REGION,
except for blocks in the REGION itself. */
VEC (basic_block, heap) *
get_dominated_by_region (enum cdi_direction dir, basic_block *region,
unsigned n_region, basic_block *doms)
unsigned n_region)
{
unsigned n_doms = 0, i;
unsigned i;
basic_block dom;
VEC (basic_block, heap) *doms = NULL;
for (i = 0; i < n_region; i++)
region[i]->flags |= BB_DUPLICATED;
@ -782,11 +779,11 @@ get_dominated_by_region (enum cdi_direction dir, basic_block *region,
dom;
dom = next_dom_son (dir, dom))
if (!(dom->flags & BB_DUPLICATED))
doms[n_doms++] = dom;
VEC_safe_push (basic_block, heap, doms, dom);
for (i = 0; i < n_region; i++)
region[i]->flags &= ~BB_DUPLICATED;
return n_doms;
return doms;
}
/* Redirect all edges pointing to BB to TO. */
@ -973,40 +970,37 @@ void
verify_dominators (enum cdi_direction dir)
{
int err = 0;
basic_block bb;
basic_block *old_dom = XNEWVEC (basic_block, last_basic_block);
basic_block bb, imm_bb;
gcc_assert (dom_info_available_p (dir));
FOR_EACH_BB (bb)
{
basic_block dom_bb;
basic_block imm_bb;
old_dom[bb->index] = get_immediate_dominator (dir, bb);
dom_bb = recount_dominator (dir, bb);
imm_bb = get_immediate_dominator (dir, bb);
if (dom_bb != imm_bb)
if (!old_dom[bb->index])
{
if ((dom_bb == NULL) || (imm_bb == NULL))
error ("dominator of %d status unknown", bb->index);
else
error ("dominator of %d should be %d, not %d",
bb->index, dom_bb->index, imm_bb->index);
error ("dominator of %d status unknown", bb->index);
err = 1;
}
}
if (dir == CDI_DOMINATORS)
free_dominance_info (dir);
calculate_dominance_info (dir);
FOR_EACH_BB (bb)
{
FOR_EACH_BB (bb)
imm_bb = get_immediate_dominator (dir, bb);
if (old_dom[bb->index] != imm_bb)
{
if (!dominated_by_p (dir, bb, ENTRY_BLOCK_PTR))
{
error ("ENTRY does not dominate bb %d", bb->index);
err = 1;
}
error ("dominator of %d should be %d, not %d",
bb->index, imm_bb->index, old_dom[bb->index]->index);
err = 1;
}
}
free (old_dom);
gcc_assert (!err);
}
@ -1016,7 +1010,7 @@ verify_dominators (enum cdi_direction dir)
reaches a fixed point. */
basic_block
recount_dominator (enum cdi_direction dir, basic_block bb)
recompute_dominator (enum cdi_direction dir, basic_block bb)
{
unsigned int dir_index = dom_convert_dir_to_idx (dir);
basic_block dom_bb = NULL;
@ -1029,11 +1023,6 @@ recount_dominator (enum cdi_direction dir, basic_block bb)
{
FOR_EACH_EDGE (e, ei, bb->preds)
{
/* Ignore the predecessors that either are not reachable from
the entry block, or whose dominator was not determined yet. */
if (!dominated_by_p (dir, e->src, ENTRY_BLOCK_PTR))
continue;
if (!dominated_by_p (dir, e->src, bb))
dom_bb = nearest_common_dominator (dir, dom_bb, e->src);
}
@ -1050,37 +1039,325 @@ recount_dominator (enum cdi_direction dir, basic_block bb)
return dom_bb;
}
/* Iteratively recount dominators of BBS. The change is supposed to be local
and not to grow further. */
void
iterate_fix_dominators (enum cdi_direction dir, basic_block *bbs, int n)
/* Use simple heuristics (see iterate_fix_dominators) to determine dominators
of BBS. We assume that all the immediate dominators except for those of the
blocks in BBS are correct. If CONSERVATIVE is true, we also assume that the
currently recorded immediate dominators of blocks in BBS really dominate the
blocks. The basic blocks for that we determine the dominator are removed
from BBS. */
static void
prune_bbs_to_update_dominators (VEC (basic_block, heap) *bbs,
bool conservative)
{
unsigned int dir_index = dom_convert_dir_to_idx (dir);
int i, changed = 1;
basic_block old_dom, new_dom;
unsigned i;
bool single;
basic_block bb, dom = NULL;
edge_iterator ei;
edge e;
gcc_assert (dom_computed[dir_index]);
for (i = 0; i < n; i++)
set_immediate_dominator (dir, bbs[i], NULL);
while (changed)
for (i = 0; VEC_iterate (basic_block, bbs, i, bb);)
{
changed = 0;
for (i = 0; i < n; i++)
if (bb == ENTRY_BLOCK_PTR)
goto succeed;
if (single_pred_p (bb))
{
old_dom = get_immediate_dominator (dir, bbs[i]);
new_dom = recount_dominator (dir, bbs[i]);
if (old_dom != new_dom)
set_immediate_dominator (CDI_DOMINATORS, bb, single_pred (bb));
goto succeed;
}
if (!conservative)
goto fail;
single = true;
dom = NULL;
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
continue;
if (!dom)
dom = e->src;
else
{
changed = 1;
set_immediate_dominator (dir, bbs[i], new_dom);
single = false;
dom = nearest_common_dominator (CDI_DOMINATORS, dom, e->src);
}
}
gcc_assert (dom != NULL);
if (single
|| find_edge (dom, bb))
{
set_immediate_dominator (CDI_DOMINATORS, bb, dom);
goto succeed;
}
fail:
i++;
continue;
succeed:
VEC_unordered_remove (basic_block, bbs, i);
}
}
/* Returns root of the dominance tree in the direction DIR that contains
BB. */
static basic_block
root_of_dom_tree (enum cdi_direction dir, basic_block bb)
{
return et_root (bb->dom[dom_convert_dir_to_idx (dir)])->data;
}
/* See the comment in iterate_fix_dominators. Finds the immediate dominators
for the sons of Y, found using the SON and BROTHER arrays representing
the dominance tree of graph G. BBS maps the vertices of G to the basic
blocks. */
static void
determine_dominators_for_sons (struct graph *g, VEC (basic_block, heap) *bbs,
int y, int *son, int *brother)
{
bitmap gprime;
int i, a, nc;
VEC (int, heap) **sccs;
basic_block bb, dom, ybb;
unsigned si;
edge e;
edge_iterator ei;
if (son[y] == -1)
return;
if (y == (int) VEC_length (basic_block, bbs))
ybb = ENTRY_BLOCK_PTR;
else
ybb = VEC_index (basic_block, bbs, y);
if (brother[son[y]] == -1)
{
/* Handle the common case Y has just one son specially. */
bb = VEC_index (basic_block, bbs, son[y]);
set_immediate_dominator (CDI_DOMINATORS, bb,
recompute_dominator (CDI_DOMINATORS, bb));
identify_vertices (g, y, son[y]);
return;
}
gprime = BITMAP_ALLOC (NULL);
for (a = son[y]; a != -1; a = brother[a])
bitmap_set_bit (gprime, a);
nc = graphds_scc (g, gprime);
BITMAP_FREE (gprime);
sccs = XCNEWVEC (VEC (int, heap) *, nc);
for (a = son[y]; a != -1; a = brother[a])
VEC_safe_push (int, heap, sccs[g->vertices[a].component], a);
for (i = nc - 1; i >= 0; i--)
{
dom = NULL;
for (si = 0; VEC_iterate (int, sccs[i], si, a); si++)
{
bb = VEC_index (basic_block, bbs, a);
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (root_of_dom_tree (CDI_DOMINATORS, e->src) != ybb)
continue;
dom = nearest_common_dominator (CDI_DOMINATORS, dom, e->src);
}
}
gcc_assert (dom != NULL);
for (si = 0; VEC_iterate (int, sccs[i], si, a); si++)
{
bb = VEC_index (basic_block, bbs, a);
set_immediate_dominator (CDI_DOMINATORS, bb, dom);
}
}
for (i = 0; i < n; i++)
gcc_assert (get_immediate_dominator (dir, bbs[i]));
for (i = 0; i < nc; i++)
VEC_free (int, heap, sccs[i]);
free (sccs);
for (a = son[y]; a != -1; a = brother[a])
identify_vertices (g, y, a);
}
/* Recompute dominance information for basic blocks in the set BBS. The
function assumes that the immediate dominators of all the other blocks
in CFG are correct, and that there are no unreachable blocks.
If CONSERVATIVE is true, we additionally assume that all the ancestors of
a block of BBS in the current dominance tree dominate it. */
void
iterate_fix_dominators (enum cdi_direction dir, VEC (basic_block, heap) *bbs,
bool conservative)
{
unsigned i;
basic_block bb, dom;
struct graph *g;
int n, y;
size_t dom_i;
edge e;
edge_iterator ei;
struct pointer_map_t *map;
int *parent, *son, *brother;
unsigned int dir_index = dom_convert_dir_to_idx (dir);
/* We only support updating dominators. There are some problems with
updating postdominators (need to add fake edges from infinite loops
and noreturn functions), and since we do not currently use
iterate_fix_dominators for postdominators, any attempt to handle these
problems would be unused, untested, and almost surely buggy. We keep
the DIR argument for consistency with the rest of the dominator analysis
interface. */
gcc_assert (dir == CDI_DOMINATORS);
gcc_assert (dom_computed[dir_index]);
/* The algorithm we use takes inspiration from the following papers, although
the details are quite different from any of them:
[1] G. Ramalingam, T. Reps, An Incremental Algorithm for Maintaining the
Dominator Tree of a Reducible Flowgraph
[2] V. C. Sreedhar, G. R. Gao, Y.-F. Lee: Incremental computation of
dominator trees
[3] K. D. Cooper, T. J. Harvey and K. Kennedy: A Simple, Fast Dominance
Algorithm
First, we use the following heuristics to decrease the size of the BBS
set:
a) if BB has a single predecessor, then its immediate dominator is this
predecessor
additionally, if CONSERVATIVE is true:
b) if all the predecessors of BB except for one (X) are dominated by BB,
then X is the immediate dominator of BB
c) if the nearest common ancestor of the predecessors of BB is X and
X -> BB is an edge in CFG, then X is the immediate dominator of BB
Then, we need to establish the dominance relation among the basic blocks
in BBS. We split the dominance tree by removing the immediate dominator
edges from BBS, creating a forrest F. We form a graph G whose vertices
are BBS and ENTRY and X -> Y is an edge of G if there exists an edge
X' -> Y in CFG such that X' belongs to the tree of the dominance forrest
whose root is X. We then determine dominance tree of G. Note that
for X, Y in BBS, X dominates Y in CFG if and only if X dominates Y in G.
In this step, we can use arbitrary algorithm to determine dominators.
We decided to prefer the algorithm [3] to the algorithm of
Lengauer and Tarjan, since the set BBS is usually small (rarely exceeding
10 during gcc bootstrap), and [3] should perform better in this case.
Finally, we need to determine the immediate dominators for the basic
blocks of BBS. If the immediate dominator of X in G is Y, then
the immediate dominator of X in CFG belongs to the tree of F rooted in
Y. We process the dominator tree T of G recursively, starting from leaves.
Suppose that X_1, X_2, ..., X_k are the sons of Y in T, and that the
subtrees of the dominance tree of CFG rooted in X_i are already correct.
Let G' be the subgraph of G induced by {X_1, X_2, ..., X_k}. We make
the following observations:
(i) the immediate dominator of all blocks in a strongly connected
component of G' is the same
(ii) if X has no predecessors in G', then the immediate dominator of X
is the nearest common ancestor of the predecessors of X in the
subtree of F rooted in Y
Therefore, it suffices to find the topological ordering of G', and
process the nodes X_i in this order using the rules (i) and (ii).
Then, we contract all the nodes X_i with Y in G, so that the further
steps work correctly. */
if (!conservative)
{
/* Split the tree now. If the idoms of blocks in BBS are not
conservatively correct, setting the dominators using the
heuristics in prune_bbs_to_update_dominators could
create cycles in the dominance "tree", and cause ICE. */
for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
set_immediate_dominator (CDI_DOMINATORS, bb, NULL);
}
prune_bbs_to_update_dominators (bbs, conservative);
n = VEC_length (basic_block, bbs);
if (n == 0)
return;
if (n == 1)
{
bb = VEC_index (basic_block, bbs, 0);
set_immediate_dominator (CDI_DOMINATORS, bb,
recompute_dominator (CDI_DOMINATORS, bb));
return;
}
/* Construct the graph G. */
map = pointer_map_create ();
for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
{
/* If the dominance tree is conservatively correct, split it now. */
if (conservative)
set_immediate_dominator (CDI_DOMINATORS, bb, NULL);
*pointer_map_insert (map, bb) = (void *) (size_t) i;
}
*pointer_map_insert (map, ENTRY_BLOCK_PTR) = (void *) (size_t) n;
g = new_graph (n + 1);
for (y = 0; y < g->n_vertices; y++)
g->vertices[y].data = BITMAP_ALLOC (NULL);
for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
{
FOR_EACH_EDGE (e, ei, bb->preds)
{
dom = root_of_dom_tree (CDI_DOMINATORS, e->src);
if (dom == bb)
continue;
dom_i = (size_t) *pointer_map_contains (map, dom);
/* Do not include parallel edges to G. */
if (bitmap_bit_p (g->vertices[dom_i].data, i))
continue;
bitmap_set_bit (g->vertices[dom_i].data, i);
add_edge (g, dom_i, i);
}
}
for (y = 0; y < g->n_vertices; y++)
BITMAP_FREE (g->vertices[y].data);
pointer_map_destroy (map);
/* Find the dominator tree of G. */
son = XNEWVEC (int, n + 1);
brother = XNEWVEC (int, n + 1);
parent = XNEWVEC (int, n + 1);
graphds_domtree (g, n, parent, son, brother);
/* Finally, traverse the tree and find the immediate dominators. */
for (y = n; son[y] != -1; y = son[y])
continue;
while (y != -1)
{
determine_dominators_for_sons (g, bbs, y, son, brother);
if (brother[y] != -1)
{
y = brother[y];
while (son[y] != -1)
y = son[y];
}
else
y = parent[y];
}
free (son);
free (brother);
free (parent);
free_graph (g);
}
void

View File

@ -747,3 +747,20 @@ et_below (struct et_node *down, struct et_node *up)
return !d->next || d->next->min + d->depth >= 0;
}
/* Returns the root of the tree that contains NODE. */
struct et_node *
et_root (struct et_node *node)
{
struct et_occ *occ = node->rightmost_occ, *r;
/* The root of the tree corresponds to the rightmost occurence in the
represented path. */
et_splay (occ);
for (r = occ; r->next; r = r->next)
continue;
et_splay (r);
return r->of;
}

View File

@ -79,6 +79,7 @@ void et_set_father (struct et_node *, struct et_node *);
void et_split (struct et_node *);
struct et_node *et_nca (struct et_node *, struct et_node *);
bool et_below (struct et_node *, struct et_node *);
struct et_node *et_root (struct et_node *);
#ifdef __cplusplus
}

View File

@ -4829,8 +4829,7 @@ static void
hoist_code (void)
{
basic_block bb, dominated;
basic_block *domby;
unsigned int domby_len;
VEC (basic_block, heap) *domby;
unsigned int i,j;
struct expr **index_map;
struct expr *expr;
@ -4852,7 +4851,7 @@ hoist_code (void)
int found = 0;
int insn_inserted_p;
domby_len = get_dominated_by (CDI_DOMINATORS, bb, &domby);
domby = get_dominated_by (CDI_DOMINATORS, bb);
/* Examine each expression that is very busy at the exit of this
block. These are the potentially hoistable expressions. */
for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
@ -4865,9 +4864,8 @@ hoist_code (void)
/* We've found a potentially hoistable expression, now
we look at every block BB dominates to see if it
computes the expression. */
for (j = 0; j < domby_len; j++)
for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++)
{
dominated = domby[j];
/* Ignore self dominance. */
if (bb == dominated)
continue;
@ -4906,8 +4904,8 @@ hoist_code (void)
/* If we found nothing to hoist, then quit now. */
if (! found)
{
free (domby);
continue;
VEC_free (basic_block, heap, domby);
continue;
}
/* Loop over all the hoistable expressions. */
@ -4923,9 +4921,8 @@ hoist_code (void)
/* We've found a potentially hoistable expression, now
we look at every block BB dominates to see if it
computes the expression. */
for (j = 0; j < domby_len; j++)
for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++)
{
dominated = domby[j];
/* Ignore self dominance. */
if (bb == dominated)
continue;
@ -4976,7 +4973,7 @@ hoist_code (void)
}
}
}
free (domby);
VEC_free (basic_block, heap, domby);
}
free (index_map);

473
gcc/graphds.c Normal file
View File

@ -0,0 +1,473 @@
/* Graph representation and manipulation functions.
Copyright (C) 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
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 COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "obstack.h"
#include "bitmap.h"
#include "vec.h"
#include "vecprim.h"
#include "graphds.h"
/* Dumps graph G into F. */
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. */
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. The new edge is returned. */
struct edge *
add_edge (struct graph *g, int f, int t)
{
struct edge *e = XNEW (struct edge);
struct vertex *vf = &g->vertices[f], *vt = &g->vertices[t];
e->src = f;
e->dest = t;
e->pred_next = vt->pred;
vt->pred = e;
e->succ_next = vf->succ;
vf->succ = e;
return e;
}
/* Moves all the edges incident with U to V. */
void
identify_vertices (struct graph *g, int v, int u)
{
struct vertex *vv = &g->vertices[v];
struct vertex *uu = &g->vertices[u];
struct edge *e, *next;
for (e = uu->succ; e; e = next)
{
next = e->succ_next;
e->src = v;
e->succ_next = vv->succ;
vv->succ = e;
}
uu->succ = NULL;
for (e = uu->pred; e; e = next)
{
next = e->pred_next;
e->dest = v;
e->pred_next = vv->pred;
vv->pred = e;
}
uu->pred = NULL;
}
/* Helper function for graphds_dfs. Returns the source vertex of E, in the
direction given by FORWARD. */
static inline int
dfs_edge_src (struct edge *e, bool forward)
{
return forward ? e->src : e->dest;
}
/* Helper function for graphds_dfs. Returns the destination vertex of E, in
the direction given by FORWARD. */
static inline int
dfs_edge_dest (struct edge *e, bool forward)
{
return forward ? e->dest : e->src;
}
/* Helper function for graphds_dfs. Returns the first edge after E (including
E), in the graph direction given by FORWARD, that belongs to SUBGRAPH. */
static inline struct edge *
foll_in_subgraph (struct edge *e, bool forward, bitmap subgraph)
{
int d;
if (!subgraph)
return e;
while (e)
{
d = dfs_edge_dest (e, forward);
if (bitmap_bit_p (subgraph, d))
return e;
e = forward ? e->succ_next : e->pred_next;
}
return e;
}
/* Helper function for graphds_dfs. Select the first edge from V in G, in the
direction given by FORWARD, that belongs to SUBGRAPH. */
static inline struct edge *
dfs_fst_edge (struct graph *g, int v, bool forward, bitmap subgraph)
{
struct edge *e;
e = (forward ? g->vertices[v].succ : g->vertices[v].pred);
return foll_in_subgraph (e, forward, subgraph);
}
/* Helper function for graphds_dfs. Returns the next edge after E, in the
graph direction given by FORWARD, that belongs to SUBGRAPH. */
static inline struct edge *
dfs_next_edge (struct edge *e, bool forward, bitmap subgraph)
{
return foll_in_subgraph (forward ? e->succ_next : e->pred_next,
forward, subgraph);
}
/* 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. If SUBGRAPH is not NULL, it specifies the
subgraph of G to run DFS on. Returns the number of the components
of the graph (number of the restarts of DFS). */
int
graphds_dfs (struct graph *g, int *qs, int nq, VEC (int, heap) **qt,
bool forward, bitmap subgraph)
{
int i, tick = 0, v, comp = 0, top;
struct edge *e;
struct edge **stack = XNEWVEC (struct edge *, g->n_vertices);
bitmap_iterator bi;
unsigned av;
if (subgraph)
{
EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, av, bi)
{
g->vertices[av].component = -1;
g->vertices[av].post = -1;
}
}
else
{
for (i = 0; i < g->n_vertices; i++)
{
g->vertices[i].component = -1;
g->vertices[i].post = -1;
}
}
for (i = 0; i < nq; i++)
{
v = qs[i];
if (g->vertices[v].post != -1)
continue;
g->vertices[v].component = comp++;
e = dfs_fst_edge (g, v, forward, subgraph);
top = 0;
while (1)
{
while (e)
{
if (g->vertices[dfs_edge_dest (e, forward)].component
== -1)
break;
e = dfs_next_edge (e, forward, subgraph);
}
if (!e)
{
if (qt)
VEC_safe_push (int, heap, *qt, v);
g->vertices[v].post = tick++;
if (!top)
break;
e = stack[--top];
v = dfs_edge_src (e, forward);
e = dfs_next_edge (e, forward, subgraph);
continue;
}
stack[top++] = e;
v = dfs_edge_dest (e, forward);
e = dfs_fst_edge (g, v, forward, subgraph);
g->vertices[v].component = comp - 1;
}
}
free (stack);
return comp;
}
/* Determines the strongly connected components of G, using 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. If SUBGRAPH is not NULL, it
specifies the subgraph of G whose strongly connected components we want
to determine.
After running this function, v->component is the number of the strongly
connected component for each vertex of G. Returns the number of the
sccs of G. */
int
graphds_scc (struct graph *g, bitmap subgraph)
{
int *queue = XNEWVEC (int, g->n_vertices);
VEC (int, heap) *postorder = NULL;
int nq, i, comp;
unsigned v;
bitmap_iterator bi;
if (subgraph)
{
nq = 0;
EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, v, bi)
{
queue[nq++] = v;
}
}
else
{
for (i = 0; i < g->n_vertices; i++)
queue[i] = i;
nq = g->n_vertices;
}
graphds_dfs (g, queue, nq, &postorder, false, subgraph);
gcc_assert (VEC_length (int, postorder) == (unsigned) nq);
for (i = 0; i < nq; i++)
queue[i] = VEC_index (int, postorder, nq - i - 1);
comp = graphds_dfs (g, queue, nq, NULL, true, subgraph);
free (queue);
VEC_free (int, heap, postorder);
return comp;
}
/* Runs CALLBACK for all edges in G. */
void
for_each_edge (struct graph *g, graphds_edge_callback callback)
{
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. */
void
free_graph (struct graph *g)
{
struct edge *e, *n;
struct vertex *v;
int i;
for (i = 0; i < g->n_vertices; i++)
{
v = &g->vertices[i];
for (e = v->succ; e; e = n)
{
n = e->succ_next;
free (e);
}
}
free (g->vertices);
free (g);
}
/* Returns the nearest common ancestor of X and Y in tree whose parent
links are given by PARENT. MARKS is the array used to mark the
vertices of the tree, and MARK is the number currently used as a mark. */
static int
tree_nca (int x, int y, int *parent, int *marks, int mark)
{
if (x == -1 || x == y)
return y;
/* We climb with X and Y up the tree, marking the visited nodes. When
we first arrive to a marked node, it is the common ancestor. */
marks[x] = mark;
marks[y] = mark;
while (1)
{
x = parent[x];
if (x == -1)
break;
if (marks[x] == mark)
return x;
marks[x] = mark;
y = parent[y];
if (y == -1)
break;
if (marks[y] == mark)
return y;
marks[y] = mark;
}
/* If we reached the root with one of the vertices, continue
with the other one till we reach the marked part of the
tree. */
if (x == -1)
{
for (y = parent[y]; marks[y] != mark; y = parent[y])
continue;
return y;
}
else
{
for (x = parent[x]; marks[x] != mark; x = parent[x])
continue;
return x;
}
}
/* Determines the dominance tree of G (stored in the PARENT, SON and BROTHER
arrays), where the entry node is ENTRY. */
void
graphds_domtree (struct graph *g, int entry,
int *parent, int *son, int *brother)
{
VEC (int, heap) *postorder = NULL;
int *marks = XCNEWVEC (int, g->n_vertices);
int mark = 1, i, v, idom;
bool changed = true;
struct edge *e;
/* We use a slight modification of the standard iterative algorithm, as
described in
K. D. Cooper, T. J. Harvey and K. Kennedy: A Simple, Fast Dominance
Algorithm
sort vertices in reverse postorder
foreach v
dom(v) = everything
dom(entry) = entry;
while (anything changes)
foreach v
dom(v) = {v} union (intersection of dom(p) over all predecessors of v)
The sets dom(v) are represented by the parent links in the current version
of the dominance tree. */
for (i = 0; i < g->n_vertices; i++)
{
parent[i] = -1;
son[i] = -1;
brother[i] = -1;
}
graphds_dfs (g, &entry, 1, &postorder, true, NULL);
gcc_assert (VEC_length (int, postorder) == (unsigned) g->n_vertices);
gcc_assert (VEC_index (int, postorder, g->n_vertices - 1) == entry);
while (changed)
{
changed = false;
for (i = g->n_vertices - 2; i >= 0; i--)
{
v = VEC_index (int, postorder, i);
idom = -1;
for (e = g->vertices[v].pred; e; e = e->pred_next)
{
if (e->src != entry
&& parent[e->src] == -1)
continue;
idom = tree_nca (idom, e->src, parent, marks, mark++);
}
if (idom != parent[v])
{
parent[v] = idom;
changed = true;
}
}
}
free (marks);
VEC_free (int, heap, postorder);
for (i = 0; i < g->n_vertices; i++)
if (parent[i] != -1)
{
brother[i] = son[parent[i]];
son[parent[i]] = i;
}
}

63
gcc/graphds.h Normal file
View File

@ -0,0 +1,63 @@
/* Graph representation.
Copyright (C) 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
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 COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
/* 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. */
void *data; /* Data attached to the vertex. */
};
/* Structure representing a graph. */
struct graph
{
int n_vertices; /* Number of vertices. */
struct vertex *vertices;
/* The vertices. */
};
struct graph *new_graph (int);
void dump_graph (FILE *, struct graph *);
struct edge *add_edge (struct graph *, int, int);
void identify_vertices (struct graph *, int, int);
int graphds_dfs (struct graph *, int *, int,
VEC (int, heap) **, bool, bitmap);
int graphds_scc (struct graph *, bitmap);
void graphds_domtree (struct graph *, int, int *, int *, int *);
typedef void (*graphds_edge_callback) (struct graph *, struct edge *);
void for_each_edge (struct graph *, graphds_edge_callback);
void free_graph (struct graph *g);

View File

@ -2521,7 +2521,7 @@ perfect_nestify (struct loop *loop,
single_exit (loop)->src);
set_immediate_dominator (CDI_DOMINATORS, latchbb, bodybb);
set_immediate_dominator (CDI_DOMINATORS, olddest,
recount_dominator (CDI_DOMINATORS, olddest));
recompute_dominator (CDI_DOMINATORS, olddest));
/* Create the new iv. */
oldivvar = VEC_index (tree, loopivs, 0);
ivvar = create_tmp_var (TREE_TYPE (oldivvar), "perfectiv");

View File

@ -422,13 +422,13 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
emit_insn_after (sequence, BB_END (set_zero));
set_immediate_dominator (CDI_DOMINATORS, set_zero,
recount_dominator (CDI_DOMINATORS,
set_zero));
recompute_dominator (CDI_DOMINATORS,
set_zero));
}
set_immediate_dominator (CDI_DOMINATORS, new_preheader,
recount_dominator (CDI_DOMINATORS,
new_preheader));
recompute_dominator (CDI_DOMINATORS,
new_preheader));
}
/* Some targets (eg, C4x) need to initialize special looping

View File

@ -953,8 +953,8 @@ unroll_loop_runtime_iterations (struct loop *loop)
{
rtx old_niter, niter, init_code, branch_code, tmp;
unsigned i, j, p;
basic_block preheader, *body, *dom_bbs, swtch, ezc_swtch;
unsigned n_dom_bbs;
basic_block preheader, *body, swtch, ezc_swtch;
VEC (basic_block, heap) *dom_bbs;
sbitmap wont_exit;
int may_exit_copy;
unsigned n_peel;
@ -972,21 +972,20 @@ unroll_loop_runtime_iterations (struct loop *loop)
opt_info = analyze_insns_in_loop (loop);
/* Remember blocks whose dominators will have to be updated. */
dom_bbs = XCNEWVEC (basic_block, n_basic_blocks);
n_dom_bbs = 0;
dom_bbs = NULL;
body = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++)
{
unsigned nldom;
basic_block *ldom;
VEC (basic_block, heap) *ldom;
basic_block bb;
nldom = get_dominated_by (CDI_DOMINATORS, body[i], &ldom);
for (j = 0; j < nldom; j++)
if (!flow_bb_inside_loop_p (loop, ldom[j]))
dom_bbs[n_dom_bbs++] = ldom[j];
ldom = get_dominated_by (CDI_DOMINATORS, body[i]);
for (j = 0; VEC_iterate (basic_block, ldom, j, bb); j++)
if (!flow_bb_inside_loop_p (loop, bb))
VEC_safe_push (basic_block, heap, dom_bbs, bb);
free (ldom);
VEC_free (basic_block, heap, ldom);
}
free (body);
@ -1105,7 +1104,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
}
/* Recount dominators for outer blocks. */
iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, n_dom_bbs);
iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, false);
/* And unroll loop. */
@ -1177,8 +1176,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
"in runtime, %i insns\n",
max_unroll, num_loop_insns (loop));
if (dom_bbs)
free (dom_bbs);
VEC_free (basic_block, heap, dom_bbs);
}
/* Decide whether to simply peel LOOP and how much. */

View File

@ -4336,11 +4336,11 @@ tree_duplicate_sese_region (edge entry, edge exit,
basic_block *region, unsigned n_region,
basic_block *region_copy)
{
unsigned i, n_doms;
unsigned i;
bool free_region_copy = false, copying_header = false;
struct loop *loop = entry->dest->loop_father;
edge exit_copy;
basic_block *doms;
VEC (basic_block, heap) *doms;
edge redirected;
int total_freq = 0, entry_freq = 0;
gcov_type total_count = 0, entry_count = 0;
@ -4392,10 +4392,10 @@ tree_duplicate_sese_region (edge entry, edge exit,
/* Record blocks outside the region that are dominated by something
inside. */
doms = XNEWVEC (basic_block, n_basic_blocks);
doms = NULL;
initialize_original_copy_tables ();
n_doms = get_dominated_by_region (CDI_DOMINATORS, region, n_region, doms);
doms = get_dominated_by_region (CDI_DOMINATORS, region, n_region);
if (entry->dest->count)
{
@ -4451,8 +4451,8 @@ tree_duplicate_sese_region (edge entry, edge exit,
region, but was dominated by something inside needs recounting as
well. */
set_immediate_dominator (CDI_DOMINATORS, entry->dest, entry->src);
doms[n_doms++] = get_bb_original (entry->dest);
iterate_fix_dominators (CDI_DOMINATORS, doms, n_doms);
VEC_safe_push (basic_block, heap, doms, get_bb_original (entry->dest));
iterate_fix_dominators (CDI_DOMINATORS, doms, false);
free (doms);
/* Add the other PHI node arguments. */
@ -5476,9 +5476,7 @@ remove_edge_and_dominated_blocks (edge e)
VEC_safe_push (basic_block, heap, bbs_to_fix_dom, dbb);
}
iterate_fix_dominators (CDI_DOMINATORS,
VEC_address (basic_block, bbs_to_fix_dom),
VEC_length (basic_block, bbs_to_fix_dom));
iterate_fix_dominators (CDI_DOMINATORS, bbs_to_fix_dom, true);
BITMAP_FREE (df);
BITMAP_FREE (df_idom);

View File

@ -577,6 +577,9 @@ thread_block (basic_block bb, bool noloop_only)
lookup_redirection_data (e, NULL, NO_INSERT)->do_not_duplicate = true;
}
/* We do not update dominance info. */
free_dominance_info (CDI_DOMINATORS);
/* Now create duplicates of BB.
Note that for a block with a high outgoing degree we can waste
@ -1057,9 +1060,6 @@ thread_through_all_blocks (bool may_peel_loop_headers)
retval |= thread_through_loop_header (loop, may_peel_loop_headers);
}
if (retval)
free_dominance_info (CDI_DOMINATORS);
if (dump_file && (dump_flags & TDF_STATS))
fprintf (dump_file, "\nJumps threaded: %lu\n",
thread_stats.num_threaded_edges);