This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Out Of SSA Rewrite - The New Coalescer patch 5/5


This is the big one. This patch restructures the out of ssa pass and
implements the slower parts faster. 

The original plan was to abandon the conflict graph completely, but with
the change to maintaining BB based live-on-entry data, that became more
difficult. Instead, the amount of things kept in the conflict graph has
been reduced to a minimum, and the only remaining slowdown I have seen
from large conflict graphs (390,000 live variables) will eventually be
addressed by the ssa_name pressure reduction code. Even in this case,
there is significant reduction in time.

The motivation for the rewrite was twofold. I needed some restructuring
in order to move forward with my longer term plan of combining out of
ssa and expand, as well as the shorter term ssa-name pressure reduction
optimizations.  The other factor was to address some of the performance
issues on the larger testcase.  While doing this, I removed a lot of the
extraneous crud that was leftover from previous work which was no longer
needed.  The reslut should be much more readable.

So what exactly is different?  The coalescing code has been split out to
tree-ssa-coalesce.c.  the original abstract implementation was based on
a TPA data structure which stood for Tree Partition Associator. It
allowed the coalescing code to be shared, and both ssa-name could be
coalesced, as well as non-ssa names when -fcombine-temps was being used.
THat flag has been removed, and so has all the TPA_ data structure.  

There also use ot be a root_var structure which was used to determine
what ssa versions were associated with any given VAR_DECL.  This data
structure has been removed, and any required equivalent functionality
placed directly in the var_map structure. 

I have also removed the -ftree-no-lrs option. This option disabled the
live range splitting out of ssa does.  It was actually more work to not
do the splitting, and the required additional code that polluted the
code base. That also helps clean things up somewhat.

In vary large functions, the sorted list of coalesceable pairs was still
causing some time issues. It turns out that something like 50% of all
coalescable pairs have a cost of 1. So there is a minor tweak in that
any "cost one" pair is simply stuck in a "cost one" list, and pulled
when needed. This made a noticeable difference on a couple of large
functions.

The conflict graph in conflict.c that I was reusing had some issues when
very large graphs were created. it is hash based, and when I had 390,000
interferences, no small amount of time was spent in the hash functions.
I implemented a custom interference graph for out of ssa using bitmaps
which runs faster.

Building the interference graph has been streamlined quite a bit as
well, and a special data structure for tracking what versions of base
variables are live (called live_track) help add conflicts more
efficiently without nearly as many bitmap examinations/traversals.

The mechanism for dealing with abnormal coalesces was combined with
normal coalesces by introducing a MUST_COALESCE_COST.  These are
max-cost pairs which if they don't coalesce, trigger an error.  This
helped clean code up as well.

The old var_map compaction mechanism was a little obscure, so it has
been replaced with a clearer partition_view set of routines. It amounts
to the same thing, but easily allows different views of the same data.

Thats most of it. This has been bootstrapped and regression tested on
i686-pc-linux-gnu.

Andrew


	* 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.




	* 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.

diff -cpN ../../ter/gcc/common.opt ./common.opt
*** ../../ter/gcc/common.opt	2006-11-10 12:36:33.000000000 -0500
--- ./common.opt	2006-11-12 09:51:35.000000000 -0500
*************** ftree-ter
*** 993,1002 ****
  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
--- 993,998 ----
diff -cpN ../../ter/gcc/Makefile.in ./Makefile.in
*** ../../ter/gcc/Makefile.in	2006-11-10 17:46:56.000000000 -0500
--- ./Makefile.in	2006-11-12 10:12:04.000000000 -0500
*************** OBJS-common = \
*** 985,991 ****
   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-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		   \
--- 985,991 ----
   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-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		   \
*************** tree-into-ssa.o : tree-into-ssa.c $(TREE
*** 1851,1867 ****
     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-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-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) \
--- 1851,1864 ----
     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) \
!    $(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) \
!    $(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) \
*************** tree-phinodes.o : tree-phinodes.c $(CONF
*** 1913,1922 ****
  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-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) \
--- 1910,1917 ----
  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) $(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) \
diff -cpN ../../ter/gcc/opts.c ./opts.c
*** ../../ter/gcc/opts.c	2006-11-06 09:02:36.000000000 -0500
--- ./opts.c	2006-11-12 09:51:35.000000000 -0500
*************** decode_options (unsigned int argc, const
*** 449,455 ****
        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;
--- 449,454 ----
diff -cpN ../../ter/gcc/tree-flow.h ./tree-flow.h
*** ../../ter/gcc/tree-flow.h	2006-11-06 09:02:36.000000000 -0500
--- ./tree-flow.h	2006-11-12 09:51:36.000000000 -0500
*************** struct var_ann_d GTY(())
*** 161,168 ****
       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;
  
    /* Nonzero if this variable is in the alias set of another variable.  */
    unsigned is_aliased : 1;
--- 161,168 ----
       been seen yet or not.  */
    unsigned out_of_ssa_tag : 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;
*************** struct var_ann_d GTY(())
*** 200,207 ****
       variable represents storage for.  */
    unsigned partition;
  
!   /* Used by the root-var object in tree-ssa-live.[ch].  */
!   unsigned root_index;
  
    /* During into-ssa and the dominator optimizer, this field holds the
       current version of this variable (an SSA_NAME).  */
--- 200,207 ----
       variable represents storage for.  */
    unsigned partition;
  
!   /* 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).  */
diff -cpN ../../ter/gcc/tree-flow-inline.h ./tree-flow-inline.h
*** ../../ter/gcc/tree-flow-inline.h	2006-11-06 09:02:36.000000000 -0500
--- ./tree-flow-inline.h	2006-11-12 10:14:08.000000000 -0500
*************** has_single_use (tree var)
*** 472,477 ****
--- 472,489 ----
    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
Common subdirectories: ../../ter/gcc/treelang and ./treelang
diff -cpN ../../ter/gcc/tree-outof-ssa.c ./tree-outof-ssa.c
*** ../../ter/gcc/tree-outof-ssa.c	2006-11-10 16:51:41.000000000 -0500
--- ./tree-outof-ssa.c	2006-11-12 10:09:02.000000000 -0500
***************
*** 1,5 ****
  /* Convert a program in SSA form into Normal form.
!    Copyright (C) 2004, 2005 Free Software Foundation, Inc.
     Contributed by Andrew Macleod <amacleod@redhat.com>
  
  This file is part of GCC.
--- 1,5 ----
  /* Convert a program in SSA form into Normal form.
!    Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
     Contributed by Andrew Macleod <amacleod@redhat.com>
  
  This file is part of GCC.
*************** Boston, MA 02110-1301, USA.  */
*** 24,57 ****
  #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
--- 24,40 ----
*************** typedef struct _elim_graph {
*** 101,136 ****
  } *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.  */
  
--- 84,89 ----
*************** elim_create (elim_graph g, int T)
*** 489,494 ****
--- 442,448 ----
    
  }
  
+ 
  /* Eliminate all the phi nodes on edge E in graph G.  */
  
  static void
*************** eliminate_phi (edge e, elim_graph g)
*** 541,947 ****
  }
  
  
- /* 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 (default_def (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;
    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++)
--- 495,510 ----
  }
  
  
  /* Take the ssa-name var_map MAP, and assign real variables to each 
     partition.  */
  
  static void
  assign_vars (var_map map)
  {
!   int x, num;
!   tree var;
    var_ann_t ann;
!   tree root;
  
    num = num_var_partitions (map);
    for (x = 0; x < num; x++)
*************** assign_vars (var_map map)
*** 949,1011 ****
        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;
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
! 	      fprintf (dump_file, "partition %d 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)
  	    {
! 	      if (dump_file && (dump_flags & TDF_DETAILS))
! 		print_exprs (dump_file, "", t, "  --> ", var, "\n");
! 	      change_partition_var (map, var, rep);
! 	      continue;
  	    }
! 
! 	  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);
! 
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
! 	      fprintf (dump_file, " -->  New temp:  '");
! 	      print_generic_expr (dump_file, var, TDF_SLIM);
! 	      fprintf (dump_file, "'\n");
  	    }
  	}
      }
- 
-   root_var_delete (rv);
  }
  
  
--- 512,546 ----
        var = partition_to_var (map, x);
        if (TREE_CODE (var) != SSA_NAME)
  	{
  	  ann = var_ann (var);
! 	  /* 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 already has variable ", x);
  	      print_generic_expr (dump_file, var, TDF_SLIM);
  	      fprintf (dump_file, " assigned to it.\n");
  	    }
  	}
!       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)
  	    {
! 	      root = create_temp (root);
! 	      ann = var_ann (root);
  	    }
! 	  /* ROOT has not been coalesced yet, so use it.  */
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
! 	      fprintf (dump_file, "Partition %d is assigned to var ", x);
! 	      print_generic_stmt (dump_file, root, TDF_SLIM);
  	    }
+ 	  change_partition_var (map, root, x);
  	}
      }
  }
  
  
*************** replace_use_variable (var_map map, use_o
*** 1028,1034 ****
          {
  	  tree new_expr = TREE_OPERAND (expr[version], 1);
  	  SET_USE (p, new_expr);
! 	  /* Clear the stmt's RHS, or GC might bite us.  */
  	  TREE_OPERAND (expr[version], 1) = NULL_TREE;
  	  return true;
  	}
--- 563,570 ----
          {
  	  tree new_expr = TREE_OPERAND (expr[version], 1);
  	  SET_USE (p, new_expr);
! 
! 	  /* Clear the stmt's RHS since it now belongs here.  */
  	  TREE_OPERAND (expr[version], 1) = NULL_TREE;
  	  return true;
  	}
*************** replace_def_variable (var_map map, def_o
*** 1056,1074 ****
    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;
! 	}
!     }
  
    new_var = var_to_partition_to_var (map, var);
    if (new_var)
--- 592,600 ----
    tree new_var;
    tree var = DEF_FROM_PTR (def_p);
  
!   /* 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)
*************** rewrite_trees (var_map map, tree *values
*** 1144,1158 ****
    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);
--- 670,681 ----
*************** static edge leader_match = NULL;
*** 1264,1271 ****
  
  
  /* 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 
  same_stmt_list_p (edge e)
  {
    return (e->aux == (PTR) leader_match) ? true : false;
--- 787,796 ----
  
  
  /* Pass this function to make_forwarder_block so that all the edges with
!    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;
*************** same_stmt_list_p (edge e)
*** 1273,1278 ****
--- 798,804 ----
  
  
  /* Return TRUE if S1 and S2 are equivalent copies.  */
+ 
  static inline bool
  identical_copies_p (tree s1, tree s2)
  {
*************** identical_copies_p (tree s1, tree s2)
*** 1296,1302 ****
  }
  
  
! /* Compare the PENDING_STMT list for two edges, and return true if the lists
     contain the same sequence of copies.  */
  
  static inline bool 
--- 822,828 ----
  }
  
  
! /* Compare the PENDING_STMT list for edges E1 and E2. Return true if the lists
     contain the same sequence of copies.  */
  
  static inline bool 
*************** analyze_edges_for_bb (basic_block bb)
*** 1383,1388 ****
--- 909,915 ----
  	  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)
*************** analyze_edges_for_bb (basic_block bb)
*** 1473,1483 ****
        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.  */
--- 1000,1008 ----
*************** perform_edge_inserts (void)
*** 1604,1631 ****
  }
  
  
! /* Remove the variables specified in MAP from SSA form.  FLAGS indicate what
!    options should be used.  */
  
  static void
! remove_ssa_form (var_map map, int flags)
  {
-   tree_live_info_p liveinfo;
    basic_block bb;
    tree phi, next;
    tree *values = NULL;
  
!   /* 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);
  
!   /* Make sure even single occurrence variables are in the list now.  */
!   compact_var_map (map, VARMAP_NORMAL);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
--- 1129,1151 ----
  }
  
  
! /* 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 (bool perform_ter)
  {
    basic_block bb;
    tree phi, next;
    tree *values = NULL;
+   var_map map;
  
!   map = coalesce_ssa_name ();
  
!   /* 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))
      {
*************** remove_ssa_form (var_map map, int flags)
*** 1633,1639 ****
        dump_var_map (dump_file, map);
      }
  
!   if (flags & SSANORM_PERFORM_TER)
      {
        values = find_replaceable_exprs (map);
        if (values && dump_file && (dump_flags & TDF_DETAILS))
--- 1153,1159 ----
        dump_var_map (dump_file, map);
      }
  
!   if (perform_ter)
      {
        values = find_replaceable_exprs (map);
        if (values && dump_file && (dump_flags & TDF_DETAILS))
*************** remove_ssa_form (var_map map, int flags)
*** 1645,1657 ****
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
!       fprintf (dump_file, "After Root variable replacement:\n");
        dump_var_map (dump_file, map);
      }
  
-   if (liveinfo)
-     delete_tree_live_info (liveinfo);
- 
    rewrite_trees (map, values);
  
    if (values)
--- 1165,1174 ----
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
!       fprintf (dump_file, "After Base variable replacement:\n");
        dump_var_map (dump_file, map);
      }
  
    rewrite_trees (map, values);
  
    if (values)
*************** remove_ssa_form (var_map map, int flags)
*** 1672,1679 ****
--- 1189,1199 ----
  
    /* 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
*************** insert_backedge_copies (void)
*** 1707,1717 ****
  	      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 ((e->flags & EDGE_DFS_BACK)
  		  && (TREE_CODE (arg) != SSA_NAME
  		      || SSA_NAME_VAR (arg) != result_var))
--- 1227,1236 ----
  	      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 then a copy statement will be 
! 		 needed.  */
  	      if ((e->flags & EDGE_DFS_BACK)
  		  && (TREE_CODE (arg) != SSA_NAME
  		      || SSA_NAME_VAR (arg) != result_var))
*************** insert_backedge_copies (void)
*** 1726,1732 ****
  		  /* 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
--- 1245,1250 ----
*************** insert_backedge_copies (void)
*** 1741,1748 ****
  			continue;
  		    }
  
! 		  /* Create a new instance of the underlying
! 		     variable of the PHI result.  */
  		  stmt = build2 (MODIFY_EXPR, TREE_TYPE (result_var),
  				 NULL_TREE, PHI_ARG_DEF (phi, i));
  		  name = make_ssa_name (result_var, stmt);
--- 1259,1266 ----
  			continue;
  		    }
  
! 		  /* Create a new instance of the underlying variable of the 
! 		     PHI result.  */
  		  stmt = build2 (MODIFY_EXPR, TREE_TYPE (result_var),
  				 NULL_TREE, PHI_ARG_DEF (phi, i));
  		  name = make_ssa_name (result_var, stmt);
*************** insert_backedge_copies (void)
*** 1761,1805 ****
      }
  }
  
! /* Take the current function out of SSA form, 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.
- 
       A significant number of such cases can be handled here by inserting
       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);
  
    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);
- 
    in_ssa_p = false;
    return 0;
  }
--- 1279,1309 ----
      }
  }
  
! 
! /* 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)
  {
    /* 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.
       A significant number of such cases can be handled here by inserting
       copies into the loop itself.  */
    insert_backedge_copies ();
  
    eliminate_virtual_phis ();
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
  
!   remove_ssa_form (flag_tree_ter && !flag_mudflap);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
  
    in_ssa_p = false;
    return 0;
  }
diff -cpN ../../ter/gcc/tree-ssa-coalesce.c ./tree-ssa-coalesce.c
*** ../../ter/gcc/tree-ssa-coalesce.c	1969-12-31 19:00:00.000000000 -0500
--- ./tree-ssa-coalesce.c	2006-11-21 10:17:41.000000000 -0500
***************
*** 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) == MODIFY_EXPR)
+ 	    {
+ 	      tree lhs = TREE_OPERAND (stmt, 0);
+ 	      tree rhs = TREE_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 MODIFY_EXPR:
+ 	      {
+ 		tree op1 = TREE_OPERAND (stmt, 0);
+ 		tree op2 = TREE_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 (default_def (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 (default_def (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;
+ }
+ 
diff -cpN ../../ter/gcc/tree-ssa-live.c ./tree-ssa-live.c
*** ../../ter/gcc/tree-ssa-live.c	2006-11-10 16:14:50.000000000 -0500
--- ./tree-ssa-live.c	2006-11-12 10:10:56.000000000 -0500
*************** Boston, MA 02110-1301, USA.  */
*** 24,67 ****
  #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.
! 
!    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.  */
  
  /* Create a variable partition map of SIZE, initialize and return it.  */
  
  var_map
--- 24,130 ----
  #include "coretypes.h"
  #include "tm.h"
  #include "tree.h"
  #include "diagnostic.h"
  #include "bitmap.h"
  #include "tree-flow.h"
  #include "tree-dump.h"
  #include "tree-ssa-live.h"
  #include "toplev.h"
  
  #ifdef ENABLE_CHECKING
  static void  verify_live_on_entry (tree_live_info_p);
  #endif
  
  
! /* 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);
+     }
+ 
+   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
*************** init_var_map (int size)
*** 75,84 ****
  	      = (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->num_partitions = size;
    map->partition_size = size;
    return map;
  }
  
--- 138,150 ----
  	      = (tree *)xmalloc (size * sizeof (tree));
    memset (map->partition_to_var, 0, size * sizeof (tree));
  
!   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;
  }
  
*************** init_var_map (int size)
*** 88,99 ****
  void
  delete_var_map (var_map 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);
    free (map);
  }
  
--- 154,166 ----
  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_view)
!     free (map->partition_to_view);
!   if (map->view_to_partition)
!     free (map->view_to_partition);
    free (map);
  }
  
*************** var_union (var_map map, tree var1, tree 
*** 109,125 ****
    tree root_var = NULL_TREE;
    tree other_var = NULL_TREE;
  
!   /* This is independent of partition_to_compact. If partition_to_compact is 
       on, then whichever one of these partitions is absorbed will never have a
!      dereference into the partition_to_compact 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];
        root_var = var1;
      }
    
--- 176,192 ----
    tree root_var = NULL_TREE;
    tree other_var = NULL_TREE;
  
!   /* 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_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->view_to_partition)
!         p1 = map->view_to_partition[p1];
        root_var = var1;
      }
    
*************** var_union (var_map map, tree var1, tree 
*** 128,135 ****
    else
      {
        p2 = var_to_partition (map, var2);
!       if (map->compact_to_partition)
!         p2 = map->compact_to_partition[p2];
  
        /* If there is no root_var set, or it's not a user variable, set the
  	 root_var to this one.  */
--- 195,202 ----
    else
      {
        p2 = var_to_partition (map, var2);
!       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.  */
*************** var_union (var_map map, tree var1, tree 
*** 150,157 ****
    else
      p3 = partition_union (map->var_partition, p1, p2);
  
!   if (map->partition_to_compact)
!     p3 = map->partition_to_compact[p3];
  
    if (root_var)
      change_partition_var (map, root_var, p3);
--- 217,224 ----
    else
      p3 = partition_union (map->var_partition, p1, p2);
  
!   if (map->partition_to_view)
!     p3 = map->partition_to_view[p3];
  
    if (root_var)
      change_partition_var (map, root_var, p3);
*************** var_union (var_map map, tree var1, tree 
*** 161,172 ****
    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.
  
     This is implemented such that compaction doesn't affect partitioning.
     Ie., once partitions are created and possibly merged, running one
--- 228,239 ----
    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.  
  
     This is implemented such that compaction doesn't affect partitioning.
     Ie., once partitions are created and possibly merged, running one
*************** var_union (var_map map, tree var1, tree 
*** 179,274 ****
     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)
  {
!   sbitmap used;
!   int tmp, root, root_i;
!   unsigned int x, limit, count;
!   tree var;
!   root_var_p rv = NULL;
  
!   limit = map->partition_size;
!   used = sbitmap_alloc (limit);
!   sbitmap_zero (used);
  
!   /* Already compressed? Abandon the old one.  */
!   if (map->partition_to_compact)
      {
!       free (map->partition_to_compact);
!       map->partition_to_compact = NULL;
      }
!   if (map->compact_to_partition)
      {
!       free (map->compact_to_partition);
!       map->compact_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++)
      {
        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++;
! 	}
      }
  
!   /* Build a compacted partitioning.  */
!   if (count != limit)
!     {
!       sbitmap_iterator sbi;
  
!       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)
  	{
! 	  map->partition_to_compact[x] = count;
! 	  map->compact_to_partition[count] = x;
  	  var = map->partition_to_var[x];
  	  if (TREE_CODE (var) != SSA_NAME)
! 	    change_partition_var (map, var, count);
! 	  count++;
  	}
      }
    else
!     {
!       free (map->partition_to_compact);
!       map->partition_to_compact = NULL;
!     }
  
!   map->num_partitions = count;
  
!   if (rv)
!     root_var_delete (rv);
!   sbitmap_free (used);
  }
  
  
  /* 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.  */
    
  void 
  change_partition_var (var_map map, tree var, int part)
--- 246,385 ----
     definitions, and then 'recompact' later to include all the single
     definitions for assignment to program variables.  */
  
! 
! /* 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)
  {
!   bitmap used;
!   int tmp;
!   unsigned int x;
  
!   used = BITMAP_ALLOC (NULL);
  
!   /* Already in a view? Abandon the old one.  */
!   if (map->partition_to_view)
      {
!       free (map->partition_to_view);
!       map->partition_to_view = NULL;
      }
!   if (map->view_to_partition)
      {
!       free (map->view_to_partition);
!       map->view_to_partition = NULL;
      }
  
    /* Find out which partitions are actually referenced.  */
!   for (x = 0; x < map->partition_size; x++)
      {
        tmp = partition_find (map->var_partition, x);
!       if (map->partition_to_var[tmp] != NULL_TREE && !bitmap_bit_p (used, tmp))
! 	bitmap_set_bit (used, tmp);
      }
  
!   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)
!     {
!       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));
! 
!       i = 0;
!       /* Give each selected partition an index.  */
!       EXECUTE_IF_SET_IN_BITMAP (selected, 0, x, bi)
  	{
! 	  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, 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)
!     {
!       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);
! 
!   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 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)
*************** change_partition_var (var_map map, tree 
*** 280,289 ****
    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;
  }
  
  static inline void mark_all_vars_used (tree *);
  
  /* Helper function for mark_all_vars_used, called via walk_tree.  */
--- 391,401 ----
    ann = var_ann (var);
    ann->out_of_ssa_tag = 1;
    VAR_ANN_PARTITION (ann) = part;
!   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.  */
*************** mark_all_vars_used_1 (tree *tp, int *wal
*** 319,324 ****
--- 431,437 ----
    return NULL;
  }
  
+ 
  /* Mark all VAR_DECLS under *EXPR_P as used, so that they won't be 
     eliminated during the tree->rtl conversion process.  */
  
*************** remove_unused_locals (void)
*** 394,495 ****
      }
  }
  
- /* 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.  */
  
--- 507,512 ----
*************** delete_tree_live_info (tree_live_info_p 
*** 541,547 ****
  }
  
  
! /* 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.  */
--- 558,564 ----
  }
  
  
! /* 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.  */
*************** loe_visit_block (tree_live_info_p live, 
*** 565,572 ****
        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.  
  	 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]);
--- 582,589 ----
        pred_bb = e->src;
        if (pred_bb == ENTRY_BLOCK_PTR)
  	continue;
!       /* 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]);
*************** set_var_live_on_entry (tree ssa_name, tr
*** 636,642 ****
    if (stmt)
      {
        def_bb = bb_for_stmt (stmt);
!       /* Mark defs in liveout bitmap for now.  */
        if (def_bb)
  	bitmap_set_bit (live->liveout[def_bb->index], p);
      }
--- 653,659 ----
    if (stmt)
      {
        def_bb = bb_for_stmt (stmt);
!       /* Mark defs in liveout bitmap temporarily.  */
        if (def_bb)
  	bitmap_set_bit (live->liveout[def_bb->index], p);
      }
*************** calculate_live_on_exit (tree_live_info_p
*** 698,704 ****
    edge e;
    edge_iterator ei;
  
!   /* live on entry calculations used the liveouit vector for defs.  */
    FOR_EACH_BB (bb)
      bitmap_clear (liveinfo->liveout[bb->index]);
  
--- 715,721 ----
    edge e;
    edge_iterator ei;
  
!   /* live on entry calculations used liveout vectors for defs, clear them.  */
    FOR_EACH_BB (bb)
      bitmap_clear (liveinfo->liveout[bb->index]);
  
*************** calculate_live_on_exit (tree_live_info_p
*** 720,726 ****
  	      bitmap_set_bit (liveinfo->liveout[e->src->index], p);
  	  }
  
!       /* 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],
--- 737,743 ----
  	      bitmap_set_bit (liveinfo->liveout[e->src->index], p);
  	  }
  
!       /* 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],
*************** calculate_live_on_exit (tree_live_info_p
*** 728,733 ****
--- 745,751 ----
      }
  }
  
+ 
  /* Given partition map MAP, calculate all the live on entry bitmaps for 
     each partition.  Return a new live info object.  */
  
*************** calculate_live_ranges (var_map map)
*** 757,1692 ****
  }
  
  
- /* 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 equivilent 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 Ascendiong 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) == MODIFY_EXPR)
- 	    {
- 	      tree lhs = TREE_OPERAND (stmt, 0);
- 	      tree rhs = TREE_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
--- 775,780 ----
*************** dump_var_map (FILE *f, var_map map)
*** 1700,1707 ****
  
    for (x = 0; x < map->num_partitions; x++)
      {
!       if (map->compact_to_partition != NULL)
! 	p = map->compact_to_partition[x];
        else
  	p = x;
  
--- 788,795 ----
  
    for (x = 0; x < map->num_partitions; x++)
      {
!       if (map->view_to_partition != NULL)
! 	p = map->view_to_partition[x];
        else
  	p = x;
  
*************** dump_var_map (FILE *f, var_map map)
*** 1712,1719 ****
        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 (p == (int)x)
  	    {
  	      if (t++ == 0)
--- 800,807 ----
        for (y = 1; y < num_ssa_names; y++)
          {
  	  p = partition_find (map->var_partition, y);
! 	  if (map->partition_to_view)
! 	    p = map->partition_to_view[p];
  	  if (p == (int)x)
  	    {
  	      if (t++ == 0)
*************** dump_live_info (FILE *f, tree_live_info_
*** 1771,1777 ****
--- 859,868 ----
      }
  }
  
+ 
  #ifdef ENABLE_CHECKING
+ /* Verify that SSA_VAR is a non-virtual SSA_NAME.  */
+ 
  void
  register_ssa_partition_check (tree ssa_var)
  {
*************** register_ssa_partition_check (tree ssa_v
*** 1787,1792 ****
--- 878,884 ----
  
  
  /* Verify that the info in LIVE matches the current cfg.  */
+ 
  static void
  verify_live_on_entry (tree_live_info_p live)
  {
*************** verify_live_on_entry (tree_live_info_p l
*** 1802,1808 ****
     /* 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)
--- 894,899 ----
diff -cpN ../../ter/gcc/tree-ssa-live.h ./tree-ssa-live.h
*** ../../ter/gcc/tree-ssa-live.h	2006-11-10 16:50:16.000000000 -0500
--- ./tree-ssa-live.h	2006-11-12 10:11:41.000000000 -0500
*************** Boston, MA 02110-1301, USA.  */
*** 26,81 ****
  #include "partition.h"
  #include "vecprim.h"
  
! /* Used to create the variable mapping when we go out of SSA form.  */
  typedef struct _var_map
  {
!   /* The partition of all variables.  */
    partition var_partition;
  
!   /* Vector for compacting partitions.  */
!   int *partition_to_compact;
!   int *compact_to_partition;
  
!   /* Mapping of partition numbers to vars.  */
    tree *partition_to_var;
  
!   /* Current number of partitions.  */
    unsigned int num_partitions;
  
!   /* Original partition size.  */
    unsigned int partition_size;
  } *var_map;
  
- #define VAR_ANN_PARTITION(ann) (ann->partition)
- #define VAR_ANN_ROOT_INDEX(ann) (ann->root_index)
  
! #define NO_PARTITION		-1
  
- /* Flags to pass to compact_var_map  */
  
! #define VARMAP_NORMAL		0
! #define VARMAP_NO_SINGLE_DEFS	1
  
  extern var_map init_var_map (int);
  extern void delete_var_map (var_map);
  extern void dump_var_map (FILE *, var_map);
  extern int var_union (var_map, tree, tree);
  extern void change_partition_var (var_map, tree, int);
! extern void compact_var_map (var_map, int);
  #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.  */
  
  static inline unsigned
  num_var_partitions (var_map map)
--- 26,108 ----
  #include "partition.h"
  #include "vecprim.h"
  
! 
! 
! /* 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 manager of all variables.  */
    partition var_partition;
  
!   /* Vector for managing partitions views.  */
!   int *partition_to_view;
!   int *view_to_partition;
  
!   /* Mapping of partition numbers to variables.  */
    tree *partition_to_var;
  
!   /* Current number of partitions in var_map based on the current view.  */
    unsigned int num_partitions;
  
!   /* Original full partition size.  */
    unsigned int partition_size;
+ 
+   /* Number of base variables in the base var list.  */
+   int num_basevars;
+ 
+   /* Map of partitions numbers to base variable table indexes.  */
+   int *partition_to_base_index;
+ 
+   /* Table of base variable's.  */
+   VEC (tree, heap) *basevars;
  } *var_map;
  
  
! /* Partition number of a  non ssa-name variable.  */
! #define VAR_ANN_PARTITION(ann) (ann->partition)
! /* Index iot the basevar table of a non ssa-name variable.  */
! #define VAR_ANN_BASE_INDEX(ann) (ann->base_index)
  
  
! /* Value used to represent no partition number.  */
! #define NO_PARTITION		-1
  
  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 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
  
  
! /* Return number of partitions in MAP.  */
  
  static inline unsigned
  num_var_partitions (var_map map)
*************** num_var_partitions (var_map map)
*** 90,97 ****
  static inline tree
  partition_to_var (var_map map, int i)
  {
!   if (map->compact_to_partition)
!     i = map->compact_to_partition[i];
    i = partition_find (map->var_partition, i);
    return map->partition_to_var[i];
  }
--- 117,124 ----
  static inline tree
  partition_to_var (var_map map, int 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];
  }
*************** partition_to_var (var_map map, int i)
*** 100,111 ****
  /* 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)
  {
    int part;
    part = partition_find (map->var_partition, version);
!   if (map->partition_to_compact)
!     part = map->partition_to_compact[part];
    if (part == NO_PARTITION)
      return NULL_TREE;
    
--- 127,139 ----
  /* 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)
  {
    int part;
    part = partition_find (map->var_partition, version);
!   if (map->partition_to_view)
!     part = map->partition_to_view[part];
    if (part == NO_PARTITION)
      return NULL_TREE;
    
*************** var_to_partition (var_map map, tree var)
*** 125,132 ****
    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];
      }
    else
      {
--- 153,160 ----
    if (TREE_CODE (var) == SSA_NAME)
      {
        part = partition_find (map->var_partition, SSA_NAME_VERSION (var));
!       if (map->partition_to_view)
! 	part = map->partition_to_view[part];
      }
    else
      {
*************** var_to_partition_to_var (var_map map, tr
*** 155,163 ****
  }
  
  
! /* 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.  */ 
  
  static inline void
  register_ssa_partition (var_map map, tree ssa_var)
--- 183,211 ----
  }
  
  
! /* 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)
*************** register_ssa_partition (var_map map, tre
*** 170,176 ****
  
    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;
  }
  
  
--- 218,224 ----
  
    version = SSA_NAME_VERSION (ssa_var);
    if (map->partition_to_var[version] == NULL_TREE)
!     map->partition_to_var[version] = ssa_var;
  }
  
  
*************** extern void delete_tree_live_info (tree_
*** 238,250 ****
  #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.  */
  
--- 286,291 ----
*************** make_live_on_entry (tree_live_info_p liv
*** 316,590 ****
  }
  
  
! /* 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");
- }
- 
- 
- /* 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);
--- 357,365 ----
  }
  
  
! /* From tree-ssa-coalesce.c  */
! extern var_map coalesce_ssa_name (void);
  
  
  /* From tree-ssa-ter.c  */
  extern tree *find_replaceable_exprs (var_map);
diff -cpN ../../ter/gcc/tree-ssa-ter.c ./tree-ssa-ter.c
*** ../../ter/gcc/tree-ssa-ter.c	2006-11-10 16:52:29.000000000 -0500
--- ./tree-ssa-ter.c	2006-11-12 10:09:02.000000000 -0500
*************** Boston, MA 02110-1301, USA.  */
*** 25,53 ****
  #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)
--- 25,35 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]