New out of ssa Coalescer.

2006-12-10  Andrew MacLeod  <amacleod@redhat.com>

	* common.opt (-ftree-lrs): Remove live range splitting option.
	* makefile.in: Add tree-ssa-coalesce.o and reduce header dependancies.
	* opts.c (decode_options): Remove flag_tree_live_range_split.
	* tree-flow.h (struct var_ann_d): Rename fields from root_ to base_.
	* tree-flow-inline.h (single_imm_use_p): New.  Check for single use.
	* tree-outof-ssa.c: Remove header files which aren't needed.
	(SSANORM_*): Remove flags.
	(print_exprs_edge, coalesce_abnormal_edges, coalesce_phi_operands, 
	coalesce_result_decls_and_copies, coalesce_asm_operands): Remove.
	(coalesce_ssa_name): Move to tree-ssa-coalesce.c.
	(assign_vars): Use Basevar instead of root_var structure.
	(replace_def_variable): Dont do anything if def is replaceable.
	(remove_ssa_form): Integrate functional changes.
	(rewrite_out_of_ssa): Remove live-range_split option.
	* tree-ssa-coalesce.c: New File for ssa-name coalescing.
	(coalesce_cost): Calculate the cost of a coalesce.
	(coalesce_cost_bb): Calculate the coalesce cost within a BB.
	(coalesce_cost_edge): Calculate the coalesce cost on an edge.
	(pop_cost_one_pair): Remove the best coalesce with cost 1 from the list.
	(pop_best_coalesce): Remove the best coalesce from the list.
	(coalesce_pair_map_hash): Calculate coalesce pair hash.
	(coalesce_pair_map_eq): Compare 2 coalesce pairs for hash function.
	(create_coalesce_list): Create a coalesce list object.
	(delete_coalesce_list): Free a coalesce list object.
	(find_coalesce_pair): Find matching pair in the coalesce list.
	(add_cost_one_coalesce): Add a coalesce to the "cost one" list.
	(add_coalesce): Add a coalesce to the coalesce list.
	(compare_pairs): Comparision function to determine pair sorted order.
	(num_coalesce_pairs): Number of coalesced pairs.
	(first_coalesce_pair, end_coalesce_pair_p, next_coalesce_pair):
	Coalesce pair iterator functions.
	(sort_coalesce_list): Sort coalesce pairs in order of expense.
	(dump_coalesce_list): Show coalesce list.
	(ssa_conflicts_new): Create an SSA conflict graph.
	(ssa_conflicts_delete): Delete an SSA conflict graph.
	(ssa_conflicts_test_p): Test for conflicts.
	(ssa_conflicts_add_one): Add a single conflict.
	(ssa_conflicts_add): Add a conflict pair.
	(ssa_conflicts_merge): Merge conflicts.
	(struct live_track_d): Struct for tracking live partitions.
	(new_live_track): Create new live_track object.
	(delete_live_track): Delete a live_track object.
	(live_track_remove_partition): Remove a partition from the live list.
	(live_track_add_partition): Add a partition from the live list.
	(live_track_clear_var): Take VAR from the live list.
	(live_track_live_p): Is var live?
	(live_track_process_use): Make var come alive.
	(live_track_process_def): Make var go dead, add conflicts.
	(live_track_init): Initialize to a live on exit set.
	(live_track_clear_base_vars): Clear live partitions.
	(build_ssa_conflict_graph): Build a conflict graph.
	(print_exprs): Common debug output routine.
	(abnormal_corrupt): Output info about a failed coalesce across an
	abnormal edge.
	(fail_abnormal_edge_coalesce): Output info about a failed MUST_COALESCE.
	(create_outofssa_var_map): Create a var map and coalesce list.
	(attempt_coalesce): Coalesce a pair.
	(coalesce_partitions): Coalesce all pairs in a coalesce list.
	(coalesce_ssa_name): Entry point.  Determine what ssa_names to coalesce.
	* tree-ssa-live.c: Remove header files which aren't needed.
	(var_map_base_init): New.  Initialize a basevar list.
	(var_map_base_fini): New.  Finish a basevar list.
	(init_var_map): Initialize new fields.
	(delete_var_map): Free new fields.
	(var_union): Use renamed fields.
	(compact_var_map): Remove.
	(partition_to_view_init): Use renamed fields, change order of an if.
	(partition_view_fini): Use renamed fields.
	(partition_view_normal): Create basevar list if requested.
	(partition_view_bitmap): Create a view based on a bitmap of partitions.
	(change_partition_var): Use renamed fields.
	(create_ssa_var_map): Remove.
	(tpa_init, tpa_remove_partition, tpa_delete, tpa_compact,
	root_var_init): Remove.
	(partition_pair_map_hash, partition_pair_map_eq, create_coalesce_list,
	delete_coalesce_list, find_partition_pair, coalesce_cost, add_coalesce,
	compare_pairs, num_coalesce_pairs, first_partition_pair,
	end_partition_pair_p, next_partition_pair, sort_coalesce_list,
	pop_best_coalesce, add_conflicts_if_valid, set_if_valid,
	build_tree_conflict_graph, coalesce_tpa_members, dump_coalesce_list,
	tpa_dump): Moved to tree-ssa-coalesce.c and/or renamed there.
	(dump_var_map): Use renamed fields.
	* tree-ssa-live.h (struct  _var_map): Modify fields.
	(partition_to_var, version_to_var, var_to_partition): Use renamed 
	fields.
	(basevar_index): New.  Index of the base variable of a partition.
	(num_basevars): New.  Number of unique base variables in partition map.
	(register_ssa_partition): Use renamed fields.
	(struct tree_partition_associator_d): Remove.
	(tpa_num_trees, tpa_tree, tpa_first_partition, tpa_next_partition,
	tpa_find_tree, tpa_decompact, root_var_init, root_var_num,
	root_var, root_var_first_partition, root_var_next_partition,
	root_var_dump, root_var_delete, root_var_remove_partition, 
	root_var_find, root_var_compact, root_var_decompact): Remove.
	(struct partition_pair, struct coalesce_list_d): Moved to 
	tree-ssa-coalesce.c
	* tree-ssa-ter.c: Remove header files which aren't needed.

From-SVN: r119711
This commit is contained in:
Andrew MacLeod 2006-12-10 21:25:40 +00:00 committed by Andrew Macleod
parent 669353d549
commit 7290d709ef
11 changed files with 1851 additions and 2043 deletions

View File

@ -1,3 +1,103 @@
2006-12-10 Andrew MacLeod <amacleod@redhat.com>
* common.opt (-ftree-lrs): Remove live range splitting option.
* makefile.in: Add tree-ssa-coalesce.o and reduce header dependancies.
* opts.c (decode_options): Remove flag_tree_live_range_split.
* tree-flow.h (struct var_ann_d): Rename fields from root_ to base_.
* tree-flow-inline.h (single_imm_use_p): New. Check for single use.
* tree-outof-ssa.c: Remove header files which aren't needed.
(SSANORM_*): Remove flags.
(print_exprs_edge, coalesce_abnormal_edges, coalesce_phi_operands,
coalesce_result_decls_and_copies, coalesce_asm_operands): Remove.
(coalesce_ssa_name): Move to tree-ssa-coalesce.c.
(assign_vars): Use Basevar instead of root_var structure.
(replace_def_variable): Dont do anything if def is replaceable.
(remove_ssa_form): Integrate functional changes.
(rewrite_out_of_ssa): Remove live-range_split option.
* tree-ssa-coalesce.c: New File for ssa-name coalescing.
(coalesce_cost): Calculate the cost of a coalesce.
(coalesce_cost_bb): Calculate the coalesce cost within a BB.
(coalesce_cost_edge): Calculate the coalesce cost on an edge.
(pop_cost_one_pair): Remove the best coalesce with cost 1 from the list.
(pop_best_coalesce): Remove the best coalesce from the list.
(coalesce_pair_map_hash): Calculate coalesce pair hash.
(coalesce_pair_map_eq): Compare 2 coalesce pairs for hash function.
(create_coalesce_list): Create a coalesce list object.
(delete_coalesce_list): Free a coalesce list object.
(find_coalesce_pair): Find matching pair in the coalesce list.
(add_cost_one_coalesce): Add a coalesce to the "cost one" list.
(add_coalesce): Add a coalesce to the coalesce list.
(compare_pairs): Comparision function to determine pair sorted order.
(num_coalesce_pairs): Number of coalesced pairs.
(first_coalesce_pair, end_coalesce_pair_p, next_coalesce_pair):
Coalesce pair iterator functions.
(sort_coalesce_list): Sort coalesce pairs in order of expense.
(dump_coalesce_list): Show coalesce list.
(ssa_conflicts_new): Create an SSA conflict graph.
(ssa_conflicts_delete): Delete an SSA conflict graph.
(ssa_conflicts_test_p): Test for conflicts.
(ssa_conflicts_add_one): Add a single conflict.
(ssa_conflicts_add): Add a conflict pair.
(ssa_conflicts_merge): Merge conflicts.
(struct live_track_d): Struct for tracking live partitions.
(new_live_track): Create new live_track object.
(delete_live_track): Delete a live_track object.
(live_track_remove_partition): Remove a partition from the live list.
(live_track_add_partition): Add a partition from the live list.
(live_track_clear_var): Take VAR from the live list.
(live_track_live_p): Is var live?
(live_track_process_use): Make var come alive.
(live_track_process_def): Make var go dead, add conflicts.
(live_track_init): Initialize to a live on exit set.
(live_track_clear_base_vars): Clear live partitions.
(build_ssa_conflict_graph): Build a conflict graph.
(print_exprs): Common debug output routine.
(abnormal_corrupt): Output info about a failed coalesce across an
abnormal edge.
(fail_abnormal_edge_coalesce): Output info about a failed MUST_COALESCE.
(create_outofssa_var_map): Create a var map and coalesce list.
(attempt_coalesce): Coalesce a pair.
(coalesce_partitions): Coalesce all pairs in a coalesce list.
(coalesce_ssa_name): Entry point. Determine what ssa_names to coalesce.
* tree-ssa-live.c: Remove header files which aren't needed.
(var_map_base_init): New. Initialize a basevar list.
(var_map_base_fini): New. Finish a basevar list.
(init_var_map): Initialize new fields.
(delete_var_map): Free new fields.
(var_union): Use renamed fields.
(compact_var_map): Remove.
(partition_to_view_init): Use renamed fields, change order of an if.
(partition_view_fini): Use renamed fields.
(partition_view_normal): Create basevar list if requested.
(partition_view_bitmap): Create a view based on a bitmap of partitions.
(change_partition_var): Use renamed fields.
(create_ssa_var_map): Remove.
(tpa_init, tpa_remove_partition, tpa_delete, tpa_compact,
root_var_init): Remove.
(partition_pair_map_hash, partition_pair_map_eq, create_coalesce_list,
delete_coalesce_list, find_partition_pair, coalesce_cost, add_coalesce,
compare_pairs, num_coalesce_pairs, first_partition_pair,
end_partition_pair_p, next_partition_pair, sort_coalesce_list,
pop_best_coalesce, add_conflicts_if_valid, set_if_valid,
build_tree_conflict_graph, coalesce_tpa_members, dump_coalesce_list,
tpa_dump): Moved to tree-ssa-coalesce.c and/or renamed there.
(dump_var_map): Use renamed fields.
* tree-ssa-live.h (struct _var_map): Modify fields.
(partition_to_var, version_to_var, var_to_partition): Use renamed
fields.
(basevar_index): New. Index of the base variable of a partition.
(num_basevars): New. Number of unique base variables in partition map.
(register_ssa_partition): Use renamed fields.
(struct tree_partition_associator_d): Remove.
(tpa_num_trees, tpa_tree, tpa_first_partition, tpa_next_partition,
tpa_find_tree, tpa_decompact, root_var_init, root_var_num,
root_var, root_var_first_partition, root_var_next_partition,
root_var_dump, root_var_delete, root_var_remove_partition,
root_var_find, root_var_compact, root_var_decompact): Remove.
(struct partition_pair, struct coalesce_list_d): Moved to
tree-ssa-coalesce.c
* tree-ssa-ter.c: Remove header files which aren't needed.
2006-12-10 Steven Bosscher <steven@gcc.gnu.org>
* cse.c: (struct cse_basic_block_data): Remove LAST field.

View File

@ -985,7 +985,7 @@ OBJS-common = \
tree-vect-generic.o tree-ssa-loop.o tree-ssa-loop-niter.o \
tree-ssa-loop-manip.o tree-ssa-threadupdate.o tree-ssa-threadedge.o \
tree-vectorizer.o tree-vect-analyze.o tree-vect-transform.o \
tree-vect-patterns.o tree-ssa-loop-prefetch.o \
tree-vect-patterns.o tree-ssa-loop-prefetch.o tree-ssa-coalesce.o \
tree-ssa-loop-ivcanon.o tree-ssa-propagate.o tree-ssa-address.o \
tree-ssa-math-opts.o \
tree-ssa-loop-ivopts.o tree-if-conv.o tree-ssa-loop-unswitch.o \
@ -1851,17 +1851,14 @@ tree-into-ssa.o : tree-into-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
bitmap.h $(CFGLOOP_H) $(FLAGS_H) hard-reg-set.h $(HASHTAB_H) \
$(TREE_GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H) vecprim.h
tree-ssa-ter.o : tree-ssa-ter.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
$(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
langhooks.h tree-pass.h $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) bitmap.h \
$(FLAGS_H) $(GGC_H) hard-reg-set.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
$(TREE_INLINE_H) $(VARRAY_H) toplev.h vecprim.h
$(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
$(TREE_SSA_LIVE_H) bitmap.h
tree-ssa-coalesce.o : tree-ssa-coalesce.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
$(TREE_SSA_LIVE_H) bitmap.h $(FLAGS_H) $(HASHTAB_H) toplev.h
tree-outof-ssa.o : tree-outof-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
$(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
langhooks.h tree-pass.h $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) bitmap.h \
$(FLAGS_H) $(GGC_H) hard-reg-set.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
$(TREE_INLINE_H) $(VARRAY_H) toplev.h vecprim.h
$(TREE_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-pass.h $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) bitmap.h $(GGC_H) toplev.h
tree-ssa-dse.o : tree-ssa-dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
$(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) domwalk.h $(FLAGS_H) \
@ -1913,10 +1910,8 @@ tree-phinodes.o : tree-phinodes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
domwalk.o : domwalk.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) domwalk.h $(GGC_H)
tree-ssa-live.o : tree-ssa-live.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) \
$(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) \
bitmap.h $(FLAGS_H) $(HASHTAB_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) \
$(VARRAY_H) toplev.h vecprim.h
$(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
$(TREE_SSA_LIVE_H) bitmap.h toplev.h
tree-ssa-copyrename.o : tree-ssa-copyrename.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) tree-pass.h \
$(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) \

View File

@ -1003,10 +1003,6 @@ ftree-ter
Common Report Var(flag_tree_ter)
Replace temporary expressions in the SSA->normal pass
ftree-lrs
Common Report Var(flag_tree_live_range_split)
Perform live range splitting during the SSA->normal pass
ftree-vrp
Common Report Var(flag_tree_vrp) Init(0)
Perform Value Range Propagation on trees

View File

@ -449,7 +449,6 @@ decode_options (unsigned int argc, const char **argv)
flag_tree_dom = 1;
flag_tree_dse = 1;
flag_tree_ter = 1;
flag_tree_live_range_split = 1;
flag_tree_sra = 1;
flag_tree_copyrename = 1;
flag_tree_fre = 1;

View File

@ -541,6 +541,18 @@ has_single_use (tree var)
return (ptr != ptr->next && ptr == ptr->next->next);
}
/* If VAR has only a single immediate use, return true. */
static inline bool
single_imm_use_p (tree var)
{
ssa_use_operand_t *ptr;
ptr = &(SSA_NAME_IMM_USE_NODE (var));
return (ptr != ptr->next && ptr == ptr->next->next);
}
/* If VAR has only a single immediate use, return true, and set USE_P and STMT
to the use pointer and stmt of occurrence. */
static inline bool

View File

@ -218,8 +218,8 @@ struct var_ann_d GTY(())
been seen yet or not. */
unsigned out_of_ssa_tag : 1;
/* Used when building root_var structures in tree_ssa_live.[ch]. */
unsigned root_var_processed : 1;
/* Used when building base variable structures in a var_map. */
unsigned base_var_processed : 1;
/* Nonzero if this variable is in the alias set of another variable. */
unsigned is_aliased : 1;
@ -257,8 +257,8 @@ struct var_ann_d GTY(())
variable represents storage for. */
unsigned partition;
/* Used by the root-var object in tree-ssa-live.[ch]. */
unsigned root_index;
/* Used by var_map for the base index of ssa base variables. */
unsigned base_index;
/* During into-ssa and the dominator optimizer, this field holds the
current version of this variable (an SSA_NAME). */

View File

@ -1,5 +1,5 @@
/* Convert a program in SSA form into Normal form.
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Andrew Macleod <amacleod@redhat.com>
This file is part of GCC.
@ -24,34 +24,17 @@ Boston, MA 02110-1301, USA. */
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "rtl.h"
#include "tm_p.h"
#include "ggc.h"
#include "langhooks.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
#include "expr.h"
#include "function.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
#include "tree-gimple.h"
#include "tree-inline.h"
#include "varray.h"
#include "timevar.h"
#include "hashtab.h"
#include "tree-dump.h"
#include "tree-ssa-live.h"
#include "tree-pass.h"
#include "toplev.h"
#include "vecprim.h"
/* Flags to pass to remove_ssa_form. */
#define SSANORM_PERFORM_TER 0x1
#define SSANORM_COALESCE_PARTITIONS 0x4
/* Used to hold all the components required to do SSA PHI elimination.
The node and pred/succ list is a simple linear list of nodes and
@ -101,36 +84,6 @@ typedef struct _elim_graph {
} *elim_graph;
/* Local functions. */
static tree create_temp (tree);
static void insert_copy_on_edge (edge, tree, tree);
static elim_graph new_elim_graph (int);
static inline void delete_elim_graph (elim_graph);
static inline void clear_elim_graph (elim_graph);
static inline int elim_graph_size (elim_graph);
static inline void elim_graph_add_node (elim_graph, tree);
static inline void elim_graph_add_edge (elim_graph, int, int);
static inline int elim_graph_remove_succ_edge (elim_graph, int);
static inline void eliminate_name (elim_graph, tree);
static void eliminate_build (elim_graph, basic_block);
static void elim_forward (elim_graph, int);
static int elim_unvisited_predecessor (elim_graph, int);
static void elim_backward (elim_graph, int);
static void elim_create (elim_graph, int);
static void eliminate_phi (edge, elim_graph);
static tree_live_info_p coalesce_ssa_name (var_map, int);
static void assign_vars (var_map);
static bool replace_use_variable (var_map, use_operand_p, tree *);
static bool replace_def_variable (var_map, def_operand_p, tree *);
static void eliminate_virtual_phis (void);
static void coalesce_abnormal_edges (var_map, conflict_graph, root_var_p);
static void print_exprs (FILE *, const char *, tree, const char *, tree,
const char *);
static void print_exprs_edge (FILE *, edge, const char *, tree, const char *,
tree);
/* Create a temporary variable based on the type of variable T. Use T's name
as the prefix. */
@ -489,6 +442,7 @@ elim_create (elim_graph g, int T)
}
/* Eliminate all the phi nodes on edge E in graph G. */
static void
@ -541,407 +495,15 @@ eliminate_phi (edge e, elim_graph g)
}
/* Shortcut routine to print messages to file F of the form:
"STR1 EXPR1 STR2 EXPR2 STR3." */
static void
print_exprs (FILE *f, const char *str1, tree expr1, const char *str2,
tree expr2, const char *str3)
{
fprintf (f, "%s", str1);
print_generic_expr (f, expr1, TDF_SLIM);
fprintf (f, "%s", str2);
print_generic_expr (f, expr2, TDF_SLIM);
fprintf (f, "%s", str3);
}
/* Shortcut routine to print abnormal edge messages to file F of the form:
"STR1 EXPR1 STR2 EXPR2 across edge E. */
static void
print_exprs_edge (FILE *f, edge e, const char *str1, tree expr1,
const char *str2, tree expr2)
{
print_exprs (f, str1, expr1, str2, expr2, " across an abnormal edge");
fprintf (f, " from BB%d->BB%d\n", e->src->index,
e->dest->index);
}
/* Coalesce partitions in MAP which are live across abnormal edges in GRAPH.
RV is the root variable groupings of the partitions in MAP. Since code
cannot be inserted on these edges, failure to coalesce something across
an abnormal edge is an error. */
static void
coalesce_abnormal_edges (var_map map, conflict_graph graph, root_var_p rv)
{
basic_block bb;
edge e;
tree phi, var, tmp;
int x, y, z;
edge_iterator ei;
/* Code cannot be inserted on abnormal edges. Look for all abnormal
edges, and coalesce any PHI results with their arguments across
that edge. */
FOR_EACH_BB (bb)
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->dest != EXIT_BLOCK_PTR && e->flags & EDGE_ABNORMAL)
for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
{
/* Visit each PHI on the destination side of this abnormal
edge, and attempt to coalesce the argument with the result. */
var = PHI_RESULT (phi);
x = var_to_partition (map, var);
/* Ignore results which are not relevant. */
if (x == NO_PARTITION)
continue;
tmp = PHI_ARG_DEF (phi, e->dest_idx);
#ifdef ENABLE_CHECKING
if (!phi_ssa_name_p (tmp))
{
print_exprs_edge (stderr, e,
"\nConstant argument in PHI. Can't insert :",
var, " = ", tmp);
internal_error ("SSA corruption");
}
#else
gcc_assert (phi_ssa_name_p (tmp));
#endif
y = var_to_partition (map, tmp);
gcc_assert (x != NO_PARTITION);
gcc_assert (y != NO_PARTITION);
#ifdef ENABLE_CHECKING
if (root_var_find (rv, x) != root_var_find (rv, y))
{
print_exprs_edge (stderr, e, "\nDifferent root vars: ",
root_var (rv, root_var_find (rv, x)),
" and ",
root_var (rv, root_var_find (rv, y)));
internal_error ("SSA corruption");
}
#else
gcc_assert (root_var_find (rv, x) == root_var_find (rv, y));
#endif
if (x != y)
{
#ifdef ENABLE_CHECKING
if (conflict_graph_conflict_p (graph, x, y))
{
print_exprs_edge (stderr, e, "\n Conflict ",
partition_to_var (map, x),
" and ", partition_to_var (map, y));
internal_error ("SSA corruption");
}
#else
gcc_assert (!conflict_graph_conflict_p (graph, x, y));
#endif
/* Now map the partitions back to their real variables. */
var = partition_to_var (map, x);
tmp = partition_to_var (map, y);
if (dump_file && (dump_flags & TDF_DETAILS))
{
print_exprs_edge (dump_file, e,
"ABNORMAL: Coalescing ",
var, " and ", tmp);
}
z = var_union (map, var, tmp);
#ifdef ENABLE_CHECKING
if (z == NO_PARTITION)
{
print_exprs_edge (stderr, e, "\nUnable to coalesce",
partition_to_var (map, x), " and ",
partition_to_var (map, y));
internal_error ("SSA corruption");
}
#else
gcc_assert (z != NO_PARTITION);
#endif
gcc_assert (z == x || z == y);
if (z == x)
conflict_graph_merge_regs (graph, x, y);
else
conflict_graph_merge_regs (graph, y, x);
}
}
}
/* Coalesce potential copies via PHI arguments. */
static void
coalesce_phi_operands (var_map map, coalesce_list_p cl)
{
basic_block bb;
tree phi;
FOR_EACH_BB (bb)
{
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
tree res = PHI_RESULT (phi);
int p = var_to_partition (map, res);
int x;
if (p == NO_PARTITION)
continue;
for (x = 0; x < PHI_NUM_ARGS (phi); x++)
{
tree arg = PHI_ARG_DEF (phi, x);
int p2;
if (TREE_CODE (arg) != SSA_NAME)
continue;
if (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg))
continue;
p2 = var_to_partition (map, PHI_ARG_DEF (phi, x));
if (p2 != NO_PARTITION)
{
edge e = PHI_ARG_EDGE (phi, x);
add_coalesce (cl, p, p2,
coalesce_cost (EDGE_FREQUENCY (e),
maybe_hot_bb_p (bb),
EDGE_CRITICAL_P (e)));
}
}
}
}
}
/* Coalesce all the result decls together. */
static void
coalesce_result_decls (var_map map, coalesce_list_p cl)
{
unsigned int i, x;
tree var = NULL;
for (i = x = 0; x < num_var_partitions (map); x++)
{
tree p = partition_to_var (map, x);
if (TREE_CODE (SSA_NAME_VAR (p)) == RESULT_DECL)
{
if (var == NULL_TREE)
{
var = p;
i = x;
}
else
add_coalesce (cl, i, x,
coalesce_cost (EXIT_BLOCK_PTR->frequency,
maybe_hot_bb_p (EXIT_BLOCK_PTR),
false));
}
}
}
/* Coalesce matching constraints in asms. */
static void
coalesce_asm_operands (var_map map, coalesce_list_p cl)
{
basic_block bb;
FOR_EACH_BB (bb)
{
block_stmt_iterator bsi;
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
unsigned long noutputs, i;
tree *outputs, link;
if (TREE_CODE (stmt) != ASM_EXPR)
continue;
noutputs = list_length (ASM_OUTPUTS (stmt));
outputs = (tree *) alloca (noutputs * sizeof (tree));
for (i = 0, link = ASM_OUTPUTS (stmt); link;
++i, link = TREE_CHAIN (link))
outputs[i] = TREE_VALUE (link);
for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
{
const char *constraint
= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
tree input = TREE_VALUE (link);
char *end;
unsigned long match;
int p1, p2;
if (TREE_CODE (input) != SSA_NAME && !DECL_P (input))
continue;
match = strtoul (constraint, &end, 10);
if (match >= noutputs || end == constraint)
continue;
if (TREE_CODE (outputs[match]) != SSA_NAME
&& !DECL_P (outputs[match]))
continue;
p1 = var_to_partition (map, outputs[match]);
if (p1 == NO_PARTITION)
continue;
p2 = var_to_partition (map, input);
if (p2 == NO_PARTITION)
continue;
add_coalesce (cl, p1, p2, coalesce_cost (REG_BR_PROB_BASE,
maybe_hot_bb_p (bb),
false));
}
}
}
}
/* Reduce the number of live ranges in MAP. Live range information is
returned if FLAGS indicates that we are combining temporaries, otherwise
NULL is returned. The only partitions which are associated with actual
variables at this point are those which are forced to be coalesced for
various reason. (live on entry, live across abnormal edges, etc.). */
static tree_live_info_p
coalesce_ssa_name (var_map map, int flags)
{
unsigned num, x;
sbitmap live;
root_var_p rv;
tree_live_info_p liveinfo;
conflict_graph graph;
coalesce_list_p cl = NULL;
sbitmap_iterator sbi;
if (num_var_partitions (map) <= 1)
return NULL;
liveinfo = calculate_live_ranges (map);
rv = root_var_init (map);
/* Remove single element variable from the list. */
root_var_compact (rv);
cl = create_coalesce_list (map);
coalesce_phi_operands (map, cl);
coalesce_result_decls (map, cl);
coalesce_asm_operands (map, cl);
/* Build a conflict graph. */
graph = build_tree_conflict_graph (liveinfo, rv, cl);
if (cl)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Before sorting:\n");
dump_coalesce_list (dump_file, cl);
}
sort_coalesce_list (cl);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "\nAfter sorting:\n");
dump_coalesce_list (dump_file, cl);
}
}
/* Put the single element variables back in. */
root_var_decompact (rv);
/* First, coalesce all live on entry variables to their root variable.
This will ensure the first use is coming from the correct location. */
num = num_var_partitions (map);
live = sbitmap_alloc (num);
sbitmap_zero (live);
/* Set 'live' vector to indicate live on entry partitions. */
for (x = 0 ; x < num; x++)
{
tree var = partition_to_var (map, x);
if (gimple_default_def (cfun, SSA_NAME_VAR (var)) == var)
SET_BIT (live, x);
}
delete_tree_live_info (liveinfo);
liveinfo = NULL;
/* Assign root variable as partition representative for each live on entry
partition. */
EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
{
tree var = root_var (rv, root_var_find (rv, x));
var_ann_t ann = var_ann (var);
/* If these aren't already coalesced... */
if (partition_to_var (map, x) != var)
{
/* This root variable should have not already been assigned
to another partition which is not coalesced with this one. */
gcc_assert (!ann->out_of_ssa_tag);
if (dump_file && (dump_flags & TDF_DETAILS))
{
print_exprs (dump_file, "Must coalesce ",
partition_to_var (map, x),
" with the root variable ", var, ".\n");
}
change_partition_var (map, var, x);
}
}
sbitmap_free (live);
/* Coalesce partitions live across abnormal edges. */
coalesce_abnormal_edges (map, graph, rv);
if (dump_file && (dump_flags & TDF_DETAILS))
dump_var_map (dump_file, map);
/* Coalesce partitions. */
coalesce_tpa_members (rv, graph, map, cl,
((dump_flags & TDF_DETAILS) ? dump_file
: NULL));
if (flags & SSANORM_COALESCE_PARTITIONS)
coalesce_tpa_members (rv, graph, map, NULL,
((dump_flags & TDF_DETAILS) ? dump_file
: NULL));
if (cl)
delete_coalesce_list (cl);
root_var_delete (rv);
conflict_graph_delete (graph);
return liveinfo;
}
/* Take the ssa-name var_map MAP, and assign real variables to each
partition. */
static void
assign_vars (var_map map)
{
int x, i, num, rep;
tree t, var;
int x, num;
tree var, root;
var_ann_t ann;
root_var_p rv;
rv = root_var_init (map);
if (!rv)
return;
/* Coalescing may already have forced some partitions to their root
variable. Find these and tag them. */
num = num_var_partitions (map);
for (x = 0; x < num; x++)
@ -949,63 +511,35 @@ assign_vars (var_map map)
var = partition_to_var (map, x);
if (TREE_CODE (var) != SSA_NAME)
{
/* Coalescing will already have verified that more than one
partition doesn't have the same root variable. Simply marked
the variable as assigned. */
ann = var_ann (var);
ann->out_of_ssa_tag = 1;
/* It must already be coalesced. */
gcc_assert (ann->out_of_ssa_tag == 1);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "partition %d has variable ", x);
fprintf (dump_file, "partition %d already has variable ", x);
print_generic_expr (dump_file, var, TDF_SLIM);
fprintf (dump_file, " assigned to it.\n");
}
}
}
num = root_var_num (rv);
for (x = 0; x < num; x++)
{
var = root_var (rv, x);
ann = var_ann (var);
for (i = root_var_first_partition (rv, x);
i != ROOT_VAR_NONE;
i = root_var_next_partition (rv, i))
{
t = partition_to_var (map, i);
if (t == var || TREE_CODE (t) != SSA_NAME)
continue;
rep = var_to_partition (map, t);
if (!ann->out_of_ssa_tag)
else
{
root = SSA_NAME_VAR (var);
ann = var_ann (root);
/* If ROOT is already associated, create a new one. */
if (ann->out_of_ssa_tag)
{
if (dump_file && (dump_flags & TDF_DETAILS))
print_exprs (dump_file, "", t, " --> ", var, "\n");
change_partition_var (map, var, rep);
continue;
root = create_temp (root);
ann = var_ann (root);
}
if (dump_file && (dump_flags & TDF_DETAILS))
print_exprs (dump_file, "", t, " not coalesced with ", var,
"");
var = create_temp (t);
change_partition_var (map, var, rep);
ann = var_ann (var);
/* ROOT has not been coalesced yet, so use it. */
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " --> New temp: '");
print_generic_expr (dump_file, var, TDF_SLIM);
fprintf (dump_file, "'\n");
fprintf (dump_file, "Partition %d is assigned to var ", x);
print_generic_stmt (dump_file, root, TDF_SLIM);
}
change_partition_var (map, root, x);
}
}
root_var_delete (rv);
}
@ -1028,6 +562,7 @@ replace_use_variable (var_map map, use_operand_p p, tree *expr)
{
tree new_expr = GIMPLE_STMT_OPERAND (expr[version], 1);
SET_USE (p, new_expr);
/* Clear the stmt's RHS, or GC might bite us. */
GIMPLE_STMT_OPERAND (expr[version], 1) = NULL_TREE;
return true;
@ -1056,19 +591,9 @@ replace_def_variable (var_map map, def_operand_p def_p, tree *expr)
tree new_var;
tree var = DEF_FROM_PTR (def_p);
/* Check if we are replacing this variable with an expression. */
if (expr)
{
int version = SSA_NAME_VERSION (var);
if (expr[version])
{
tree new_expr = TREE_OPERAND (expr[version], 1);
SET_DEF (def_p, new_expr);
/* Clear the stmt's RHS, or GC might bite us. */
TREE_OPERAND (expr[version], 1) = NULL_TREE;
return true;
}
}
/* Do nothing if we are replacing this variable with an expression. */
if (expr && expr[SSA_NAME_VERSION (var)])
return true;
new_var = var_to_partition_to_var (map, var);
if (new_var)
@ -1144,15 +669,12 @@ rewrite_trees (var_map map, tree *values)
FOR_EACH_BB (bb)
{
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
tree T0 = var_to_partition_to_var (map, PHI_RESULT (phi));
if (T0 == NULL_TREE)
{
int i;
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
{
tree arg = PHI_ARG_DEF (phi, i);
@ -1261,8 +783,10 @@ static edge leader_match = NULL;
/* Pass this function to make_forwarder_block so that all the edges with
matching PENDING_STMT lists to 'curr_stmt_list' get redirected. */
static bool
matching PENDING_STMT lists to 'curr_stmt_list' get redirected. E is the
edge to test for a match. */
static inline bool
same_stmt_list_p (edge e)
{
return (e->aux == (PTR) leader_match) ? true : false;
@ -1270,6 +794,7 @@ same_stmt_list_p (edge e)
/* Return TRUE if S1 and S2 are equivalent copies. */
static inline bool
identical_copies_p (tree s1, tree s2)
{
@ -1293,7 +818,7 @@ identical_copies_p (tree s1, tree s2)
}
/* Compare the PENDING_STMT list for two edges, and return true if the lists
/* Compare the PENDING_STMT list for edges E1 and E2. Return true if the lists
contain the same sequence of copies. */
static inline bool
@ -1380,6 +905,7 @@ analyze_edges_for_bb (basic_block bb)
bsi_commit_one_edge_insert (e, NULL);
return;
}
/* Find out how many edges there are with interesting pending stmts on them.
Commit the stmts on edges we are not interested in. */
FOR_EACH_EDGE (e, ei, bb->preds)
@ -1470,11 +996,9 @@ analyze_edges_for_bb (basic_block bb)
return;
}
if (dump_file)
fprintf (dump_file, "\nOpportunities in BB %d for stmt/block reduction:\n",
bb->index);
/* For each common list, create a forwarding block and issue the stmt's
in that block. */
@ -1601,28 +1125,23 @@ perform_edge_inserts (void)
}
/* Remove the variables specified in MAP from SSA form. FLAGS indicate what
options should be used. */
/* Remove the ssa-names in the current function and translate them into normal
compiler variables. PERFORM_TER is true if Temporary Expression Replacement
should also be used. */
static void
remove_ssa_form (var_map map, int flags)
remove_ssa_form (bool perform_ter)
{
tree_live_info_p liveinfo;
basic_block bb;
tree phi, next;
tree *values = NULL;
var_map map;
/* If we are not combining temps, don't calculate live ranges for variables
with only one SSA version. */
compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
map = coalesce_ssa_name ();
if (dump_file && (dump_flags & TDF_DETAILS))
dump_var_map (dump_file, map);
liveinfo = coalesce_ssa_name (map, flags);
/* Make sure even single occurrence variables are in the list now. */
compact_var_map (map, VARMAP_NORMAL);
/* Return to viewing the variable list as just all reference variables after
coalescing has been performed. */
partition_view_normal (map, false);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@ -1630,7 +1149,7 @@ remove_ssa_form (var_map map, int flags)
dump_var_map (dump_file, map);
}
if (flags & SSANORM_PERFORM_TER)
if (perform_ter)
{
values = find_replaceable_exprs (map);
if (values && dump_file && (dump_flags & TDF_DETAILS))
@ -1642,13 +1161,10 @@ remove_ssa_form (var_map map, int flags)
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "After Root variable replacement:\n");
fprintf (dump_file, "After Base variable replacement:\n");
dump_var_map (dump_file, map);
}
if (liveinfo)
delete_tree_live_info (liveinfo);
rewrite_trees (map, values);
if (values)
@ -1669,8 +1185,11 @@ remove_ssa_form (var_map map, int flags)
/* If any copies were inserted on edges, analyze and insert them now. */
perform_edge_inserts ();
delete_var_map (map);
}
/* Search every PHI node for arguments associated with backedges which
we can trivially determine will need a copy (the argument is either
not an SSA_NAME or the argument has a different underlying variable
@ -1704,11 +1223,10 @@ insert_backedge_copies (void)
tree arg = PHI_ARG_DEF (phi, i);
edge e = PHI_ARG_EDGE (phi, i);
/* If the argument is not an SSA_NAME, then we will
need a constant initialization. If the argument is
an SSA_NAME with a different underlying variable and
we are not combining temporaries, then we will
need a copy statement. */
/* If the argument is not an SSA_NAME, then we will need a
constant initialization. If the argument is an SSA_NAME with
a different underlying variable then a copy statement will be
needed. */
if ((e->flags & EDGE_DFS_BACK)
&& (TREE_CODE (arg) != SSA_NAME
|| SSA_NAME_VAR (arg) != result_var))
@ -1723,7 +1241,6 @@ insert_backedge_copies (void)
/* In theory the only way we ought to get back to the
start of a loop should be with a COND_EXPR or GOTO_EXPR.
However, better safe than sorry.
If the block ends with a control statement or
something that might throw, then we have to
insert this assignment before the last
@ -1738,8 +1255,8 @@ insert_backedge_copies (void)
continue;
}
/* Create a new instance of the underlying
variable of the PHI result. */
/* Create a new instance of the underlying variable of the
PHI result. */
stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (result_var),
NULL_TREE, PHI_ARG_DEF (phi, i));
name = make_ssa_name (result_var, stmt);
@ -1758,16 +1275,13 @@ insert_backedge_copies (void)
}
}
/* Take the current function out of SSA form, as described in
/* Take the current function out of SSA form, translating PHIs as described in
R. Morgan, ``Building an Optimizing Compiler'',
Butterworth-Heinemann, Boston, MA, 1998. pp 176-186. */
static unsigned int
rewrite_out_of_ssa (void)
{
var_map map;
int ssa_flags = 0;
/* If elimination of a PHI requires inserting a copy on a backedge,
then we will have to split the backedge which has numerous
undesirable performance effects.
@ -1776,27 +1290,16 @@ rewrite_out_of_ssa (void)
copies into the loop itself. */
insert_backedge_copies ();
if (!flag_tree_live_range_split)
ssa_flags |= SSANORM_COALESCE_PARTITIONS;
eliminate_virtual_phis ();
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
map = create_ssa_var_map ();
if (flag_tree_ter && !flag_mudflap)
ssa_flags |= SSANORM_PERFORM_TER;
remove_ssa_form (map, ssa_flags);
remove_ssa_form (flag_tree_ter && !flag_mudflap);
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
/* Flush out flow graph and SSA data. */
delete_var_map (map);
cfun->gimple_df->in_ssa_p = false;
return 0;
}

1355
gcc/tree-ssa-coalesce.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,56 +26,83 @@ Boston, MA 02110-1301, USA. */
#include "partition.h"
#include "vecprim.h"
/* Used to create the variable mapping when we go out of SSA form. */
/* Used to create the variable mapping when we go out of SSA form.
Mapping from an ssa_name to a partition number is maintained, as well as
partition number to back to ssa_name. A parition can also be represented
by a non-ssa_name variable. This allows ssa_names and thier partition to
be coalesced with live on entry compiler variables, as well as eventually
having real compiler variables assigned to each partition as part of the
final stage of going of of ssa.
Non-ssa_names maintain their partition index in the variable annotation.
This data structure also supports "views", which work on a subset of all
partitions. This allows the coalescer to decide what partitions are
interesting to it, and only work with those partitions. Whenever the view
is changed, the partition numbers change, but none of the partition groupings
change. (ie, it is truly a view since it doesnt change anything)
The final component of the data structure is the basevar map. This provides
a list of all the different base variables which occue in a partition view,
and a unique index for each one. Routines are provided to quickly produce
the base variable of a partition.
Note that members of a partition MUST all have the same base variable. */
typedef struct _var_map
{
/* The partition of all variables. */
/* The partition manager of all variables. */
partition var_partition;
/* Vector for compacting partitions. */
int *partition_to_compact;
int *compact_to_partition;
/* Vector for managing partitions views. */
int *partition_to_view;
int *view_to_partition;
/* Mapping of partition numbers to vars. */
/* Mapping of partition numbers to variables. */
tree *partition_to_var;
/* Current number of partitions. */
/* Current number of partitions in var_map based on the current view. */
unsigned int num_partitions;
/* Original partition size. */
/* Original full partition size. */
unsigned int partition_size;
/* Number of base variables in the base var list. */
int num_basevars;
/* Map of partitions numbers to base variable table indexes. */
int *partition_to_base_index;
/* Table of base variable's. */
VEC (tree, heap) *basevars;
} *var_map;
/* Partition number of a non ssa-name variable. */
#define VAR_ANN_PARTITION(ann) (ann->partition)
#define VAR_ANN_ROOT_INDEX(ann) (ann->root_index)
/* Index iot the basevar table of a non ssa-name variable. */
#define VAR_ANN_BASE_INDEX(ann) (ann->base_index)
/* Value used to represent no partition number. */
#define NO_PARTITION -1
/* Flags to pass to compact_var_map */
#define VARMAP_NORMAL 0
#define VARMAP_NO_SINGLE_DEFS 1
extern var_map init_var_map (int);
extern void delete_var_map (var_map);
extern void dump_var_map (FILE *, var_map);
extern int var_union (var_map, tree, tree);
extern void change_partition_var (var_map, tree, int);
extern void compact_var_map (var_map, int);
extern void partition_view_normal (var_map, bool);
extern void partition_view_bitmap (var_map, bitmap, bool);
#ifdef ENABLE_CHECKING
extern void register_ssa_partition_check (tree ssa_var);
#endif
static inline unsigned num_var_partitions (var_map);
static inline tree var_to_partition_to_var (var_map, tree);
static inline tree partition_to_var (var_map, int);
static inline int var_to_partition (var_map, tree);
static inline tree version_to_var (var_map, int);
static inline void register_ssa_partition (var_map, tree);
extern var_map create_ssa_var_map (void);
/* Number of partitions in MAP. */
/* Return number of partitions in MAP. */
static inline unsigned
num_var_partitions (var_map map)
@ -90,8 +117,8 @@ num_var_partitions (var_map map)
static inline tree
partition_to_var (var_map map, int i)
{
if (map->compact_to_partition)
i = map->compact_to_partition[i];
if (map->view_to_partition)
i = map->view_to_partition[i];
i = partition_find (map->var_partition, i);
return map->partition_to_var[i];
}
@ -100,12 +127,13 @@ partition_to_var (var_map map, int i)
/* Given ssa_name VERSION, if it has a partition in MAP, return the var it
is associated with. Otherwise return NULL. */
static inline tree version_to_var (var_map map, int version)
static inline tree
version_to_var (var_map map, int version)
{
int part;
part = partition_find (map->var_partition, version);
if (map->partition_to_compact)
part = map->partition_to_compact[part];
if (map->partition_to_view)
part = map->partition_to_view[part];
if (part == NO_PARTITION)
return NULL_TREE;
@ -125,8 +153,8 @@ var_to_partition (var_map map, tree var)
if (TREE_CODE (var) == SSA_NAME)
{
part = partition_find (map->var_partition, SSA_NAME_VERSION (var));
if (map->partition_to_compact)
part = map->partition_to_compact[part];
if (map->partition_to_view)
part = map->partition_to_view[part];
}
else
{
@ -155,9 +183,29 @@ var_to_partition_to_var (var_map map, tree var)
}
/* This routine registers a partition for SSA_VAR with MAP. IS_USE is used
to count references. Any unregistered partitions may be compacted out
later. */
/* Return the index into the basevar table for PARTITION's base in MAP. */
static inline int
basevar_index (var_map map, int partition)
{
gcc_assert (partition >= 0
&& partition <= (int) num_var_partitions (map));
return map->partition_to_base_index[partition];
}
/* Return the number of different base variables in MAP. */
static inline int
num_basevars (var_map map)
{
return map->num_basevars;
}
/* This routine registers a partition for SSA_VAR with MAP. Any unregistered
partitions may be filtered out by a view later. */
static inline void
register_ssa_partition (var_map map, tree ssa_var)
@ -170,7 +218,7 @@ register_ssa_partition (var_map map, tree ssa_var)
version = SSA_NAME_VERSION (ssa_var);
if (map->partition_to_var[version] == NULL_TREE)
map->partition_to_var[SSA_NAME_VERSION (ssa_var)] = ssa_var;
map->partition_to_var[version] = ssa_var;
}
@ -238,13 +286,6 @@ extern void delete_tree_live_info (tree_live_info_p);
#define LIVEDUMP_ALL (LIVEDUMP_ENTRY | LIVEDUMP_EXIT)
extern void dump_live_info (FILE *, tree_live_info_p, int);
static inline int partition_is_global (tree_live_info_p, int);
static inline bitmap live_on_entry (tree_live_info_p, basic_block);
static inline bitmap live_on_exit (tree_live_info_p, basic_block);
static inline var_map live_var_map (tree_live_info_p);
static inline void live_merge_and_clear (tree_live_info_p, int, int);
static inline void make_live_on_entry (tree_live_info_p, basic_block, int);
/* Return TRUE if P is marked as a global in LIVE. */
@ -316,275 +357,9 @@ make_live_on_entry (tree_live_info_p live, basic_block bb , int p)
}
/* A tree_partition_associator (TPA)object is a base structure which allows
partitions to be associated with a tree object.
/* From tree-ssa-coalesce.c */
extern var_map coalesce_ssa_name (void);
A varray of tree elements represent each distinct tree item.
A parallel int array represents the first partition number associated with
the tree.
This partition number is then used as in index into the next_partition
array, which returns the index of the next partition which is associated
with the tree. TPA_NONE indicates the end of the list.
A varray paralleling the partition list 'partition_to_tree_map' is used
to indicate which tree index the partition is in. */
typedef struct tree_partition_associator_d
{
VEC(tree,heap) *trees;
VEC(int,heap) *first_partition;
int *next_partition;
int *partition_to_tree_map;
int num_trees;
int uncompressed_num;
var_map map;
} *tpa_p;
/* Value returned when there are no more partitions associated with a tree. */
#define TPA_NONE -1
static inline tree tpa_tree (tpa_p, int);
static inline int tpa_first_partition (tpa_p, int);
static inline int tpa_next_partition (tpa_p, int);
static inline int tpa_num_trees (tpa_p);
static inline int tpa_find_tree (tpa_p, int);
static inline void tpa_decompact (tpa_p);
extern void tpa_delete (tpa_p);
extern void tpa_dump (FILE *, tpa_p);
extern void tpa_remove_partition (tpa_p, int, int);
extern int tpa_compact (tpa_p);
/* Return the number of distinct tree nodes in TPA. */
static inline int
tpa_num_trees (tpa_p tpa)
{
return tpa->num_trees;
}
/* Return the tree node for index I in TPA. */
static inline tree
tpa_tree (tpa_p tpa, int i)
{
return VEC_index (tree, tpa->trees, i);
}
/* Return the first partition associated with tree list I in TPA. */
static inline int
tpa_first_partition (tpa_p tpa, int i)
{
return VEC_index (int, tpa->first_partition, i);
}
/* Return the next partition after partition I in TPA's list. */
static inline int
tpa_next_partition (tpa_p tpa, int i)
{
return tpa->next_partition[i];
}
/* Return the tree index from TPA whose list contains partition I.
TPA_NONE is returned if I is not associated with any list. */
static inline int
tpa_find_tree (tpa_p tpa, int i)
{
int index;
index = tpa->partition_to_tree_map[i];
/* When compressed, any index higher than the number of tree elements is
a compressed element, so return TPA_NONE. */
if (index != TPA_NONE && index >= tpa_num_trees (tpa))
{
gcc_assert (tpa->uncompressed_num != -1);
index = TPA_NONE;
}
return index;
}
/* This function removes any compaction which was performed on TPA. */
static inline void
tpa_decompact(tpa_p tpa)
{
gcc_assert (tpa->uncompressed_num != -1);
tpa->num_trees = tpa->uncompressed_num;
}
/* Once a var_map has been created and compressed, a complementary root_var
object can be built. This creates a list of all the root variables from
which ssa version names are derived. Each root variable has a list of
which partitions are versions of that root.
This is implemented using the tree_partition_associator.
The tree vector is used to represent the root variable.
The list of partitions represent SSA versions of the root variable. */
typedef tpa_p root_var_p;
static inline tree root_var (root_var_p, int);
static inline int root_var_first_partition (root_var_p, int);
static inline int root_var_next_partition (root_var_p, int);
static inline int root_var_num (root_var_p);
static inline void root_var_dump (FILE *, root_var_p);
static inline void root_var_remove_partition (root_var_p, int, int);
static inline void root_var_delete (root_var_p);
static inline int root_var_find (root_var_p, int);
static inline int root_var_compact (root_var_p);
static inline void root_var_decompact (tpa_p);
extern root_var_p root_var_init (var_map);
/* Value returned when there are no more partitions associated with a root
variable. */
#define ROOT_VAR_NONE TPA_NONE
/* Return the number of distinct root variables in RV. */
static inline int
root_var_num (root_var_p rv)
{
return tpa_num_trees (rv);
}
/* Return root variable I from RV. */
static inline tree
root_var (root_var_p rv, int i)
{
return tpa_tree (rv, i);
}
/* Return the first partition in RV belonging to root variable list I. */
static inline int
root_var_first_partition (root_var_p rv, int i)
{
return tpa_first_partition (rv, i);
}
/* Return the next partition after partition I in a root list from RV. */
static inline int
root_var_next_partition (root_var_p rv, int i)
{
return tpa_next_partition (rv, i);
}
/* Send debug info for root_var list RV to file F. */
static inline void
root_var_dump (FILE *f, root_var_p rv)
{
fprintf (f, "\nRoot Var dump\n");
tpa_dump (f, rv);
fprintf (f, "\n");
}
/* Destroy root_var object RV. */
static inline void
root_var_delete (root_var_p rv)
{
tpa_delete (rv);
}
/* Remove partition PARTITION_INDEX from root_var list ROOT_INDEX in RV. */
static inline void
root_var_remove_partition (root_var_p rv, int root_index, int partition_index)
{
tpa_remove_partition (rv, root_index, partition_index);
}
/* Return the root_var list index for partition I in RV. */
static inline int
root_var_find (root_var_p rv, int i)
{
return tpa_find_tree (rv, i);
}
/* Hide single element lists in RV. */
static inline int
root_var_compact (root_var_p rv)
{
return tpa_compact (rv);
}
/* Expose the single element lists in RV. */
static inline void
root_var_decompact (root_var_p rv)
{
tpa_decompact (rv);
}
/* This set of routines implements a coalesce_list. This is an object which
is used to track pairs of partitions which are desirable to coalesce
together at some point. Costs are associated with each pair, and when
all desired information has been collected, the object can be used to
order the pairs for processing. */
/* This structure defines a pair entry. */
typedef struct partition_pair
{
int first_partition;
int second_partition;
int cost;
} * partition_pair_p;
extern unsigned int partition_pair_map_hash (const void *);
extern int partition_pair_map_eq (const void *, const void *);
/* This structure maintains the list of coalesce pairs. */
typedef struct coalesce_list_d
{
var_map map;
htab_t list;
partition_pair_p *sorted;
int num_sorted;
bool add_mode;
} *coalesce_list_p;
extern coalesce_list_p create_coalesce_list (var_map);
extern void add_coalesce (coalesce_list_p, int, int, int);
extern int coalesce_cost (int, bool, bool);
extern void sort_coalesce_list (coalesce_list_p);
extern void dump_coalesce_list (FILE *, coalesce_list_p);
extern void delete_coalesce_list (coalesce_list_p);
#define NO_BEST_COALESCE -1
extern conflict_graph build_tree_conflict_graph (tree_live_info_p, tpa_p,
coalesce_list_p);
extern void coalesce_tpa_members (tpa_p tpa, conflict_graph graph, var_map map,
coalesce_list_p cl, FILE *);
/* From tree-ssa-ter.c */
extern tree *find_replaceable_exprs (var_map);

View File

@ -25,29 +25,11 @@ Boston, MA 02110-1301, USA. */
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "rtl.h"
#include "tm_p.h"
#include "ggc.h"
#include "langhooks.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
#include "expr.h"
#include "function.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
#include "tree-gimple.h"
#include "tree-inline.h"
#include "varray.h"
#include "timevar.h"
#include "hashtab.h"
#include "tree-dump.h"
#include "tree-ssa-live.h"
#include "tree-pass.h"
#include "toplev.h"
#include "vecprim.h"
/* Temporary Expression Replacement (TER)