New out of ssa Coalescer.
authorAndrew MacLeod <amacleod@redhat.com>
Sun, 10 Dec 2006 21:25:40 +0000 (21:25 +0000)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Sun, 10 Dec 2006 21:25:40 +0000 (21:25 +0000)
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

gcc/ChangeLog
gcc/Makefile.in
gcc/common.opt
gcc/opts.c
gcc/tree-flow-inline.h
gcc/tree-flow.h
gcc/tree-outof-ssa.c
gcc/tree-ssa-coalesce.c [new file with mode: 0644]
gcc/tree-ssa-live.c
gcc/tree-ssa-live.h
gcc/tree-ssa-ter.c

index b984524..60ff40a 100644 (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.
index bf954eb..8da131d 100644 (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) \
index 2251b86..7ec6f47 100644 (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
index da16f7b..b31d67d 100644 (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;
index f19faa1..bc4c394 100644 (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
index b3aa655..bb6b4ae 100644 (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).  */
index 5edea64..f591eb5 100644 (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);
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    dump_var_map (dump_file, map);
-
-  liveinfo = coalesce_ssa_name (map, flags);
+  map = coalesce_ssa_name ();
 
-  /* 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;
 }
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
new file mode 100644 (file)
index 0000000..0079361
--- /dev/null
@@ -0,0 +1,1355 @@
+/* Coalesce SSA_NAMES together for the out-of-ssa pass.
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+   Contributed by Andrew MacLeod <amacleod@redhat.com>
+
+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 "tm.h"
+#include "tree.h"
+#include "flags.h"
+#include "diagnostic.h"
+#include "bitmap.h"
+#include "tree-flow.h"
+#include "hashtab.h"
+#include "tree-dump.h"
+#include "tree-ssa-live.h"
+#include "toplev.h"
+
+
+/* This set of routines implements a coalesce_list.  This is an object which
+   is used to track pairs of ssa_names which are desirable to coalesce
+   together to avoid copies.  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 coalesce_pair
+{
+  int first_element;
+  int second_element;
+  int cost;
+} * coalesce_pair_p;
+
+typedef struct cost_one_pair_d
+{
+  int first_element;
+  int second_element;
+  struct cost_one_pair_d *next;
+} * cost_one_pair_p;
+
+/* This structure maintains the list of coalesce pairs.  */
+
+typedef struct coalesce_list_d 
+{
+  htab_t list;                 /* Hash table.  */
+  coalesce_pair_p *sorted;     /* List when sorted.  */
+  int num_sorted;              /* Number in the sorted list.  */
+  cost_one_pair_p cost_one_list;/* Single use coalesces with cost 1.  */
+} *coalesce_list_p;
+
+#define NO_BEST_COALESCE       -1
+#define MUST_COALESCE_COST     INT_MAX
+
+
+/* Return cost of execution of copy instruction with FREQUENCY
+   possibly on CRITICAL edge and in HOT basic block.  */
+
+static inline int
+coalesce_cost (int frequency, bool hot, bool critical)
+{
+  /* Base costs on BB frequencies bounded by 1.  */
+  int cost = frequency;
+
+  if (!cost)
+    cost = 1;
+
+  if (optimize_size)
+    cost = 1;
+  else
+    /* It is more important to coalesce in HOT blocks.  */
+    if (hot)
+      cost *= 2;
+
+  /* Inserting copy on critical edge costs more than inserting it elsewhere.  */
+  if (critical)
+    cost *= 2;
+  return cost;
+}
+
+
+/* Return the cost of executing a copy instruction in basic block BB.  */
+
+static inline int 
+coalesce_cost_bb (basic_block bb)
+{
+  return coalesce_cost (bb->frequency, maybe_hot_bb_p (bb), false);
+}
+
+
+/* Return the cost of executing a copy instruction on edge E.  */
+
+static inline int 
+coalesce_cost_edge (edge e)
+{
+  if (e->flags & EDGE_ABNORMAL)
+    return MUST_COALESCE_COST;
+
+  return coalesce_cost (EDGE_FREQUENCY (e), 
+                       maybe_hot_bb_p (e->src), 
+                       EDGE_CRITICAL_P (e));
+}
+
+
+/* Retrieve a pair to coalesce from the cost_one_list in CL.  Returns the 
+   2 elements via P1 and P2.  1 is returned by the function if there is a pair,
+   NO_BEST_COALESCE is returned if there aren't any.  */
+
+static inline int
+pop_cost_one_pair (coalesce_list_p cl, int *p1, int *p2)
+{
+  cost_one_pair_p ptr;
+
+  ptr = cl->cost_one_list;
+  if (!ptr)
+    return NO_BEST_COALESCE;
+
+  *p1 = ptr->first_element;
+  *p2 = ptr->second_element;
+  cl->cost_one_list = ptr->next;
+
+  free (ptr);
+
+  return 1;
+}
+
+/* Retrieve the most expensive remaining pair to coalesce from CL.  Returns the 
+   2 elements via P1 and P2.  Their calculated cost is returned by the function.
+   NO_BEST_COALESCE is returned if the coalesce list is empty.  */
+
+static inline int
+pop_best_coalesce (coalesce_list_p cl, int *p1, int *p2)
+{
+  coalesce_pair_p node;
+  int ret;
+
+  if (cl->sorted == NULL)
+    return pop_cost_one_pair (cl, p1, p2);
+
+  if (cl->num_sorted == 0)
+    return pop_cost_one_pair (cl, p1, p2);
+
+  node = cl->sorted[--(cl->num_sorted)];
+  *p1 = node->first_element;
+  *p2 = node->second_element;
+  ret = node->cost;
+  free (node);
+
+  return ret;
+}
+
+
+#define COALESCE_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
+
+/* Hash function for coalesce list.  Calculate hash for PAIR.   */
+
+static unsigned int 
+coalesce_pair_map_hash (const void *pair)
+{
+  hashval_t a = (hashval_t)(((coalesce_pair_p)pair)->first_element);
+  hashval_t b = (hashval_t)(((coalesce_pair_p)pair)->second_element);
+
+  return COALESCE_HASH_FN (a,b);
+}
+
+
+/* Equality function for coalesce list hash table.  Compare PAIR1 and PAIR2,
+   returning TRUE if the two pairs are equivilent. */
+
+static int 
+coalesce_pair_map_eq (const void *pair1, const void *pair2)
+{
+  coalesce_pair_p p1 = (coalesce_pair_p) pair1;
+  coalesce_pair_p p2 = (coalesce_pair_p) pair2;
+
+  return (p1->first_element == p2->first_element
+         && p1->second_element == p2->second_element);
+}
+
+
+/* Create a new empty coalesce list object and return it.  */
+
+static inline coalesce_list_p 
+create_coalesce_list (void)
+{
+  coalesce_list_p list;
+  unsigned size = num_ssa_names * 3;
+
+  if (size < 40) 
+    size = 40;
+
+  list = (coalesce_list_p) xmalloc (sizeof (struct coalesce_list_d));
+  list->list = htab_create (size, coalesce_pair_map_hash,
+                           coalesce_pair_map_eq, NULL);
+  list->sorted = NULL;
+  list->num_sorted = 0;
+  list->cost_one_list = NULL;
+  return list;
+}
+
+
+/* Delete coalesce list CL.  */
+
+static inline void 
+delete_coalesce_list (coalesce_list_p cl)
+{
+  gcc_assert (cl->cost_one_list == NULL);
+  htab_delete (cl->list);
+  if (cl->sorted)
+    free (cl->sorted);
+  gcc_assert (cl->num_sorted == 0);
+  free (cl);
+}
+
+
+/* Find a matching coalesce pair object in CL for the pair P1 and P2.  If 
+   one isn't found, return NULL if CREATE is false, otherwise create a new 
+   coalesce pair object and return it.  */
+
+static coalesce_pair_p
+find_coalesce_pair (coalesce_list_p cl, int p1, int p2, bool create)
+{
+  struct coalesce_pair p, *pair;
+  void **slot;
+  unsigned int hash;
+    
+  /* Normalize so that p1 is the smaller value.  */
+  if (p2 < p1)
+    {
+      p.first_element = p2;
+      p.second_element = p1;
+    }
+  else
+    {
+      p.first_element = p1;
+      p.second_element = p2;
+    }
+  
+  
+  hash = coalesce_pair_map_hash (&p);
+  pair = (struct coalesce_pair *) htab_find_with_hash (cl->list, &p, hash);
+
+  if (create && !pair)
+    {
+      gcc_assert (cl->sorted == NULL);
+      pair = xmalloc (sizeof (struct coalesce_pair));
+      pair->first_element = p.first_element;
+      pair->second_element = p.second_element;
+      pair->cost = 0;
+      slot = htab_find_slot_with_hash (cl->list, pair, hash, INSERT);
+      *(struct coalesce_pair **)slot = pair;
+    }
+
+  return pair;
+}
+
+static inline void
+add_cost_one_coalesce (coalesce_list_p cl, int p1, int p2)
+{
+  cost_one_pair_p pair;
+
+  pair = xmalloc (sizeof (struct cost_one_pair_d));
+  pair->first_element = p1;
+  pair->second_element = p2;
+  pair->next = cl->cost_one_list;
+  cl->cost_one_list = pair;
+}
+
+
+/* Add a coalesce between P1 and P2 in list CL with a cost of VALUE.  */
+
+static inline void 
+add_coalesce (coalesce_list_p cl, int p1, int p2,
+             int value)
+{
+  coalesce_pair_p node;
+
+  gcc_assert (cl->sorted == NULL);
+  if (p1 == p2)
+    return;
+
+  node = find_coalesce_pair (cl, p1, p2, true);
+
+  /* Once the value is MUST_COALESCE_COST, leave it that way.  */
+  if (node->cost != MUST_COALESCE_COST)
+    {
+      if (value == MUST_COALESCE_COST)
+       node->cost = value;
+      else
+       node->cost += value;
+    }
+}
+
+
+/* Comparison function to allow qsort to sort P1 and P2 in Ascendiong order.  */
+
+static int 
+compare_pairs (const void *p1, const void *p2)
+{
+  return (*(coalesce_pair_p *)p1)->cost - (*(coalesce_pair_p *)p2)->cost;
+}
+
+
+/* Return the number of unique coalesce pairs in CL.  */
+
+static inline int
+num_coalesce_pairs (coalesce_list_p cl)
+{
+  return htab_elements (cl->list);
+}
+
+
+/* Iterator over hash table pairs.  */
+typedef struct
+{
+  htab_iterator hti;
+} coalesce_pair_iterator;
+
+
+/* Return first partition pair from list CL, initializing iterator ITER.  */
+
+static inline coalesce_pair_p
+first_coalesce_pair (coalesce_list_p cl, coalesce_pair_iterator *iter)
+{
+  coalesce_pair_p pair;
+
+  pair = (coalesce_pair_p) first_htab_element (&(iter->hti), cl->list);
+  return pair;
+}
+
+
+/* Return TRUE if there are no more partitions in for ITER to process.  */
+
+static inline bool
+end_coalesce_pair_p (coalesce_pair_iterator *iter)
+{
+  return end_htab_p (&(iter->hti));
+}
+
+
+/* Return the next parttition pair to be visited by ITER.  */
+
+static inline coalesce_pair_p
+next_coalesce_pair (coalesce_pair_iterator *iter)
+{
+  coalesce_pair_p pair;
+
+  pair = (coalesce_pair_p) next_htab_element (&(iter->hti));
+  return pair;
+}
+
+
+/* Iterate over CL using ITER, returning values in PAIR.  */
+
+#define FOR_EACH_PARTITION_PAIR(PAIR, ITER, CL)                \
+  for ((PAIR) = first_coalesce_pair ((CL), &(ITER));   \
+       !end_coalesce_pair_p (&(ITER));                 \
+       (PAIR) = next_coalesce_pair (&(ITER)))
+
+
+/* Prepare CL for removal of preferred pairs.  When finished they are sorted
+   in order from most important coalesce to least important.  */
+
+static void
+sort_coalesce_list (coalesce_list_p cl)
+{
+  unsigned x, num;
+  coalesce_pair_p p;
+  coalesce_pair_iterator ppi;
+
+  gcc_assert (cl->sorted == NULL);
+
+  num = num_coalesce_pairs (cl);
+  cl->num_sorted = num;
+  if (num == 0)
+    return;
+
+  /* Allocate a vector for the pair pointers.  */
+  cl->sorted = XNEWVEC (coalesce_pair_p, num);
+
+  /* Populate the vector with pointers to the pairs.  */
+  x = 0;
+  FOR_EACH_PARTITION_PAIR (p, ppi, cl)
+    cl->sorted[x++] = p;
+  gcc_assert (x == num);
+
+  /* Already sorted.  */
+  if (num == 1)
+    return;
+
+  /* If there are only 2, just pick swap them if the order isn't correct.  */
+  if (num == 2)
+    {
+      if (cl->sorted[0]->cost > cl->sorted[1]->cost)
+        {
+         p = cl->sorted[0];
+         cl->sorted[0] = cl->sorted[1];
+         cl->sorted[1] = p;
+       }
+      return;
+    }
+
+  /* Only call qsort if there are more than 2 items.  */
+  if (num > 2)
+      qsort (cl->sorted, num, sizeof (coalesce_pair_p), compare_pairs);
+}
+
+
+/* Send debug info for coalesce list CL to file F.  */
+
+static void 
+dump_coalesce_list (FILE *f, coalesce_list_p cl)
+{
+  coalesce_pair_p node;
+  coalesce_pair_iterator ppi;
+  int x;
+  tree var;
+
+  if (cl->sorted == NULL)
+    {
+      fprintf (f, "Coalesce List:\n");
+      FOR_EACH_PARTITION_PAIR (node, ppi, cl)
+        {
+         tree var1 = ssa_name (node->first_element);
+         tree var2 = ssa_name (node->second_element);
+         print_generic_expr (f, var1, TDF_SLIM);
+         fprintf (f, " <-> ");
+         print_generic_expr (f, var2, TDF_SLIM);
+         fprintf (f, "  (%1d), ", node->cost);
+         fprintf (f, "\n");
+       }
+    }
+  else
+    {
+      fprintf (f, "Sorted Coalesce list:\n");
+      for (x = cl->num_sorted - 1 ; x >=0; x--)
+        {
+         node = cl->sorted[x];
+         fprintf (f, "(%d) ", node->cost);
+         var = ssa_name (node->first_element);
+         print_generic_expr (f, var, TDF_SLIM);
+         fprintf (f, " <-> ");
+         var = ssa_name (node->second_element);
+         print_generic_expr (f, var, TDF_SLIM);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+
+/* This represents a conflict graph.  Implemented as an array of bitmaps.  
+   A full matrix isused for conflicts rather than just upper triangular form.
+   this make sit much simpler and faster to perform conflict merges.  */
+
+typedef struct ssa_conflicts_d
+{
+  unsigned size;
+  bitmap *conflicts;
+} * ssa_conflicts_p;
+
+
+/* Return a empty new conflict graph for SIZE elements.  */
+
+static inline ssa_conflicts_p
+ssa_conflicts_new (unsigned size)
+{
+  ssa_conflicts_p ptr;
+
+  ptr = XNEW (struct ssa_conflicts_d);
+  ptr->conflicts = XCNEWVEC (bitmap, size);
+  ptr->size = size;
+  return ptr;
+}
+
+
+/* Free storage for conflict graph PTR.  */
+
+static inline void
+ssa_conflicts_delete (ssa_conflicts_p ptr)
+{
+  unsigned x;
+  for (x = 0; x < ptr->size; x++)
+    if (ptr->conflicts[x])
+      BITMAP_FREE (ptr->conflicts[x]);
+
+  free (ptr->conflicts);
+  free (ptr);
+}
+
+
+/* Test if elements X and Y conflict in graph PTR.  */
+
+static inline bool
+ssa_conflicts_test_p (ssa_conflicts_p ptr, unsigned x, unsigned y)
+{
+  bitmap b;
+
+#ifdef ENABLE_CHECKING
+  gcc_assert (x < ptr->size);
+  gcc_assert (y < ptr->size);
+  gcc_assert (x != y);
+#endif
+
+  b = ptr->conflicts[x];
+  if (b)
+    /* Avoid the lookup if Y has no conflicts.  */
+    return ptr->conflicts[y] ? bitmap_bit_p (b, y) : false;
+  else
+    return false;
+}
+
+
+/* Add a conflict with Y to the bitmap for X in graph PTR.  */
+
+static inline void
+ssa_conflicts_add_one (ssa_conflicts_p ptr, unsigned x, unsigned y)
+{
+  /* If there are no conflicts yet, allocate the bitmap and set bit.  */
+  if (!ptr->conflicts[x])
+    ptr->conflicts[x] = BITMAP_ALLOC (NULL);
+  bitmap_set_bit (ptr->conflicts[x], y);
+}
+
+
+/* Add conflicts between X and Y in graph PTR.  */
+
+static inline void
+ssa_conflicts_add (ssa_conflicts_p ptr, unsigned x, unsigned y)
+{
+#ifdef ENABLE_CHECKING
+  gcc_assert (x < ptr->size);
+  gcc_assert (y < ptr->size);
+  gcc_assert (x != y);
+#endif
+  ssa_conflicts_add_one (ptr, x, y);
+  ssa_conflicts_add_one (ptr, y, x);
+}
+
+
+/* Merge all Y's conflict into X in graph PTR.  */
+
+static inline void
+ssa_conflicts_merge (ssa_conflicts_p ptr, unsigned x, unsigned y)
+{
+  unsigned z;
+  bitmap_iterator bi;
+
+  gcc_assert (x != y);
+  if (!(ptr->conflicts[y]))
+    return;
+
+  /* Add a conflict between X and every one Y has.  If the bitmap doesn't
+     exist, then it has already been coalesced, and we dont need to add a 
+     conflict.  */
+  EXECUTE_IF_SET_IN_BITMAP (ptr->conflicts[y], 0, z, bi)
+    if (ptr->conflicts[z])
+      bitmap_set_bit (ptr->conflicts[z], x);
+
+  if (ptr->conflicts[x])
+    {
+      /* If X has conflicts, add Y's to X.  */
+      bitmap_ior_into (ptr->conflicts[x], ptr->conflicts[y]);
+      BITMAP_FREE (ptr->conflicts[y]);
+    }
+  else
+    {
+      /* If X has no conflicts, simply use Y's.  */
+      ptr->conflicts[x] = ptr->conflicts[y];
+      ptr->conflicts[y] = NULL;
+    }
+}
+
+
+/* This structure is used to efficiently record the current status of live 
+   SSA_NAMES when building a conflict graph.  
+   LIVE_BASE_VAR has a bit set for each base variable which has at least one
+   ssa version live.
+   LIVE_BASE_PARTITIONS is an array of bitmaps using the basevar table as an 
+   index, and is used to track what partitions of each base variable are 
+   live.  This makes it easy to add conflicts between just live partitions 
+   with the same base variable.  
+   The values in LIVE_BASE_PARTITIONS are only valid if the base variable is 
+   marked as being live.  This delays clearing of these bitmaps until
+   they are actually needed again.  */
+
+typedef struct live_track_d
+{
+  bitmap live_base_var;                /* Indicates if a basevar is live.  */
+  bitmap *live_base_partitions;        /* Live partitions for each basevar.  */
+  var_map map;                 /* Var_map being used for partition mapping.  */
+} * live_track_p;
+
+
+/* This routine will create a new live track structure based on the partitions
+   in MAP.  */
+
+static live_track_p
+new_live_track (var_map map)
+{
+  live_track_p ptr;
+  int lim, x;
+
+  /* Make sure there is a partition view in place.  */
+  gcc_assert (map->partition_to_base_index != NULL);
+
+  ptr = (live_track_p) xmalloc (sizeof (struct live_track_d));
+  ptr->map = map;
+  lim = num_basevars (map);
+  ptr->live_base_partitions = (bitmap *) xmalloc(sizeof (bitmap *) * lim);
+  ptr->live_base_var = BITMAP_ALLOC (NULL);
+  for (x = 0; x < lim; x++)
+    ptr->live_base_partitions[x] = BITMAP_ALLOC (NULL);
+  return ptr;
+}
+
+
+/* This routine will free the memory associated with PTR.  */
+
+static void
+delete_live_track (live_track_p ptr)
+{
+  int x, lim;
+
+  lim = num_basevars (ptr->map);
+  for (x = 0; x < lim; x++)
+    BITMAP_FREE (ptr->live_base_partitions[x]);
+  BITMAP_FREE (ptr->live_base_var);
+  free (ptr->live_base_partitions);
+  free (ptr);
+}
+
+
+/* This function will remove PARTITION from the live list in PTR.  */
+
+static inline void
+live_track_remove_partition (live_track_p ptr, int partition)
+{
+  int root;
+
+  root = basevar_index (ptr->map, partition);
+  bitmap_clear_bit (ptr->live_base_partitions[root], partition);
+  /* If the element list is empty, make the base variable not live either.  */
+  if (bitmap_empty_p (ptr->live_base_partitions[root]))
+    bitmap_clear_bit (ptr->live_base_var, root);
+}
+
+
+/* This function will adds PARTITION to the live list in PTR.  */
+
+static inline void
+live_track_add_partition (live_track_p ptr, int partition)
+{
+  int root;
+
+  root = basevar_index (ptr->map, partition);
+  /* If this base var wasn't live before, it is now.  Clear the element list 
+     since it was delayed until needed.  */
+  if (!bitmap_bit_p (ptr->live_base_var, root))
+    {
+      bitmap_set_bit (ptr->live_base_var, root);
+      bitmap_clear (ptr->live_base_partitions[root]);
+    }
+  bitmap_set_bit (ptr->live_base_partitions[root], partition);
+    
+}
+
+
+/* Clear the live bit for VAR in PTR.  */
+
+static inline void
+live_track_clear_var (live_track_p ptr, tree var)
+{
+  int p;
+
+  p = var_to_partition (ptr->map, var);
+  if (p != NO_PARTITION)
+    live_track_remove_partition (ptr, p);
+}
+
+
+/* Return TRUE if VAR is live in PTR.  */
+
+static inline bool
+live_track_live_p (live_track_p ptr, tree var)
+{
+  int p, root;
+
+  p = var_to_partition (ptr->map, var);
+  if (p != NO_PARTITION)
+    {
+      root = basevar_index (ptr->map, p);
+      if (bitmap_bit_p (ptr->live_base_var, root))
+       return bitmap_bit_p (ptr->live_base_partitions[root], p);
+    }
+  return false;
+}
+
+
+/* This routine will add USE to PTR.  USE will be marked as live in both the 
+   ssa live map and the live bitmap for the root of USE.  */
+
+static inline void
+live_track_process_use (live_track_p ptr, tree use)
+{
+  int p;
+
+  p = var_to_partition (ptr->map, use);
+  if (p == NO_PARTITION)
+    return;
+
+  /* Mark as live in the appropriate live list.  */
+  live_track_add_partition (ptr, p);
+}
+
+
+/* This routine will process a DEF in PTR.  DEF will be removed from the live
+   lists, and if there are any other live partitions with the same base 
+   variable, conflicts will be added to GRAPH.  */
+
+static inline void
+live_track_process_def (live_track_p ptr, tree def, ssa_conflicts_p graph)
+{
+  int p, root;
+  bitmap b;
+  unsigned x;
+  bitmap_iterator bi;
+
+  p = var_to_partition (ptr->map, def);
+  if (p == NO_PARTITION)
+    return;
+
+  /* Clear the liveness bit.  */
+  live_track_remove_partition (ptr, p);
+
+  /* If the bitmap isn't empty now, conflicts need to be added.  */
+  root = basevar_index (ptr->map, p);
+  if (bitmap_bit_p (ptr->live_base_var, root))
+    {
+      b = ptr->live_base_partitions[root];
+      EXECUTE_IF_SET_IN_BITMAP (b, 0, x, bi)
+        ssa_conflicts_add (graph, p, x);
+    }
+}
+
+
+/* Initialize PTR with the partitions set in INIT.  */
+
+static inline void
+live_track_init (live_track_p ptr, bitmap init)
+{
+  unsigned p;
+  bitmap_iterator bi;
+
+  /* Mark all live on exit partitions.  */
+  EXECUTE_IF_SET_IN_BITMAP (init, 0, p, bi)
+    live_track_add_partition (ptr, p);
+}
+
+
+/* This routine will clear all live partitions in PTR.   */
+
+static inline void
+live_track_clear_base_vars (live_track_p ptr)
+{
+  /* Simply clear the live base list.  Anything marked as live in the element
+     lists will be cleared later if/when the base variable ever comes alive
+     again.  */
+  bitmap_clear (ptr->live_base_var);
+}
+
+
+/* Build a conflict graph based on LIVEINFO.  Any partitions which are in the
+   partition view of the var_map liveinfo is based on get entires in the 
+   conflict graph.  Only conflicts between ssa_name partitions with the same 
+   base variableare added.  */
+
+static ssa_conflicts_p
+build_ssa_conflict_graph (tree_live_info_p liveinfo)
+{
+  ssa_conflicts_p graph;
+  var_map map;
+  basic_block bb;
+  ssa_op_iter iter;
+  live_track_p live;
+
+  map = live_var_map (liveinfo);
+  graph = ssa_conflicts_new (num_var_partitions (map));
+
+  live = new_live_track (map);
+
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator bsi;
+      tree phi;
+
+      /* Start with live on exit temporaries.  */
+      live_track_init (live, live_on_exit (liveinfo, bb));
+
+      for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
+        {
+         tree var;
+         tree stmt = bsi_stmt (bsi);
+
+         /* A copy between 2 partitions does not introduce an interference 
+            by itself.  If they did, you would never be able to coalesce 
+            two things which are copied.  If the two variables really do 
+            conflict, they will conflict elsewhere in the program.  
+            
+            This is handled by simply removing the SRC of the copy from the 
+            live list, and processing the stmt normally.  */
+         if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
+           {
+             tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+             tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+             if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME)
+               live_track_clear_var (live, rhs);
+           }
+
+         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_DEF)
+           live_track_process_def (live, var, graph);
+
+         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
+           live_track_process_use (live, var);
+       }
+
+      /* If result of a PHI is unused, looping over the statements will not 
+        record any conflicts since the def was never live.  Since the PHI node
+        is going to be translated out of SSA form, it will insert a copy.
+        There must be a conflict recorded between the result of the PHI and 
+        any variables that are live.  Otherwise the out-of-ssa translation 
+        may create incorrect code.  */
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+       {
+         tree result = PHI_RESULT (phi);
+         if (live_track_live_p (live, result))
+           live_track_process_def (live, result, graph);
+       }
+
+     live_track_clear_base_vars (live);
+    }
+
+  delete_live_track (live);
+  return graph;
+}
+
+
+/* Shortcut routine to print messages to file F of the form:
+   "STR1 EXPR1 STR2 EXPR2 STR3."  */
+
+static inline 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);
+}
+
+
+/* Called if a coalesce across and abnormal edge cannot be performed.  PHI is
+   the phi node at fault, I is the argument index at fault.  A message is 
+   printed and compilation is then terminated.  */
+
+static inline void
+abnormal_corrupt (tree phi, int i)
+{
+  edge e = PHI_ARG_EDGE (phi, i);
+  tree res = PHI_RESULT (phi);
+  tree arg = PHI_ARG_DEF (phi, i);
+
+  fprintf (stderr, " Corrupt SSA across abnormal edge BB%d->BB%d\n",
+          e->src->index, e->dest->index);
+  fprintf (stderr, "Argument %d (", i);
+  print_generic_expr (stderr, arg, TDF_SLIM);
+  if (TREE_CODE (arg) != SSA_NAME)
+    fprintf (stderr, ") is not an SSA_NAME.\n");
+  else
+    {
+      gcc_assert (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg));
+      fprintf (stderr, ") does not have the same base variable as the result ");
+      print_generic_stmt (stderr, res, TDF_SLIM);
+    }
+
+  internal_error ("SSA corruption");
+}
+
+
+/* Print a failure to coalesce a MUST_COALESCE pair X and Y.  */
+
+static inline void
+fail_abnormal_edge_coalesce (int x, int y)
+{
+  fprintf (stderr, "\nUnable to coalesce ssa_names %d  and %d ",x, y);
+  fprintf (stderr, " which are marked as MUST COALESCE.\n");
+  print_generic_expr (stderr, ssa_name (x), TDF_SLIM);
+  fprintf (stderr, " and  ");
+  print_generic_stmt (stderr, ssa_name (y), TDF_SLIM);
+
+  internal_error ("SSA corruption");
+}
+
+
+/* This function creates a var_map for the current function as well as creating
+   a coalesce list for use later in the out of ssa process.  */
+
+static var_map
+create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
+{
+  block_stmt_iterator bsi;
+  basic_block bb;
+  tree var;
+  tree stmt;
+  tree first;
+  var_map map;
+  ssa_op_iter iter;
+  int v1, v2, cost;
+  unsigned i;
+
+#ifdef ENABLE_CHECKING
+  bitmap used_in_real_ops;
+  bitmap used_in_virtual_ops;
+
+  used_in_real_ops = BITMAP_ALLOC (NULL);
+  used_in_virtual_ops = BITMAP_ALLOC (NULL);
+#endif
+
+  map = init_var_map (num_ssa_names + 1);
+
+  FOR_EACH_BB (bb)
+    {
+      tree phi, arg;
+
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+       {
+         int i;
+         int ver;
+         tree res;
+         bool saw_copy = false;
+
+         res = PHI_RESULT (phi);
+         ver = SSA_NAME_VERSION (res);
+         register_ssa_partition (map, res);
+
+         /* Register ssa_names and coalesces between the args and the result 
+            of all PHI.  */
+         for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+           {
+             edge e = PHI_ARG_EDGE (phi, i);
+             arg = PHI_ARG_DEF (phi, i);
+             if (TREE_CODE (arg) == SSA_NAME)
+               register_ssa_partition (map, arg);
+             if (TREE_CODE (arg) == SSA_NAME 
+                 && SSA_NAME_VAR (arg) == SSA_NAME_VAR (res))
+               {
+                 saw_copy = true;
+                 bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (arg));
+                 if ((e->flags & EDGE_ABNORMAL) == 0)
+                   {
+                     int cost = coalesce_cost_edge (e);
+                     if (cost == 1 && single_imm_use_p (arg))
+                       add_cost_one_coalesce (cl, ver, SSA_NAME_VERSION (arg));
+                     else
+                       add_coalesce (cl, ver, SSA_NAME_VERSION (arg), cost);
+                   }
+               }
+             else
+               if (e->flags & EDGE_ABNORMAL)
+                 abnormal_corrupt (phi, i);
+           }
+         if (saw_copy)
+           bitmap_set_bit (used_in_copy, ver);
+       }
+
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+        {
+         stmt = bsi_stmt (bsi);
+
+         /* Register USE and DEF operands in each statement.  */
+         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE))
+           register_ssa_partition (map, var);
+
+         /* Check for copy coalesces.  */
+         switch (TREE_CODE (stmt))
+           {
+           case GIMPLE_MODIFY_STMT:
+             {
+               tree op1 = GIMPLE_STMT_OPERAND (stmt, 0);
+               tree op2 = GIMPLE_STMT_OPERAND (stmt, 1);
+               if (TREE_CODE (op1) == SSA_NAME 
+                   && TREE_CODE (op2) == SSA_NAME
+                   && SSA_NAME_VAR (op1) == SSA_NAME_VAR (op2))
+                 {
+                   v1 = SSA_NAME_VERSION (op1);
+                   v2 = SSA_NAME_VERSION (op2);
+                   cost = coalesce_cost_bb (bb);
+                   add_coalesce (cl, v1, v2, cost);
+                   bitmap_set_bit (used_in_copy, v1);
+                   bitmap_set_bit (used_in_copy, v2);
+                 }
+             }
+             break;
+
+           case ASM_EXPR:
+             {
+               unsigned long noutputs, i;
+               tree *outputs, link;
+               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;
+
+                   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)
+                     continue;
+
+                   v1 = SSA_NAME_VERSION (outputs[match]);
+                   v2 = SSA_NAME_VERSION (input);
+
+                   if (SSA_NAME_VAR (outputs[match]) == SSA_NAME_VAR (input))
+                     {
+                       cost = coalesce_cost (REG_BR_PROB_BASE, 
+                                             maybe_hot_bb_p (bb),
+                                             false);
+                       add_coalesce (cl, v1, v2, cost);
+                       bitmap_set_bit (used_in_copy, v1);
+                       bitmap_set_bit (used_in_copy, v2);
+                     }
+                 }
+               break;
+             }
+
+           default:
+             break;
+           }
+           
+#ifdef ENABLE_CHECKING
+         /* Mark real uses and defs.  */
+         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE))
+           bitmap_set_bit (used_in_real_ops, DECL_UID (SSA_NAME_VAR (var)));
+
+         /* Validate that virtual ops don't get used in funny ways.  */
+         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, 
+                                    SSA_OP_VIRTUAL_USES | SSA_OP_VMUSTDEF)
+           {
+             bitmap_set_bit (used_in_virtual_ops, 
+                             DECL_UID (SSA_NAME_VAR (var)));
+           }
+
+#endif /* ENABLE_CHECKING */
+       }
+    }
+
+  /* Now process result decls and live on entry variables for entry into
+     the coalesce list.  */
+  first = NULL_TREE;
+  for (i = 1; i < num_ssa_names; i++)
+    {
+      var = map->partition_to_var[i];
+      if (var != NULL_TREE)
+        {
+         /* Add coalesces between all the result decls.  */
+         if (TREE_CODE (SSA_NAME_VAR (var)) == RESULT_DECL)
+           {
+             if (first == NULL_TREE)
+               first = var;
+             else
+               {
+                 gcc_assert (SSA_NAME_VAR (var) == SSA_NAME_VAR (first));
+                 v1 = SSA_NAME_VERSION (first);
+                 v2 = SSA_NAME_VERSION (var);
+                 bitmap_set_bit (used_in_copy, v1);
+                 bitmap_set_bit (used_in_copy, v2);
+                 cost = coalesce_cost_bb (EXIT_BLOCK_PTR);
+                 add_coalesce (cl, v1, v2, cost);
+               }
+           }
+         /* Mark any default_def variables as being in the coalesce list
+            since they will have to be coalesced with the base variable.  If
+            not marked as present, they won't be in the coalesce view. */
+         if (gimple_default_def (cfun, SSA_NAME_VAR (var)) == var)
+           bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (var));
+       }
+    }
+
+#if defined ENABLE_CHECKING
+  {
+    unsigned i;
+    bitmap both = BITMAP_ALLOC (NULL);
+    bitmap_and (both, used_in_real_ops, used_in_virtual_ops);
+    if (!bitmap_empty_p (both))
+      {
+       bitmap_iterator bi;
+
+       EXECUTE_IF_SET_IN_BITMAP (both, 0, i, bi)
+         fprintf (stderr, "Variable %s used in real and virtual operands\n",
+                  get_name (referenced_var (i)));
+       internal_error ("SSA corruption");
+      }
+
+    BITMAP_FREE (used_in_real_ops);
+    BITMAP_FREE (used_in_virtual_ops);
+    BITMAP_FREE (both);
+  }
+#endif
+
+  return map;
+}
+
+
+/* Attempt to coalesce ssa verisons X and Y together using the partition
+   mapping in MAP and checking conflicts in GRAPH.  Output any debug info to
+   DEBUG, if it is nun-NULL.  */
+
+static inline bool
+attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
+                 FILE *debug)
+{
+  int z;
+  tree var1, var2;
+  int p1, p2;
+
+  p1 = var_to_partition (map, ssa_name (x));
+  p2 = var_to_partition (map, ssa_name (y));
+
+  if (debug)
+    {
+      fprintf (debug, "(%d)", x);
+      print_generic_expr (debug, partition_to_var (map, p1), TDF_SLIM);
+      fprintf (debug, " & (%d)", y);
+      print_generic_expr (debug, partition_to_var (map, p2), TDF_SLIM);
+    }
+
+  if (p1 == p2) 
+    {
+      if (debug)
+       fprintf (debug, ": Already Coalesced.\n");
+      return true;
+    }
+
+  if (debug)
+    fprintf (debug, " [map: %d, %d] ", p1, p2);
+
+
+  if (!ssa_conflicts_test_p (graph, p1, p2))
+    {
+      var1 = partition_to_var (map, p1);
+      var2 = partition_to_var (map, p2);
+      z = var_union (map, var1, var2);
+      if (z == NO_PARTITION)
+       {
+         if (debug)
+           fprintf (debug, ": Unable to perform partition union.\n");
+         return false;
+       }
+
+      /* z is the new combined partition.  Remove the other partition from 
+        the list, and merge the conflicts.  */
+      if (z == p1)
+       ssa_conflicts_merge (graph, p1, p2);
+      else
+       ssa_conflicts_merge (graph, p2, p1);
+
+      if (debug)
+       fprintf (debug, ": Success -> %d\n", z);
+      return true;
+    }
+
+  if (debug)
+    fprintf (debug, ": Fail due to conflict\n");
+
+  return false;
+}
+
+
+/* Attempt to Coalesce partitions in MAP which occur in the list CL using 
+   GRAPH.  Debug output is sent to DEBUG if it is non-NULL.  */
+
+static void
+coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl, 
+                    FILE *debug)
+{
+  int x = 0, y = 0;
+  tree var1, var2, phi;
+  int cost;
+  basic_block bb;
+  edge e;
+  edge_iterator ei;
+
+  /* First, coalece all the copie across abnormal edges.  These are not placed
+     in the coalesce list becase they do not need to be sorted, and simply 
+     consume extra memory/compilation time in large programs.  */
+
+  FOR_EACH_BB (bb)
+    {
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (e->flags & EDGE_ABNORMAL)
+         {
+           for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+             {
+               tree res = PHI_RESULT (phi);
+               tree arg = PHI_ARG_DEF (phi, e->dest_idx);
+               int v1 = SSA_NAME_VERSION (res);
+               int v2 = SSA_NAME_VERSION (arg);
+
+               if (SSA_NAME_VAR (arg) != SSA_NAME_VAR (res))
+                 abnormal_corrupt (phi, e->dest_idx);
+
+               if (debug)
+                 fprintf (debug, "Abnormal coalesce: ");
+
+               if (!attempt_coalesce (map, graph, v1, v2, debug))
+                 fail_abnormal_edge_coalesce (v1, v2);
+             }
+         }
+    }
+
+  /* Now process the items in the coalesce list.  */
+
+  while ((cost = pop_best_coalesce (cl, &x, &y)) != NO_BEST_COALESCE)
+    {
+      var1 = ssa_name (x);
+      var2 = ssa_name (y);
+
+      /* Assert the coalesces have the same base variable.  */
+      gcc_assert (SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2));
+
+      if (debug)
+       fprintf (debug, "Coalesce list: ");
+      attempt_coalesce (map, graph, x, y, debug);
+    }
+}
+
+
+/* Reduce the number of copies by coalescing variables in the function.  Return
+   a partition map with the resulting coalesces.  */
+
+extern var_map
+coalesce_ssa_name (void)
+{
+  unsigned num, x;
+  tree_live_info_p liveinfo;
+  ssa_conflicts_p graph;
+  coalesce_list_p cl;
+  bitmap used_in_copies = BITMAP_ALLOC (NULL);
+  var_map map;
+
+  cl = create_coalesce_list ();
+  map = create_outofssa_var_map (cl, used_in_copies);
+
+  /* Don't calculate live ranges for variables not in the coalesce list.  */
+  partition_view_bitmap (map, used_in_copies, true);
+  BITMAP_FREE (used_in_copies);
+
+  if (num_var_partitions (map) <= 1)
+    {
+      delete_coalesce_list (cl);
+      return map;
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_var_map (dump_file, map);
+
+  liveinfo = calculate_live_ranges (map);
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_live_info (dump_file, liveinfo, LIVEDUMP_ENTRY);
+
+  /* Build a conflict graph.  */
+  graph = build_ssa_conflict_graph (liveinfo);
+  delete_tree_live_info (liveinfo);
+
+  sort_coalesce_list (cl);
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "\nAfter sorting:\n");
+      dump_coalesce_list (dump_file, cl);
+    }
+
+  /* First, coalesce all live on entry variables to their base variable. 
+     This will ensure the first use is coming from the correct location.  */
+
+  num = num_var_partitions (map);
+  for (x = 0 ; x < num; x++)
+    {
+      tree var = partition_to_var (map, x);
+      tree root;
+
+      if (TREE_CODE (var) != SSA_NAME)
+       continue;
+
+      root = SSA_NAME_VAR (var);
+      if (gimple_default_def (cfun, root) == var)
+        {
+         /* This root variable should have not already been assigned
+            to another partition which is not coalesced with this one.  */
+         gcc_assert (!var_ann (root)->out_of_ssa_tag);
+
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             print_exprs (dump_file, "Must coalesce ", var,
+                          " with the root variable ", root, ".\n");
+           }
+         change_partition_var (map, root, x);
+       }
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_var_map (dump_file, map);
+
+  /* Now coalesce everything in the list.  */
+  coalesce_partitions (map, graph, cl, 
+                      ((dump_flags & TDF_DETAILS) ? dump_file
+                                                  : NULL));
+
+  delete_coalesce_list (cl);
+  ssa_conflicts_delete (graph);
+
+  return map;
+}
+
index 277e276..2049e43 100644 (file)
@@ -24,44 +24,107 @@ Boston, MA 02110-1301, USA.  */
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "flags.h"
-#include "basic-block.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 "toplev.h"
-#include "vecprim.h"
-
-static void live_worklist (tree_live_info_p);
-static tree_live_info_p new_tree_live_info (var_map);
-static inline void set_if_valid (var_map, bitmap, tree);
-static inline void add_conflicts_if_valid (tpa_p, conflict_graph,
-                                          var_map, bitmap, tree);
-static partition_pair_p find_partition_pair (coalesce_list_p, int, int, bool);
+
 #ifdef ENABLE_CHECKING
 static void  verify_live_on_entry (tree_live_info_p);
 #endif
 
-/* This is where the mapping from SSA version number to real storage variable
-   is tracked.  
 
-   All SSA versions of the same variable may not ultimately be mapped back to
-   the same real variable. In that instance, we need to detect the live
-   range overlap, and give one of the variable new storage. The vector
-   'partition_to_var' tracks which partition maps to which variable.
+/* VARMAP maintains a mapping from SSA version number to real variables.
+
+   All SSA_NAMES are divided into partitions.  Initially each ssa_name is the
+   only member of it's own partition.  Coalescing will attempt to group any
+   ssa_names which occur in a copy or in a PHI node into the same partition.
+
+   At the end of out-of-ssa, each partition becomes a "real" variable and is
+   rewritten as a compiler variable.
+
+   The var_map datat structure is used to manage these partitions.  It allows
+   partitions to be combined, and determines which partition belongs to what
+   ssa_name or variable, and vice versa.  */
+
+
+/* This routine will initialize the basevar fields of MAP.  */
+
+static void
+var_map_base_init (var_map map)
+{
+  int x, num_part, num;
+  tree var;
+  var_ann_t ann;
+  
+  num = 0;
+  num_part = num_var_partitions (map);
+
+  /* If a base table already exists, clear it, otherwise create it.  */
+  if (map->partition_to_base_index != NULL)
+    {
+      free (map->partition_to_base_index);
+      VEC_truncate (tree, map->basevars, 0);
+    }
+  else
+    map->basevars = VEC_alloc (tree, heap, MAX (40, (num_part / 10)));
+
+  map->partition_to_base_index = (int *) xmalloc (sizeof (int) * num_part);
+
+  /* Build the base variable list, and point partitions at their bases.  */
+  for (x = 0; x < num_part; x++)
+    {
+      var = partition_to_var (map, x);
+      if (TREE_CODE (var) == SSA_NAME)
+        var = SSA_NAME_VAR (var);
+      ann = var_ann (var);
+      /* If base variable hasn't been seen, set it up.  */
+      if (!ann->base_var_processed)
+        {
+         ann->base_var_processed = 1;
+         VAR_ANN_BASE_INDEX (ann) = num++;
+         VEC_safe_push (tree, heap, map->basevars, var);
+       }
+      map->partition_to_base_index[x] = VAR_ANN_BASE_INDEX (ann);
+    }
 
-   Given a VAR, it is sometimes desirable to know which partition that VAR
-   represents.  There is an additional field in the variable annotation to
-   track that information.  */
+  map->num_basevars = num;
 
+  /* Now clear the processed bit.  */
+  for (x = 0; x < num; x++)
+    {
+       var = VEC_index (tree, map->basevars, x);
+       var_ann (var)->base_var_processed = 0;
+    }
+
+#ifdef ENABLE_CHECKING
+  for (x = 0; x < num_part; x++)
+    {
+      tree var2;
+      var = SSA_NAME_VAR (partition_to_var (map, x));
+      var2 = VEC_index (tree, map->basevars, basevar_index (map, x));
+      gcc_assert (var == var2);
+    }
+#endif
+}
+
+
+/* Remove the base table in MAP.  */
+
+static void
+var_map_base_fini (var_map map)
+{
+  /* Free the basevar info if it is present.  */
+  if (map->partition_to_base_index != NULL)
+    {
+      VEC_free (tree, heap, map->basevars);
+      free (map->partition_to_base_index);
+      map->partition_to_base_index = NULL;
+      map->num_basevars = 0;
+    }
+}
 /* Create a variable partition map of SIZE, initialize and return it.  */
 
 var_map
@@ -75,10 +138,13 @@ init_var_map (int size)
              = (tree *)xmalloc (size * sizeof (tree));
   memset (map->partition_to_var, 0, size * sizeof (tree));
 
-  map->partition_to_compact = NULL;
-  map->compact_to_partition = NULL;
+  map->partition_to_view = NULL;
+  map->view_to_partition = NULL;
   map->num_partitions = size;
   map->partition_size = size;
+  map->num_basevars = 0;
+  map->partition_to_base_index = NULL;
+  map->basevars = NULL;
   return map;
 }
 
@@ -88,12 +154,13 @@ init_var_map (int size)
 void
 delete_var_map (var_map map)
 {
+  var_map_base_fini (map);
   free (map->partition_to_var);
   partition_delete (map->var_partition);
-  if (map->partition_to_compact)
-    free (map->partition_to_compact);
-  if (map->compact_to_partition)
-    free (map->compact_to_partition);
+  if (map->partition_to_view)
+    free (map->partition_to_view);
+  if (map->view_to_partition)
+    free (map->view_to_partition);
   free (map);
 }
 
@@ -109,17 +176,17 @@ var_union (var_map map, tree var1, tree var2)
   tree root_var = NULL_TREE;
   tree other_var = NULL_TREE;
 
-  /* This is independent of partition_to_compact. If partition_to_compact is 
+  /* This is independent of partition_to_view. If partition_to_view is 
      on, then whichever one of these partitions is absorbed will never have a
-     dereference into the partition_to_compact array any more.  */
+     dereference into the partition_to_view array any more.  */
 
   if (TREE_CODE (var1) == SSA_NAME)
     p1 = partition_find (map->var_partition, SSA_NAME_VERSION (var1));
   else
     {
       p1 = var_to_partition (map, var1);
-      if (map->compact_to_partition)
-        p1 = map->compact_to_partition[p1];
+      if (map->view_to_partition)
+        p1 = map->view_to_partition[p1];
       root_var = var1;
     }
   
@@ -128,8 +195,8 @@ var_union (var_map map, tree var1, tree var2)
   else
     {
       p2 = var_to_partition (map, var2);
-      if (map->compact_to_partition)
-        p2 = map->compact_to_partition[p2];
+      if (map->view_to_partition)
+        p2 = map->view_to_partition[p2];
 
       /* If there is no root_var set, or it's not a user variable, set the
         root_var to this one.  */
@@ -150,8 +217,8 @@ var_union (var_map map, tree var1, tree var2)
   else
     p3 = partition_union (map->var_partition, p1, p2);
 
-  if (map->partition_to_compact)
-    p3 = map->partition_to_compact[p3];
+  if (map->partition_to_view)
+    p3 = map->partition_to_view[p3];
 
   if (root_var)
     change_partition_var (map, root_var, p3);
@@ -161,12 +228,12 @@ var_union (var_map map, tree var1, tree var2)
   return p3;
 }
 
-
 /* Compress the partition numbers in MAP such that they fall in the range 
    0..(num_partitions-1) instead of wherever they turned out during
    the partitioning exercise.  This removes any references to unused
    partitions, thereby allowing bitmaps and other vectors to be much
-   denser.  Compression type is controlled by FLAGS.
+   denser.  
 
    This is implemented such that compaction doesn't affect partitioning.
    Ie., once partitions are created and possibly merged, running one
@@ -179,96 +246,140 @@ var_union (var_map map, tree var1, tree var2)
    definitions, and then 'recompact' later to include all the single
    definitions for assignment to program variables.  */
 
-void 
-compact_var_map (var_map map, int flags)
+
+/* Set MAP back to the initial state of having no partition view.  Return a 
+   bitmap which has a bit set for each partition number which is in use in the 
+   varmap.  */
+
+static bitmap
+partition_view_init (var_map map)
 {
-  sbitmap used;
-  int tmp, root, root_i;
-  unsigned int x, limit, count;
-  tree var;
-  root_var_p rv = NULL;
+  bitmap used;
+  int tmp;
+  unsigned int x;
 
-  limit = map->partition_size;
-  used = sbitmap_alloc (limit);
-  sbitmap_zero (used);
+  used = BITMAP_ALLOC (NULL);
 
-  /* Already compressed? Abandon the old one.  */
-  if (map->partition_to_compact)
+  /* Already in a view? Abandon the old one.  */
+  if (map->partition_to_view)
     {
-      free (map->partition_to_compact);
-      map->partition_to_compact = NULL;
+      free (map->partition_to_view);
+      map->partition_to_view = NULL;
     }
-  if (map->compact_to_partition)
+  if (map->view_to_partition)
     {
-      free (map->compact_to_partition);
-      map->compact_to_partition = NULL;
+      free (map->view_to_partition);
+      map->view_to_partition = NULL;
     }
 
-  map->num_partitions = map->partition_size;
-
-  if (flags & VARMAP_NO_SINGLE_DEFS)
-    rv = root_var_init (map);
-
-  map->partition_to_compact = (int *)xmalloc (limit * sizeof (int));
-  memset (map->partition_to_compact, 0xff, (limit * sizeof (int)));
-
   /* Find out which partitions are actually referenced.  */
-  count = 0;
-  for (x = 0; x < limit; x++)
+  for (x = 0; x < map->partition_size; x++)
     {
       tmp = partition_find (map->var_partition, x);
-      if (!TEST_BIT (used, tmp) && map->partition_to_var[tmp] != NULL_TREE)
-        {
-         /* It is referenced, check to see if there is more than one version
-            in the root_var table, if one is available.  */
-         if (rv)
-           {
-             root = root_var_find (rv, tmp);
-             root_i = root_var_first_partition (rv, root);
-             /* If there is only one, don't include this in the compaction.  */
-             if (root_var_next_partition (rv, root_i) == ROOT_VAR_NONE)
-               continue;
-           }
-         SET_BIT (used, tmp);
-         count++;
-       }
+      if (map->partition_to_var[tmp] != NULL_TREE && !bitmap_bit_p (used, tmp))
+       bitmap_set_bit (used, tmp);
     }
 
-  /* Build a compacted partitioning.  */
-  if (count != limit)
+  map->num_partitions = map->partition_size;
+  return used;
+}
+
+
+/* This routine will finalize the view data for MAP based on the partitions
+   set in SELECTED.  This is either the same bitmap returned from 
+   partition_view_init, or a trimmed down version if some of those partitions
+   were not desired in this view.  SELECTED is freed before returning.  */
+
+static void 
+partition_view_fini (var_map map, bitmap selected)
+{
+  bitmap_iterator bi;
+  unsigned count, i, x, limit;
+  tree var;
+
+  gcc_assert (selected);
+
+  count = bitmap_count_bits (selected);
+  limit = map->partition_size;
+
+  /* If its a one-to-one ratio, we don't need any view compaction.  */
+  if (count < limit)
     {
-      sbitmap_iterator sbi;
+      map->partition_to_view = (int *)xmalloc (limit * sizeof (int));
+      memset (map->partition_to_view, 0xff, (limit * sizeof (int)));
+      map->view_to_partition = (int *)xmalloc (count * sizeof (int));
 
-      map->compact_to_partition = (int *)xmalloc (count * sizeof (int));
-      count = 0;
-      /* SSA renaming begins at 1, so skip 0 when compacting.  */
-      EXECUTE_IF_SET_IN_SBITMAP (used, 1, x, sbi)
+      i = 0;
+      /* Give each selected partition an index.  */
+      EXECUTE_IF_SET_IN_BITMAP (selected, 0, x, bi)
        {
-         map->partition_to_compact[x] = count;
-         map->compact_to_partition[count] = x;
+         map->partition_to_view[x] = i;
+         map->view_to_partition[i] = x;
          var = map->partition_to_var[x];
+         /* If any one of the members of a partition is not an SSA_NAME, make
+            sure it is the representative.  */
          if (TREE_CODE (var) != SSA_NAME)
-           change_partition_var (map, var, count);
-         count++;
+           change_partition_var (map, var, i);
+         i++;
        }
+      gcc_assert (i == count);
+      map->num_partitions = i;
     }
+
+  BITMAP_FREE (selected);
+}
+
+
+/* Create a partition view which includes all the used partitions in MAP.  If 
+   WANT_BASES is true, create the base variable map as well.  */
+
+extern void
+partition_view_normal (var_map map, bool want_bases)
+{
+  bitmap used;
+
+  used = partition_view_init (map);
+  partition_view_fini (map, used);
+
+  if (want_bases)
+    var_map_base_init (map);
   else
+    var_map_base_fini (map);
+}
+
+
+/* Create a partition view in MAP which includes just partitions which occur in 
+   the bitmap ONLY. If WANT_BASES is true, create the base variable map 
+   as well.  */
+
+extern void
+partition_view_bitmap (var_map map, bitmap only, bool want_bases)
+{
+  bitmap used;
+  bitmap new_partitions = BITMAP_ALLOC (NULL);
+  unsigned x, p;
+  bitmap_iterator bi;
+
+  used = partition_view_init (map);
+  EXECUTE_IF_SET_IN_BITMAP (only, 0, x, bi)
     {
-      free (map->partition_to_compact);
-      map->partition_to_compact = NULL;
+      p = partition_find (map->var_partition, x);
+      gcc_assert (bitmap_bit_p (used, p));
+      bitmap_set_bit (new_partitions, p);
     }
+  partition_view_fini (map, new_partitions);
 
-  map->num_partitions = count;
-
-  if (rv)
-    root_var_delete (rv);
-  sbitmap_free (used);
+  BITMAP_FREE (used);
+  if (want_bases)
+    var_map_base_init (map);
+  else
+    var_map_base_fini (map);
 }
 
 
 /* This function is used to change the representative variable in MAP for VAR's 
-   partition from an SSA_NAME variable to a regular variable.  This allows 
-   partitions to be mapped back to real variables.  */
+   partition to a regular non-ssa variable.  This allows partitions to be 
+   mapped back to real variables.  */
   
 void 
 change_partition_var (var_map map, tree var, int part)
@@ -280,10 +391,11 @@ change_partition_var (var_map map, tree var, int part)
   ann = var_ann (var);
   ann->out_of_ssa_tag = 1;
   VAR_ANN_PARTITION (ann) = part;
-  if (map->compact_to_partition)
-    map->partition_to_var[map->compact_to_partition[part]] = var;
+  if (map->view_to_partition)
+    map->partition_to_var[map->view_to_partition[part]] = var;
 }
 
+
 static inline void mark_all_vars_used (tree *);
 
 /* Helper function for mark_all_vars_used, called via walk_tree.  */
@@ -319,6 +431,7 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
   return NULL;
 }
 
+
 /* Mark all VAR_DECLS under *EXPR_P as used, so that they won't be 
    eliminated during the tree->rtl conversion process.  */
 
@@ -394,102 +507,6 @@ remove_unused_locals (void)
     }
 }
 
-/* This function looks through the program and uses FLAGS to determine what 
-   SSA versioned variables are given entries in a new partition table.  This
-   new partition map is returned.  */
-
-var_map
-create_ssa_var_map (void)
-{
-  block_stmt_iterator bsi;
-  basic_block bb;
-  tree var;
-  tree stmt;
-  var_map map;
-  ssa_op_iter iter;
-#ifdef ENABLE_CHECKING
-  bitmap used_in_real_ops;
-  bitmap used_in_virtual_ops;
-#endif
-
-  map = init_var_map (num_ssa_names + 1);
-
-#ifdef ENABLE_CHECKING
-  used_in_real_ops = BITMAP_ALLOC (NULL);
-  used_in_virtual_ops = BITMAP_ALLOC (NULL);
-#endif
-
-  FOR_EACH_BB (bb)
-    {
-      tree phi, arg;
-
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-       {
-         int i;
-         register_ssa_partition (map, PHI_RESULT (phi));
-         for (i = 0; i < PHI_NUM_ARGS (phi); i++)
-           {
-             arg = PHI_ARG_DEF (phi, i);
-             if (TREE_CODE (arg) == SSA_NAME)
-               register_ssa_partition (map, arg);
-
-             mark_all_vars_used (&PHI_ARG_DEF_TREE (phi, i));
-           }
-       }
-
-      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-        {
-         stmt = bsi_stmt (bsi);
-
-         /* Register USE and DEF operands in each statement.  */
-         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE))
-           {
-             register_ssa_partition (map, var);
-
-#ifdef ENABLE_CHECKING
-             bitmap_set_bit (used_in_real_ops, DECL_UID (SSA_NAME_VAR (var)));
-#endif
-           }
-
-#ifdef ENABLE_CHECKING
-         /* Validate that virtual ops don't get used in funny ways.  */
-         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, 
-                                    SSA_OP_VIRTUAL_USES | SSA_OP_VMUSTDEF)
-           {
-             bitmap_set_bit (used_in_virtual_ops, 
-                             DECL_UID (SSA_NAME_VAR (var)));
-           }
-
-#endif /* ENABLE_CHECKING */
-
-         mark_all_vars_used (bsi_stmt_ptr (bsi));
-       }
-    }
-
-#if defined ENABLE_CHECKING
-  {
-    unsigned i;
-    bitmap both = BITMAP_ALLOC (NULL);
-    bitmap_and (both, used_in_real_ops, used_in_virtual_ops);
-    if (!bitmap_empty_p (both))
-      {
-       bitmap_iterator bi;
-
-       EXECUTE_IF_SET_IN_BITMAP (both, 0, i, bi)
-         fprintf (stderr, "Variable %s used in real and virtual operands\n",
-                  get_name (referenced_var (i)));
-       internal_error ("SSA corruption");
-      }
-
-    BITMAP_FREE (used_in_real_ops);
-    BITMAP_FREE (used_in_virtual_ops);
-    BITMAP_FREE (both);
-  }
-#endif
-
-  return map;
-}
-
 
 /* Allocate and return a new live range information object base on MAP.  */
 
@@ -541,7 +558,7 @@ delete_tree_live_info (tree_live_info_p live)
 }
 
 
-/* Visit basic block BB, and propogate any required live on entry bits from 
+/* Visit basic block BB and propogate any required live on entry bits from 
    LIVE into the predecessors.  VISITED is the bitmap of visited blocks.  
    TMP is a temporary work bitmap which is passed in to avoid reallocting
    it each time.  */
@@ -565,8 +582,8 @@ loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited,
       pred_bb = e->src;
       if (pred_bb == ENTRY_BLOCK_PTR)
        continue;
-      /* tmp is vars live-=on-entry from BB that aren't defined in the
-        pred. block.  This should be the live on entry vars to pred.  
+      /* TMP is variables live-on-entry from BB that aren't defined in the
+        predecessor block.  This should be the live on entry vars to pred.  
         Note that liveout is the DEFs in a block while live on entry is
         being calculated.  */
       bitmap_and_compl (tmp, loe, live->liveout[pred_bb->index]);
@@ -636,7 +653,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
   if (stmt)
     {
       def_bb = bb_for_stmt (stmt);
-      /* Mark defs in liveout bitmap for now.  */
+      /* Mark defs in liveout bitmap temporarily.  */
       if (def_bb)
        bitmap_set_bit (live->liveout[def_bb->index], p);
     }
@@ -698,7 +715,7 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
   edge e;
   edge_iterator ei;
 
-  /* live on entry calculations used the liveouit vector for defs.  */
+  /* live on entry calculations used liveout vectors for defs, clear them.  */
   FOR_EACH_BB (bb)
     bitmap_clear (liveinfo->liveout[bb->index]);
 
@@ -720,7 +737,7 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
              bitmap_set_bit (liveinfo->liveout[e->src->index], p);
          }
 
-      /* add each successors live on entry to this bock live on exit.  */
+      /* Add each successors live on entry to this bock live on exit.  */
       FOR_EACH_EDGE (e, ei, bb->succs)
         if (e->dest != EXIT_BLOCK_PTR)
          bitmap_ior_into (liveinfo->liveout[bb->index],
@@ -728,6 +745,7 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
     }
 }
 
+
 /* Given partition map MAP, calculate all the live on entry bitmaps for 
    each partition.  Return a new live info object.  */
 
@@ -757,936 +775,6 @@ calculate_live_ranges (var_map map)
 }
 
 
-/* Initialize a tree_partition_associator object using MAP.  */
-
-static tpa_p
-tpa_init (var_map map)
-{
-  tpa_p tpa;
-  int num_partitions = num_var_partitions (map);
-  int x;
-
-  if (num_partitions == 0)
-    return NULL;
-
-  tpa = (tpa_p) xmalloc (sizeof (struct tree_partition_associator_d));
-  tpa->num_trees = 0;
-  tpa->uncompressed_num = -1;
-  tpa->map = map;
-  tpa->next_partition = (int *)xmalloc (num_partitions * sizeof (int));
-  memset (tpa->next_partition, TPA_NONE, num_partitions * sizeof (int));
-
-  tpa->partition_to_tree_map = (int *)xmalloc (num_partitions * sizeof (int));
-  memset (tpa->partition_to_tree_map, TPA_NONE, num_partitions * sizeof (int));
-
-  x = MAX (40, (num_partitions / 20));
-  tpa->trees = VEC_alloc (tree, heap, x);
-  tpa->first_partition = VEC_alloc (int, heap, x);
-
-  return tpa;
-
-}
-
-
-/* Remove PARTITION_INDEX from TREE_INDEX's list in the tpa structure TPA.  */
-
-void
-tpa_remove_partition (tpa_p tpa, int tree_index, int partition_index)
-{
-  int i;
-
-  i = tpa_first_partition (tpa, tree_index);
-  if (i == partition_index)
-    {
-      VEC_replace (int, tpa->first_partition, tree_index,
-                  tpa->next_partition[i]);
-    }
-  else
-    {
-      for ( ; i != TPA_NONE; i = tpa_next_partition (tpa, i))
-        {
-         if (tpa->next_partition[i] == partition_index)
-           {
-             tpa->next_partition[i] = tpa->next_partition[partition_index];
-             break;
-           }
-       }
-    }
-}
-
-
-/* Free the memory used by tree_partition_associator object TPA.  */
-
-void
-tpa_delete (tpa_p tpa)
-{
-  if (!tpa)
-    return;
-
-  VEC_free (tree, heap, tpa->trees);
-  VEC_free (int, heap, tpa->first_partition);
-  free (tpa->partition_to_tree_map);
-  free (tpa->next_partition);
-  free (tpa);
-}
-
-
-/* This function will remove any tree entries from TPA which have only a single
-   element.  This will help keep the size of the conflict graph down.  The 
-   function returns the number of remaining tree lists.  */
-
-int 
-tpa_compact (tpa_p tpa)
-{
-  int last, x, y, first, swap_i;
-  tree swap_t;
-
-  /* Find the last list which has more than 1 partition.  */
-  for (last = tpa->num_trees - 1; last > 0; last--)
-    {
-      first = tpa_first_partition (tpa, last);
-      if (tpa_next_partition (tpa, first) != NO_PARTITION)
-        break;
-    }
-
-  x = 0;
-  while (x < last)
-    {
-      first = tpa_first_partition (tpa, x);
-
-      /* If there is not more than one partition, swap with the current end
-        of the tree list.  */
-      if (tpa_next_partition (tpa, first) == NO_PARTITION)
-        {
-         swap_t = VEC_index (tree, tpa->trees, last);
-         swap_i = VEC_index (int, tpa->first_partition, last);
-
-         /* Update the last entry. Since it is known to only have one
-            partition, there is nothing else to update.  */
-         VEC_replace (tree, tpa->trees, last,
-                      VEC_index (tree, tpa->trees, x));
-         VEC_replace (int, tpa->first_partition, last,
-                      VEC_index (int, tpa->first_partition, x));
-         tpa->partition_to_tree_map[tpa_first_partition (tpa, last)] = last;
-
-         /* Since this list is known to have more than one partition, update
-            the list owner entries.  */
-         VEC_replace (tree, tpa->trees, x, swap_t);
-         VEC_replace (int, tpa->first_partition, x, swap_i);
-         for (y = tpa_first_partition (tpa, x); 
-              y != NO_PARTITION; 
-              y = tpa_next_partition (tpa, y))
-           tpa->partition_to_tree_map[y] = x;
-
-         /* Ensure last is a list with more than one partition.  */
-         last--;
-         for (; last > x; last--)
-           {
-             first = tpa_first_partition (tpa, last);
-             if (tpa_next_partition (tpa, first) != NO_PARTITION)
-               break;
-           }
-       }
-      x++;
-    }
-
-  first = tpa_first_partition (tpa, x);
-  if (tpa_next_partition (tpa, first) != NO_PARTITION)
-    x++;
-  tpa->uncompressed_num = tpa->num_trees;
-  tpa->num_trees = x;
-  return last;
-}
-
-
-/* Initialize a root_var object with SSA partitions from MAP which are based 
-   on each root variable.  */
-
-root_var_p
-root_var_init (var_map map)
-{
-  root_var_p rv;
-  int num_partitions = num_var_partitions (map);
-  int x, p;
-  tree t;
-  var_ann_t ann;
-  sbitmap seen;
-
-  rv = tpa_init (map);
-  if (!rv)
-    return NULL;
-
-  seen = sbitmap_alloc (num_partitions);
-  sbitmap_zero (seen);
-
-  /* Start at the end and work towards the front. This will provide a list
-     that is ordered from smallest to largest.  */
-  for (x = num_partitions - 1; x >= 0; x--)
-    {
-      t = partition_to_var (map, x);
-
-      /* The var map may not be compacted yet, so check for NULL.  */
-      if (!t) 
-        continue;
-
-      p = var_to_partition (map, t);
-
-      gcc_assert (p != NO_PARTITION);
-
-      /* Make sure we only put coalesced partitions into the list once.  */
-      if (TEST_BIT (seen, p))
-        continue;
-      SET_BIT (seen, p);
-      if (TREE_CODE (t) == SSA_NAME)
-       t = SSA_NAME_VAR (t);
-      ann = var_ann (t);
-      if (ann->root_var_processed)
-        {
-         rv->next_partition[p] = VEC_index (int, rv->first_partition, 
-                                            VAR_ANN_ROOT_INDEX (ann));
-         VEC_replace (int, rv->first_partition, VAR_ANN_ROOT_INDEX (ann), p);
-       }
-      else
-        {
-         ann->root_var_processed = 1;
-         VAR_ANN_ROOT_INDEX (ann) = rv->num_trees++;
-         VEC_safe_push (tree, heap, rv->trees, t);
-         VEC_safe_push (int, heap, rv->first_partition, p);
-       }
-      rv->partition_to_tree_map[p] = VAR_ANN_ROOT_INDEX (ann);
-    }
-
-  /* Reset the out_of_ssa_tag flag on each variable for later use.  */
-  for (x = 0; x < rv->num_trees; x++)
-    {
-      t = VEC_index (tree, rv->trees, x);
-      var_ann (t)->root_var_processed = 0;
-    }
-
-  sbitmap_free (seen);
-  return rv;
-}
-
-
-/* Hash function for 2 integer coalesce pairs.  */
-#define COALESCE_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
-
-
-/* Return hash value for partition pair PAIR.  */
-
-unsigned int 
-partition_pair_map_hash (const void *pair)
-{
-  hashval_t a = (hashval_t)(((partition_pair_p)pair)->first_partition);
-  hashval_t b = (hashval_t)(((partition_pair_p)pair)->second_partition);
-
-  return COALESCE_HASH_FN (a,b);
-}
-
-
-/* Return TRUE if PAIR1 is equivalent to PAIR2.  */
-
-int 
-partition_pair_map_eq (const void *pair1, const void *pair2)
-{
-  partition_pair_p p1 = (partition_pair_p) pair1;
-  partition_pair_p p2 = (partition_pair_p) pair2;
-
-  return (p1->first_partition == p2->first_partition
-         && p1->second_partition == p2->second_partition);
-}
-
-
-/* Create a new coalesce list object from MAP and return it.  */
-
-coalesce_list_p 
-create_coalesce_list (var_map map)
-{
-  coalesce_list_p list;
-  unsigned size = num_ssa_names * 3;
-
-  if (size < 40)
-    size = 40;
-
-  list = xmalloc (sizeof (struct coalesce_list_d));
-  list->list = htab_create (size, partition_pair_map_hash,
-                           partition_pair_map_eq, NULL);
-
-  list->map = map;
-  list->sorted = NULL;
-  list->add_mode = true;
-  list->num_sorted = 0;
-  return list;
-}
-
-
-/* Delete coalesce list CL.  */
-
-void 
-delete_coalesce_list (coalesce_list_p cl)
-{
-  htab_delete (cl->list);
-  if (cl->sorted)
-    free (cl->sorted);
-  gcc_assert (cl->num_sorted == 0);
-  free (cl);
-}
-
-
-/* Find a matching coalesce pair object in CL for partitions P1 and P2.  If 
-   one isn't found, return NULL if CREATE is false, otherwise create a new 
-   coalesce pair object and return it.  */
-
-static partition_pair_p
-find_partition_pair (coalesce_list_p cl, int p1, int p2, bool create)
-{
-  struct partition_pair p, *pair;
-  void **slot;
-  unsigned int hash;
-    
-  /* normalize so that p1 is the smaller value.  */
-  if (p2 < p1)
-    {
-      p.first_partition = p2;
-      p.second_partition = p1;
-    }
-  else
-    {
-      p.first_partition = p1;
-      p.second_partition = p2;
-    }
-  
-  
-  hash = partition_pair_map_hash (&p);
-  pair = (struct partition_pair *) htab_find_with_hash (cl->list, &p, hash);
-
-  if (create && !pair)
-    {
-      gcc_assert (cl->add_mode);
-      pair = xmalloc (sizeof (struct partition_pair));
-      pair->first_partition = p.first_partition;
-      pair->second_partition = p.second_partition;
-      pair->cost = 0;
-      slot = htab_find_slot_with_hash (cl->list, pair, hash, INSERT);
-      *(struct partition_pair **)slot = pair;
-    }
-
-  return pair;
-}
-
-/* Return cost of execution of copy instruction with FREQUENCY
-   possibly on CRITICAL edge and in HOT basic block.  */
-int
-coalesce_cost (int frequency, bool hot, bool critical)
-{
-  /* Base costs on BB frequencies bounded by 1.  */
-  int cost = frequency;
-
-  if (!cost)
-    cost = 1;
-  if (optimize_size || hot)
-    cost = 1;
-  /* Inserting copy on critical edge costs more
-     than inserting it elsewhere.  */
-  if (critical)
-    cost *= 2;
-  return cost;
-}
-
-/* Add a potential coalesce between P1 and P2 in CL with a cost of VALUE.  */
-
-void 
-add_coalesce (coalesce_list_p cl, int p1, int p2,
-             int value)
-{
-  partition_pair_p node;
-
-  gcc_assert (cl->add_mode);
-
-  if (p1 == p2)
-    return;
-
-  node = find_partition_pair (cl, p1, p2, true);
-
-  node->cost += value;
-}
-
-
-/* Comparison function to allow qsort to sort P1 and P2 in Ascending order.  */
-
-static
-int compare_pairs (const void *p1, const void *p2)
-{
-  return (*(partition_pair_p *)p1)->cost - (*(partition_pair_p *)p2)->cost;
-}
-
-
-static inline int
-num_coalesce_pairs (coalesce_list_p cl)
-{
-  return htab_elements (cl->list);
-}
-
-typedef struct
-{
-  htab_iterator hti;
-} partition_pair_iterator;
-
-static inline partition_pair_p
-first_partition_pair (coalesce_list_p cl, partition_pair_iterator *iter)
-{
-  partition_pair_p pair;
-
-  pair = (partition_pair_p) first_htab_element (&(iter->hti), cl->list);
-  return pair;
-}
-
-static inline bool
-end_partition_pair_p (partition_pair_iterator *iter)
-{
-  return end_htab_p (&(iter->hti));
-}
-
-static inline partition_pair_p
-next_partition_pair (partition_pair_iterator *iter)
-{
-  partition_pair_p pair;
-
-  pair = (partition_pair_p) next_htab_element (&(iter->hti));
-  return pair;
-}
-
-#define FOR_EACH_PARTITION_PAIR(PAIR, ITER, CL)                \
-  for ((PAIR) = first_partition_pair ((CL), &(ITER));  \
-       !end_partition_pair_p (&(ITER));                        \
-       (PAIR) = next_partition_pair (&(ITER)))
-
-
-/* Prepare CL for removal of preferred pairs.  When finished, list element 
-   0 has all the coalesce pairs, sorted in order from most important coalesce 
-   to least important.  */
-
-void
-sort_coalesce_list (coalesce_list_p cl)
-{
-  unsigned x, num;
-  partition_pair_p p;
-  partition_pair_iterator ppi;
-
-  gcc_assert (cl->add_mode);
-
-  cl->add_mode = false;
-
-  /* allocate a vector for the pair pointers.  */
-  num = num_coalesce_pairs (cl);
-  cl->num_sorted = num;
-  if (num == 0)
-    return;
-  cl->sorted = XNEWVEC (partition_pair_p, num);
-
-  /* Populate the vector with pointers to the partition pairs.  */
-  
-  x = 0;
-  FOR_EACH_PARTITION_PAIR (p, ppi, cl)
-    cl->sorted[x++] = p;
-  gcc_assert (x == num);
-
-  if (num == 1)
-    return;
-
-  if (num == 2)
-    {
-      if (cl->sorted[0]->cost > cl->sorted[1]->cost)
-        {
-         p = cl->sorted[0];
-         cl->sorted[0] = cl->sorted[1];
-         cl->sorted[1] = p;
-       }
-      return;
-    }
-
-  /* Only call qsort if there are more than 2 items.  */
-  if (num > 2)
-      qsort (cl->sorted, num, sizeof (partition_pair_p), compare_pairs);
-}
-
-
-/* Retrieve the best remaining pair to coalesce from CL.  Returns the 2 
-   partitions via P1 and P2.  Their calculated cost is returned by the function.
-   NO_BEST_COALESCE is returned if the coalesce list is empty.  */
-
-static int
-pop_best_coalesce (coalesce_list_p cl, int *p1, int *p2)
-{
-  partition_pair_p node;
-  int ret;
-
-  gcc_assert (!cl->add_mode);
-
-  if (cl->num_sorted == 0)
-    return NO_BEST_COALESCE;
-
-  node = cl->sorted[--(cl->num_sorted)];
-
-  *p1 = node->first_partition;
-  *p2 = node->second_partition;
-  ret = node->cost;
-  free (node);
-
-  return ret;
-}
-
-
-/* If variable VAR is in a partition in MAP, add a conflict in GRAPH between 
-   VAR and any other live partitions in VEC which are associated via TPA.  
-   Reset the live bit in VEC.  */
-
-static inline void 
-add_conflicts_if_valid (tpa_p tpa, conflict_graph graph,
-                       var_map map, bitmap vec, tree var)
-{ 
-  int p, y, first;
-  p = var_to_partition (map, var);
-  if (p != NO_PARTITION)
-    { 
-      bitmap_clear_bit (vec, p);
-      first = tpa_find_tree (tpa, p);
-      /* If find returns nothing, this object isn't interesting.  */
-      if (first == TPA_NONE)
-        return;
-      /* Only add interferences between objects in the same list.  */
-      for (y = tpa_first_partition (tpa, first);
-          y != TPA_NONE;
-          y = tpa_next_partition (tpa, y))
-       {
-         if (bitmap_bit_p (vec, y))
-           conflict_graph_add (graph, p, y);
-       }
-    }
-}
-
-
-/* If VAR is in a partition of MAP, set the bit for that partition in VEC.  */
-
-static inline void
-set_if_valid (var_map map, bitmap vec, tree var)
-{
-  int p = var_to_partition (map, var);
-  if (p != NO_PARTITION)
-    bitmap_set_bit (vec, p);
-}
-
-/* Return a conflict graph for the information contained in LIVE_INFO.  Only
-   conflicts between items in the same TPA list are added.  If optional 
-   coalesce list CL is passed in, any copies encountered are added.  */
-
-conflict_graph
-build_tree_conflict_graph (tree_live_info_p liveinfo, tpa_p tpa, 
-                          coalesce_list_p cl)
-{
-  conflict_graph graph;
-  var_map map;
-  bitmap live;
-  unsigned x, y, i;
-  basic_block bb;
-  int *partition_link, *tpa_nodes;
-  VEC(int,heap) *tpa_to_clear;
-  unsigned l;
-  ssa_op_iter iter;
-  bitmap_iterator bi;
-
-  map = live_var_map (liveinfo);
-  graph = conflict_graph_new (num_var_partitions (map));
-
-  if (tpa_num_trees (tpa) == 0)
-    return graph;
-
-  live = BITMAP_ALLOC (NULL);
-
-  partition_link = XCNEWVEC (int, num_var_partitions (map) + 1);
-  tpa_nodes = XCNEWVEC (int, tpa_num_trees (tpa));
-  tpa_to_clear = VEC_alloc (int, heap, 50);
-
-  FOR_EACH_BB (bb)
-    {
-      block_stmt_iterator bsi;
-      tree phi;
-      int idx;
-
-      /* Start with live on exit temporaries.  */
-      bitmap_copy (live, live_on_exit (liveinfo, bb));
-
-      for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
-        {
-         bool is_a_copy = false;
-         tree stmt = bsi_stmt (bsi);
-
-         /* A copy between 2 partitions does not introduce an interference 
-            by itself.  If they did, you would never be able to coalesce 
-            two things which are copied.  If the two variables really do 
-            conflict, they will conflict elsewhere in the program.  
-            
-            This is handled specially here since we may also be interested 
-            in copies between real variables and SSA_NAME variables.  We may
-            be interested in trying to coalesce SSA_NAME variables with
-            root variables in some cases.  */
-
-         if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
-           {
-             tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
-             tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-             int p1, p2;
-             int bit;
-
-             if (DECL_P (lhs) || TREE_CODE (lhs) == SSA_NAME)
-               p1 = var_to_partition (map, lhs);
-             else 
-               p1 = NO_PARTITION;
-
-             if (DECL_P (rhs) || TREE_CODE (rhs) == SSA_NAME)
-               p2 = var_to_partition (map, rhs);
-             else 
-               p2 = NO_PARTITION;
-
-             if (p1 != NO_PARTITION && p2 != NO_PARTITION)
-               {
-                 is_a_copy = true;
-                 bit = bitmap_bit_p (live, p2);
-                 /* If the RHS is live, make it not live while we add
-                    the conflicts, then make it live again.  */
-                 if (bit)
-                   bitmap_clear_bit (live, p2);
-                 add_conflicts_if_valid (tpa, graph, map, live, lhs);
-                 if (bit)
-                   bitmap_set_bit (live, p2);
-                 if (cl)
-                   add_coalesce (cl, p1, p2,
-                                 coalesce_cost (bb->frequency,
-                                                maybe_hot_bb_p (bb), false));
-                 set_if_valid (map, live, rhs);
-               }
-           }
-
-         if (!is_a_copy)
-           {
-             tree var;
-             FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_DEF)
-               {
-                 add_conflicts_if_valid (tpa, graph, map, live, var);
-               }
-
-             FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
-               {
-                 set_if_valid (map, live, var);
-               }
-           }
-       }
-
-      /* If result of a PHI is unused, then the loops over the statements
-        will not record any conflicts.  However, since the PHI node is 
-        going to be translated out of SSA form we must record a conflict
-        between the result of the PHI and any variables with are live. 
-        Otherwise the out-of-ssa translation may create incorrect code.  */
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-       {
-         tree result = PHI_RESULT (phi);
-         int p = var_to_partition (map, result);
-
-         if (p != NO_PARTITION && ! bitmap_bit_p (live, p))
-           add_conflicts_if_valid (tpa, graph, map, live, result);
-       }
-
-      /* Anything which is still live at this point interferes.  
-        In order to implement this efficiently, only conflicts between
-        partitions which have the same TPA root need be added.
-        TPA roots which have been seen are tracked in 'tpa_nodes'.  A nonzero
-        entry points to an index into 'partition_link', which then indexes 
-        into itself forming a linked list of partitions sharing a tpa root 
-        which have been seen as live up to this point.  Since partitions start
-        at index zero, all entries in partition_link are (partition + 1).
-
-        Conflicts are added between the current partition and any already seen.
-        tpa_clear contains all the tpa_roots processed, and these are the only
-        entries which need to be zero'd out for a clean restart.  */
-
-      EXECUTE_IF_SET_IN_BITMAP (live, 0, x, bi)
-        {
-         i = tpa_find_tree (tpa, x);
-         if (i != (unsigned)TPA_NONE)
-           {
-             int start = tpa_nodes[i];
-             /* If start is 0, a new root reference list is being started.
-                Register it to be cleared.  */
-             if (!start)
-               VEC_safe_push (int, heap, tpa_to_clear, i);
-
-             /* Add interferences to other tpa members seen.  */
-             for (y = start; y != 0; y = partition_link[y])
-               conflict_graph_add (graph, x, y - 1);
-             tpa_nodes[i] = x + 1;
-             partition_link[x + 1] = start;
-           }
-       }
-
-       /* Now clear the used tpa root references.  */
-       for (l = 0; VEC_iterate (int, tpa_to_clear, l, idx); l++)
-         tpa_nodes[idx] = 0;
-       VEC_truncate (int, tpa_to_clear, 0);
-    }
-
-  free (tpa_nodes);
-  free (partition_link);
-  VEC_free (int, heap, tpa_to_clear);
-  BITMAP_FREE (live);
-  return graph;
-}
-
-
-/* This routine will attempt to coalesce the elements in TPA subject to the
-   conflicts found in GRAPH.  If optional coalesce_list CL is provided, 
-   only coalesces specified within the coalesce list are attempted.  Otherwise 
-   an attempt is made to coalesce as many partitions within each TPA grouping 
-   as possible.  If DEBUG is provided, debug output will be sent there.  */
-
-void
-coalesce_tpa_members (tpa_p tpa, conflict_graph graph, var_map map, 
-                     coalesce_list_p cl, FILE *debug)
-{
-  int x, y, z, w;
-  tree var, tmp;
-
-  /* Attempt to coalesce any items in a coalesce list.  */
-  if (cl)
-    {
-      while (pop_best_coalesce (cl, &x, &y) != NO_BEST_COALESCE)
-        {
-         if (debug)
-           {
-             fprintf (debug, "Coalesce list: (%d)", x);
-             print_generic_expr (debug, partition_to_var (map, x), TDF_SLIM);
-             fprintf (debug, " & (%d)", y);
-             print_generic_expr (debug, partition_to_var (map, y), TDF_SLIM);
-           }
-
-         w = tpa_find_tree (tpa, x);
-         z = tpa_find_tree (tpa, y);
-         if (w != z || w == TPA_NONE || z == TPA_NONE)
-           {
-             if (debug)
-               {
-                 if (w != z)
-                   fprintf (debug, ": Fail, Non-matching TPA's\n");
-                 if (w == TPA_NONE)
-                   fprintf (debug, ": Fail %d non TPA.\n", x);
-                 else
-                   fprintf (debug, ": Fail %d non TPA.\n", y);
-               }
-             continue;
-           }
-         var = partition_to_var (map, x);
-         tmp = partition_to_var (map, y);
-         x = var_to_partition (map, var);
-         y = var_to_partition (map, tmp);
-         if (debug)
-           fprintf (debug, " [map: %d, %d] ", x, y);
-         if (x == y)
-           {
-             if (debug)
-               fprintf (debug, ": Already Coalesced.\n");
-             continue;
-           }
-         if (!conflict_graph_conflict_p (graph, x, y))
-           {
-             z = var_union (map, var, tmp);
-             if (z == NO_PARTITION)
-               {
-                 if (debug)
-                   fprintf (debug, ": Unable to perform partition union.\n");
-                 continue;
-               }
-
-             /* z is the new combined partition. We need to remove the other
-                partition from the list. Set x to be that other partition.  */
-             if (z == x)
-               {
-                 conflict_graph_merge_regs (graph, x, y);
-                 w = tpa_find_tree (tpa, y);
-                 tpa_remove_partition (tpa, w, y);
-               }
-             else
-               {
-                 conflict_graph_merge_regs (graph, y, x);
-                 w = tpa_find_tree (tpa, x);
-                 tpa_remove_partition (tpa, w, x);
-               }
-
-             if (debug)
-               fprintf (debug, ": Success -> %d\n", z);
-           }
-         else
-           if (debug)
-             fprintf (debug, ": Fail due to conflict\n");
-       }
-      /* If using a coalesce list, don't try to coalesce anything else.  */
-      return;
-    }
-
-  for (x = 0; x < tpa_num_trees (tpa); x++)
-    {
-      while (tpa_first_partition (tpa, x) != TPA_NONE)
-        {
-         int p1, p2;
-         /* Coalesce first partition with anything that doesn't conflict.  */
-         y = tpa_first_partition (tpa, x);
-         tpa_remove_partition (tpa, x, y);
-
-         var = partition_to_var (map, y);
-         /* p1 is the partition representative to which y belongs.  */
-         p1 = var_to_partition (map, var);
-         
-         for (z = tpa_next_partition (tpa, y); 
-              z != TPA_NONE; 
-              z = tpa_next_partition (tpa, z))
-           {
-             tmp = partition_to_var (map, z);
-             /* p2 is the partition representative to which z belongs.  */
-             p2 = var_to_partition (map, tmp);
-             if (debug)
-               {
-                 fprintf (debug, "Coalesce : ");
-                 print_generic_expr (debug, var, TDF_SLIM);
-                 fprintf (debug, " &");
-                 print_generic_expr (debug, tmp, TDF_SLIM);
-                 fprintf (debug, "  (%d ,%d)", p1, p2);
-               }
-
-             /* If partitions are already merged, don't check for conflict.  */
-             if (tmp == var)
-               {
-                 tpa_remove_partition (tpa, x, z);
-                 if (debug)
-                   fprintf (debug, ": Already coalesced\n");
-               }
-             else
-               if (!conflict_graph_conflict_p (graph, p1, p2))
-                 {
-                   int v;
-                   if (tpa_find_tree (tpa, y) == TPA_NONE 
-                       || tpa_find_tree (tpa, z) == TPA_NONE)
-                     {
-                       if (debug)
-                         fprintf (debug, ": Fail non-TPA member\n");
-                       continue;
-                     }
-                   if ((v = var_union (map, var, tmp)) == NO_PARTITION)
-                     {
-                       if (debug)
-                         fprintf (debug, ": Fail cannot combine partitions\n");
-                       continue;
-                     }
-
-                   tpa_remove_partition (tpa, x, z);
-                   if (v == p1)
-                     conflict_graph_merge_regs (graph, v, z);
-                   else
-                     {
-                       /* Update the first partition's representative.  */
-                       conflict_graph_merge_regs (graph, v, y);
-                       p1 = v;
-                     }
-
-                   /* The root variable of the partition may be changed
-                      now.  */
-                   var = partition_to_var (map, p1);
-
-                   if (debug)
-                     fprintf (debug, ": Success -> %d\n", v);
-                 }
-               else
-                 if (debug)
-                   fprintf (debug, ": Fail, Conflict\n");
-           }
-       }
-    }
-}
-
-
-/* Send debug info for coalesce list CL to file F.  */
-
-void 
-dump_coalesce_list (FILE *f, coalesce_list_p cl)
-{
-  partition_pair_p node;
-  partition_pair_iterator ppi;
-  int x;
-  tree var;
-
-  if (cl->add_mode)
-    {
-      fprintf (f, "Coalesce List:\n");
-      FOR_EACH_PARTITION_PAIR (node, ppi, cl)
-        {
-         tree var1 = partition_to_var (cl->map, node->first_partition);
-         tree var2 = partition_to_var (cl->map, node->second_partition);
-         print_generic_expr (f, var1, TDF_SLIM);
-         fprintf (f, " <-> ");
-         print_generic_expr (f, var2, TDF_SLIM);
-         fprintf (f, "  (%1d), ", node->cost);
-         fprintf (f, "\n");
-       }
-    }
-  else
-    {
-      fprintf (f, "Sorted Coalesce list:\n");
-      for (x = cl->num_sorted - 1 ; x >=0; x--)
-        {
-         node = cl->sorted[x];
-         fprintf (f, "(%d) ", node->cost);
-         var = partition_to_var (cl->map, node->first_partition);
-         print_generic_expr (f, var, TDF_SLIM);
-         fprintf (f, " <-> ");
-         var = partition_to_var (cl->map, node->second_partition);
-         print_generic_expr (f, var, TDF_SLIM);
-         fprintf (f, "\n");
-       }
-    }
-}
-
-
-/* Output tree_partition_associator object TPA to file F..  */
-
-void
-tpa_dump (FILE *f, tpa_p tpa)
-{
-  int x, i;
-
-  if (!tpa)
-    return;
-
-  for (x = 0; x < tpa_num_trees (tpa); x++)
-    {
-      print_generic_expr (f, tpa_tree (tpa, x), TDF_SLIM);
-      fprintf (f, " : (");
-      for (i = tpa_first_partition (tpa, x); 
-          i != TPA_NONE;
-          i = tpa_next_partition (tpa, i))
-       {
-         fprintf (f, "(%d)",i);
-         print_generic_expr (f, partition_to_var (tpa->map, i), TDF_SLIM);
-         fprintf (f, " ");
-
-#ifdef ENABLE_CHECKING
-         if (tpa_find_tree (tpa, i) != x)
-           fprintf (f, "**find tree incorrectly set** ");
-#endif
-
-       }
-      fprintf (f, ")\n");
-    }
-  fflush (f);
-}
-
-
 /* Output partition map MAP to file F.  */
 
 void
@@ -1700,8 +788,8 @@ dump_var_map (FILE *f, var_map map)
 
   for (x = 0; x < map->num_partitions; x++)
     {
-      if (map->compact_to_partition != NULL)
-       p = map->compact_to_partition[x];
+      if (map->view_to_partition != NULL)
+       p = map->view_to_partition[x];
       else
        p = x;
 
@@ -1712,8 +800,8 @@ dump_var_map (FILE *f, var_map map)
       for (y = 1; y < num_ssa_names; y++)
         {
          p = partition_find (map->var_partition, y);
-         if (map->partition_to_compact)
-           p = map->partition_to_compact[p];
+         if (map->partition_to_view)
+           p = map->partition_to_view[p];
          if (p == (int)x)
            {
              if (t++ == 0)
@@ -1771,7 +859,10 @@ dump_live_info (FILE *f, tree_live_info_p live, int flag)
     }
 }
 
+
 #ifdef ENABLE_CHECKING
+/* Verify that SSA_VAR is a non-virtual SSA_NAME.  */
+
 void
 register_ssa_partition_check (tree ssa_var)
 {
@@ -1787,6 +878,7 @@ register_ssa_partition_check (tree ssa_var)
 
 
 /* Verify that the info in LIVE matches the current cfg.  */
+
 static void
 verify_live_on_entry (tree_live_info_p live)
 {
@@ -1802,7 +894,6 @@ verify_live_on_entry (tree_live_info_p live)
    /* Check for live on entry partitions and report those with a DEF in
       the program. This will typically mean an optimization has done
       something wrong.  */
-
   bb = ENTRY_BLOCK_PTR;
   num = 0;
   FOR_EACH_EDGE (e, ei, bb->succs)
index 19c7089..bddd4ba 100644 (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;
 
-#define VAR_ANN_PARTITION(ann) (ann->partition)
-#define VAR_ANN_ROOT_INDEX(ann) (ann->root_index)
 
-#define NO_PARTITION           -1
+/* Partition number of a  non ssa-name variable.  */
+#define VAR_ANN_PARTITION(ann) (ann->partition)
+/* Index iot the basevar table of a non ssa-name variable.  */
+#define VAR_ANN_BASE_INDEX(ann) (ann->base_index)
 
-/* Flags to pass to compact_var_map  */
 
-#define VARMAP_NORMAL          0
-#define VARMAP_NO_SINGLE_DEFS  1
+/* Value used to represent no partition number.  */
+#define NO_PARTITION           -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.
-
-   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");
-}
-
+/* From tree-ssa-coalesce.c  */
+extern var_map coalesce_ssa_name (void);
 
-/* 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);
index 2bd58cc..78f8a12 100644 (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)