Commit 42759f1e by Zdenek Dvorak Committed by Zdenek Dvorak

Makefile.in (tree-cfg.o): Add CFGLAYOUT_H dependency.

	* Makefile.in (tree-cfg.o): Add CFGLAYOUT_H dependency.
	* basic-block.h (get_dominated_by_region): Declare.
	* dominance.c (get_dominated_by_region): New function.
	* tree-cfg.c: Include cfglayout.h.
	(tree_duplicate_bb): Duplicate also phi nodes.
	(struct ssa_name_map_entry): New type.
	(add_phi_args_after_copy_bb, add_phi_args_after_copy,
	ssa_name_map_entry_hash, ssa_name_map_entry_eq,
	allocate_ssa_names, rewrite_to_new_ssa_names_def,
	rewrite_to_new_ssa_names_use, rewrite_to_new_ssa_names_bb,
	rewrite_to_new_ssa_names, tree_duplicate_sese_region): New functions.
	* tree-flow.h (tree_duplicate_sese_region, add_phi_args_after_copy_bb,
	add_phi_args_after_copy, rewrite_to_new_ssa_names_bb,
	rewrite_to_new_ssa_names, allocate_ssa_names,
	rewrite_into_loop_closed_ssa, verify_loop_closed_ssa): Declare.
	* tree-ssa-loop-ch.c (duplicate_blocks): Removed.
	(copy_loop_headers): Use tree_duplicate_sese_region.

	* gcc.dg/tree-ssa/copy-headers.c: Update outcome.

From-SVN: r87614
parent 2731cf24
2004-09-16 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* Makefile.in (tree-cfg.o): Add CFGLAYOUT_H dependency.
* basic-block.h (get_dominated_by_region): Declare.
* dominance.c (get_dominated_by_region): New function.
* tree-cfg.c: Include cfglayout.h.
(tree_duplicate_bb): Duplicate also phi nodes.
(struct ssa_name_map_entry): New type.
(add_phi_args_after_copy_bb, add_phi_args_after_copy,
ssa_name_map_entry_hash, ssa_name_map_entry_eq,
allocate_ssa_names, rewrite_to_new_ssa_names_def,
rewrite_to_new_ssa_names_use, rewrite_to_new_ssa_names_bb,
rewrite_to_new_ssa_names, tree_duplicate_sese_region): New functions.
* tree-flow.h (tree_duplicate_sese_region, add_phi_args_after_copy_bb,
add_phi_args_after_copy, rewrite_to_new_ssa_names_bb,
rewrite_to_new_ssa_names, allocate_ssa_names,
rewrite_into_loop_closed_ssa, verify_loop_closed_ssa): Declare.
* tree-ssa-loop-ch.c (duplicate_blocks): Removed.
(copy_loop_headers): Use tree_duplicate_sese_region.
2004-09-16 Frank Ch. Eigler <fche@redhat.com> 2004-09-16 Frank Ch. Eigler <fche@redhat.com>
* profile.c (branch_prob): Restore support for USE_MAPPED_LOCATION. * profile.c (branch_prob): Restore support for USE_MAPPED_LOCATION.
......
...@@ -1667,7 +1667,8 @@ tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \ ...@@ -1667,7 +1667,8 @@ tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \ diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
$(TREE_DUMP_H) except.h langhooks.h $(CFGLOOP_H) gt-tree-cfg.h tree-pass.h $(TREE_DUMP_H) except.h langhooks.h $(CFGLOOP_H) gt-tree-cfg.h tree-pass.h \
$(CFGLAYOUT_H)
tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) function.h $(TM_H) coretypes.h \ $(RTL_H) $(TREE_H) $(TM_P_H) function.h $(TM_H) coretypes.h \
$(TREE_DUMP_H) diagnostic.h except.h tree-pass.h $(FLAGS_H) langhooks.h $(TREE_DUMP_H) diagnostic.h except.h tree-pass.h $(FLAGS_H) langhooks.h
......
...@@ -732,6 +732,8 @@ extern void set_immediate_dominator (enum cdi_direction, basic_block, ...@@ -732,6 +732,8 @@ extern void set_immediate_dominator (enum cdi_direction, basic_block,
extern basic_block get_immediate_dominator (enum cdi_direction, 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 bool dominated_by_p (enum cdi_direction, basic_block, basic_block);
extern int get_dominated_by (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 void add_to_dominance_info (enum cdi_direction, basic_block); extern void add_to_dominance_info (enum cdi_direction, basic_block);
extern void delete_from_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 recount_dominator (enum cdi_direction, basic_block);
......
...@@ -738,6 +738,32 @@ get_dominated_by (enum cdi_direction dir, basic_block bb, basic_block **bbs) ...@@ -738,6 +738,32 @@ get_dominated_by (enum cdi_direction dir, basic_block bb, basic_block **bbs)
return n; return n;
} }
/* 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
get_dominated_by_region (enum cdi_direction dir, basic_block *region,
unsigned n_region, basic_block *doms)
{
unsigned n_doms = 0, i;
basic_block dom;
for (i = 0; i < n_region; i++)
region[i]->rbi->duplicated = 1;
for (i = 0; i < n_region; i++)
for (dom = first_dom_son (dir, region[i]);
dom;
dom = next_dom_son (dir, dom))
if (!dom->rbi->duplicated)
doms[n_doms++] = dom;
for (i = 0; i < n_region; i++)
region[i]->rbi->duplicated = 0;
return n_doms;
}
/* Redirect all edges pointing to BB to TO. */ /* Redirect all edges pointing to BB to TO. */
void void
redirect_immediate_dominators (enum cdi_direction dir, basic_block bb, redirect_immediate_dominators (enum cdi_direction dir, basic_block bb,
......
2004-09-16 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* gcc.dg/tree-ssa/copy-headers.c: Update outcome.
2004-09-16 Frank Ch. Eigler <fche@redhat.com> 2004-09-16 Frank Ch. Eigler <fche@redhat.com>
* gcc.misc-tests/bprob.exp, g++.dg/bprob/bprob.exp: Iterate tests * gcc.misc-tests/bprob.exp, g++.dg/bprob/bprob.exp: Iterate tests
......
...@@ -11,5 +11,5 @@ void bla (void) ...@@ -11,5 +11,5 @@ void bla (void)
foo (i); foo (i);
} }
/* There should be a header scheduled for duplication. */ /* There should be a header duplicated. */
/* { dg-final { scan-tree-dump-times "Scheduled" 1 "ch"} } */ /* { dg-final { scan-tree-dump-times "Duplicating header" 1 "ch"} } */
...@@ -495,6 +495,13 @@ extern void clear_special_calls (void); ...@@ -495,6 +495,13 @@ extern void clear_special_calls (void);
extern void verify_stmts (void); extern void verify_stmts (void);
extern tree tree_block_label (basic_block bb); extern tree tree_block_label (basic_block bb);
extern void extract_true_false_edges_from_block (basic_block, edge *, edge *); extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
extern bool tree_duplicate_sese_region (edge, edge, basic_block *, unsigned,
basic_block *);
extern void add_phi_args_after_copy_bb (basic_block);
extern void add_phi_args_after_copy (basic_block *, unsigned);
extern void rewrite_to_new_ssa_names_bb (basic_block, struct htab *);
extern void rewrite_to_new_ssa_names (basic_block *, unsigned, htab_t);
extern void allocate_ssa_names (bitmap, struct htab **);
extern bool tree_purge_dead_eh_edges (basic_block); extern bool tree_purge_dead_eh_edges (basic_block);
extern bool tree_purge_all_dead_eh_edges (bitmap); extern bool tree_purge_all_dead_eh_edges (bitmap);
extern tree gimplify_val (block_stmt_iterator *, tree, tree); extern tree gimplify_val (block_stmt_iterator *, tree, tree);
......
...@@ -98,59 +98,6 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, ...@@ -98,59 +98,6 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
return true; return true;
} }
/* Duplicates destinations of edges in BBS_TO_DUPLICATE. */
static void
duplicate_blocks (varray_type bbs_to_duplicate)
{
unsigned i;
edge preheader_edge, e, e1;
basic_block header, new_header;
tree phi, new_phi, var;
/* TODO: It should be quite easy to keep the dominance information
up-to-date. */
free_dominance_info (CDI_DOMINATORS);
for (i = 0; i < VARRAY_ACTIVE_SIZE (bbs_to_duplicate); i++)
{
preheader_edge = VARRAY_GENERIC_PTR_NOGC (bbs_to_duplicate, i);
header = preheader_edge->dest;
gcc_assert (header->aux);
header->aux = NULL;
new_header = duplicate_block (header, preheader_edge);
/* Create the phi nodes on on entry to new_header. */
for (phi = phi_nodes (header), var = PENDING_STMT (preheader_edge);
phi;
phi = TREE_CHAIN (phi), var = TREE_CHAIN (var))
{
new_phi = create_phi_node (PHI_RESULT (phi), new_header);
add_phi_arg (&new_phi, TREE_VALUE (var), preheader_edge);
}
PENDING_STMT (preheader_edge) = NULL;
/* Add the phi arguments to the outgoing edges. */
for (e = header->succ; e; e = e->succ_next)
{
for (e1 = new_header->succ; e1->dest != e->dest; e1 = e1->succ_next)
continue;
for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
{
tree def = PHI_ARG_DEF_FROM_EDGE (phi, e);
add_phi_arg (&phi, def, e1);
}
}
}
calculate_dominance_info (CDI_DOMINATORS);
rewrite_ssa_into_ssa ();
}
/* Checks whether LOOP is a do-while style loop. */ /* Checks whether LOOP is a do-while style loop. */
static bool static bool
...@@ -183,12 +130,14 @@ copy_loop_headers (void) ...@@ -183,12 +130,14 @@ copy_loop_headers (void)
unsigned i; unsigned i;
struct loop *loop; struct loop *loop;
basic_block header; basic_block header;
edge preheader_edge; edge exit;
varray_type bbs_to_duplicate = NULL; basic_block *bbs;
unsigned n_bbs;
loops = loop_optimizer_init (dump_file); loops = loop_optimizer_init (dump_file);
if (!loops) if (!loops)
return; return;
rewrite_into_loop_closed_ssa ();
/* We do not try to keep the information about irreducible regions /* We do not try to keep the information about irreducible regions
up-to-date. */ up-to-date. */
...@@ -198,14 +147,15 @@ copy_loop_headers (void) ...@@ -198,14 +147,15 @@ copy_loop_headers (void)
verify_loop_structure (loops); verify_loop_structure (loops);
#endif #endif
bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);
for (i = 1; i < loops->num; i++) for (i = 1; i < loops->num; i++)
{ {
/* Copy at most 20 insns. */ /* Copy at most 20 insns. */
int limit = 20; int limit = 20;
loop = loops->parray[i]; loop = loops->parray[i];
preheader_edge = loop_preheader_edge (loop); header = loop->header;
header = preheader_edge->dest;
/* If the loop is already a do-while style one (either because it was /* If the loop is already a do-while style one (either because it was
written as such, or because jump threading transformed it into one), written as such, or because jump threading transformed it into one),
...@@ -218,44 +168,56 @@ copy_loop_headers (void) ...@@ -218,44 +168,56 @@ copy_loop_headers (void)
like while (a && b) {...}, where we want to have both of the conditions like while (a && b) {...}, where we want to have both of the conditions
copied. TODO -- handle while (a || b) - like cases, by not requiring copied. TODO -- handle while (a || b) - like cases, by not requiring
the header to have just a single successor and copying up to the header to have just a single successor and copying up to
postdominator. postdominator. */
We do not really copy the blocks immediately, so that we do not have exit = NULL;
to worry about updating loop structures, and also so that we do not n_bbs = 0;
have to rewrite variables out of and into ssa form for each block.
Instead we just record the block into worklist and duplicate all of
them at once. */
while (should_duplicate_loop_header_p (header, loop, &limit)) while (should_duplicate_loop_header_p (header, loop, &limit))
{ {
if (!bbs_to_duplicate)
VARRAY_GENERIC_PTR_NOGC_INIT (bbs_to_duplicate, 10,
"bbs_to_duplicate");
VARRAY_PUSH_GENERIC_PTR_NOGC (bbs_to_duplicate, preheader_edge);
header->aux = &header->aux;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Scheduled basic block %d for duplication.\n",
header->index);
/* Find a successor of header that is inside a loop; i.e. the new /* Find a successor of header that is inside a loop; i.e. the new
header after the condition is copied. */ header after the condition is copied. */
if (flow_bb_inside_loop_p (loop, header->succ->dest)) if (flow_bb_inside_loop_p (loop, header->succ->dest))
preheader_edge = header->succ; exit = header->succ;
else else
preheader_edge = header->succ->succ_next; exit = header->succ->succ_next;
header = preheader_edge->dest; bbs[n_bbs++] = header;
header = exit->dest;
} }
}
loop_optimizer_finalize (loops, NULL); if (!exit)
continue;
if (bbs_to_duplicate) if (dump_file && (dump_flags & TDF_DETAILS))
{ fprintf (dump_file,
duplicate_blocks (bbs_to_duplicate); "Duplicating header of the loop %d up to edge %d->%d.\n",
VARRAY_FREE (bbs_to_duplicate); loop->num, exit->src->index, exit->dest->index);
/* Ensure that the header will have just the latch as a predecessor
inside the loop. */
if (exit->dest->pred->pred_next)
exit = loop_split_edge_with (exit, NULL)->succ;
if (!tree_duplicate_sese_region (loop_preheader_edge (loop), exit,
bbs, n_bbs, NULL))
{
fprintf (dump_file, "Duplication failed.\n");
continue;
}
/* Ensure that the latch and the preheader is simple (we know that they
are not now, since there was the loop exit condition. */
loop_split_edge_with (loop_preheader_edge (loop), NULL);
loop_split_edge_with (loop_latch_edge (loop), NULL);
} }
free (bbs);
#ifdef ENABLE_CHECKING
verify_loop_closed_ssa ();
#endif
loop_optimizer_finalize (loops, NULL);
/* Run cleanup_tree_cfg here regardless of whether we have done anything, so /* Run cleanup_tree_cfg here regardless of whether we have done anything, so
that we cleanup the blocks created in order to get the loops into a that we cleanup the blocks created in order to get the loops into a
canonical shape. */ canonical shape. */
...@@ -277,7 +239,7 @@ struct tree_opt_pass pass_ch = ...@@ -277,7 +239,7 @@ struct tree_opt_pass pass_ch =
NULL, /* next */ NULL, /* next */
0, /* static_pass_number */ 0, /* static_pass_number */
TV_TREE_CH, /* tv_id */ TV_TREE_CH, /* tv_id */
PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */ PROP_cfg | PROP_ssa, /* properties_required */
0, /* properties_provided */ 0, /* properties_provided */
0, /* properties_destroyed */ 0, /* properties_destroyed */
0, /* todo_flags_start */ 0, /* todo_flags_start */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment