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]

[PATCH][alias-improvements] Get rid of old TBAA aliasing code, fix early call-clobbers


This removes all traces of SMTs, NMTs, MPTs and the code creating or
dealing with them.

It also makes us have correct call-clobber state during early
optimization, possibly refined by points-to analysis when available.
As we glob nonlocals in points-to we can also glob globals for
call clobber purposes and simply only record locals in the call-clobber
bitmap.  I dropped the bit in the var annotation because it is tedious
and error-prone to keep them in sync.

I tried to split both patches (after the fact), but it was too difficult.

Bootstrapped and tested on x86_64-unknown-linux-gnu w/o ada (Ada is broken
with that patch, the testsuite is clean but stage3 just complains about
ada.ads:19:01: "end Ada;" expected in column 1
I failed to even start debugging where the error comes from, so be it -
Ada is broken on the branch now).  Installed to the branch.

_The_ major cleanup opportunity left is moving the virtual operands
to a more sane representation - now that we have at most one VDEF
and one V{MAY,}USE.  A simple idea would be to use the first SSA
operand slot for them.  The bitmap of stores can become a single
pointer (we have at most one stored symbol, not counting .MEM, which
I do not record anymore).  We can still have many loads in call
arguments though.

Richard.

2008-11-25  Richard Guenther  <rguenther@suse.de>

	* gimple.c (is_gimple_reg): Do not handle memory tags.
	* ipa-cp.c (ipcp_update_callgraph): Fix typo.
	* passes.c (init_optimization_passes): Schedule
	update_address_taken pass before points-to analysis.
	* tree-data-ref.c (dr_analyze_alias): Ignore vops and SMTs.
	(free_data_ref): Likewise.
	(create_data_ref): Likewise.
	(dr_may_alias_p): Likewise.
	(analyze_all_data_dependences): Likewise.
	* tree-dfa.c (dump_variable): Do not dump SMTs, memory stats,
	may-aliases or partitions.
	(remove_referenced_var): Do not clear mpt or symbol_mem_tag.
	* tree-dump.c (dequeue_and_dump): Do not handle SYMBOL_MEMORY_TAG
	or NAME_MEMORY_TAG.
	* tree-flow-inline.h (gimple_aliases_computed_p): Remove.
	(gimple_global_var): Likewise.
	(may_aliases): Likewise.
	(is_global_var): Remove MTAG code.
	(unmodifiable_var_p): Likewise.
	(memory_partition): Remove.
	(factoring_name_p): Likewise.
	(symbol_mem_tag): Likewise.
	(set_symbol_mem_tag): Likewise.
	(gimple_mem_ref_stats): Likewise.
	* tree-flow.h (struct mem_sym_stats_d): Remove.
	(struct mem_ref_stats_d): Likewise.
	(struct gimple_df): Remove global_var, aliases_computed_p and
	mem_ref_stats fields.
	(struct ptr_info_def): Remove memory_tag_needed and name_mem_tag
	fields.
	(struct var_ann_d): Remove call_clobbered, mpt and symbol_mem_tag
	fields.
	* tree-into-ssa (mark_sym_for_renaming): Remove memory paritioning
	code.
	(update_ssa): Likewise.
	* tree-outof-ssa.c (create_temp): Do not set SMT.
	* tree-predcom.c (set_alias_info): Remove.
	(prepare_initializers_chain): Do not call it.
	* tree-pretty-print.c (dump_generic_node): Do not handle memory tags.
	* tree-sra.c (sra_walk_function): Use gimple_references_memory_p.
	* tree-ssa-alias.c (struct alias_info): Remove.
	(get_mem_sym_stats_for, mem_sym_stats, set_memory_partition,
	mark_non_addressable, sort_tags_by_id, init_transitive_clobber_worklist,
	add_to_worklist, mark_aliases_call_clobbered, compute_tag_properties):
	Remove.
	(set_initial_properties): Rename to compute_call_clobbered.
	(dump_memory_partitions, debug_memory_partitions, need_to_partition_p,
	mem_sym_score, count_mem_refs, dump_mem_ref_stats, debug_mem_ref_stats,
	dump_mem_sym_stats, debug_mem_sym_stats, dump_mem_sym_stats_for_var,
	dump_all_mem_sym_stats, debug_all_mem_sym_stats, dump_mp_info,
	debug_mp_info, update_mem_sym_stats_from_stmt, compare_mp_info_entries,
	mp_info_cmp, sort_mp_info, get_mpt_for, find_partition_for,
	rewrite_alias_set_for, estimate_vop_reduction, update_reference_counts,
	build_mp_info, compute_memory_partitions): Remove.
	(compute_may_aliases): Remove all but points-to analysis code.
	(reset_alias_info): Likewise.
	(init_alias_info): Likewise.
	(compute_flow_sensitive_aliasing): Likewise.
	(delete_mem_ref_stats, init_mem_ref_stats, delete_alias_info,
	eq_ptr_info, ptr_info_hash, create_name_tags, union_alias_set_into,
	have_common_aliases_p, compute_flow_insensitive_aliasing,
	create_alias_map_for, update_alias_info_1, update_alias_info,
	setup_pointers_and_addressables, maybe_create_global_var): Remove.
	(may_alias_p): Remove SMT code.
	(may_point_to_global_var): Adjust.
	(add_may_alias): Remove.
	(set_pt_anything): Adjust.
	(create_tag_raw, create_memory_tag, get_nmt_for, get_smt_for,
	create_global_var): Remove.
	(dump_alias_info): Adjust.
	(dump_points_to_info_for): Likewise.
	(dump_may_aliases_for, debug_may_aliases_for, add_may_alias_for_new_tag,
	new_type_alias): Remove.
	* tree-ssa-ccp.c (get_symbol_constant_value): Remove memory-tag
	related code.
	* tree-ssa-copy.c (may_propagate_copy): Likewise.
	(may_propagate_copy_into_stmt): Likewise.
	(merge_alias_info): Do nothing for now.
	* tree-ssa-copyrename.c (copy_rename_partition_coalesce): Remove
	memory-tag related code.
	* tree-ssa-live.c (remove_unused_locals): Likewise.
	* tree-ssa-loop-ivopts.c (get_ref_tag): Remove.
	(copy_ref_info): Remove memory-tag related code.
	* tree-ssa-operands.c (init_ssa_operands): Likewise.
	(fini_ssa_operands): Likewise.
	(get_expr_operands): Likewise.
	* tree-ssa-operands.h (struct ssa_operands): Remove mpt_table field.
	* tree-ssa-phiprop.c (propagate_with_phi): Remove memory-tag related
	code.
	* tree-ssa-structalias.c (find_func_aliases): Do not mark stmts
	modified.
	(var_can_have_subvars): Remove memory-tag related code.   
	(set_uids_in_ptset): Mark pointer-info as pt_global_mem if the set
	contains a global variable.
	(delete_alias_heapvars): Allow unconditional call.
	* tree-ssa-structalias.h (update_mem_sym_stats_from_stmt): Remove.
	* tree-ssa.c (verify_flow_insensitive_alias_info): Remove.
	(verify_flow_sensitive_alias_info): Likewise.
	(verify_call_clobbering): Adjust.
	(verify_memory_partitions): Remove.
	(verify_alias_info): Adjust.
	(verify_ssa): Likewise.
	(delete_tree_ssa): Remove memory-tag related code.
	(warn_uninitialized_var): Aliases are always available.
	(execute_update_addresses_taken): Update gimple_addressable_vars.
	Update call-clobber state.
	* tree-tailcall.c (suitable_for_tail_opt_p): Remove memory-tag
	related code.
	(find_tail_calls): Use gimple_references_memory_p.
	* tree-vect-transform.c (vect_create_data_ref_ptr): Remove memory-tag
	related code.
	* tree.c (init_ttree): Likewise.
	(tree_code_size): Likewise.
	(tree_node_structure): Likewise.
	(build7_stat): Re-write to be build6_stat.
	* tree.h (MTAG_P, TREE_MEMORY_TAG_CHECK, TMR_TAG): Remove.
	(SSA_VAR_P): Adjust.
	(struct tree_memory_tag): Remove.
	(struct tree_memory_partition_tag): Likewise.
	(union tree_node): Adjust.
	(build7): Re-write to be build6.
	* treestruct.def (TS_MEMORY_TAG, TS_MEMORY_PARTITION_TAG): Remove.
	* tree-ssa-alias-warnings.c (build_reference_table): Remove
	memory-tag related code.
	(ffan_walker): Likewise.
	(detect_strict_aliasing_named): Likewise.
	* tree-data-ref.h (struct dr_alias): Remove symbol_tag field.
	(DR_SYMBOL_TAG, DR_VOPS): Remove.
	* tree-ssa-address.c (create_mem_ref_raw): Use build6.
	(get_address_description): Remove memory-tag related code.
	* tree-vect-analyze.c (vect_analyze_data_refs): Likewise.
	* tree.def (NAME_MEMORY_TAG, SYMBOL_MEMORY_TAG, MEMORY_PARTITION_TAG):
	Remove.
	(TARGET_MEM_REF): Remove TMR_TAG operand.

	* tree-dfa.c (add_referenced_var): Initialize call-clobber state.
	* tree-flow-inline.h (is_call_used): Use is_call_clobbered.
	(is_call_clobbered): Global variables are always call clobbered,
	query the call-clobbers bitmap.
	(mark_call_clobbered): Ignore global variables.
	(clear_call_clobbered): Likewise.
	* tree-ssa-alias.c (reset_cc_flags): Do not clear all
	call-clobber flags.  Verify initial state instead.
	* tree-ssa.c (verify_call_clobbering): Adjust.


Index: alias-improvements/gcc/tree-ssa-alias.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-alias.c	2008-11-26 13:47:33.000000000 +0100
--- alias-improvements/gcc/tree-ssa-alias.c	2008-11-26 16:49:17.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 167,207 ****
     ourselves.  */
  
  
- /* Alias information used by compute_may_aliases and its helpers.  */
- struct alias_info
- {
-   /* SSA names visited while collecting points-to information.  If bit I
-      is set, it means that SSA variable with version I has already been
-      visited.  */
-   sbitmap ssa_names_visited;
- 
-   /* Array of SSA_NAME pointers processed by the points-to collector.  */
-   VEC(tree,heap) *processed_ptrs;
- 
-   /* ADDRESSABLE_VARS contains all the global variables and locals that
-      have had their address taken.  */
-   struct alias_map_d **addressable_vars;
-   size_t num_addressable_vars;
- 
-   /* POINTERS contains all the _DECL pointers with unique memory tags
-      that have been referenced in the program.  */
-   struct alias_map_d **pointers;
-   size_t num_pointers;
- 
-   /* Pointers that have been used in an indirect load/store operation.  */
-   struct pointer_set_t *dereferenced_ptrs;
- };
- 
- 
- /* Structure to map a variable to its alias set.  */
- struct alias_map_d
- {
-   /* Variable and its alias set.  */
-   tree var;
-   alias_set_type set;
- };
- 
- 
  /* Counters used to display statistics on alias analysis.  */
  struct alias_stats_d
  {
--- 167,172 ----
*************** struct alias_stats_d
*** 219,553 ****
  
  /* Local variables.  */
  static struct alias_stats_d alias_stats;
- static bitmap_obstack alias_bitmap_obstack;
  
  /* Local functions.  */
- static void compute_flow_insensitive_aliasing (struct alias_info *);
  static void dump_alias_stats (FILE *);
! static tree create_memory_tag (tree type, bool is_type_tag);
! static tree get_smt_for (tree, struct alias_info *);
! static tree get_nmt_for (tree);
! static void add_may_alias (tree, tree);
! static struct alias_info *init_alias_info (void);
! static void delete_alias_info (struct alias_info *);
! static void compute_flow_sensitive_aliasing (struct alias_info *);
! static void setup_pointers_and_addressables (struct alias_info *);
! static void update_alias_info (struct alias_info *);
! static void create_global_var (void);
! static void maybe_create_global_var (void);
  static void set_pt_anything (tree);
  
- void debug_mp_info (VEC(mem_sym_stats_t,heap) *);
- 
- static alloc_pool mem_sym_stats_pool;
- 
- /* Return memory reference stats for symbol VAR.  Create a new slot in
-    cfun->gimple_df->mem_sym_stats if needed.  */
- 
- static struct mem_sym_stats_d *
- get_mem_sym_stats_for (tree var)
- {
-   void **slot;
-   struct mem_sym_stats_d *stats;
-   struct pointer_map_t *map = gimple_mem_ref_stats (cfun)->mem_sym_stats;
-   
-   gcc_assert (map);
- 
-   slot = pointer_map_insert (map, var);
-   if (*slot == NULL)
-     {
-       stats = (struct mem_sym_stats_d *) pool_alloc (mem_sym_stats_pool);
-       memset (stats, 0, sizeof (*stats));
-       stats->var = var;
-       *slot = (void *) stats;
-     }
-   else
-     stats = (struct mem_sym_stats_d *) *slot;
- 
-   return stats;
- }
- 
- 
- /* Return memory reference statistics for variable VAR in function FN.
-    This is computed by alias analysis, but it is not kept
-    incrementally up-to-date.  So, these stats are only accurate if
-    pass_may_alias has been run recently.  If no alias information
-    exists, this function returns NULL.  */
- 
- static mem_sym_stats_t
- mem_sym_stats (struct function *fn, tree var)
- {
-   void **slot;
-   struct pointer_map_t *stats_map = gimple_mem_ref_stats (fn)->mem_sym_stats;
- 
-   if (stats_map == NULL)
-     return NULL;
- 
-   slot = pointer_map_contains (stats_map, var);
-   if (slot == NULL)
-     return NULL;
- 
-   return (mem_sym_stats_t) *slot;
- }
- 
- 
- /* Set MPT to be the memory partition associated with symbol SYM.  */
- 
- static inline void
- set_memory_partition (tree sym, tree mpt)
- {
- #if defined ENABLE_CHECKING
-   if (mpt)
-     gcc_assert (TREE_CODE (mpt) == MEMORY_PARTITION_TAG
- 	        && !is_gimple_reg (sym));
- #endif
- 
-   var_ann (sym)->mpt = mpt;
-   if (mpt)
-     {
-       if (MPT_SYMBOLS (mpt) == NULL)
- 	MPT_SYMBOLS (mpt) = BITMAP_ALLOC (&alias_bitmap_obstack);
- 
-       bitmap_set_bit (MPT_SYMBOLS (mpt), DECL_UID (sym));
- 
-       /* MPT inherits the call-clobbering attributes from SYM.  */
-       if (is_call_clobbered (sym))
- 	{
- 	  MTAG_GLOBAL (mpt) = 1;
- 	  mark_call_clobbered (mpt, ESCAPE_IS_GLOBAL);
- 	}
-     }
- }
- 
- 
- /* Mark variable VAR as being non-addressable.  */
- 
- static void
- mark_non_addressable (tree var)
- {
-   tree mpt;
- 
-   if (!TREE_ADDRESSABLE (var))
-     return;
- 
-   mpt = memory_partition (var);
- 
-   clear_call_clobbered (var);
-   TREE_ADDRESSABLE (var) = 0;
- 
-   if (mpt)
-     {
-       /* Note that it's possible for a symbol to have an associated
- 	 MPT and the MPT have a NULL empty set.  During
- 	 init_alias_info, all MPTs get their sets cleared out, but the
- 	 symbols still point to the old MPTs that used to hold them.
- 	 This is done so that compute_memory_partitions can now which
- 	 symbols are losing or changing partitions and mark them for
- 	 renaming.  */
-       if (MPT_SYMBOLS (mpt))
- 	bitmap_clear_bit (MPT_SYMBOLS (mpt), DECL_UID (var));
-       set_memory_partition (var, NULL_TREE);
-     }
- }
- 
- 
- /* qsort comparison function to sort type/name tags by DECL_UID.  */
- 
- static int
- sort_tags_by_id (const void *pa, const void *pb)
- {
-   const_tree const a = *(const_tree const *)pa;
-   const_tree const b = *(const_tree const *)pb;
-  
-   return DECL_UID (a) - DECL_UID (b);
- }
- 
- /* Initialize WORKLIST to contain those memory tags that are marked call
-    clobbered.  Initialized WORKLIST2 to contain the reasons these
-    memory tags escaped.  */
- 
- static void
- init_transitive_clobber_worklist (VEC (tree, heap) **worklist,
- 				  VEC (int, heap) **worklist2,
- 				  bitmap on_worklist)
- {
-   referenced_var_iterator rvi;
-   tree curr;
- 
-   FOR_EACH_REFERENCED_VAR (curr, rvi)
-     {
-       if (MTAG_P (curr) && is_call_clobbered (curr))
- 	{
- 	  VEC_safe_push (tree, heap, *worklist, curr);
- 	  VEC_safe_push (int, heap, *worklist2,
- 			 var_ann (curr)->escape_mask);
- 	  bitmap_set_bit (on_worklist, DECL_UID (curr));
- 	}
-     }
- }
- 
- /* Add ALIAS to WORKLIST (and the reason for escaping REASON to WORKLIST2) if
-    ALIAS is not already marked call clobbered, and is a memory
-    tag.  */
- 
- static void
- add_to_worklist (tree alias, VEC (tree, heap) **worklist,
- 		 VEC (int, heap) **worklist2, int reason,
- 		 bitmap on_worklist)
- {
-   if (MTAG_P (alias) && !is_call_clobbered (alias)
-       && !bitmap_bit_p (on_worklist, DECL_UID (alias)))
-     {
-       VEC_safe_push (tree, heap, *worklist, alias);
-       VEC_safe_push (int, heap, *worklist2, reason);
-       bitmap_set_bit (on_worklist, DECL_UID (alias));
-     }
- }
- 
- /* Mark aliases of TAG as call clobbered, and place any tags on the
-    alias list that were not already call clobbered on WORKLIST.  */
- 
- static void
- mark_aliases_call_clobbered (tree tag, VEC (tree, heap) **worklist,
- 			     VEC (int, heap) **worklist2, bitmap on_worklist)
- {
-   bitmap aliases;
-   bitmap_iterator bi;
-   unsigned int i;
-   tree entry;
-   var_ann_t ta = var_ann (tag);
- 
-   if (!MTAG_P (tag))
-     return;
-   aliases = may_aliases (tag);
-   if (!aliases)
-     return;
- 
-   EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
-     {
-       entry = referenced_var (i);
-       /* If you clobber one part of a structure, you
- 	 clobber the entire thing.  While this does not make
- 	 the world a particularly nice place, it is necessary
- 	 in order to allow C/C++ tricks that involve
- 	 pointer arithmetic to work.  */
-       if (!unmodifiable_var_p (entry))
- 	{
- 	  add_to_worklist (entry, worklist, worklist2, ta->escape_mask,
- 			   on_worklist);
- 	  mark_call_clobbered (entry, ta->escape_mask);
- 	}
-     }
- }
- 
- /* Tags containing global vars need to be marked as global.
-    Tags containing call clobbered vars need to be marked as call
-    clobbered. */
- 
- static void
- compute_tag_properties (void)
- {
-   referenced_var_iterator rvi;
-   tree tag;
-   bool changed = true;
-   VEC (tree, heap) *taglist = NULL;
- 
-   FOR_EACH_REFERENCED_VAR (tag, rvi)
-     {
-       if (!MTAG_P (tag))
- 	continue;
-       VEC_safe_push (tree, heap, taglist, tag);
-     }
- 
-   /* We sort the taglist by DECL_UID, for two reasons.
-      1. To get a sequential ordering to make the bitmap accesses
-      faster.
-      2. Because of the way we compute aliases, it's more likely that
-      an earlier tag is included in a later tag, and this will reduce
-      the number of iterations.
- 
-      If we had a real tag graph, we would just topo-order it and be
-      done with it.  */
-   qsort (VEC_address (tree, taglist),
- 	 VEC_length (tree, taglist),
- 	 sizeof (tree),
- 	 sort_tags_by_id);
- 
-   /* Go through each tag not marked as global, and if it aliases
-      global vars, mark it global. 
-      
-      If the tag contains call clobbered vars, mark it call
-      clobbered.  
- 
-      This loop iterates because tags may appear in the may-aliases
-      list of other tags when we group.  */
- 
-   while (changed)
-     {
-       unsigned int k;
- 
-       changed = false;      
-       for (k = 0; VEC_iterate (tree, taglist, k, tag); k++)
- 	{
- 	  bitmap ma;
- 	  bitmap_iterator bi;
- 	  unsigned int i;
- 	  tree entry;
- 	  bool tagcc = is_call_clobbered (tag);
- 	  bool tagglobal = MTAG_GLOBAL (tag);
- 	  
- 	  if (tagcc && tagglobal)
- 	    continue;
- 	  
- 	  ma = may_aliases (tag);
- 	  if (!ma)
- 	    continue;
- 
- 	  EXECUTE_IF_SET_IN_BITMAP (ma, 0, i, bi)
- 	    {
- 	      entry = referenced_var (i);
- 	      /* Call clobbered entries cause the tag to be marked
- 		 call clobbered.  */
- 	      if (!tagcc && is_call_clobbered (entry))
- 		{
- 		  mark_call_clobbered (tag, var_ann (entry)->escape_mask);
- 		  tagcc = true;
- 		  changed = true;
- 		}
- 
- 	      /* Global vars cause the tag to be marked global.  */
- 	      if (!tagglobal && is_global_var (entry))
- 		{
- 		  MTAG_GLOBAL (tag) = true;
- 		  changed = true;
- 		  tagglobal = true;
- 		}
- 
- 	      /* Early exit once both global and cc are set, since the
- 		 loop can't do any more than that.  */
- 	      if (tagcc && tagglobal)
- 		break;
- 	    }
- 	}
-     }
-   VEC_free (tree, heap, taglist);
- }
  
! /* Set up the initial variable clobbers, call-uses and globalness.
!    When this function completes, only tags whose aliases need to be
!    clobbered will be set clobbered.  Tags clobbered because they   
!    contain call clobbered vars are handled in compute_tag_properties.  */
  
  static void
! set_initial_properties (struct alias_info *ai)
  {
-   unsigned int i;
    referenced_var_iterator rvi;
    tree var;
-   tree ptr;
    bool any_pt_anything = false;
    enum escape_type pt_anything_mask = 0;
  
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (is_global_var (var))
--- 184,210 ----
  
  /* Local variables.  */
  static struct alias_stats_d alias_stats;
  
  /* Local functions.  */
  static void dump_alias_stats (FILE *);
! static void compute_flow_sensitive_aliasing (void);
  static void set_pt_anything (tree);
+ static void reset_alias_info (void);
  
  
! /* Transfer the call-clobber solutions from the points-to solution
!    to the call-clobber state of the variables.  */
  
  static void
! compute_call_clobbered (void)
  {
    referenced_var_iterator rvi;
    tree var;
    bool any_pt_anything = false;
    enum escape_type pt_anything_mask = 0;
  
+   timevar_push (TV_CALL_CLOBBER);
+ 
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (is_global_var (var))
*************** set_initial_properties (struct alias_inf
*** 573,631 ****
  
    compute_call_used_vars ();
  
-   for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
-     {
-       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
-       tree tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
- 
-       /* A pointer that only escapes via a function return does not
-          add to the call clobber or call used solution.
- 	 To exclude ESCAPE_TO_PURE_CONST we would need to track
- 	 call used variables separately or compute those properly
- 	 in the operand scanner.  */
-       if (pi->value_escapes_p
- 	  && pi->escape_mask & ~ESCAPE_TO_RETURN)
- 	{
- 	  /* If PTR escapes then its associated memory tags and
- 	     pointed-to variables are call-clobbered.  */
- 	  if (pi->name_mem_tag)
- 	    mark_call_clobbered (pi->name_mem_tag, pi->escape_mask);
- 
- 	  if (tag)
- 	    mark_call_clobbered (tag, pi->escape_mask);
- 	}
- 
-       /* If the name tag is call clobbered, so is the symbol tag
- 	 associated with the base VAR_DECL.  */
-       if (pi->name_mem_tag
- 	  && tag
- 	  && is_call_clobbered (pi->name_mem_tag))
- 	mark_call_clobbered (tag, pi->escape_mask);
- 
-       /* Name tags and symbol tags that we don't know where they point
- 	 to, might point to global memory, and thus, are clobbered.
- 
-          FIXME:  This is not quite right.  They should only be
-          clobbered if value_escapes_p is true, regardless of whether
-          they point to global memory or not.
-          So removing this code and fixing all the bugs would be nice.
-          It is the cause of a bunch of clobbering.  */
-       if ((pi->pt_global_mem || pi->pt_anything) 
- 	  && pi->memory_tag_needed && pi->name_mem_tag)
- 	{
- 	  mark_call_clobbered (pi->name_mem_tag, ESCAPE_IS_GLOBAL);
- 	  MTAG_GLOBAL (pi->name_mem_tag) = true;
- 	}
-       
-       if ((pi->pt_global_mem || pi->pt_anything) 
- 	  && pi->memory_tag_needed
- 	  && tag)
- 	{
- 	  mark_call_clobbered (tag, ESCAPE_IS_GLOBAL);
- 	  MTAG_GLOBAL (tag) = true;
- 	}
-     }
- 
    /* If a pt_anything pointer escaped we need to mark all addressable
       variables call clobbered.  */
    if (any_pt_anything)
--- 230,235 ----
*************** set_initial_properties (struct alias_inf
*** 640,2907 ****
  	    mark_call_clobbered (var, pt_anything_mask);
  	}
      }
- }
  
- /* Compute which variables need to be marked call clobbered because
-    their tag is call clobbered, and which tags need to be marked
-    global because they contain global variables.  */
- 
- static void
- compute_call_clobbered (struct alias_info *ai)
- {
-   VEC (tree, heap) *worklist = NULL;
-   VEC (int,heap) *worklist2 = NULL;
-   bitmap on_worklist;
- 
-   timevar_push (TV_CALL_CLOBBER);
-   on_worklist = BITMAP_ALLOC (NULL);
-     
-   set_initial_properties (ai);
-   init_transitive_clobber_worklist (&worklist, &worklist2, on_worklist);
-   while (VEC_length (tree, worklist) != 0)
-     {
-       tree curr = VEC_pop (tree, worklist);
-       int reason = VEC_pop (int, worklist2);
- 
-       bitmap_clear_bit (on_worklist, DECL_UID (curr));
-       mark_call_clobbered (curr, reason);
-       mark_aliases_call_clobbered (curr, &worklist, &worklist2, on_worklist);
-     }
-   VEC_free (tree, heap, worklist);
-   VEC_free (int, heap, worklist2);
-   BITMAP_FREE (on_worklist);
-   compute_tag_properties ();
    timevar_pop (TV_CALL_CLOBBER);
  }
  
  
! /* Dump memory partition information to FILE.  */
  
! static void
! dump_memory_partitions (FILE *file)
! {
!   unsigned i, npart;
!   unsigned long nsyms;
!   tree mpt;
! 
!   fprintf (file, "\nMemory partitions\n\n");
!   for (i = 0, npart = 0, nsyms = 0;
!        VEC_iterate (tree, gimple_ssa_operands (cfun)->mpt_table, i, mpt);
!        i++)
!     {
!       if (mpt)
! 	{
! 	  bitmap syms = MPT_SYMBOLS (mpt);
! 	  unsigned long n = (syms) ? bitmap_count_bits (syms) : 0;
  
! 	  fprintf (file, "#%u: ", i);
! 	  print_generic_expr (file, mpt, 0);
! 	  fprintf (file, ": %lu elements: ", n);
! 	  dump_decl_set (file, syms);
! 	  npart++;
! 	  nsyms += n;
! 	}
!     }
  
!   fprintf (file, "\n%u memory partitions holding %lu symbols\n", npart, nsyms);
! }
  
  
! /* Dump memory partition information to stderr.  */
  
! void
! debug_memory_partitions (void)
! {
!   dump_memory_partitions (stderr);
! }
  
  
! /* Return true if memory partitioning is required given the memory
!    reference estimates in STATS.  */
  
! static inline bool
! need_to_partition_p (struct mem_ref_stats_d *stats)
! {
!   long num_vops = stats->num_vuses + stats->num_vdefs;
!   long avg_vops = CEIL (num_vops, stats->num_mem_stmts);
!   return (num_vops > (long) MAX_ALIASED_VOPS
!           && avg_vops > (long) AVG_ALIASED_VOPS);
! }
  
  
- /* Count the actual number of virtual operators in CFUN.  Note that
-    this is only meaningful after virtual operands have been populated,
-    so it should be invoked at the end of compute_may_aliases.
- 
-    The number of virtual operators are stored in *NUM_VDEFS_P and
-    *NUM_VUSES_P, the number of partitioned symbols in
-    *NUM_PARTITIONED_P and the number of unpartitioned symbols in
-    *NUM_UNPARTITIONED_P.
  
!    If any of these pointers is NULL the corresponding count is not
!    computed.  */
  
! static void
! count_mem_refs (long *num_vuses_p, long *num_vdefs_p,
! 		long *num_partitioned_p, long *num_unpartitioned_p)
! {
!   gimple_stmt_iterator gsi;
!   basic_block bb;
!   long num_vdefs, num_vuses, num_partitioned, num_unpartitioned;
!   referenced_var_iterator rvi;
!   tree sym;
  
!   num_vuses = num_vdefs = num_partitioned = num_unpartitioned = 0;
  
!   if (num_vuses_p || num_vdefs_p)
!     FOR_EACH_BB (bb)
!       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
! 	{
! 	  gimple stmt = gsi_stmt (gsi);
! 	  if (gimple_references_memory_p (stmt))
  	    {
! 	      num_vuses += NUM_SSA_OPERANDS (stmt, SSA_OP_VUSE);
! 	      num_vdefs += NUM_SSA_OPERANDS (stmt, SSA_OP_VDEF);
  	    }
- 	}
  
!   if (num_partitioned_p || num_unpartitioned_p)
!     FOR_EACH_REFERENCED_VAR (sym, rvi)
!       {
! 	if (is_gimple_reg (sym))
! 	  continue;
! 
! 	if (memory_partition (sym))
! 	  num_partitioned++;
! 	else
! 	  num_unpartitioned++;
!       }
! 
!   if (num_vdefs_p)
!     *num_vdefs_p = num_vdefs;
  
!   if (num_vuses_p)
!     *num_vuses_p = num_vuses;
  
!   if (num_partitioned_p)
!     *num_partitioned_p = num_partitioned;
  
!   if (num_unpartitioned_p)
!     *num_unpartitioned_p = num_unpartitioned;
! }
  
  
! /* The list is sorted by increasing partitioning score (PSCORE).
!    This score is computed such that symbols with high scores are
!    those that are least likely to be partitioned.  Given a symbol
!    MP->VAR, PSCORE(S) is the result of the following weighted sum
! 
!    PSCORE(S) =   FW * 64 + FR * 32
!    	       + DW * 16 + DR *  8 
!    	       + IW *  4 + IR *  2
!                + NO_ALIAS
! 
!    where
! 
!    FW		Execution frequency of writes to S
!    FR		Execution frequency of reads from S
!    DW		Number of direct writes to S
!    DR		Number of direct reads from S
!    IW		Number of indirect writes to S
!    IR		Number of indirect reads from S
!    NO_ALIAS	State of the NO_ALIAS* flags
! 
!    The basic idea here is that symbols that are frequently
!    written-to in hot paths of the code are the last to be considered
!    for partitioning.  */
! 
! static inline long
! mem_sym_score (mem_sym_stats_t mp)
! {
!   return mp->frequency_writes * 64 + mp->frequency_reads * 32
!          + mp->num_direct_writes * 16 + mp->num_direct_reads * 8
! 	 + mp->num_indirect_writes * 4 + mp->num_indirect_reads * 2
! 	 + var_ann (mp->var)->noalias_state;
! }
  
  
! /* Dump memory reference stats for function CFUN to FILE.  */
  
! void
! dump_mem_ref_stats (FILE *file)
  {
!   long actual_num_vuses, actual_num_vdefs;
!   long num_partitioned, num_unpartitioned;
!   struct mem_ref_stats_d *stats;
    
!   stats = gimple_mem_ref_stats (cfun);
! 
!   count_mem_refs (&actual_num_vuses, &actual_num_vdefs, &num_partitioned,
!                   &num_unpartitioned);
  
!   fprintf (file, "\nMemory reference statistics for %s\n\n", 
! 	   lang_hooks.decl_printable_name (current_function_decl, 2));
  
!   fprintf (file, "Number of memory statements:     %ld\n",
!            stats->num_mem_stmts);
!   fprintf (file, "Number of call sites:            %ld\n",
! 	   stats->num_call_sites);
!   fprintf (file, "Number of pure/const call sites: %ld\n",
! 	   stats->num_pure_const_call_sites);
!   fprintf (file, "Number of asm sites:             %ld\n",
! 	   stats->num_asm_sites);
!   fprintf (file, "Estimated number of loads:       %ld (%ld/stmt)\n",
! 	   stats->num_vuses,
! 	   (stats->num_mem_stmts)
! 	   ? CEIL (stats->num_vuses, stats->num_mem_stmts)
! 	   : 0);
!   fprintf (file, "Actual number of loads:          %ld (%ld/stmt)\n",
! 	   actual_num_vuses, 
! 	   (stats->num_mem_stmts)
! 	   ? CEIL (actual_num_vuses, stats->num_mem_stmts)
! 	   : 0);
! 
!   if (actual_num_vuses > stats->num_vuses + (stats->num_vuses / 25))
!     fprintf (file, "\t(warning: estimation is lower by more than 25%%)\n");
! 
!   fprintf (file, "Estimated number of stores:      %ld (%ld/stmt)\n",
! 	   stats->num_vdefs,
! 	   (stats->num_mem_stmts)
! 	   ? CEIL (stats->num_vdefs, stats->num_mem_stmts)
! 	   : 0);
!   fprintf (file, "Actual number of stores:         %ld (%ld/stmt)\n",
! 	   actual_num_vdefs, 
! 	   (stats->num_mem_stmts)
! 	   ? CEIL (actual_num_vdefs, stats->num_mem_stmts)
! 	   : 0);
! 
!   if (actual_num_vdefs > stats->num_vdefs + (stats->num_vdefs / 25))
!     fprintf (file, "\t(warning: estimation is lower by more than 25%%)\n");
! 
!   fprintf (file, "Partitioning thresholds:         MAX = %d   AVG = %d "
!            "(%sNEED TO PARTITION)\n", MAX_ALIASED_VOPS, AVG_ALIASED_VOPS,
! 	   stats->num_mem_stmts && need_to_partition_p (stats) ? "" : "NO ");
!   fprintf (file, "Number of partitioned symbols:   %ld\n", num_partitioned);
!   fprintf (file, "Number of unpartitioned symbols: %ld\n", num_unpartitioned);
! }
  
  
! /* Dump memory reference stats for function FN to stderr.  */
  
! void
! debug_mem_ref_stats (void)
! {
!   dump_mem_ref_stats (stderr);
! }
  
! 
! /* Dump memory reference stats for variable VAR to FILE.  */
! 
! static void
! dump_mem_sym_stats (FILE *file, tree var)
! {
!   mem_sym_stats_t stats = mem_sym_stats (cfun, var);
! 
!   if (stats == NULL)
!     return;
! 
!   fprintf (file, "read frequency: %6ld, write frequency: %6ld, "
!            "direct reads: %3ld, direct writes: %3ld, "
! 	   "indirect reads: %4ld, indirect writes: %4ld, symbol: ",
! 	   stats->frequency_reads, stats->frequency_writes,
! 	   stats->num_direct_reads, stats->num_direct_writes,
! 	   stats->num_indirect_reads, stats->num_indirect_writes);
!   print_generic_expr (file, stats->var, 0);
!   fprintf (file, ", tags: ");
!   dump_decl_set (file, stats->parent_tags);
! }
! 
! 
! /* Dump memory reference stats for variable VAR to stderr.  */
! 
! void
! debug_mem_sym_stats (tree var)
! {
!   dump_mem_sym_stats (stderr, var);
! }
! 
! /* Dump memory reference stats for variable VAR to FILE.  For use
!    of tree-dfa.c:dump_variable.  */
! 
! void
! dump_mem_sym_stats_for_var (FILE *file, tree var)
! {
!   mem_sym_stats_t stats = mem_sym_stats (cfun, var);
! 
!   if (stats == NULL)
!     return;
! 
!   fprintf (file, ", score: %ld", mem_sym_score (stats));
!   fprintf (file, ", direct reads: %ld", stats->num_direct_reads);
!   fprintf (file, ", direct writes: %ld", stats->num_direct_writes);
!   fprintf (file, ", indirect reads: %ld", stats->num_indirect_reads);
!   fprintf (file, ", indirect writes: %ld", stats->num_indirect_writes);
! }
! 
! /* Dump memory reference stats for all memory symbols to FILE.  */
! 
! static void
! dump_all_mem_sym_stats (FILE *file)
! {
!   referenced_var_iterator rvi;
!   tree sym;
! 
!   FOR_EACH_REFERENCED_VAR (sym, rvi)
!     {
!       if (is_gimple_reg (sym))
! 	continue;
! 
!       dump_mem_sym_stats (file, sym);
!     }
! }
! 
! 
! /* Dump memory reference stats for all memory symbols to stderr.  */
! 
! void
! debug_all_mem_sym_stats (void)
! {
!   dump_all_mem_sym_stats (stderr);
! }
! 
! 
! /* Dump the MP_INFO array to FILE.  */
! 
! static void
! dump_mp_info (FILE *file, VEC(mem_sym_stats_t,heap) *mp_info)
! {
!   unsigned i;
!   mem_sym_stats_t mp_p;
! 
!   for (i = 0; VEC_iterate (mem_sym_stats_t, mp_info, i, mp_p); i++)
!     if (!mp_p->partitioned_p)
!       dump_mem_sym_stats (file, mp_p->var);
! }
! 
! 
! /* Dump the MP_INFO array to stderr.  */
! 
! void
! debug_mp_info (VEC(mem_sym_stats_t,heap) *mp_info)
! {
!   dump_mp_info (stderr, mp_info);
! }
! 
! 
! /* Update memory reference stats for symbol VAR in statement STMT.
!    NUM_DIRECT_READS and NUM_DIRECT_WRITES specify the number of times
!    that VAR is read/written in STMT (indirect reads/writes are not
!    recorded by this function, see compute_memory_partitions).  */
! 
! void
! update_mem_sym_stats_from_stmt (tree var, gimple stmt, long num_direct_reads,
!                                 long num_direct_writes)
! {
!   mem_sym_stats_t stats;
! 
!   gcc_assert (num_direct_reads >= 0 && num_direct_writes >= 0);
! 
!   stats = get_mem_sym_stats_for (var);
! 
!   stats->num_direct_reads += num_direct_reads;
!   stats->frequency_reads += ((long) gimple_bb (stmt)->frequency
!                              * num_direct_reads);
! 
!   stats->num_direct_writes += num_direct_writes;
!   stats->frequency_writes += ((long) gimple_bb (stmt)->frequency
!                               * num_direct_writes);
! }
! 
! 
! /* Given two MP_INFO entries MP1 and MP2, return -1 if MP1->VAR should
!    be partitioned before MP2->VAR, 0 if they are the same or 1 if
!    MP1->VAR should be partitioned after MP2->VAR.  */
! 
! static inline int
! compare_mp_info_entries (mem_sym_stats_t mp1, mem_sym_stats_t mp2)
! {
!   long pscore1 = mem_sym_score (mp1);
!   long pscore2 = mem_sym_score (mp2);
! 
!   if (pscore1 < pscore2)
!     return -1;
!   else if (pscore1 > pscore2)
!     return 1;
!   else
!     return DECL_UID (mp1->var) - DECL_UID (mp2->var);
! }
! 
! 
! /* Comparison routine for qsort.  The list is sorted by increasing
!    partitioning score (PSCORE).  This score is computed such that
!    symbols with high scores are those that are least likely to be
!    partitioned.  */
! 
! static int
! mp_info_cmp (const void *p, const void *q)
! {
!   mem_sym_stats_t e1 = *((const mem_sym_stats_t *) p);
!   mem_sym_stats_t e2 = *((const mem_sym_stats_t *) q);
!   return compare_mp_info_entries (e1, e2);
! }
! 
! 
! /* Sort the array of reference counts used to compute memory partitions.
!    Elements are sorted in ascending order of execution frequency and 
!    descending order of virtual operators needed.  */
! 
! static inline void
! sort_mp_info (VEC(mem_sym_stats_t,heap) *list)
! {
!   unsigned num = VEC_length (mem_sym_stats_t, list);
! 
!   if (num < 2)
!     return;
! 
!   if (num == 2)
!     {
!       if (compare_mp_info_entries (VEC_index (mem_sym_stats_t, list, 0),
! 	                           VEC_index (mem_sym_stats_t, list, 1)) > 0)
! 	{  
! 	  /* Swap elements if they are in the wrong order.  */
! 	  mem_sym_stats_t tmp = VEC_index (mem_sym_stats_t, list, 0);
! 	  VEC_replace (mem_sym_stats_t, list, 0,
! 	               VEC_index (mem_sym_stats_t, list, 1));
! 	  VEC_replace (mem_sym_stats_t, list, 1, tmp);
! 	}
! 
!       return;
!     }
! 
!   /* There are 3 or more elements, call qsort.  */
!   qsort (VEC_address (mem_sym_stats_t, list),
!          VEC_length (mem_sym_stats_t, list), 
! 	 sizeof (mem_sym_stats_t),
! 	 mp_info_cmp);
! }
! 
! 
! /* Return the memory partition tag (MPT) associated with memory
!    symbol SYM.  */
! 
! static tree
! get_mpt_for (tree sym)
! {
!   tree mpt;
! 
!   /* Don't create a new tag unnecessarily.  */
!   mpt = memory_partition (sym);
!   if (mpt == NULL_TREE)
!     {
!       mpt = create_tag_raw (MEMORY_PARTITION_TAG, TREE_TYPE (sym), "MPT");
!       TREE_ADDRESSABLE (mpt) = 0;
!       add_referenced_var (mpt);
!       VEC_safe_push (tree, heap, gimple_ssa_operands (cfun)->mpt_table, mpt);
!       gcc_assert (MPT_SYMBOLS (mpt) == NULL);
!       set_memory_partition (sym, mpt);
!     }
! 
!   return mpt;
! }
! 
! 
! /* Add MP_P->VAR to a memory partition and return the partition.  */
! 
! static tree
! find_partition_for (mem_sym_stats_t mp_p)
! {
!   unsigned i;
!   VEC(tree,heap) *mpt_table;
!   tree mpt;
! 
!   mpt_table = gimple_ssa_operands (cfun)->mpt_table;
!   mpt = NULL_TREE;
! 
!   /* Find an existing partition for MP_P->VAR.  */
!   for (i = 0; VEC_iterate (tree, mpt_table, i, mpt); i++)
!     {
!       mem_sym_stats_t mpt_stats;
! 
!       /* If MPT does not have any symbols yet, use it.  */
!       if (MPT_SYMBOLS (mpt) == NULL)
! 	break;
! 
!       /* Otherwise, see if MPT has common parent tags with MP_P->VAR,
! 	 but avoid grouping clobbered variables with non-clobbered
! 	 variables (otherwise, this tends to creates a single memory
! 	 partition because other call-clobbered variables may have
! 	 common parent tags with non-clobbered ones).  */
!       mpt_stats = get_mem_sym_stats_for (mpt);
!       if (mp_p->parent_tags
! 	  && mpt_stats->parent_tags
! 	  && is_call_clobbered (mpt) == is_call_clobbered (mp_p->var)
! 	  && bitmap_intersect_p (mpt_stats->parent_tags, mp_p->parent_tags))
! 	break;
! 
!       /* If no common parent tags are found, see if both MPT and
! 	 MP_P->VAR are call-clobbered.  */
!       if (is_call_clobbered (mpt) && is_call_clobbered (mp_p->var))
! 	break;
!     }
! 
!   if (mpt == NULL_TREE)
!     mpt = get_mpt_for (mp_p->var);
!   else
!     set_memory_partition (mp_p->var, mpt);
! 
!   mp_p->partitioned_p = true;
! 
!   mark_sym_for_renaming (mp_p->var);
!   mark_sym_for_renaming (mpt);
! 
!   return mpt;
! }
! 
! 
! /* Rewrite the alias set for TAG to use the newly created partitions.
!    If TAG is NULL, rewrite the set of call-clobbered variables.
!    NEW_ALIASES is a scratch bitmap to build the new set of aliases for
!    TAG.  */
! 
! static void
! rewrite_alias_set_for (tree tag, bitmap new_aliases)
! {
!   bitmap_iterator bi;
!   unsigned i;
!   tree mpt, sym;
! 
!   EXECUTE_IF_SET_IN_BITMAP (MTAG_ALIASES (tag), 0, i, bi)
!     {
!       sym = referenced_var (i);
!       mpt = memory_partition (sym);
!       if (mpt)
! 	bitmap_set_bit (new_aliases, DECL_UID (mpt));
!       else
! 	bitmap_set_bit (new_aliases, DECL_UID (sym));
!     }
! 
!   /* Rebuild the may-alias array for TAG.  */
!   bitmap_copy (MTAG_ALIASES (tag), new_aliases);
! }
! 
! 
! /* Determine how many virtual operands can be saved by partitioning
!    MP_P->VAR into MPT.  When a symbol S is thrown inside a partition
!    P, every virtual operand that used to reference S will now
!    reference P.  Whether it reduces the number of virtual operands
!    depends on:
! 
!    1- Direct references to S are never saved.  Instead of the virtual
!       operand to S, we will now have a virtual operand to P.
! 
!    2- Indirect references to S are reduced only for those memory tags
!       holding S that already had other symbols partitioned into P.
!       For instance, if a memory tag T has the alias set { a b S c },
!       the first time we partition S into P, the alias set will become
!       { a b P c }, so no virtual operands will be saved. However, if
!       we now partition symbol 'c' into P, then the alias set for T
!       will become { a b P }, so we will be saving one virtual operand
!       for every indirect reference to 'c'.
! 
!    3- Is S is call-clobbered, we save as many virtual operands as
!       call/asm sites exist in the code, but only if other
!       call-clobbered symbols have been grouped into P.  The first
!       call-clobbered symbol that we group does not produce any
!       savings.
! 
!    MEM_REF_STATS points to CFUN's memory reference information.  */
! 
! static void
! estimate_vop_reduction (struct mem_ref_stats_d *mem_ref_stats,
!                         mem_sym_stats_t mp_p, tree mpt)
! {
!   unsigned i;
!   bitmap_iterator bi;
!   mem_sym_stats_t mpt_stats;
! 
!   /* We should only get symbols with indirect references here.  */
!   gcc_assert (mp_p->num_indirect_reads > 0 || mp_p->num_indirect_writes > 0);
! 
!   /* Note that the only statistics we keep for MPT is the set of
!      parent tags to know which memory tags have had alias members
!      partitioned, and the indicator has_call_clobbered_vars.
!      Reference counts are not important for MPT.  */
!   mpt_stats = get_mem_sym_stats_for (mpt);
! 
!   /* Traverse all the parent tags for MP_P->VAR.  For every tag T, if
!      partition P is already grouping aliases of T, then reduce the
!      number of virtual operands by the number of direct references
!      to T.  */
!   if (mp_p->parent_tags)
!     {
!       if (mpt_stats->parent_tags == NULL)
! 	mpt_stats->parent_tags = BITMAP_ALLOC (&alias_bitmap_obstack);
! 
!       EXECUTE_IF_SET_IN_BITMAP (mp_p->parent_tags, 0, i, bi)
! 	{
! 	  if (bitmap_bit_p (mpt_stats->parent_tags, i))
! 	    {
! 	      /* Partition MPT is already partitioning symbols in the
! 		 alias set for TAG.  This means that we are now saving
! 		 1 virtual operand for every direct reference to TAG.  */
! 	      tree tag = referenced_var (i);
! 	      mem_sym_stats_t tag_stats = mem_sym_stats (cfun, tag);
! 	      mem_ref_stats->num_vuses -= tag_stats->num_direct_reads;
! 	      mem_ref_stats->num_vdefs -= tag_stats->num_direct_writes;
! 	    }
! 	  else
! 	    {
! 	      /* This is the first symbol in tag I's alias set that is
! 		 being grouped under MPT.  We will not save any
! 		 virtual operands this time, but record that MPT is
! 		 grouping a symbol from TAG's alias set so that the
! 		 next time we get the savings.  */
! 	      bitmap_set_bit (mpt_stats->parent_tags, i);
! 	    }
! 	}
!     }
! 
!   /* If MP_P->VAR is call-clobbered, and MPT is already grouping
!      call-clobbered symbols, then we will save as many virtual
!      operands as asm/call sites there are.  */
!   if (is_call_clobbered (mp_p->var))
!     {
!       if (mpt_stats->has_call_clobbered_vars)
! 	mem_ref_stats->num_vdefs -= mem_ref_stats->num_call_sites
! 	                            + mem_ref_stats->num_asm_sites;
!       else
! 	mpt_stats->has_call_clobbered_vars = true;
!     }
! }
! 
! 
! /* Helper for compute_memory_partitions.  Transfer reference counts
!    from pointers to their pointed-to sets.  Counters for pointers were
!    computed by update_alias_info.  MEM_REF_STATS points to CFUN's
!    memory reference information.  */
! 
! static void
! update_reference_counts (struct mem_ref_stats_d *mem_ref_stats)
! {
!   unsigned i;
!   bitmap_iterator bi;
!   mem_sym_stats_t sym_stats;
! 
!   for (i = 1; i < num_ssa_names; i++)
!     {
!       tree ptr;
!       struct ptr_info_def *pi;
! 
!       ptr = ssa_name (i);
!       if (ptr
! 	  && POINTER_TYPE_P (TREE_TYPE (ptr))
! 	  && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
! 	  && pi->memory_tag_needed)
! 	{
! 	  unsigned j;
! 	  bitmap_iterator bj;
! 	  tree tag;
! 	  mem_sym_stats_t ptr_stats, tag_stats;
! 
! 	  /* If PTR has flow-sensitive points-to information, use
! 	     PTR's name tag, otherwise use the symbol tag associated
! 	     with PTR's symbol.  */
! 	  if (pi->name_mem_tag)
! 	    tag = pi->name_mem_tag;
! 	  else
! 	    tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
! 
! 	  ptr_stats = get_mem_sym_stats_for (ptr);
! 	  tag_stats = get_mem_sym_stats_for (tag);
! 
! 	  /* TAG has as many direct references as dereferences we
! 	     found for its parent pointer.  */
! 	  tag_stats->num_direct_reads += ptr_stats->num_direct_reads;
! 	  tag_stats->num_direct_writes += ptr_stats->num_direct_writes;
! 
! 	  /* All the dereferences of pointer PTR are considered direct
! 	     references to PTR's memory tag (TAG).  In turn,
! 	     references to TAG will become virtual operands for every
! 	     symbol in TAG's alias set.  So, for every symbol ALIAS in
! 	     TAG's alias set, add as many indirect references to ALIAS
! 	     as direct references there are for TAG.  */
! 	  if (MTAG_ALIASES (tag))
! 	    EXECUTE_IF_SET_IN_BITMAP (MTAG_ALIASES (tag), 0, j, bj)
! 	      {
! 		tree alias = referenced_var (j);
! 		sym_stats = get_mem_sym_stats_for (alias);
! 
! 		/* All the direct references to TAG are indirect references
! 		   to ALIAS.  */
! 		sym_stats->num_indirect_reads += ptr_stats->num_direct_reads;
! 		sym_stats->num_indirect_writes += ptr_stats->num_direct_writes;
! 		sym_stats->frequency_reads += ptr_stats->frequency_reads;
! 		sym_stats->frequency_writes += ptr_stats->frequency_writes;
! 
! 		/* Indicate that TAG is one of ALIAS's parent tags.  */
! 		if (sym_stats->parent_tags == NULL)
! 		  sym_stats->parent_tags = BITMAP_ALLOC (&alias_bitmap_obstack);
! 		bitmap_set_bit (sym_stats->parent_tags, DECL_UID (tag));
! 	      }
! 	}
!     }
! 
!   /* Call-clobbered symbols are indirectly written at every
!      call/asm site.  */
!   EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, i, bi)
!     {
!       tree sym = referenced_var (i);
!       sym_stats = get_mem_sym_stats_for (sym);
!       sym_stats->num_indirect_writes += mem_ref_stats->num_call_sites
! 	                                + mem_ref_stats->num_asm_sites;
!     }
! 
!   /* Addressable symbols are indirectly written at some ASM sites.
!      Since only ASM sites that clobber memory actually affect
!      addressable symbols, this is an over-estimation.  */
!   EXECUTE_IF_SET_IN_BITMAP (gimple_addressable_vars (cfun), 0, i, bi)
!     {
!       tree sym = referenced_var (i);
!       sym_stats = get_mem_sym_stats_for (sym);
!       sym_stats->num_indirect_writes += mem_ref_stats->num_asm_sites;
!     }
! }
! 
! 
! /* Helper for compute_memory_partitions.  Add all memory symbols to
!    *MP_INFO_P and compute the initial estimate for the total number of
!    virtual operands needed.  MEM_REF_STATS points to CFUN's memory
!    reference information.  On exit, *TAGS_P will contain the list of
!    memory tags whose alias set need to be rewritten after
!    partitioning.  */
! 
! static void
! build_mp_info (struct mem_ref_stats_d *mem_ref_stats,
!                VEC(mem_sym_stats_t,heap) **mp_info_p,
! 	       VEC(tree,heap) **tags_p)
! {
!   tree var;
!   referenced_var_iterator rvi;
! 
!   FOR_EACH_REFERENCED_VAR (var, rvi)
!     {
!       mem_sym_stats_t sym_stats;
!       tree old_mpt;
! 
!       /* We are only interested in memory symbols other than MPTs.  */
!       if (is_gimple_reg (var) || TREE_CODE (var) == MEMORY_PARTITION_TAG)
! 	continue;
! 
!       /* Collect memory tags into the TAGS array so that we can
! 	 rewrite their alias sets after partitioning.  */
!       if (MTAG_P (var) && MTAG_ALIASES (var))
! 	VEC_safe_push (tree, heap, *tags_p, var);
! 
!       /* Since we are going to re-compute partitions, any symbols that
! 	 used to belong to a partition must be detached from it and
! 	 marked for renaming.  */
!       if ((old_mpt = memory_partition (var)) != NULL)
! 	{
! 	  mark_sym_for_renaming (old_mpt);
! 	  set_memory_partition (var, NULL_TREE);
! 	  mark_sym_for_renaming (var);
! 	}
! 
!       sym_stats = get_mem_sym_stats_for (var);
! 
!       /* Add VAR's reference info to MP_INFO.  Note that the only
! 	 symbols that make sense to partition are those that have
! 	 indirect references.  If a symbol S is always directly
! 	 referenced, partitioning it will not reduce the number of
! 	 virtual operators.  The only symbols that are profitable to
! 	 partition are those that belong to alias sets and/or are
! 	 call-clobbered.  */
!       if (sym_stats->num_indirect_reads > 0
! 	  || sym_stats->num_indirect_writes > 0)
! 	VEC_safe_push (mem_sym_stats_t, heap, *mp_info_p, sym_stats);
! 
!       /* Update the number of estimated VOPS.  Note that direct
! 	 references to memory tags are always counted as indirect
! 	 references to their alias set members, so if a memory tag has
! 	 aliases, do not count its direct references to avoid double
! 	 accounting.  */
!       if (!MTAG_P (var) || !MTAG_ALIASES (var))
! 	{
! 	  mem_ref_stats->num_vuses += sym_stats->num_direct_reads;
! 	  mem_ref_stats->num_vdefs += sym_stats->num_direct_writes;
! 	}
! 
!       mem_ref_stats->num_vuses += sym_stats->num_indirect_reads;
!       mem_ref_stats->num_vdefs += sym_stats->num_indirect_writes;
!     }
! }
! 
! 
! /* Compute memory partitions.  A memory partition (MPT) is an
!    arbitrary grouping of memory symbols, such that references to one
!    member of the group is considered a reference to all the members of
!    the group.
!    
!    As opposed to alias sets in memory tags, the grouping into
!    partitions is completely arbitrary and only done to reduce the
!    number of virtual operands.  The only rule that needs to be
!    observed when creating memory partitions is that given two memory
!    partitions MPT.i and MPT.j, they must not contain symbols in
!    common.
! 
!    Memory partitions are used when putting the program into Memory-SSA
!    form.  In particular, in Memory-SSA PHI nodes are not computed for
!    individual memory symbols.  They are computed for memory
!    partitions.  This reduces the amount of PHI nodes in the SSA graph
!    at the expense of precision (i.e., it makes unrelated stores affect
!    each other).
!    
!    However, it is possible to increase precision by changing this
!    partitioning scheme.  For instance, if the partitioning scheme is
!    such that get_mpt_for is the identity function (that is,
!    get_mpt_for (s) = s), this will result in ultimate precision at the
!    expense of huge SSA webs.
! 
!    At the other extreme, a partitioning scheme that groups all the
!    symbols in the same set results in minimal SSA webs and almost
!    total loss of precision.
! 
!    There partitioning heuristic uses three parameters to decide the
!    order in which symbols are processed.  The list of symbols is
!    sorted so that symbols that are more likely to be partitioned are
!    near the top of the list:
! 
!    - Execution frequency.  If a memory references is in a frequently
!      executed code path, grouping it into a partition may block useful
!      transformations and cause sub-optimal code generation.  So, the
!      partition heuristic tries to avoid grouping symbols with high
!      execution frequency scores.  Execution frequency is taken
!      directly from the basic blocks where every reference is made (see
!      update_mem_sym_stats_from_stmt), which in turn uses the
!      profile guided machinery, so if the program is compiled with PGO
!      enabled, more accurate partitioning decisions will be made.
! 
!    - Number of references.  Symbols with few references in the code,
!      are partitioned before symbols with many references.
! 
!    - NO_ALIAS attributes.  Symbols with any of the NO_ALIAS*
!      attributes are partitioned after symbols marked MAY_ALIAS.
! 
!    Once the list is sorted, the partitioning proceeds as follows:
! 
!    1- For every symbol S in MP_INFO, create a new memory partition MP,
!       if necessary.  To avoid memory partitions that contain symbols
!       from non-conflicting alias sets, memory partitions are
!       associated to the memory tag that holds S in its alias set.  So,
!       when looking for a memory partition for S, the memory partition
!       associated with one of the memory tags holding S is chosen.  If
!       none exists, a new one is created.
! 
!    2- Add S to memory partition MP.
! 
!    3- Reduce by 1 the number of VOPS for every memory tag holding S.
! 
!    4- If the total number of VOPS is less than MAX_ALIASED_VOPS or the
!       average number of VOPS per statement is less than
!       AVG_ALIASED_VOPS, stop.  Otherwise, go to the next symbol in the
!       list.  */
! 
! static void
! compute_memory_partitions (void)
! {
!   tree tag;
!   unsigned i;
!   mem_sym_stats_t mp_p;
!   VEC(mem_sym_stats_t,heap) *mp_info;
!   bitmap new_aliases;
!   VEC(tree,heap) *tags;
!   struct mem_ref_stats_d *mem_ref_stats;
!   int prev_max_aliased_vops;
! 
!   mem_ref_stats = gimple_mem_ref_stats (cfun);
!   gcc_assert (mem_ref_stats->num_vuses == 0 && mem_ref_stats->num_vdefs == 0);
! 
!   if (mem_ref_stats->num_mem_stmts == 0)
!     return;
! 
!   timevar_push (TV_MEMORY_PARTITIONING);
! 
!   mp_info = NULL;
!   tags = NULL;
!   prev_max_aliased_vops = MAX_ALIASED_VOPS;
! 
!   /* Since we clearly cannot lower the number of virtual operators
!      below the total number of memory statements in the function, we
!      may need to adjust MAX_ALIASED_VOPS beforehand.  */
!   if (MAX_ALIASED_VOPS < mem_ref_stats->num_mem_stmts)
!     MAX_ALIASED_VOPS = mem_ref_stats->num_mem_stmts;
! 
!   /* Update reference stats for all the pointed-to variables and
!      memory tags.  */
!   update_reference_counts (mem_ref_stats);
! 
!   /* Add all the memory symbols to MP_INFO.  */
!   build_mp_info (mem_ref_stats, &mp_info, &tags);
! 
!   /* No partitions required if we are below the threshold.  */
!   if (!need_to_partition_p (mem_ref_stats))
!     {
!       if (dump_file)
! 	fprintf (dump_file, "\nMemory partitioning NOT NEEDED for %s\n",
! 	         get_name (current_function_decl));
!       goto done;
!     }
! 
!   /* Sort the MP_INFO array so that symbols that should be partitioned
!      first are near the top of the list.  */
!   sort_mp_info (mp_info);
! 
!   if (dump_file)
!     {
!       fprintf (dump_file, "\nMemory partitioning NEEDED for %s\n\n",
! 	       get_name (current_function_decl));
!       fprintf (dump_file, "Memory symbol references before partitioning:\n");
!       dump_mp_info (dump_file, mp_info);
!     }
! 
!   /* Create partitions for variables in MP_INFO until we have enough
!      to lower the total number of VOPS below MAX_ALIASED_VOPS or if
!      the average number of VOPS per statement is below
!      AVG_ALIASED_VOPS.  */
!   for (i = 0; VEC_iterate (mem_sym_stats_t, mp_info, i, mp_p); i++)
!     {
!       tree mpt;
! 
!       /* If we are below the threshold, stop.  */
!       if (!need_to_partition_p (mem_ref_stats))
! 	break;
! 
!       mpt = find_partition_for (mp_p);
!       estimate_vop_reduction (mem_ref_stats, mp_p, mpt);
!     }
! 
!   /* After partitions have been created, rewrite alias sets to use
!      them instead of the original symbols.  This way, if the alias set
!      was computed as { a b c d e f }, and the subset { b e f } was
!      grouped into partition MPT.3, then the new alias set for the tag
!      will be  { a c d MPT.3 }.
!      
!      Note that this is not strictly necessary.  The operand scanner
!      will always check if a symbol belongs to a partition when adding
!      virtual operands.  However, by reducing the size of the alias
!      sets to be scanned, the work needed inside the operand scanner is
!      significantly reduced.  */
!   new_aliases = BITMAP_ALLOC (&alias_bitmap_obstack);
! 
!   for (i = 0; VEC_iterate (tree, tags, i, tag); i++)
!     {
!       rewrite_alias_set_for (tag, new_aliases);
!       bitmap_clear (new_aliases);
!     }
! 
!   BITMAP_FREE (new_aliases);
! 
!   if (dump_file)
!     {
!       fprintf (dump_file, "\nMemory symbol references after partitioning:\n");
!       dump_mp_info (dump_file, mp_info);
!     }
! 
! done:
!   /* Free allocated memory.  */
!   VEC_free (mem_sym_stats_t, heap, mp_info);
!   VEC_free (tree, heap, tags);
! 
!   MAX_ALIASED_VOPS = prev_max_aliased_vops;
! 
!   timevar_pop (TV_MEMORY_PARTITIONING);
! }
! 
! /* Compute may-alias information for every variable referenced in function
!    FNDECL.
! 
!    Alias analysis proceeds in 3 main phases:
! 
!    1- Points-to and escape analysis.
! 
!    This phase walks the use-def chains in the SSA web looking for three
!    things:
! 
! 	* Assignments of the form P_i = &VAR
! 	* Assignments of the form P_i = malloc()
! 	* Pointers and ADDR_EXPR that escape the current function.
! 
!    The concept of 'escaping' is the same one used in the Java world.  When
!    a pointer or an ADDR_EXPR escapes, it means that it has been exposed
!    outside of the current function.  So, assignment to global variables,
!    function arguments and returning a pointer are all escape sites, as are
!    conversions between pointers and integers.
! 
!    This is where we are currently limited.  Since not everything is renamed
!    into SSA, we lose track of escape properties when a pointer is stashed
!    inside a field in a structure, for instance.  In those cases, we are
!    assuming that the pointer does escape.
! 
!    We use escape analysis to determine whether a variable is
!    call-clobbered.  Simply put, if an ADDR_EXPR escapes, then the variable
!    is call-clobbered.  If a pointer P_i escapes, then all the variables
!    pointed-to by P_i (and its memory tag) also escape.
! 
!    2- Compute flow-sensitive aliases
! 
!    We have two classes of memory tags.  Memory tags associated with the
!    pointed-to data type of the pointers in the program.  These tags are
!    called "symbol memory tag" (SMT).  The other class are those associated
!    with SSA_NAMEs, called "name memory tag" (NMT). The basic idea is that
!    when adding operands for an INDIRECT_REF *P_i, we will first check
!    whether P_i has a name tag, if it does we use it, because that will have
!    more precise aliasing information.  Otherwise, we use the standard symbol
!    tag.
! 
!    In this phase, we go through all the pointers we found in points-to
!    analysis and create alias sets for the name memory tags associated with
!    each pointer P_i.  If P_i escapes, we mark call-clobbered the variables
!    it points to and its tag.
! 
! 
!    3- Compute flow-insensitive aliases
! 
!    This pass will compare the alias set of every symbol memory tag and
!    every addressable variable found in the program.  Given a symbol
!    memory tag SMT and an addressable variable V.  If the alias sets of
!    SMT and V conflict (as computed by may_alias_p), then V is marked
!    as an alias tag and added to the alias set of SMT.
! 
!    For instance, consider the following function:
! 
! 	    foo (int i)
! 	    {
! 	      int *p, a, b;
! 	    
! 	      if (i > 10)
! 	        p = &a;
! 	      else
! 	        p = &b;
! 	    
! 	      *p = 3;
! 	      a = b + 2;
! 	      return *p;
! 	    }
! 
!    After aliasing analysis has finished, the symbol memory tag for pointer
!    'p' will have two aliases, namely variables 'a' and 'b'.  Every time
!    pointer 'p' is dereferenced, we want to mark the operation as a
!    potential reference to 'a' and 'b'.
! 
! 	    foo (int i)
! 	    {
! 	      int *p, a, b;
! 
! 	      if (i_2 > 10)
! 		p_4 = &a;
! 	      else
! 		p_6 = &b;
! 	      # p_1 = PHI <p_4(1), p_6(2)>;
! 
! 	      # a_7 = VDEF <a_3>;
! 	      # b_8 = VDEF <b_5>;
! 	      *p_1 = 3;
! 
! 	      # a_9 = VDEF <a_7>
! 	      # VUSE <b_8>
! 	      a_9 = b_8 + 2;
! 
! 	      # VUSE <a_9>;
! 	      # VUSE <b_8>;
! 	      return *p_1;
! 	    }
! 
!    In certain cases, the list of may aliases for a pointer may grow too
!    large.  This may cause an explosion in the number of virtual operands
!    inserted in the code.  Resulting in increased memory consumption and
!    compilation time.
! 
!    When the number of virtual operands needed to represent aliased
!    loads and stores grows too large (configurable with option --param
!    max-aliased-vops and --param avg-aliased-vops), alias sets are
!    grouped to avoid severe compile-time slow downs and memory
!    consumption. See compute_memory_partitions.  */
! 
! unsigned int
! compute_may_aliases (void)
! {
!   struct alias_info *ai;
! 
!   timevar_push (TV_TREE_MAY_ALIAS);
!   
!   memset (&alias_stats, 0, sizeof (alias_stats));
! 
!   /* Initialize aliasing information.  */
!   ai = init_alias_info ();
! 
!   /* For each pointer P_i, determine the sets of variables that P_i may
!      point-to.  For every addressable variable V, determine whether the
!      address of V escapes the current function, making V call-clobbered
!      (i.e., whether &V is stored in a global variable or if its passed as a
!      function call argument).  */
!   compute_points_to_sets ();
! 
!   /* Update various related attributes like escaped addresses,
!      pointer dereferences for loads and stores.  This is used
!      when creating name tags and alias sets.  */
!   update_alias_info (ai);
! 
!   /* Collect all pointers and addressable variables, compute alias sets,
!      create memory tags for pointers and promote variables whose address is
!      not needed anymore.  */
!   setup_pointers_and_addressables (ai);
! 
!   /* Compute type-based flow-insensitive aliasing for all the type
!      memory tags.  */
!   compute_flow_insensitive_aliasing (ai);
! 
!   /* Compute flow-sensitive, points-to based aliasing for all the name
!      memory tags.  */
!   compute_flow_sensitive_aliasing (ai);
!   
!   /* Compute call clobbering information.  */
!   compute_call_clobbered (ai);
! 
!   /* If the program makes no reference to global variables, but it
!      contains a mixture of pure and non-pure functions, then we need
!      to create use-def and def-def links between these functions to
!      avoid invalid transformations on them.  */
!   maybe_create_global_var ();
! 
!   /* Compute memory partitions for every memory variable.  */
!   compute_memory_partitions ();
! 
!   /* Remove partitions with no symbols.  Partitions may end up with an
!      empty MPT_SYMBOLS set if a previous round of alias analysis
!      needed to partition more symbols.  Since we don't need those
!      partitions anymore, remove them to free up the space.  */
!   {
!     tree mpt;
!     unsigned i;
!     VEC(tree,heap) *mpt_table;
! 
!     mpt_table = gimple_ssa_operands (cfun)->mpt_table;
!     i = 0;
!     while (i < VEC_length (tree, mpt_table))
!       {
! 	mpt = VEC_index (tree, mpt_table, i);
! 	if (MPT_SYMBOLS (mpt) == NULL)
! 	  VEC_unordered_remove (tree, mpt_table, i);
! 	else
! 	  i++;
!       }
!   }
! 
!   /* Populate all virtual operands and newly promoted register operands.  */
!   {
!     gimple_stmt_iterator gsi;
!     basic_block bb;
!     FOR_EACH_BB (bb)
!       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
! 	update_stmt_if_modified (gsi_stmt (gsi));
!   }
! 
!   /* Debugging dumps.  */
!   if (dump_file)
!     {
!       dump_mem_ref_stats (dump_file);
!       dump_alias_info (dump_file);
!       dump_points_to_info (dump_file);
! 
!       if (dump_flags & TDF_STATS)
! 	dump_alias_stats (dump_file);
! 
!       if (dump_flags & TDF_DETAILS)
! 	dump_referenced_vars (dump_file);
!     }
! 
!   /* Report strict aliasing violations.  */
!   strict_aliasing_warning_backend ();
! 
!   /* Deallocate memory used by aliasing data structures.  */
!   delete_alias_info (ai);
! 
!   if (need_ssa_update_p ())
!     update_ssa (TODO_update_ssa);
! 
!   timevar_pop (TV_TREE_MAY_ALIAS);
!   
!   return 0;
! }
! 
! /* Data structure used to count the number of dereferences to PTR
!    inside an expression.  */
! struct count_ptr_d
! {
!   tree ptr;
!   unsigned num_stores;
!   unsigned num_loads;
! };
! 
! 
! /* Helper for count_uses_and_derefs.  Called by walk_tree to look for
!    (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
! 
! static tree
! count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
! {
!   struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
!   struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
! 
!   /* Do not walk inside ADDR_EXPR nodes.  In the expression &ptr->fld,
!      pointer 'ptr' is *not* dereferenced, it is simply used to compute
!      the address of 'fld' as 'ptr + offsetof(fld)'.  */
!   if (TREE_CODE (*tp) == ADDR_EXPR)
!     {
!       *walk_subtrees = 0;
!       return NULL_TREE;
!     }
! 
!   if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
!     {
!       if (wi_p->is_lhs)
! 	count_p->num_stores++;
!       else
! 	count_p->num_loads++;
!     }
! 
!   return NULL_TREE;
! }
! 
! 
! /* Count the number of direct and indirect uses for pointer PTR in
!    statement STMT.  The number of direct uses is stored in
!    *NUM_USES_P.  Indirect references are counted separately depending
!    on whether they are store or load operations.  The counts are
!    stored in *NUM_STORES_P and *NUM_LOADS_P.  */
! 
! void
! count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
! 		       unsigned *num_loads_p, unsigned *num_stores_p)
! {
!   ssa_op_iter i;
!   tree use;
! 
!   *num_uses_p = 0;
!   *num_loads_p = 0;
!   *num_stores_p = 0;
! 
!   /* Find out the total number of uses of PTR in STMT.  */
!   FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
!     if (use == ptr)
!       (*num_uses_p)++;
! 
!   /* Now count the number of indirect references to PTR.  This is
!      truly awful, but we don't have much choice.  There are no parent
!      pointers inside INDIRECT_REFs, so an expression like
!      '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to
!      find all the indirect and direct uses of x_1 inside.  The only
!      shortcut we can take is the fact that GIMPLE only allows
!      INDIRECT_REFs inside the expressions below.  */
!   if (is_gimple_assign (stmt)
!       || gimple_code (stmt) == GIMPLE_RETURN
!       || gimple_code (stmt) == GIMPLE_ASM
!       || is_gimple_call (stmt))
!     {
!       struct walk_stmt_info wi;
!       struct count_ptr_d count;
! 
!       count.ptr = ptr;
!       count.num_stores = 0;
!       count.num_loads = 0;
! 
!       memset (&wi, 0, sizeof (wi));
!       wi.info = &count;
!       walk_gimple_op (stmt, count_ptr_derefs, &wi);
! 
!       *num_stores_p = count.num_stores;
!       *num_loads_p = count.num_loads;
!     }
! 
!   gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
! }
! 
! /* Remove memory references stats for function FN.  */
! 
! void
! delete_mem_ref_stats (struct function *fn)
! {
!   if (gimple_mem_ref_stats (fn)->mem_sym_stats)
!     {
!       free_alloc_pool (mem_sym_stats_pool);
!       pointer_map_destroy (gimple_mem_ref_stats (fn)->mem_sym_stats);
!     }
!   gimple_mem_ref_stats (fn)->mem_sym_stats = NULL;
! }
! 
! 
! /* Initialize memory reference stats.  */
! 
! static void
! init_mem_ref_stats (void)
! {
!   struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
! 
!   mem_sym_stats_pool = create_alloc_pool ("Mem sym stats",
! 					  sizeof (struct mem_sym_stats_d),
! 					  100);
!   memset (mem_ref_stats, 0, sizeof (struct mem_ref_stats_d));
!   mem_ref_stats->mem_sym_stats = pointer_map_create ();
! }
! 
! 
! /* Helper for init_alias_info.  Reset existing aliasing information.  */
! 
! static void
! reset_alias_info (void)
! {
!   referenced_var_iterator rvi;
!   tree var;
!   unsigned i;
!   bitmap active_nmts, all_nmts;
! 
!   /* Clear the set of addressable variables.  We do not need to clear
!      the TREE_ADDRESSABLE bit on every symbol because we are going to
!      re-compute addressability here.  */
!   bitmap_clear (gimple_addressable_vars (cfun));
! 
!   active_nmts = BITMAP_ALLOC (&alias_bitmap_obstack);
!   all_nmts = BITMAP_ALLOC (&alias_bitmap_obstack);
! 
!   /* Clear flow-insensitive alias information from each symbol.  */
!   FOR_EACH_REFERENCED_VAR (var, rvi)
!     {
!       if (is_gimple_reg (var))
! 	continue;
! 
!       if (MTAG_P (var))
! 	MTAG_ALIASES (var) = NULL;
! 
!       /* Memory partition information will be computed from scratch.  */
!       if (TREE_CODE (var) == MEMORY_PARTITION_TAG)
! 	MPT_SYMBOLS (var) = NULL;
! 
!       /* Collect all the name tags to determine if we have any
! 	 orphaned that need to be removed from the IL.  A name tag
! 	 will be orphaned if it is not associated with any active SSA
! 	 name.  */
!       if (TREE_CODE (var) == NAME_MEMORY_TAG)
! 	bitmap_set_bit (all_nmts, DECL_UID (var));
! 
!       /* Since we are about to re-discover call-clobbered
! 	 variables, clear the call-clobbered flag.  */
!       clear_call_clobbered (var);
!     }
! 
!   /* There should be no call-clobbered variable left.  */
!   gcc_assert (bitmap_empty_p (gimple_call_clobbered_vars (cfun)));
! 
!   /* Clear the call-used variables.  */
!   bitmap_clear (gimple_call_used_vars (cfun));
! 
!   /* Clear flow-sensitive points-to information from each SSA name.  */
!   for (i = 1; i < num_ssa_names; i++)
!     {
!       tree name = ssa_name (i);
! 
!       if (!name || !POINTER_TYPE_P (TREE_TYPE (name)))
! 	continue;
! 
!       if (SSA_NAME_PTR_INFO (name))
! 	{
! 	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
! 
! 	  /* Clear all the flags but keep the name tag to
! 	     avoid creating new temporaries unnecessarily.  If
! 	     this pointer is found to point to a subset or
! 	     superset of its former points-to set, then a new
! 	     tag will need to be created in create_name_tags.  */
! 	  pi->pt_anything = 0;
! 	  pi->pt_null = 0;
! 	  pi->value_escapes_p = 0;
! 	  pi->memory_tag_needed = 0;
! 	  pi->is_dereferenced = 0;
! 	  if (pi->pt_vars)
! 	    bitmap_clear (pi->pt_vars);
! 
! 	  /* Add NAME's name tag to the set of active tags.  */
! 	  if (pi->name_mem_tag)
! 	    bitmap_set_bit (active_nmts, DECL_UID (pi->name_mem_tag));
! 	}
      }
  
!   /* Name memory tags that are no longer associated with an SSA name
!      are considered stale and should be removed from the IL.  All the
!      name tags that are in the set ALL_NMTS but not in ACTIVE_NMTS are
!      considered stale and marked for renaming.  */
!   bitmap_and_compl_into (all_nmts, active_nmts);
!   mark_set_for_renaming (all_nmts);
! 
!   BITMAP_FREE (all_nmts);
!   BITMAP_FREE (active_nmts);
! }
! 
! 
! /* Initialize the data structures used for alias analysis.  */
! 
! static struct alias_info *
! init_alias_info (void)
! {
!   struct alias_info *ai;
!   referenced_var_iterator rvi;
!   tree var;
!   static bool alias_bitmap_obstack_initialized;
! 
!   ai = XCNEW (struct alias_info);
!   ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
!   sbitmap_zero (ai->ssa_names_visited);
!   ai->processed_ptrs = VEC_alloc (tree, heap, 50);
!   ai->dereferenced_ptrs = pointer_set_create ();
! 
!   /* Clear out all memory reference stats.  */
!   init_mem_ref_stats ();
! 
!   /* If aliases have been computed before, clear existing information.  */
!   if (gimple_aliases_computed_p (cfun))
!     reset_alias_info ();
!   else
!     {
!       /* If this is the first time we compute aliasing information,
! 	 every non-register symbol will need to be put into SSA form
! 	 (the initial SSA form only operates on GIMPLE registers).  */
!       FOR_EACH_REFERENCED_VAR (var, rvi)
! 	if (!is_gimple_reg (var))
! 	  mark_sym_for_renaming (var);
!     }
! 
!   /* Next time, we will need to reset alias information.  */
!   cfun->gimple_df->aliases_computed_p = true;
!   if (alias_bitmap_obstack_initialized)
!     bitmap_obstack_release (&alias_bitmap_obstack);    
!   bitmap_obstack_initialize (&alias_bitmap_obstack);
!   alias_bitmap_obstack_initialized = true;
! 
!   return ai;
! }
! 
! 
! /* Deallocate memory used by alias analysis.  */
! 
! static void
! delete_alias_info (struct alias_info *ai)
! {
!   size_t i;
! 
!   sbitmap_free (ai->ssa_names_visited);
! 
!   VEC_free (tree, heap, ai->processed_ptrs);
! 
!   for (i = 0; i < ai->num_addressable_vars; i++)
!     free (ai->addressable_vars[i]);
!   free (ai->addressable_vars);
!   
!   for (i = 0; i < ai->num_pointers; i++)
!     free (ai->pointers[i]);
!   free (ai->pointers);
! 
!   pointer_set_destroy (ai->dereferenced_ptrs);
!   free (ai);
  
!   delete_mem_ref_stats (cfun);
    delete_points_to_sets ();
- }
- 
- 
- /* Used for hashing to identify pointer infos with identical
-    pt_vars bitmaps.  */
- 
- static int
- eq_ptr_info (const void *p1, const void *p2)
- {
-   const struct ptr_info_def *n1 = (const struct ptr_info_def *) p1;
-   const struct ptr_info_def *n2 = (const struct ptr_info_def *) p2;
-   return bitmap_equal_p (n1->pt_vars, n2->pt_vars);
- }
- 
- static hashval_t
- ptr_info_hash (const void *p)
- {
-   const struct ptr_info_def *n = (const struct ptr_info_def *) p;
-   return bitmap_hash (n->pt_vars);
- }
- 
- 
- /* Create name tags for all the pointers that have been dereferenced.
-    We only create a name tag for a pointer P if P is found to point to
-    a set of variables (so that we can alias them to *P) or if it is
-    the result of a call to malloc (which means that P cannot point to
-    anything else nor alias any other variable).
- 
-    If two pointers P and Q point to the same set of variables, they
-    are assigned the same name tag.  */
- 
- static void
- create_name_tags (void)
- {
-   size_t i;
-   VEC (tree, heap) *with_ptvars = NULL;
-   tree ptr;
-   htab_t ptr_hash;
- 
-   /* Collect the list of pointers with a non-empty points to set.  */
-   for (i = 1; i < num_ssa_names; i++)
-     {
-       tree ptr = ssa_name (i);
-       struct ptr_info_def *pi;
- 
-       if (!ptr
- 	  || !POINTER_TYPE_P (TREE_TYPE (ptr))
- 	  || !SSA_NAME_PTR_INFO (ptr))
- 	continue;
- 
-       pi = SSA_NAME_PTR_INFO (ptr);
- 
-       if (pi->pt_anything || !pi->memory_tag_needed)
- 	{
- 	  /* No name tags for pointers that have not been
- 	     dereferenced or point to an arbitrary location.  */
- 	  pi->name_mem_tag = NULL_TREE;
- 	  continue;
- 	}
- 
-       /* Set pt_anything on the pointers without pt_vars filled in so
- 	 that they are assigned a symbol tag.  */
-       if (pi->pt_vars && !bitmap_empty_p (pi->pt_vars))	
- 	VEC_safe_push (tree, heap, with_ptvars, ptr);
-       else
- 	set_pt_anything (ptr);
-     }
-   
-   /* If we didn't find any pointers with pt_vars set, we're done.  */
-   if (!with_ptvars)
-     return;
- 
-   ptr_hash = htab_create (10, ptr_info_hash, eq_ptr_info, NULL);
- 
-   /* Now go through the pointers with pt_vars, and find a name tag
-      with the same pt_vars as this pointer, or create one if one
-      doesn't exist.  */
-   for (i = 0; VEC_iterate (tree, with_ptvars, i, ptr); i++)
-     {
-       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
-       tree old_name_tag = pi->name_mem_tag;
-       struct ptr_info_def **slot;
-       
-       /* If PTR points to a set of variables, check if we don't
- 	 have another pointer Q with the same points-to set before
- 	 creating a tag.  If so, use Q's tag instead of creating a
- 	 new one.
- 	 
- 	 This is important for not creating unnecessary symbols
- 	 and also for copy propagation.  If we ever need to
- 	 propagate PTR into Q or vice-versa, we would run into
- 	 problems if they both had different name tags because
- 	 they would have different SSA version numbers (which
- 	 would force us to take the name tags in and out of SSA).  */
-       slot = (struct ptr_info_def **) htab_find_slot (ptr_hash, pi, INSERT);
-       if (*slot)
-         pi->name_mem_tag = (*slot)->name_mem_tag;
-       else
- 	{
- 	  *slot = pi;
- 
- 	  /* If we didn't find a pointer with the same points-to set
- 	     as PTR, create a new name tag if needed.  */
- 	  if (pi->name_mem_tag == NULL_TREE)
- 	    pi->name_mem_tag = get_nmt_for (ptr);
- 	}
-       
-       /* If the new name tag computed for PTR is different than
- 	 the old name tag that it used to have, then the old tag
- 	 needs to be removed from the IL, so we mark it for
- 	 renaming.  */
-       if (old_name_tag && old_name_tag != pi->name_mem_tag)
- 	mark_sym_for_renaming (old_name_tag);
- 
-       /* Inherit volatility from the pointed-to type.  */
-       TREE_THIS_VOLATILE (pi->name_mem_tag)
- 	|= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (ptr)));
-       
-       /* Mark the new name tag for renaming.  */
-       mark_sym_for_renaming (pi->name_mem_tag);
-     }
- 
-   htab_delete (ptr_hash);
- 
-   VEC_free (tree, heap, with_ptvars);
- }
- 
  
! /* Union the alias set SET into the may-aliases for TAG.  */
  
! static void
! union_alias_set_into (tree tag, bitmap set)
! {
!   bitmap ma = MTAG_ALIASES (tag);
!   
!   if (bitmap_empty_p (set))
!     return;
    
!   if (!ma)
!     ma = MTAG_ALIASES (tag) = BITMAP_ALLOC (&alias_bitmap_obstack);
!   bitmap_ior_into (ma, set);
  }
  
! 
! /* For every pointer P_i in AI->PROCESSED_PTRS, create may-alias sets for
!    the name memory tag (NMT) associated with P_i.  If P_i escapes, then its
!    name tag and the variables it points-to are call-clobbered.  Finally, if
!    P_i escapes and we could not determine where it points to, then all the
!    variables in the same alias set as *P_i are marked call-clobbered.  This
!    is necessary because we must assume that P_i may take the address of any
!    variable in the same alias set.  */
! 
! static void
! compute_flow_sensitive_aliasing (struct alias_info *ai)
  {
-   size_t i;
    tree ptr;
!   
!   timevar_push (TV_FLOW_SENSITIVE);
!   
!   for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
!     {
!       if (!find_what_p_points_to (ptr))
! 	set_pt_anything (ptr);
!     }
! 
!   create_name_tags ();
! 
!   for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
!     {
!       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
! 
!       /* Set up aliasing information for PTR's name memory tag (if it has
! 	 one).  Note that only pointers that have been dereferenced will
! 	 have a name memory tag.  */
!       if (pi->name_mem_tag && pi->pt_vars)
! 	{
! 	  if (!bitmap_empty_p (pi->pt_vars))
! 	    union_alias_set_into (pi->name_mem_tag, pi->pt_vars);
! 	}
!     }
!   timevar_pop (TV_FLOW_SENSITIVE);
! }
! 
! 
! /* Return TRUE if at least one symbol in TAG2's alias set is also
!    present in TAG1's alias set.  */
! 
! static bool
! have_common_aliases_p (bitmap tag1aliases, bitmap tag2aliases)
! {
! 
!   /* This is the old behavior of have_common_aliases_p, which is to
!      return false if both sets are empty, or one set is and the other
!      isn't.  */
!   if (tag1aliases == NULL || tag2aliases == NULL)
!     return false;
  
-   return bitmap_intersect_p (tag1aliases, tag2aliases);
- }
  
! /* Compute type-based alias sets.  Traverse all the pointers and
!    addressable variables found in setup_pointers_and_addressables.
!    
!    For every pointer P in AI->POINTERS and addressable variable V in
!    AI->ADDRESSABLE_VARS, add V to the may-alias sets of P's symbol
!    memory tag (SMT) if their alias sets conflict.  V is then marked as
!    an aliased symbol so that the operand scanner knows that statements
!    containing V have aliased operands.  */
  
! static void
! compute_flow_insensitive_aliasing (struct alias_info *ai)
  {
!   referenced_var_iterator rvi;
!   tree var;
!   size_t i;
! 
!   timevar_push (TV_FLOW_INSENSITIVE);
!   /* For every pointer P, determine which addressable variables may alias
!      with P's symbol memory tag.  */
!   for (i = 0; i < ai->num_pointers; i++)
!     {
!       size_t j;
!       struct alias_map_d *p_map = ai->pointers[i];
!       tree tag = symbol_mem_tag (p_map->var);
!       tree var;
! 
!       for (j = 0; j < ai->num_addressable_vars; j++)
! 	{
! 	  struct alias_map_d *v_map;
! 	  var_ann_t v_ann;
! 	  
! 	  v_map = ai->addressable_vars[j];
! 	  var = v_map->var;
! 	  v_ann = var_ann (var);
! 
! 	  /* We used to skip variables that have never been written to
! 	     if the memory tag has been never written to directly (or
! 	     either of them were call clobbered).  This is not enough
! 	     though, as this misses writes through the tags aliases.
! 	     So, for correctness we need to include any aliased
! 	     variable here.  */
! 
! 	  if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
! 	    {
! 	      /* Add VAR to TAG's may-aliases set.  */
! 	      add_may_alias (tag, var);
! 	    }
! 	}
!     }
! 
!   /* Since this analysis is based exclusively on symbols, it fails to
!      handle cases where two pointers P and Q have different memory
!      tags with conflicting alias set numbers but no aliased symbols in
!      common.
! 
!      For example, suppose that we have two memory tags SMT.1 and SMT.2
!      such that
!      
!      		may-aliases (SMT.1) = { a }
! 		may-aliases (SMT.2) = { b }
! 
!      and the alias set number of SMT.1 conflicts with that of SMT.2.
!      Since they don't have symbols in common, loads and stores from
!      SMT.1 and SMT.2 will seem independent of each other, which will
!      lead to the optimizers making invalid transformations (see
!      testsuite/gcc.c-torture/execute/pr15262-[12].c).
! 
!      To avoid this problem, we do a final traversal of AI->POINTERS
!      looking for pairs of pointers that have no aliased symbols in
!      common and yet have conflicting alias set numbers.  */
!   for (i = 0; i < ai->num_pointers; i++)
!     {
!       size_t j;
!       struct alias_map_d *p_map1 = ai->pointers[i];
!       tree tag1 = symbol_mem_tag (p_map1->var);
!       bitmap may_aliases1 = MTAG_ALIASES (tag1);
! 
!       for (j = 0; j < ai->num_pointers; j++)
! 	{
! 	  struct alias_map_d *p_map2 = ai->pointers[j];
! 	  tree tag2 = symbol_mem_tag (p_map2->var);
! 	  bitmap may_aliases2 = may_aliases (tag2);
! 
! 	  /* By convention tags don't alias themselves.  */
! 	  if (tag1 == tag2)
! 	    continue;
! 
! 	  /* If the pointers may not point to each other, do nothing.  */
! 	  if (!may_alias_p (p_map1->var, p_map1->set, tag2, p_map2->set, true))
! 	    continue;
! 
! 	  /* The two pointers may alias each other.  If they already have
! 	     symbols in common, do nothing.  */
! 	  if (have_common_aliases_p (may_aliases1, may_aliases2))
! 	    continue;
  
! 	  add_may_alias (tag1, tag2);
! 	}
      }
  
!   /* We have to add all HEAP variables to all SMTs aliases bitmaps.
!      As we don't know which effective type the HEAP will have we cannot
!      do better here and we need the conflicts with obfuscated pointers
!      (a simple (*(int[n] *)ptr)[i] will do, with ptr from a VLA array
!      allocation).  */
!   for (i = 0; i < ai->num_pointers; i++)
      {
!       struct alias_map_d *p_map = ai->pointers[i];
!       tree tag = symbol_mem_tag (p_map->var);
! 
!       FOR_EACH_REFERENCED_VAR (var, rvi)
! 	{
! 	  if (var_ann (var)->is_heapvar)
! 	    add_may_alias (tag, var);
! 	}
      }
  
!   timevar_pop (TV_FLOW_INSENSITIVE);
! }
! 
! 
! /* Create a new alias set entry for VAR in AI->ADDRESSABLE_VARS.  */
! 
! static void
! create_alias_map_for (tree var, struct alias_info *ai)
! {
!   struct alias_map_d *alias_map;
!   alias_map = XCNEW (struct alias_map_d);
!   alias_map->var = var;
!   alias_map->set = get_alias_set (var);
!   ai->addressable_vars[ai->num_addressable_vars++] = alias_map;
  }
  
  
! /* Update related alias information kept in AI.  This is used when
!    building name tags, alias sets and deciding grouping heuristics.
!    STMT is the statement to process.  This function also updates
!    ADDRESSABLE_VARS.  */
  
! static void
! update_alias_info_1 (gimple stmt, struct alias_info *ai)
  {
!   bitmap addr_taken;
!   use_operand_p use_p;
!   ssa_op_iter iter;
!   bool stmt_dereferences_ptr_p;
!   enum escape_type stmt_escape_type = is_escape_site (stmt);
!   struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
! 
!   stmt_dereferences_ptr_p = false;
! 
!   if (stmt_escape_type == ESCAPE_TO_CALL
!       || stmt_escape_type == ESCAPE_TO_PURE_CONST)
!     {
!       mem_ref_stats->num_call_sites++;
!       if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
! 	mem_ref_stats->num_pure_const_call_sites++;
!     }
!   else if (stmt_escape_type == ESCAPE_TO_ASM)
!     mem_ref_stats->num_asm_sites++;
! 
!   /* Mark all the variables whose address are taken by the statement.  */
!   addr_taken = gimple_addresses_taken (stmt);
!   if (addr_taken)
!     bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
! 
!   /* Process each operand use.  For pointers, determine whether they
!      are dereferenced by the statement, or whether their value
!      escapes, etc.  */
!   FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
!     {
!       tree op, var;
!       var_ann_t v_ann;
!       struct ptr_info_def *pi;
!       unsigned num_uses, num_loads, num_stores;
! 
!       op = USE_FROM_PTR (use_p);
! 
!       /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
! 	 to the set of addressable variables.  */
!       if (TREE_CODE (op) == ADDR_EXPR)
! 	{
! 	  bitmap addressable_vars = gimple_addressable_vars (cfun);
! 
! 	  gcc_assert (gimple_code (stmt) == GIMPLE_PHI);
! 	  gcc_assert (addressable_vars);
! 
! 	  /* PHI nodes don't have annotations for pinning the set
! 	     of addresses taken, so we collect them here.
! 
! 	     FIXME, should we allow PHI nodes to have annotations
! 	     so that they can be treated like regular statements?
! 	     Currently, they are treated as second-class
! 	     statements.  */
! 	  add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
! 	  continue;
! 	}
! 
!       /* Ignore constants (they may occur in PHI node arguments).  */
!       if (TREE_CODE (op) != SSA_NAME)
! 	continue;
! 
!       var = SSA_NAME_VAR (op);
!       v_ann = var_ann (var);
! 
!       /* The base variable of an SSA name must be a GIMPLE register, and thus
! 	 it cannot be aliased.  */
!       gcc_assert (!may_be_aliased (var));
! 
!       /* We are only interested in pointers.  */
!       if (!POINTER_TYPE_P (TREE_TYPE (op)))
! 	continue;
! 
!       pi = get_ptr_info (op);
! 
!       /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
!       if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
! 	{
! 	  SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
! 	  VEC_safe_push (tree, heap, ai->processed_ptrs, op);
! 	}
! 
!       /* If STMT is a PHI node, then it will not have pointer
! 	 dereferences and it will not be an escape point.  */
!       if (gimple_code (stmt) == GIMPLE_PHI)
! 	continue;
! 
!       /* Determine whether OP is a dereferenced pointer, and if STMT
! 	 is an escape point, whether OP escapes.  */
!       count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
! 
!       /* For directly dereferenced pointers we can apply
! 	 TBAA-pruning to their points-to set.  We may not count the
! 	 implicit dereferences &PTR->FLD here.  */
!       if (num_loads + num_stores > 0)
! 	pi->is_dereferenced = 1;
! 
!       /* Handle a corner case involving address expressions of the
! 	 form '&PTR->FLD'.  The problem with these expressions is that
! 	 they do not represent a dereference of PTR.  However, if some
! 	 other transformation propagates them into an INDIRECT_REF
! 	 expression, we end up with '*(&PTR->FLD)' which is folded
! 	 into 'PTR->FLD'.
! 
! 	 So, if the original code had no other dereferences of PTR,
! 	 the aliaser will not create memory tags for it, and when
! 	 &PTR->FLD gets propagated to INDIRECT_REF expressions, the
! 	 memory operations will receive no VDEF/VUSE operands.
! 
! 	 One solution would be to have count_uses_and_derefs consider
! 	 &PTR->FLD a dereference of PTR.  But that is wrong, since it
! 	 is not really a dereference but an offset calculation.
! 
! 	 What we do here is to recognize these special ADDR_EXPR
! 	 nodes.  Since these expressions are never GIMPLE values (they
! 	 are not GIMPLE invariants), they can only appear on the RHS
! 	 of an assignment and their base address is always an
! 	 INDIRECT_REF expression.  */
!       if (is_gimple_assign (stmt)
! 	  && gimple_assign_rhs_code (stmt) == ADDR_EXPR
! 	  && !is_gimple_val (gimple_assign_rhs1 (stmt)))
! 	{
! 	  /* If the RHS if of the form &PTR->FLD and PTR == OP, then
! 	     this represents a potential dereference of PTR.  */
! 	  tree rhs = gimple_assign_rhs1 (stmt);
! 	  tree base = get_base_address (TREE_OPERAND (rhs, 0));
! 	  if (TREE_CODE (base) == INDIRECT_REF
! 	      && TREE_OPERAND (base, 0) == op)
! 	    num_loads++;
! 	}
! 
!       if (num_loads + num_stores > 0)
! 	{
! 	  /* Mark OP as dereferenced.  In a subsequent pass,
! 	     dereferenced pointers that point to a set of
! 	     variables will be assigned a name tag to alias
! 	     all the variables OP points to.  */
! 	  pi->memory_tag_needed = 1;
! 
! 	  /* ???  For always executed direct dereferences we can
! 	     apply TBAA-pruning to their escape set.  */
! 
! 	  /* Mark OP as being dereferenced.  */
! 	  pointer_set_insert (ai->dereferenced_ptrs, var);
! 
! 	  /* Update the frequency estimate for all the dereferences of
! 	     pointer OP.  */
! 	  update_mem_sym_stats_from_stmt (op, stmt, num_loads, num_stores);
! 
! 	  /* Indicate that STMT contains pointer dereferences.  */
! 	  stmt_dereferences_ptr_p = true;
! 	}
! 
!       if (stmt_escape_type != NO_ESCAPE && num_loads + num_stores < num_uses)
! 	{
! 	  /* If STMT is an escape point and STMT contains at
! 	     least one direct use of OP, then the value of OP
! 	     escapes and so the pointed-to variables need to
! 	     be marked call-clobbered.  */
! 	  pi->value_escapes_p = 1;
! 	  pi->escape_mask |= stmt_escape_type;
! 
! 	  /* If the statement makes a function call, assume
! 	     that pointer OP will be dereferenced in a store
! 	     operation inside the called function.  */
! 	  if (is_gimple_call (stmt)
! 	      || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
! 	    {
! 	      pointer_set_insert (ai->dereferenced_ptrs, var);
! 	      pi->memory_tag_needed = 1;
! 	    }
! 	}
!     }
! 
!   if (gimple_code (stmt) == GIMPLE_PHI)
!     return;
! 
!   /* Mark stored variables in STMT as being written to and update the
!      memory reference stats for all memory symbols referenced by STMT.  */
!   if (gimple_references_memory_p (stmt))
!     {
!       unsigned i;
!       bitmap_iterator bi;
! 
!       mem_ref_stats->num_mem_stmts++;
! 
!       /* Notice that we only update memory reference stats for symbols
! 	 loaded and stored by the statement if the statement does not
! 	 contain pointer dereferences and it is not a call/asm site.
! 	 This is to avoid double accounting problems when creating
! 	 memory partitions.  After computing points-to information,
! 	 pointer dereference statistics are used to update the
! 	 reference stats of the pointed-to variables, so here we
! 	 should only update direct references to symbols.
! 
! 	 Indirect references are not updated here for two reasons: (1)
! 	 The first time we compute alias information, the sets
! 	 LOADED/STORED are empty for pointer dereferences, (2) After
! 	 partitioning, LOADED/STORED may have references to
! 	 partitions, not the original pointed-to variables.  So, if we
! 	 always counted LOADED/STORED here and during partitioning, we
! 	 would count many symbols more than once.
! 
! 	 This does cause some imprecision when a statement has a
! 	 combination of direct symbol references and pointer
! 	 dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
! 	 memory symbols in its argument list, but these cases do not
! 	 occur so frequently as to constitute a serious problem.  */
!       if (!stmt_dereferences_ptr_p
! 	  && stmt_escape_type != ESCAPE_TO_CALL
! 	  && stmt_escape_type != ESCAPE_TO_PURE_CONST
! 	  && stmt_escape_type != ESCAPE_TO_ASM)
! 	{
! 	  if (gimple_stored_syms (stmt))
! 	    EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
! 	      update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 0, 1);
! 
! 	  if (gimple_loaded_syms (stmt))
! 	    EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
! 	      update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
! 	}
!     }
! }
  
! /* Update various related attributes like escaped addresses,
!    pointer dereferences for loads and stores.  This is used
!    when creating name tags and alias sets.  */
  
! static void
! update_alias_info (struct alias_info *ai)
! {
!   basic_block bb;
  
!   FOR_EACH_BB (bb)
      {
!       gimple_stmt_iterator gsi;
!       gimple phi;
  
!       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
! 	{
! 	  phi = gsi_stmt (gsi);
! 	  if (is_gimple_reg (PHI_RESULT (phi)))
! 	    update_alias_info_1 (phi, ai);
! 	}
  
!       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
! 	update_alias_info_1 (gsi_stmt (gsi), ai);
      }
  }
  
! /* Create memory tags for all the dereferenced pointers and build the
!    ADDRESSABLE_VARS and POINTERS arrays used for building the may-alias
!    sets.  Based on the address escape and points-to information collected
!    earlier, this pass will also clear the TREE_ADDRESSABLE flag from those
!    variables whose address is not needed anymore.  */
  
  static void
! setup_pointers_and_addressables (struct alias_info *ai)
  {
-   size_t num_addressable_vars, num_pointers;
    referenced_var_iterator rvi;
    tree var;
!   VEC (tree, heap) *varvec = NULL;
!   safe_referenced_var_iterator srvi;
  
!   /* Size up the arrays ADDRESSABLE_VARS and POINTERS.  */
!   num_addressable_vars = num_pointers = 0;
!   
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
!       if (may_be_aliased (var))
! 	num_addressable_vars++;
! 
!       if (POINTER_TYPE_P (TREE_TYPE (var)))
! 	{
! 	  /* Since we don't keep track of volatile variables, assume that
! 	     these pointers are used in indirect store operations.  */
! 	  if (TREE_THIS_VOLATILE (var))
! 	    pointer_set_insert (ai->dereferenced_ptrs, var);
  
! 	  num_pointers++;
! 	}
      }
  
!   /* Create ADDRESSABLE_VARS and POINTERS.  Note that these arrays are
!      always going to be slightly bigger than we actually need them
!      because some TREE_ADDRESSABLE variables will be marked
!      non-addressable below and only pointers with unique symbol tags are
!      going to be added to POINTERS.  */
!   ai->addressable_vars = XCNEWVEC (struct alias_map_d *, num_addressable_vars);
!   ai->pointers = XCNEWVEC (struct alias_map_d *, num_pointers);
!   ai->num_addressable_vars = 0;
!   ai->num_pointers = 0;
! 
!   FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, srvi)
!     {
!       /* Name memory tags already have flow-sensitive aliasing
! 	 information, so they need not be processed by
! 	 compute_flow_insensitive_aliasing.  Similarly, symbol memory
! 	 tags are already accounted for when we process their
! 	 associated pointer. 
!       
!          Structure fields, on the other hand, have to have some of this
!          information processed for them, but it's pointless to mark them
!          non-addressable (since they are fake variables anyway).  */
!       if (MTAG_P (var))
! 	continue;
! 
!       /* Remove the ADDRESSABLE flag from every addressable variable whose
!          address is not needed anymore.  This is caused by the propagation
!          of ADDR_EXPR constants into INDIRECT_REF expressions and the
!          removal of dead pointer assignments done by the early scalar
!          cleanup passes.  */
!       if (TREE_ADDRESSABLE (var))
! 	{
! 	  if (!bitmap_bit_p (gimple_addressable_vars (cfun), DECL_UID (var))
! 	      && TREE_CODE (var) != RESULT_DECL
! 	      && !is_global_var (var))
! 	    {
! 	      bool okay_to_mark = true;
  
! 	      /* Since VAR is now a regular GIMPLE register, we will need
! 		 to rename VAR into SSA afterwards.  */
! 	      mark_sym_for_renaming (var);
! 
! 	      /* The address of VAR is not needed, remove the
! 		 addressable bit, so that it can be optimized as a
! 		 regular variable.  */
! 	      if (okay_to_mark)
! 		{
! 		  /* The memory partition holding VAR will no longer
! 		     contain VAR, and statements referencing it will need
! 		     to be updated.  */
! 		  if (memory_partition (var))
! 		    mark_sym_for_renaming (memory_partition (var));
  
! 		  mark_non_addressable (var);
! 		}
! 	    }
! 	}
  
!       /* Global variables and addressable locals may be aliased.  Create an
!          entry in ADDRESSABLE_VARS for VAR.  */
!       if (may_be_aliased (var))
! 	{
! 	  create_alias_map_for (var, ai);
! 	  mark_sym_for_renaming (var);
! 	}
  
!       /* Add pointer variables that have been dereferenced to the POINTERS
!          array and create a symbol memory tag for them.  */
!       if (POINTER_TYPE_P (TREE_TYPE (var)))
  	{
! 	  if (pointer_set_contains (ai->dereferenced_ptrs, var))
! 	    {
! 	      tree tag, old_tag;
! 	      var_ann_t t_ann;
! 
! 	      /* If pointer VAR still doesn't have a memory tag
! 		 associated with it, create it now or re-use an
! 		 existing one.  */
! 	      tag = get_smt_for (var, ai);
! 	      t_ann = var_ann (tag);
! 
! 	      /* The symbol tag will need to be renamed into SSA
! 		 afterwards. Note that we cannot do this inside
! 		 get_smt_for because aliasing may run multiple times
! 		 and we only create symbol tags the first time.  */
! 	      mark_sym_for_renaming (tag);
! 
! 	      /* Similarly, if pointer VAR used to have another type
! 		 tag, we will need to process it in the renamer to
! 		 remove the stale virtual operands.  */
! 	      old_tag = symbol_mem_tag (var);
! 	      if (old_tag)
! 		mark_sym_for_renaming (old_tag);
  
! 	      /* Associate the tag with pointer VAR.  */
! 	      set_symbol_mem_tag (var, tag);
! 	    }
! 	  else
! 	    {
! 	      /* The pointer has not been dereferenced.  If it had a
! 		 symbol memory tag, remove it and mark the old tag for
! 		 renaming to remove it out of the IL.  */
! 	      tree tag = symbol_mem_tag (var);
! 	      if (tag)
! 		{
! 		  mark_sym_for_renaming (tag);
! 		  set_symbol_mem_tag (var, NULL_TREE);
! 		}
! 	    }
  	}
      }
- 
-   VEC_free (tree, heap, varvec);
  }
  
  
! /* Determine whether to use .GLOBAL_VAR to model call clobbering
!    semantics.  If the function makes no references to global
!    variables and contains at least one call to a non-pure function,
!    then we need to mark the side-effects of the call using .GLOBAL_VAR
!    to represent all possible global memory referenced by the callee.  */
  
  static void
! maybe_create_global_var (void)
  {
!   /* No need to create it, if we have one already.  */
!   if (gimple_global_var (cfun) == NULL_TREE)
!     {
!       struct mem_ref_stats_d *stats = gimple_mem_ref_stats (cfun);
  
!       /* Create .GLOBAL_VAR if there are no call-clobbered
! 	 variables and the program contains a mixture of pure/const
! 	 and regular function calls.  This is to avoid the problem
! 	 described in PR 20115:
! 
! 	      int X;
! 	      int func_pure (void) { return X; }
! 	      int func_non_pure (int a) { X += a; }
! 	      int foo ()
! 	      {
! 	 	int a = func_pure ();
! 		func_non_pure (a);
! 		a = func_pure ();
! 		return a;
! 	      }
! 
! 	 Since foo() has no call-clobbered variables, there is
! 	 no relationship between the calls to func_pure and
! 	 func_non_pure.  Since func_pure has no side-effects, value
! 	 numbering optimizations elide the second call to func_pure.
! 	 So, if we have some pure/const and some regular calls in the
! 	 program we create .GLOBAL_VAR to avoid missing these
! 	 relations.  */
!       if (bitmap_empty_p (gimple_call_clobbered_vars (cfun))
! 	  && stats->num_call_sites > 0
! 	  && stats->num_pure_const_call_sites > 0
! 	  && stats->num_call_sites > stats->num_pure_const_call_sites)
! 	create_global_var ();
      }
  }
  
  
--- 244,586 ----
  	    mark_call_clobbered (var, pt_anything_mask);
  	}
      }
  
    timevar_pop (TV_CALL_CLOBBER);
  }
  
  
! /* Compute may-alias information for every variable referenced in function
!    FNDECL.
  
!    Alias analysis proceeds in 3 main phases:
  
!    1- Points-to and escape analysis.
  
!    This phase walks the use-def chains in the SSA web looking for three
!    things:
  
+ 	* Assignments of the form P_i = &VAR
+ 	* Assignments of the form P_i = malloc()
+ 	* Pointers and ADDR_EXPR that escape the current function.
  
!    The concept of 'escaping' is the same one used in the Java world.  When
!    a pointer or an ADDR_EXPR escapes, it means that it has been exposed
!    outside of the current function.  So, assignment to global variables,
!    function arguments and returning a pointer are all escape sites, as are
!    conversions between pointers and integers.
  
!    This is where we are currently limited.  Since not everything is renamed
!    into SSA, we lose track of escape properties when a pointer is stashed
!    inside a field in a structure, for instance.  In those cases, we are
!    assuming that the pointer does escape.
  
+    We use escape analysis to determine whether a variable is
+    call-clobbered.  Simply put, if an ADDR_EXPR escapes, then the variable
+    is call-clobbered.  If a pointer P_i escapes, then all the variables
+    pointed-to by P_i (and its memory tag) also escape.
  
!    2- Compute flow-sensitive aliases
  
!    We have two classes of memory tags.  Memory tags associated with the
!    pointed-to data type of the pointers in the program.  These tags are
!    called "symbol memory tag" (SMT).  The other class are those associated
!    with SSA_NAMEs, called "name memory tag" (NMT). The basic idea is that
!    when adding operands for an INDIRECT_REF *P_i, we will first check
!    whether P_i has a name tag, if it does we use it, because that will have
!    more precise aliasing information.  Otherwise, we use the standard symbol
!    tag.
  
+    In this phase, we go through all the pointers we found in points-to
+    analysis and create alias sets for the name memory tags associated with
+    each pointer P_i.  If P_i escapes, we mark call-clobbered the variables
+    it points to and its tag.
  
  
!    3- Compute flow-insensitive aliases
  
!    This pass will compare the alias set of every symbol memory tag and
!    every addressable variable found in the program.  Given a symbol
!    memory tag SMT and an addressable variable V.  If the alias sets of
!    SMT and V conflict (as computed by may_alias_p), then V is marked
!    as an alias tag and added to the alias set of SMT.
  
!    For instance, consider the following function:
  
! 	    foo (int i)
  	    {
! 	      int *p, a, b;
! 	    
! 	      if (i > 10)
! 	        p = &a;
! 	      else
! 	        p = &b;
! 	    
! 	      *p = 3;
! 	      a = b + 2;
! 	      return *p;
  	    }
  
!    After aliasing analysis has finished, the symbol memory tag for pointer
!    'p' will have two aliases, namely variables 'a' and 'b'.  Every time
!    pointer 'p' is dereferenced, we want to mark the operation as a
!    potential reference to 'a' and 'b'.
  
! 	    foo (int i)
! 	    {
! 	      int *p, a, b;
  
! 	      if (i_2 > 10)
! 		p_4 = &a;
! 	      else
! 		p_6 = &b;
! 	      # p_1 = PHI <p_4(1), p_6(2)>;
  
! 	      # a_7 = VDEF <a_3>;
! 	      # b_8 = VDEF <b_5>;
! 	      *p_1 = 3;
  
+ 	      # a_9 = VDEF <a_7>
+ 	      # VUSE <b_8>
+ 	      a_9 = b_8 + 2;
  
! 	      # VUSE <a_9>;
! 	      # VUSE <b_8>;
! 	      return *p_1;
! 	    }
  
+    In certain cases, the list of may aliases for a pointer may grow too
+    large.  This may cause an explosion in the number of virtual operands
+    inserted in the code.  Resulting in increased memory consumption and
+    compilation time.
  
!    When the number of virtual operands needed to represent aliased
!    loads and stores grows too large (configurable with option --param
!    max-aliased-vops and --param avg-aliased-vops), alias sets are
!    grouped to avoid severe compile-time slow downs and memory
!    consumption. See compute_memory_partitions.  */
  
! unsigned int
! compute_may_aliases (void)
  {
!   timevar_push (TV_TREE_MAY_ALIAS);
    
!   memset (&alias_stats, 0, sizeof (alias_stats));
  
!   /* Reset aliasing information.  */
!   reset_alias_info ();
  
!   /* For each pointer P_i, determine the sets of variables that P_i may
!      point-to.  For every addressable variable V, determine whether the
!      address of V escapes the current function, making V call-clobbered
!      (i.e., whether &V is stored in a global variable or if its passed as a
!      function call argument).  */
!   compute_points_to_sets ();
  
+   /* Compute flow-sensitive, points-to based aliasing for all the name
+      memory tags.  */
+   compute_flow_sensitive_aliasing ();
+   
+   /* Compute call clobbering information.  */
+   compute_call_clobbered ();
  
!   /* Debugging dumps.  */
!   if (dump_file)
!     {
!       dump_alias_info (dump_file);
!       dump_points_to_info (dump_file);
  
!       if (dump_flags & TDF_STATS)
! 	dump_alias_stats (dump_file);
  
!       if (dump_flags & TDF_DETAILS)
! 	dump_referenced_vars (dump_file);
      }
  
!   /* Report strict aliasing violations.  */
!   strict_aliasing_warning_backend ();
  
!   /* Deallocate memory used by aliasing data structures.  */
    delete_points_to_sets ();
  
!   gcc_assert (!need_ssa_update_p ());
  
!   timevar_pop (TV_TREE_MAY_ALIAS);
    
!   return 0;
  }
  
! /* Data structure used to count the number of dereferences to PTR
!    inside an expression.  */
! struct count_ptr_d
  {
    tree ptr;
!   unsigned num_stores;
!   unsigned num_loads;
! };
  
  
! /* Helper for count_uses_and_derefs.  Called by walk_tree to look for
!    (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
  
! static tree
! count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
  {
!   struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
!   struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
  
!   /* Do not walk inside ADDR_EXPR nodes.  In the expression &ptr->fld,
!      pointer 'ptr' is *not* dereferenced, it is simply used to compute
!      the address of 'fld' as 'ptr + offsetof(fld)'.  */
!   if (TREE_CODE (*tp) == ADDR_EXPR)
!     {
!       *walk_subtrees = 0;
!       return NULL_TREE;
      }
  
!   if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
      {
!       if (wi_p->is_lhs)
! 	count_p->num_stores++;
!       else
! 	count_p->num_loads++;
      }
  
!   return NULL_TREE;
  }
  
  
! /* Count the number of direct and indirect uses for pointer PTR in
!    statement STMT.  The number of direct uses is stored in
!    *NUM_USES_P.  Indirect references are counted separately depending
!    on whether they are store or load operations.  The counts are
!    stored in *NUM_STORES_P and *NUM_LOADS_P.  */
  
! void
! count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
! 		       unsigned *num_loads_p, unsigned *num_stores_p)
  {
!   ssa_op_iter i;
!   tree use;
  
!   *num_uses_p = 0;
!   *num_loads_p = 0;
!   *num_stores_p = 0;
  
!   /* Find out the total number of uses of PTR in STMT.  */
!   FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
!     if (use == ptr)
!       (*num_uses_p)++;
  
!   /* Now count the number of indirect references to PTR.  This is
!      truly awful, but we don't have much choice.  There are no parent
!      pointers inside INDIRECT_REFs, so an expression like
!      '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to
!      find all the indirect and direct uses of x_1 inside.  The only
!      shortcut we can take is the fact that GIMPLE only allows
!      INDIRECT_REFs inside the expressions below.  */
!   if (is_gimple_assign (stmt)
!       || gimple_code (stmt) == GIMPLE_RETURN
!       || gimple_code (stmt) == GIMPLE_ASM
!       || is_gimple_call (stmt))
      {
!       struct walk_stmt_info wi;
!       struct count_ptr_d count;
  
!       count.ptr = ptr;
!       count.num_stores = 0;
!       count.num_loads = 0;
! 
!       memset (&wi, 0, sizeof (wi));
!       wi.info = &count;
!       walk_gimple_op (stmt, count_ptr_derefs, &wi);
  
!       *num_stores_p = count.num_stores;
!       *num_loads_p = count.num_loads;
      }
+ 
+   gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
  }
  
! /* Helper for init_alias_info.  Reset existing aliasing information.  */
  
  static void
! reset_alias_info (void)
  {
    referenced_var_iterator rvi;
    tree var;
!   unsigned i;
  
!   /* Since we are about to re-discover call-clobbered
!      variables, clear all the call-clobbered flags.  */
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
!       if (is_gimple_reg (var)
! 	  || is_global_var (var))
! 	continue;
  
!       clear_call_clobbered (var);
      }
  
!   /* There should be no call-clobbered variable left.  */
!   gcc_assert (bitmap_empty_p (gimple_call_clobbered_vars (cfun)));
  
!   /* Clear the call-used variables.  */
!   bitmap_clear (gimple_call_used_vars (cfun));
  
!   /* Clear points-to information from each SSA name.  */
!   for (i = 1; i < num_ssa_names; i++)
!     {
!       tree name = ssa_name (i);
  
!       if (!name || !POINTER_TYPE_P (TREE_TYPE (name)))
! 	continue;
  
!       if (SSA_NAME_PTR_INFO (name))
  	{
! 	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
  
! 	  /* Clear all the flags but keep the name tag to
! 	     avoid creating new temporaries unnecessarily.  If
! 	     this pointer is found to point to a subset or
! 	     superset of its former points-to set, then a new
! 	     tag will need to be created in create_name_tags.  */
! 	  pi->pt_anything = 0;
! 	  pi->pt_null = 0;
! 	  pi->value_escapes_p = 0;
! 	  pi->is_dereferenced = 0;
! 	  if (pi->pt_vars)
! 	    bitmap_clear (pi->pt_vars);
  	}
      }
  }
  
  
! 
! /* For every pointer P_i in AI->PROCESSED_PTRS, create may-alias sets for
!    the name memory tag (NMT) associated with P_i.  If P_i escapes, then its
!    name tag and the variables it points-to are call-clobbered.  Finally, if
!    P_i escapes and we could not determine where it points to, then all the
!    variables in the same alias set as *P_i are marked call-clobbered.  This
!    is necessary because we must assume that P_i may take the address of any
!    variable in the same alias set.  */
  
  static void
! compute_flow_sensitive_aliasing (void)
  {
!   unsigned i;
! 
!   timevar_push (TV_FLOW_SENSITIVE);
  
!   for (i = 0; i < num_ssa_names; ++i)
!     {
!       tree ptr = ssa_name (i);
!       if (ptr
! 	  && POINTER_TYPE_P (TREE_TYPE (ptr)))
! 	if (!find_what_p_points_to (ptr))
! 	  set_pt_anything (ptr);
      }
+ 
+   timevar_pop (TV_FLOW_SENSITIVE);
  }
  
  
*************** may_alias_p (tree ptr, alias_set_type me
*** 2919,2938 ****
  	     tree var, alias_set_type var_alias_set,
  	     bool alias_set_only)
  {
-   tree mem;
- 
    alias_stats.alias_queries++;
    alias_stats.simple_queries++;
  
-   /* By convention, a variable cannot alias itself.  */
-   mem = symbol_mem_tag (ptr);
-   if (mem == var)
-     {
-       alias_stats.alias_noalias++;
-       alias_stats.simple_resolved++;
-       return false;
-     }
- 
    /* If -fargument-noalias-global is > 2, pointer arguments may
       not point to anything else.  */
    if (flag_argument_noalias > 2 && TREE_CODE (ptr) == PARM_DECL)
--- 598,606 ----
*************** may_alias_p (tree ptr, alias_set_type me
*** 2965,2972 ****
        return true;
      }
  
-   gcc_assert (TREE_CODE (mem) == SYMBOL_MEMORY_TAG);
- 
    alias_stats.tbaa_queries++;
  
    /* If the alias sets don't conflict then MEM cannot alias VAR.  */
--- 633,638 ----
*************** may_point_to_global_var (tree ptr)
*** 3054,3091 ****
  
    /* If we do not have points-to information for this variable,
       we have to punt.  */
!   if (!pi
!       || !pi->name_mem_tag)
      return true;
  
!   /* The name memory tag is marked as global variable if the points-to
!      set contains a global variable.  */
!   return is_global_var (pi->name_mem_tag);
! }
! 
! /* Add ALIAS to the set of variables that may alias VAR.  */
! 
! static void
! add_may_alias (tree var, tree alias)
! {
!   /* Don't allow self-referential aliases.  */
!   gcc_assert (var != alias);
! 
!   /* ALIAS must be addressable if it's being added to an alias set.  */
! #if 1
!   TREE_ADDRESSABLE (alias) = 1;
! #else
!   gcc_assert (may_be_aliased (alias));
! #endif
! 
!   /* VAR must be a symbol or a name tag.  */
!   gcc_assert (TREE_CODE (var) == SYMBOL_MEMORY_TAG
!               || TREE_CODE (var) == NAME_MEMORY_TAG);
! 
!   if (MTAG_ALIASES (var) == NULL)
!     MTAG_ALIASES (var) = BITMAP_ALLOC (&alias_bitmap_obstack);
!   
!   bitmap_set_bit (MTAG_ALIASES (var), DECL_UID (alias));
  }
  
  
--- 720,729 ----
  
    /* If we do not have points-to information for this variable,
       we have to punt.  */
!   if (!pi)
      return true;
  
!   return pi->pt_global_mem;
  }
  
  
*************** set_pt_anything (tree ptr)
*** 3100,3114 ****
    /* Anything includes global memory.  */
    pi->pt_global_mem = 1;
    pi->pt_vars = NULL;
- 
-   /* The pointer used to have a name tag, but we now found it pointing
-      to an arbitrary location.  The name tag needs to be renamed and
-      disassociated from PTR.  */
-   if (pi->name_mem_tag)
-     {
-       mark_sym_for_renaming (pi->name_mem_tag);
-       pi->name_mem_tag = NULL_TREE;
-     }
  }
  
  
--- 738,743 ----
*************** is_escape_site (gimple stmt)
*** 3188,3371 ****
    return NO_ESCAPE;
  }
  
- /* Create a new memory tag of type TYPE.
-    Does NOT push it into the current binding.  */
- 
- tree
- create_tag_raw (enum tree_code code, tree type, const char *prefix)
- {
-   tree tmp_var;
- 
-   tmp_var = build_decl (code, create_tmp_var_name (prefix), type);
- 
-   /* Memory tags are always writable and non-static.  */
-   TREE_READONLY (tmp_var) = 0;
-   TREE_STATIC (tmp_var) = 0;
- 
-   /* It doesn't start out global.  */
-   MTAG_GLOBAL (tmp_var) = 0;
-   TREE_USED (tmp_var) = 1;
- 
-   return tmp_var;
- }
- 
- /* Create a new memory tag of type TYPE.  If IS_TYPE_TAG is true, the tag
-    is considered to represent all the pointers whose pointed-to types are
-    in the same alias set class.  Otherwise, the tag represents a single
-    SSA_NAME pointer variable.  */
- 
- static tree
- create_memory_tag (tree type, bool is_type_tag)
- {
-   tree tag = create_tag_raw (is_type_tag ? SYMBOL_MEMORY_TAG : NAME_MEMORY_TAG,
- 			     type, (is_type_tag) ? "SMT" : "NMT");
- 
-   /* By default, memory tags are local variables.  Alias analysis will
-      determine whether they should be considered globals.  */
-   DECL_CONTEXT (tag) = current_function_decl;
- 
-   /* Memory tags are by definition addressable.  */
-   TREE_ADDRESSABLE (tag) = 1;
- 
-   set_symbol_mem_tag (tag, NULL_TREE);
- 
-   /* Add the tag to the symbol table.  */
-   add_referenced_var (tag);
- 
-   return tag;
- }
- 
- 
- /* Create a name memory tag to represent a specific SSA_NAME pointer P_i.
-    This is used if P_i has been found to point to a specific set of
-    variables or to a non-aliased memory location like the address returned
-    by malloc functions.  */
- 
- static tree
- get_nmt_for (tree ptr)
- {
-   struct ptr_info_def *pi = get_ptr_info (ptr);
-   tree tag = pi->name_mem_tag;
- 
-   if (tag == NULL_TREE)
-     tag = create_memory_tag (TREE_TYPE (TREE_TYPE (ptr)), false);
-   return tag;
- }
- 
- 
- /* Return the symbol memory tag associated to pointer PTR.  A memory
-    tag is an artificial variable that represents the memory location
-    pointed-to by PTR.  It is used to model the effects of pointer
-    de-references on addressable variables.
-    
-    AI points to the data gathered during alias analysis.  This
-    function populates the array AI->POINTERS.  */
- 
- static tree
- get_smt_for (tree ptr, struct alias_info *ai)
- {
-   size_t i;
-   tree tag;
-   tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
-   alias_set_type tag_set;
- 
-   /* Get the alias set to be used for the pointed-to memory.  If that
-      differs from what we would get from looking at the type adjust
-      the tag_type to void to make sure we get a proper alias set from
-      just looking at the SMT we create.  */
-   tag_set = get_alias_set (tag_type);
-   if (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr))
-       /* This is overly conservative but we do not want to assign
-          restrict alias sets here (which if they are not assigned
-          are -2 but still "known").  */
-       || DECL_POINTER_ALIAS_SET_KNOWN_P (ptr))
-     {
-       tag_set = 0;
-       tag_type = void_type_node;
-     }
- 
-   /* To avoid creating unnecessary memory tags, only create one memory tag
-      per alias set class.  Note that it may be tempting to group
-      memory tags based on conflicting alias sets instead of
-      equivalence.  That would be wrong because alias sets are not
-      necessarily transitive (as demonstrated by the libstdc++ test
-      23_containers/vector/cons/4.cc).  Given three alias sets A, B, C
-      such that conflicts (A, B) == true and conflicts (A, C) == true,
-      it does not necessarily follow that conflicts (B, C) == true.  */
-   for (i = 0, tag = NULL_TREE; i < ai->num_pointers; i++)
-     {
-       struct alias_map_d *curr = ai->pointers[i];
-       tree curr_tag = symbol_mem_tag (curr->var);
-       if (tag_set == curr->set)
- 	{
- 	  tag = curr_tag;
- 	  break;
- 	}
-     }
- 
-   /* If VAR cannot alias with any of the existing memory tags, create a new
-      tag for PTR and add it to the POINTERS array.  */
-   if (tag == NULL_TREE)
-     {
-       struct alias_map_d *alias_map;
- 
-       /* If PTR did not have a symbol tag already, create a new SMT.*
- 	 artificial variable representing the memory location
- 	 pointed-to by PTR.  */
-       tag = symbol_mem_tag (ptr);
-       if (tag == NULL_TREE
- 	  || tag_set != get_alias_set (tag))
- 	tag = create_memory_tag (tag_type, true);
- 
-       /* Add PTR to the POINTERS array.  Note that we are not interested in
- 	 PTR's alias set.  Instead, we cache the alias set for the memory that
- 	 PTR points to.  */
-       alias_map = XCNEW (struct alias_map_d);
-       alias_map->var = ptr;
-       alias_map->set = tag_set;
-       ai->pointers[ai->num_pointers++] = alias_map;
-     }
- 
-   /* If the pointed-to type is volatile, so is the tag.  */
-   TREE_THIS_VOLATILE (tag) |= TREE_THIS_VOLATILE (tag_type);
- 
-   /* Make sure that the symbol tag has the same alias set as the
-      pointed-to type or at least accesses through the pointer will
-      alias that set.  The latter can happen after the vectorizer
-      created pointers of vector type.  */
-   gcc_assert (tag_set == get_alias_set (tag)
- 	      || alias_set_subset_of (tag_set, get_alias_set (tag)));
- 
-   return tag;
- }
- 
- 
- /* Create GLOBAL_VAR, an artificial global variable to act as a
-    representative of all the variables that may be clobbered by function
-    calls.  */
- 
- static void
- create_global_var (void)
- {
-   tree global_var = build_decl (VAR_DECL, get_identifier (".GLOBAL_VAR"),
-                                 void_type_node);
-   DECL_ARTIFICIAL (global_var) = 1;
-   TREE_READONLY (global_var) = 0;
-   DECL_EXTERNAL (global_var) = 1;
-   TREE_STATIC (global_var) = 1;
-   TREE_USED (global_var) = 1;
-   DECL_CONTEXT (global_var) = NULL_TREE;
-   TREE_THIS_VOLATILE (global_var) = 0;
-   TREE_ADDRESSABLE (global_var) = 0;
- 
-   create_var_ann (global_var);
-   mark_call_clobbered (global_var, ESCAPE_UNKNOWN);
-   add_referenced_var (global_var);
-   mark_sym_for_renaming (global_var);
-   cfun->gimple_df->global_var = global_var;
- }
- 
- 
  /* Dump alias statistics on FILE.  */
  
  static void 
--- 817,822 ----
*************** dump_alias_stats (FILE *file)
*** 3392,3398 ****
    fprintf (file, "Total non-addressable structure type resolved:\t%u\n",
  	   alias_stats.structnoaddress_resolved);
  }
!   
  
  /* Dump alias information on FILE.  */
  
--- 843,872 ----
    fprintf (file, "Total non-addressable structure type resolved:\t%u\n",
  	   alias_stats.structnoaddress_resolved);
  }
! 
! 
! /* Return true if VAR may be aliased.  */
! 
! static bool
! may_be_aliased (tree var)
! {
!   /* Obviously.  */
!   if (TREE_ADDRESSABLE (var))
!     return true;
! 
!   /* ???  Why does this differ from is_global_var ()?  */
!   if (DECL_EXTERNAL (var) || TREE_PUBLIC (var))
!     return true;
! 
!   /* Automatic variables can't have their addresses escape any other
!      way.  This must be after the check for global variables, as
!      extern declarations do not have TREE_STATIC set.  */
!   if (!TREE_STATIC (var))
!     return false;
! 
!   return false;
! }
! 
  
  /* Dump alias information on FILE.  */
  
*************** dump_alias_info (FILE *file)
*** 3407,3416 ****
  
    fprintf (file, "\nAlias information for %s\n\n", funcname);
  
-   dump_memory_partitions (file);
- 
-   fprintf (file, "\nFlow-insensitive alias information for %s\n\n", funcname);
- 
    fprintf (file, "Aliased symbols\n\n");
    
    FOR_EACH_REFERENCED_VAR (var, rvi)
--- 881,886 ----
*************** dump_alias_info (FILE *file)
*** 3421,3438 ****
  
    fprintf (file, "\nDereferenced pointers\n\n");
  
-   FOR_EACH_REFERENCED_VAR (var, rvi)
-     if (symbol_mem_tag (var))
-       dump_variable (file, var);
- 
-   fprintf (file, "\nSymbol memory tags\n\n");
-   
-   FOR_EACH_REFERENCED_VAR (var, rvi)
-     {
-       if (TREE_CODE (var) == SYMBOL_MEMORY_TAG)
- 	dump_variable (file, var);
-     }
- 
    fprintf (file, "\n\nFlow-sensitive alias information for %s\n\n", funcname);
  
    fprintf (file, "SSA_NAME pointers\n\n");
--- 891,896 ----
*************** dump_alias_info (FILE *file)
*** 3441,3464 ****
        tree ptr = ssa_name (i);
        struct ptr_info_def *pi;
        
!       if (ptr == NULL_TREE)
  	continue;
  
        pi = SSA_NAME_PTR_INFO (ptr);
!       if (!SSA_NAME_IN_FREE_LIST (ptr)
! 	  && pi
! 	  && pi->name_mem_tag)
  	dump_points_to_info_for (file, ptr);
      }
  
-   fprintf (file, "\nName memory tags\n\n");
-   
-   FOR_EACH_REFERENCED_VAR (var, rvi)
-     {
-       if (TREE_CODE (var) == NAME_MEMORY_TAG)
- 	dump_variable (file, var);
-     }
- 
    fprintf (file, "\n");
  }
  
--- 899,913 ----
        tree ptr = ssa_name (i);
        struct ptr_info_def *pi;
        
!       if (ptr == NULL_TREE
! 	  || SSA_NAME_IN_FREE_LIST (ptr))
  	continue;
  
        pi = SSA_NAME_PTR_INFO (ptr);
!       if (pi)
  	dump_points_to_info_for (file, ptr);
      }
  
    fprintf (file, "\n");
  }
  
*************** dump_points_to_info_for (FILE *file, tre
*** 3503,3518 ****
  
    if (pi)
      {
-       if (pi->name_mem_tag)
- 	{
- 	  fprintf (file, ", name memory tag: ");
- 	  print_generic_expr (file, pi->name_mem_tag, dump_flags);
- 	}
- 
        if (pi->is_dereferenced)
  	fprintf (file, ", is dereferenced");
-       else if (pi->memory_tag_needed)
- 	fprintf (file, ", is dereferenced in call");
  
        if (pi->value_escapes_p)
  	fprintf (file, ", its value escapes");
--- 952,959 ----
*************** debug_points_to_info (void)
*** 3606,3741 ****
    dump_points_to_info (stderr);
  }
  
- /* Dump to FILE the list of variables that may be aliasing VAR.  */
- 
- void
- dump_may_aliases_for (FILE *file, tree var)
- {
-   bitmap aliases;
-   
-   aliases = MTAG_ALIASES (var);
-   if (aliases)
-     {
-       bitmap_iterator bi;
-       unsigned int i;
-       tree al;
- 
-       fprintf (file, "{ ");
-       EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
- 	{
- 	  al = referenced_var (i);
- 	  print_generic_expr (file, al, dump_flags);
- 	  fprintf (file, " ");
- 	}
-       fprintf (file, "}");
-     }
- }
- 
- 
- /* Dump to stderr the list of variables that may be aliasing VAR.  */
- 
- void
- debug_may_aliases_for (tree var)
- {
-   dump_may_aliases_for (stderr, var);
- }
- 
- /* Return true if VAR may be aliased.  */
- 
- bool
- may_be_aliased (tree var)
- {
-   /* Obviously.  */
-   if (TREE_ADDRESSABLE (var))
-     return true;
- 
-   /* Globally visible variables can have their addresses taken by other
-      translation units.  */
-   if (MTAG_P (var)
-       && MTAG_GLOBAL (var))
-     return true;
-   else if (!MTAG_P (var)
-            && (DECL_EXTERNAL (var) || TREE_PUBLIC (var)))
-     return true;
- 
-   /* Automatic variables can't have their addresses escape any other
-      way.  This must be after the check for global variables, as
-      extern declarations do not have TREE_STATIC set.  */
-   if (!TREE_STATIC (var))
-     return false;
- 
-   return false;
- }
- 
- /* The following is based on code in add_stmt_operand to ensure that the
-    same defs/uses/vdefs/vuses will be found after replacing a reference
-    to var (or ARRAY_REF to var) with an INDIRECT_REF to ptr whose value
-    is the address of var.  Return a memtag for the ptr, after adding the 
-    proper may_aliases to it (which are the aliases of var, if it has any,
-    or var itself).  */
- 
- static tree
- add_may_alias_for_new_tag (tree tag, tree var)
- {
-   bitmap aliases = NULL;
-   
-   if (MTAG_P (var))
-     aliases = may_aliases (var);
- 
-   /* Case 1: |aliases| == 1  */
-   if (aliases
-       && bitmap_single_bit_set_p (aliases))
-     {
-       tree ali = referenced_var (bitmap_first_set_bit (aliases));
-       if (TREE_CODE (ali) == SYMBOL_MEMORY_TAG)
-         return ali;
-     }
- 
-   /* Case 2: |aliases| == 0  */
-   if (aliases == NULL)
-     add_may_alias (tag, var);
-   else
-     {
-       /* Case 3: |aliases| > 1  */
-       union_alias_set_into (tag, aliases);
-     }
-   return tag;
- }
- 
- /* Create a new symbol tag for PTR.  Construct the may-alias list of
-    this type tag so that it has the aliasing of VAR according to the
-    location accessed by EXPR.
- 
-    Note, the set of aliases represented by the new symbol tag are not
-    marked for renaming.  */
- 
- void
- new_type_alias (tree ptr, tree var, tree expr)
- {
-   tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
-   tree tag;
-   tree ali = NULL_TREE;
-   HOST_WIDE_INT offset, size, maxsize;
-   tree ref;
- 
-   gcc_assert (symbol_mem_tag (ptr) == NULL_TREE);
-   gcc_assert (!MTAG_P (var));
- 
-   ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
-   gcc_assert (ref);
- 
-   tag = create_memory_tag (tag_type, true);
-   set_symbol_mem_tag (ptr, tag);
- 
-   ali = add_may_alias_for_new_tag (tag, var);
- 
-   set_symbol_mem_tag (ptr, ali);
-   MTAG_GLOBAL (tag) = is_global_var (var);
- }
- 
  
! /* Reset the call_clobbered flags on our referenced vars.  In
!    theory, this only needs to be done for globals.  */
  
  static unsigned int
  reset_cc_flags (void)
--- 1047,1055 ----
    dump_points_to_info (stderr);
  }
  
  
! /* ???  Remove me.
!    For now just a quick verification run on sane initial properties.  */
  
  static unsigned int
  reset_cc_flags (void)
*************** reset_cc_flags (void)
*** 3744,3750 ****
    referenced_var_iterator rvi;
  
    FOR_EACH_REFERENCED_VAR (var, rvi)
!     var_ann (var)->call_clobbered = false;
    return 0;
  }
  
--- 1058,1069 ----
    referenced_var_iterator rvi;
  
    FOR_EACH_REFERENCED_VAR (var, rvi)
!     if (is_global_var (var)
! 	|| TREE_ADDRESSABLE (var))
!       gcc_assert (is_call_clobbered (var));
!     else
!       gcc_assert (!is_call_clobbered (var));
! 
    return 0;
  }
  
Index: alias-improvements/gcc/gimple.c
===================================================================
*** alias-improvements.orig/gcc/gimple.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/gimple.c	2008-11-26 13:48:08.000000000 +0100
*************** is_gimple_reg (tree t)
*** 2889,2897 ****
    if (TREE_CODE (t) == SSA_NAME)
      t = SSA_NAME_VAR (t);
  
-   if (MTAG_P (t))
-     return false;
- 
    if (!is_gimple_variable (t))
      return false;
  
--- 2889,2894 ----
Index: alias-improvements/gcc/ipa-cp.c
===================================================================
*** alias-improvements.orig/gcc/ipa-cp.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/ipa-cp.c	2008-11-26 13:48:08.000000000 +0100
*************** ipcp_update_callgraph (void)
*** 972,978 ****
  		gsi = gsi_for_stmt (cs->call_stmt);
  		gsi_replace (&gsi, new_stmt, true);
  		cgraph_set_call_stmt (cs, new_stmt);
! 		/* ???  We loose pure/const or clobber information during
  		   cloning so we may end up with different VOPs for
  		   the call.  See gcc.c-torture/execute/20000113-1.c.  */
  		update_ssa (TODO_update_ssa);
--- 972,978 ----
  		gsi = gsi_for_stmt (cs->call_stmt);
  		gsi_replace (&gsi, new_stmt, true);
  		cgraph_set_call_stmt (cs, new_stmt);
! 		/* ???  We lose pure/const or clobber information during
  		   cloning so we may end up with different VOPs for
  		   the call.  See gcc.c-torture/execute/20000113-1.c.  */
  		update_ssa (TODO_update_ssa);
Index: alias-improvements/gcc/passes.c
===================================================================
*** alias-improvements.orig/gcc/passes.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/passes.c	2008-11-26 13:48:08.000000000 +0100
*************** init_optimization_passes (void)
*** 600,605 ****
--- 600,606 ----
  	 calls, it is better to do the transformation
  	 here where memory SSA is not built yet.  */
        NEXT_PASS (pass_call_cdce);
+       NEXT_PASS (pass_update_address_taken);
        /* pass_build_alias is a dummy pass that ensures that we
  	 execute TODO_rebuild_alias at this point.  Re-building
  	 alias information also rewrites no longer addressed
Index: alias-improvements/gcc/tree-data-ref.c
===================================================================
*** alias-improvements.orig/gcc/tree-data-ref.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-data-ref.c	2008-11-26 13:48:08.000000000 +0100
*************** dr_analyze_indices (struct data_referenc
*** 788,821 ****
  static void
  dr_analyze_alias (struct data_reference *dr)
  {
-   gimple stmt = DR_STMT (dr);
    tree ref = DR_REF (dr);
!   tree base = get_base_address (ref), addr, smt = NULL_TREE;
!   ssa_op_iter it;
!   tree op;
!   bitmap vops;
! 
!   if (DECL_P (base))
!     smt = base;
!   else if (INDIRECT_REF_P (base))
      {
        addr = TREE_OPERAND (base, 0);
        if (TREE_CODE (addr) == SSA_NAME)
! 	{
! 	  smt = symbol_mem_tag (SSA_NAME_VAR (addr));
! 	  DR_PTR_INFO (dr) = SSA_NAME_PTR_INFO (addr);
! 	}
!     }
! 
!   DR_SYMBOL_TAG (dr) = smt;
! 
!   vops = BITMAP_ALLOC (NULL);
!   FOR_EACH_SSA_TREE_OPERAND (op, stmt, it, SSA_OP_VIRTUAL_USES)
!     {
!       bitmap_set_bit (vops, DECL_UID (SSA_NAME_VAR (op)));
      }
- 
-   DR_VOPS (dr) = vops;
  }
  
  /* Returns true if the address of DR is invariant.  */
--- 788,802 ----
  static void
  dr_analyze_alias (struct data_reference *dr)
  {
    tree ref = DR_REF (dr);
!   tree base = get_base_address (ref), addr;
! 
!   if (INDIRECT_REF_P (base))
      {
        addr = TREE_OPERAND (base, 0);
        if (TREE_CODE (addr) == SSA_NAME)
! 	DR_PTR_INFO (dr) = SSA_NAME_PTR_INFO (addr);
      }
  }
  
  /* Returns true if the address of DR is invariant.  */
*************** dr_address_invariant_p (struct data_refe
*** 838,844 ****
  void
  free_data_ref (data_reference_p dr)
  {
-   BITMAP_FREE (DR_VOPS (dr));
    VEC_free (tree, heap, DR_ACCESS_FNS (dr));
    free (dr);
  }
--- 819,824 ----
*************** create_data_ref (struct loop *nest, tree
*** 883,890 ****
        print_generic_expr (dump_file, DR_ALIGNED_TO (dr), TDF_SLIM);
        fprintf (dump_file, "\n\tbase_object: ");
        print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);
-       fprintf (dump_file, "\n\tsymbol tag: ");
-       print_generic_expr (dump_file, DR_SYMBOL_TAG (dr), TDF_SLIM);
        fprintf (dump_file, "\n");
      }
  
--- 863,868 ----
*************** dr_may_alias_p (const struct data_refere
*** 1234,1244 ****
    const_tree type_a, type_b;
    const_tree decl_a = NULL_TREE, decl_b = NULL_TREE;
  
-   /* If the sets of virtual operands are disjoint, the memory references do not
-      alias.  */
-   if (!bitmap_intersect_p (DR_VOPS (a), DR_VOPS (b)))
-     return false;
- 
    /* If the accessed objects are disjoint, the memory references do not
       alias.  */
    if (disjoint_objects_p (DR_BASE_OBJECT (a), DR_BASE_OBJECT (b)))
--- 1212,1217 ----
*************** analyze_all_data_dependences (struct loo
*** 4349,4355 ****
  	{
  	  unsigned nb_top_relations = 0;
  	  unsigned nb_bot_relations = 0;
- 	  unsigned nb_basename_differ = 0;
  	  unsigned nb_chrec_relations = 0;
  	  struct data_dependence_relation *ddr;
  
--- 4322,4327 ----
*************** analyze_all_data_dependences (struct loo
*** 4359,4373 ****
  		nb_top_relations++;
  	  
  	      else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
! 		{
! 		  struct data_reference *a = DDR_A (ddr);
! 		  struct data_reference *b = DDR_B (ddr);
! 
! 		  if (!bitmap_intersect_p (DR_VOPS (a), DR_VOPS (b)))
! 		    nb_basename_differ++;
! 		  else
! 		    nb_bot_relations++;
! 		}
  	  
  	      else 
  		nb_chrec_relations++;
--- 4331,4337 ----
  		nb_top_relations++;
  	  
  	      else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
! 		nb_bot_relations++;
  	  
  	      else 
  		nb_chrec_relations++;
Index: alias-improvements/gcc/tree-dfa.c
===================================================================
*** alias-improvements.orig/gcc/tree-dfa.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-dfa.c	2008-11-26 13:48:08.000000000 +0100
*************** dump_variable (FILE *file, tree var)
*** 297,308 ****
    fprintf (file, ", ");
    print_generic_expr (file, TREE_TYPE (var), dump_flags);
  
-   if (ann && ann->symbol_mem_tag)
-     {
-       fprintf (file, ", symbol memory tag: ");
-       print_generic_expr (file, ann->symbol_mem_tag, dump_flags);
-     }
- 
    if (TREE_ADDRESSABLE (var))
      fprintf (file, ", is addressable");
    
--- 297,302 ----
*************** dump_variable (FILE *file, tree var)
*** 312,319 ****
    if (TREE_THIS_VOLATILE (var))
      fprintf (file, ", is volatile");
  
-   dump_mem_sym_stats_for_var (file, var);
- 
    if (is_call_clobbered (var))
      {
        const char *s = "";
--- 306,311 ----
*************** dump_variable (FILE *file, tree var)
*** 357,383 ****
        print_generic_expr (file, gimple_default_def (cfun, var), dump_flags);
      }
  
-   if (MTAG_P (var) && may_aliases (var))
-     {
-       fprintf (file, ", may aliases: ");
-       dump_may_aliases_for (file, var);
-     }
- 
-   if (!is_gimple_reg (var))
-     {
-       if (memory_partition (var))
- 	{
- 	  fprintf (file, ", belongs to partition: ");
- 	  print_generic_expr (file, memory_partition (var), dump_flags);
- 	}
- 
-       if (TREE_CODE (var) == MEMORY_PARTITION_TAG)
- 	{
- 	  fprintf (file, ", partition symbols: ");
- 	  dump_decl_set (file, MPT_SYMBOLS (var));
- 	}
-     }
- 
    fprintf (file, "\n");
  }
  
--- 349,354 ----
*************** add_referenced_var (tree var)
*** 650,661 ****
    /* Insert VAR into the referenced_vars has table if it isn't present.  */
    if (referenced_var_check_and_insert (var))
      {
!       /* This is the first time we found this variable, annotate it with
! 	 attributes that are intrinsic to the variable.  */
!       
!       /* Tag's don't have DECL_INITIAL.  */
!       if (MTAG_P (var))
! 	return;
  
        /* Scan DECL_INITIAL for pointer variables as they may contain
  	 address arithmetic referencing the address of other
--- 621,634 ----
    /* Insert VAR into the referenced_vars has table if it isn't present.  */
    if (referenced_var_check_and_insert (var))
      {
!       /* If this is a new global or addressable variable conservatively
!          initialize its call-clobber state.  */
!       if (is_global_var (var))
! 	mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
!       else if (TREE_ADDRESSABLE (var))
! 	mark_call_clobbered (var, ESCAPE_UNKNOWN);
!       else
! 	clear_call_clobbered (var);
  
        /* Scan DECL_INITIAL for pointer variables as they may contain
  	 address arithmetic referencing the address of other
*************** remove_referenced_var (tree var)
*** 682,701 ****
  
    clear_call_clobbered (var);
    bitmap_clear_bit (gimple_call_used_vars (cfun), uid);
!   if ((v_ann = var_ann (var)))
      {
!       /* Preserve var_anns of globals, but clear their alias info.  */
!       if (MTAG_P (var)
! 	  || (!TREE_STATIC (var) && !DECL_EXTERNAL (var)))
! 	{
! 	  ggc_free (v_ann);
! 	  var->base.ann = NULL;
! 	}
!       else
! 	{
! 	  v_ann->mpt = NULL_TREE;
! 	  v_ann->symbol_mem_tag = NULL_TREE;
! 	}
      }
    gcc_assert (DECL_P (var));
    in.uid = uid;
--- 655,666 ----
  
    clear_call_clobbered (var);
    bitmap_clear_bit (gimple_call_used_vars (cfun), uid);
!   /* Preserve var_anns of globals.  */
!   if (!is_global_var (var)
!       && (v_ann = var_ann (var)))
      {
!       ggc_free (v_ann);
!       var->base.ann = NULL;
      }
    gcc_assert (DECL_P (var));
    in.uid = uid;
Index: alias-improvements/gcc/tree-dump.c
===================================================================
*** alias-improvements.orig/gcc/tree-dump.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-dump.c	2008-11-26 13:48:08.000000000 +0100
*************** dequeue_and_dump (dump_info_p di)
*** 510,519 ****
      case CONST_DECL:
        dump_child ("cnst", DECL_INITIAL (t));
        break;
-       
-     case SYMBOL_MEMORY_TAG:
-     case NAME_MEMORY_TAG:
-       break;
  
      case VAR_DECL:
      case PARM_DECL:
--- 510,515 ----
Index: alias-improvements/gcc/tree-flow-inline.h
===================================================================
*** alias-improvements.orig/gcc/tree-flow-inline.h	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-flow-inline.h	2008-11-26 13:48:08.000000000 +0100
*************** gimple_in_ssa_p (const struct function *
*** 35,48 ****
    return fun && fun->gimple_df && fun->gimple_df->in_ssa_p;
  }
  
- /* 'true' after aliases have been computed (see compute_may_aliases).  */
- static inline bool
- gimple_aliases_computed_p (const struct function *fun)
- {
-   gcc_assert (fun && fun->gimple_df);
-   return fun->gimple_df->aliases_computed_p;
- }
- 
  /* Addressable variables in the function.  If bit I is set, then
     REFERENCED_VARS (I) has had its address taken.  Note that
     CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related.  An
--- 35,40 ----
*************** gimple_referenced_vars (const struct fun
*** 84,97 ****
    return fun->gimple_df->referenced_vars;
  }
  
- /* Artificial variable used to model the effects of function calls.  */
- static inline tree
- gimple_global_var (const struct function *fun)
- {
-   gcc_assert (fun && fun->gimple_df);
-   return fun->gimple_df->global_var;
- }
- 
  /* Artificial variable used to model the effects of nonlocal
     variables.  */
  static inline tree
--- 76,81 ----
*************** ann_type (tree_ann_t ann)
*** 271,284 ****
    return ann->common.type;
  }
  
- /* Return the may_aliases bitmap for variable VAR, or NULL if it has
-    no may aliases.  */
- static inline bitmap
- may_aliases (const_tree var)
- {
-   return MTAG_ALIASES (var);
- }
- 
  /* Return the line number for EXPR, or return -1 if we have no line
     number information for it.  */
  static inline int
--- 255,260 ----
*************** set_is_used (tree var)
*** 605,614 ****
  static inline bool
  is_global_var (const_tree t)
  {
!   if (MTAG_P (t))
!     return MTAG_GLOBAL (t);
!   else
!     return (TREE_STATIC (t) || DECL_EXTERNAL (t));
  }
  
  /* PHI nodes should contain only ssa_names and invariants.  A test
--- 581,587 ----
  static inline bool
  is_global_var (const_tree t)
  {
!   return (TREE_STATIC (t) || DECL_EXTERNAL (t));
  }
  
  /* PHI nodes should contain only ssa_names and invariants.  A test
*************** loop_containing_stmt (gimple stmt)
*** 640,703 ****
  }
  
  
! /* Return the memory partition tag associated with symbol SYM.  */
! 
! static inline tree
! memory_partition (tree sym)
! {
!   tree tag;
! 
!   /* MPTs belong to their own partition.  */
!   if (TREE_CODE (sym) == MEMORY_PARTITION_TAG)
!     return sym;
! 
!   gcc_assert (!is_gimple_reg (sym));
!   /* Autoparallelization moves statements from the original function (which has
!      aliases computed) to the new one (which does not).  When rebuilding
!      operands for the statement in the new function, we do not want to
!      record the memory partition tags of the original function.  */
!   if (!gimple_aliases_computed_p (cfun))
!     return NULL_TREE;
!   tag = get_var_ann (sym)->mpt;
! 
! #if defined ENABLE_CHECKING
!   if (tag)
!     gcc_assert (TREE_CODE (tag) == MEMORY_PARTITION_TAG);
! #endif
! 
!   return tag;
! }
! 
! /* Return true if NAME is a memory factoring SSA name (i.e., an SSA
!    name for a memory partition.  */
! 
  static inline bool
! factoring_name_p (const_tree name)
  {
!   return TREE_CODE (SSA_NAME_VAR (name)) == MEMORY_PARTITION_TAG;
  }
  
  /* Return true if VAR is used by function calls.  */
  static inline bool
  is_call_used (const_tree var)
  {
!   return (var_ann (var)->call_clobbered
  	  || bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (var)));
  }
  
- /* Return true if VAR is clobbered by function calls.  */
- static inline bool
- is_call_clobbered (const_tree var)
- {
-   return var_ann (var)->call_clobbered;
- }
- 
  /* Mark variable VAR as being clobbered by function calls.  */
  static inline void
  mark_call_clobbered (tree var, unsigned int escape_type)
  {
    var_ann (var)->escape_mask |= escape_type;
-   var_ann (var)->call_clobbered = true;
    bitmap_set_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var));
  }
  
--- 613,641 ----
  }
  
  
! /* Return true if VAR is clobbered by function calls.  */
  static inline bool
! is_call_clobbered (const_tree var)
  {
!   return (is_global_var (var)
! 	  || bitmap_bit_p (gimple_call_clobbered_vars (cfun), DECL_UID (var)));
  }
  
  /* Return true if VAR is used by function calls.  */
  static inline bool
  is_call_used (const_tree var)
  {
!   return (is_call_clobbered (var)
  	  || bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (var)));
  }
  
  /* Mark variable VAR as being clobbered by function calls.  */
  static inline void
  mark_call_clobbered (tree var, unsigned int escape_type)
  {
+   if (is_global_var (var))
+     return;
    var_ann (var)->escape_mask |= escape_type;
    bitmap_set_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var));
  }
  
*************** mark_call_clobbered (tree var, unsigned
*** 705,715 ****
  static inline void
  clear_call_clobbered (tree var)
  {
!   var_ann_t ann = var_ann (var);
!   ann->escape_mask = 0;
!   if (MTAG_P (var))
!     MTAG_GLOBAL (var) = 0;
!   var_ann (var)->call_clobbered = false;
    bitmap_clear_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var));
  }
  
--- 643,651 ----
  static inline void
  clear_call_clobbered (tree var)
  {
!   if (is_global_var (var))
!     return;
!   var_ann (var)->escape_mask = 0;
    bitmap_clear_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var));
  }
  
*************** unmodifiable_var_p (const_tree var)
*** 1363,1371 ****
    if (TREE_CODE (var) == SSA_NAME)
      var = SSA_NAME_VAR (var);
  
-   if (MTAG_P (var))
-     return false;
- 
    return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var));
  }
  
--- 1299,1304 ----
*************** ranges_overlap_p (unsigned HOST_WIDE_INT
*** 1422,1456 ****
    return false;
  }
  
- /* Return the memory tag associated with symbol SYM.  */
- 
- static inline tree
- symbol_mem_tag (tree sym)
- {
-   tree tag = get_var_ann (sym)->symbol_mem_tag;
- 
- #if defined ENABLE_CHECKING
-   if (tag)
-     gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
- #endif
- 
-   return tag;
- }
- 
- 
- /* Set the memory tag associated with symbol SYM.  */
- 
- static inline void
- set_symbol_mem_tag (tree sym, tree tag)
- {
- #if defined ENABLE_CHECKING
-   if (tag)
-     gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
- #endif
- 
-   get_var_ann (sym)->symbol_mem_tag = tag;
- }
- 
  /* Accessor to tree-ssa-operands.c caches.  */
  static inline struct ssa_operands *
  gimple_ssa_operands (const struct function *fun)
--- 1355,1360 ----
*************** gimple_ssa_operands (const struct functi
*** 1458,1470 ****
    return &fun->gimple_df->ssa_operands;
  }
  
- /* Map describing reference statistics for function FN.  */
- static inline struct mem_ref_stats_d *
- gimple_mem_ref_stats (const struct function *fn)
- {
-   return &fn->gimple_df->mem_ref_stats;
- }
- 
  /* Given an edge_var_map V, return the PHI arg definition.  */
  
  static inline tree
--- 1362,1367 ----
Index: alias-improvements/gcc/tree-flow.h
===================================================================
*** alias-improvements.orig/gcc/tree-flow.h	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-flow.h	2008-11-26 13:48:08.000000000 +0100
*************** enum escape_type
*** 59,138 ****
  					   above.  */
  };
  
- /* Memory reference statistics for individual memory symbols,
-    collected during alias analysis.  */
- struct mem_sym_stats_d GTY(())
- {
-   /* Memory symbol.  */
-   tree var;
- 
-   /* Nonzero if this entry has been assigned a partition.  */
-   unsigned int partitioned_p : 1;
- 
-   /* Nonzero if VAR is a memory partition tag that already contains
-      call-clobbered variables in its partition set.  */
-   unsigned int has_call_clobbered_vars : 1;
- 
-   /* Number of direct reference sites.  A direct reference to VAR is any
-      reference of the form 'VAR = ' or ' = VAR'.  For GIMPLE reg
-      pointers, this is the number of sites where the pointer is
-      dereferenced.  */
-   long num_direct_writes;
-   long num_direct_reads;
- 
-   /* Number of indirect reference sites.  An indirect reference to VAR
-      is any reference via a pointer that contains VAR in its points-to
-      set or, in the case of call-clobbered symbols, a function call.  */
-   long num_indirect_writes;
-   long num_indirect_reads;
- 
-   /* Execution frequency.  This is the sum of the execution
-      frequencies of all the statements that reference this object
-      weighted by the number of references in each statement.  This is
-      the main key used to sort the list of symbols to partition.
-      Symbols with high execution frequencies are put at the bottom of
-      the work list (ie, they are partitioned last).
-      Execution frequencies are taken directly from each basic block,
-      so compiling with PGO enabled will increase the precision of this
-      estimate.  */
-   long frequency_reads;
-   long frequency_writes;
- 
-   /* Set of memory tags that contain VAR in their alias set.  */
-   bitmap parent_tags;
- };
- 
- typedef struct mem_sym_stats_d *mem_sym_stats_t;
- DEF_VEC_P(mem_sym_stats_t);
- DEF_VEC_ALLOC_P(mem_sym_stats_t, heap);
- 
- /* Memory reference statistics collected during alias analysis.  */
- struct mem_ref_stats_d GTY(())
- {
-   /* Number of statements that make memory references.  */
-   long num_mem_stmts;
- 
-   /* Number of statements that make function calls.  */
-   long num_call_sites;
- 
-   /* Number of statements that make calls to pure/const functions.  */
-   long num_pure_const_call_sites;
- 
-   /* Number of ASM statements.  */
-   long num_asm_sites;
- 
-   /* Estimated number of virtual operands needed as computed by
-    compute_memory_partitions.  */
-   long num_vuses;
-   long num_vdefs;
- 
-   /* This maps every symbol used to make "memory" references
-      (pointers, arrays, structures, etc) to an instance of struct
-      mem_sym_stats_d describing reference statistics for the symbol.  */
-   struct pointer_map_t * GTY((skip)) mem_sym_stats;
- };
- 
- 
  /* Gimple dataflow datastructure. All publicly available fields shall have
     gimple_ accessor defined in tree-flow-inline.h, all publicly modifiable
     fields should have gimple_set accessor.  */
--- 59,64 ----
*************** struct gimple_df GTY(())
*** 154,162 ****
    /* Artificial variable used for the virtual operand FUD chain.  */
    tree vop;
  
-   /* Artificial variable used to model the effects of function calls.  */
-   tree global_var;
- 
    /* Artificial variable used to model the effects of nonlocal
       variables.  */
    tree nonlocal_all;
--- 80,85 ----
*************** struct gimple_df GTY(())
*** 187,195 ****
       for this variable with an empty defining statement.  */
    htab_t GTY((param_is (union tree_node))) default_defs;
  
-   /* 'true' after aliases have been computed (see compute_may_aliases).  */
-   unsigned int aliases_computed_p : 1;
- 
    /* True if the code is in ssa form.  */
    unsigned int in_ssa_p : 1;
  
--- 110,115 ----
*************** struct gimple_df GTY(())
*** 197,207 ****
    unsigned int vop_needs_renaming : 1;
  
    struct ssa_operands ssa_operands;
- 
-   /* Memory reference statistics collected during alias analysis.
-      This information is used to drive the memory partitioning
-      heuristics in compute_memory_partitions.  */
-   struct mem_ref_stats_d mem_ref_stats;
  };
  
  /* Accessors for internal use only.  Generic code should use abstraction
--- 117,122 ----
*************** struct ptr_info_def GTY(())
*** 247,256 ****
    /* Nonzero if the value of this pointer escapes the current function.  */
    unsigned int value_escapes_p : 1;
  
-   /* Nonzero if a memory tag is needed for this pointer.  This is
-      true if this pointer is eventually dereferenced.  */
-   unsigned int memory_tag_needed : 1;
- 
    /* Nonzero if this pointer is really dereferenced.  */
    unsigned int is_dereferenced : 1;
  
--- 162,167 ----
*************** struct ptr_info_def GTY(())
*** 262,273 ****
  
    /* Set of variables that this pointer may point to.  */
    bitmap pt_vars;
- 
-   /* If this pointer has been dereferenced, and points-to information is
-      more precise than type-based aliasing, indirect references to this
-      pointer will be represented by this memory tag, instead of the type
-      tag computed by TBAA.  */
-   tree name_mem_tag;
  };
  
  
--- 173,178 ----
*************** struct var_ann_d GTY(())
*** 377,385 ****
       the memory area allocated by a call to malloc.  */
    unsigned is_heapvar : 1;
  
-   /* True if the variable is call clobbered.  */
-   unsigned call_clobbered : 1;
- 
    /* This field describes several "no alias" attributes that some
       symbols are known to have.  See the enum's definition for more
       information on each attribute.  */
--- 282,287 ----
*************** struct var_ann_d GTY(())
*** 389,406 ****
       the function.  */
    ENUM_BITFIELD (escape_type) escape_mask : 9;
  
-   /* Memory partition tag assigned to this symbol.  */
-   tree mpt;
- 
-   /* If this variable is a pointer P that has been dereferenced, this
-      field is an artificial variable that represents the memory
-      location *P.  Every other pointer Q that is type-compatible with
-      P will also have the same memory tag.  If the variable is not a
-      pointer or if it is never dereferenced, this must be NULL.
-      FIXME, do we really need this here?  How much slower would it be
-      to convert to hash table?  */
-   tree symbol_mem_tag;
- 
    /* Used when going out of SSA form to indicate which partition this
       variable represents storage for.  */
    unsigned partition;
--- 291,296 ----
*************** static inline function_ann_t function_an
*** 541,547 ****
  static inline function_ann_t get_function_ann (tree);
  static inline enum tree_ann_type ann_type (tree_ann_t);
  static inline void update_stmt (gimple);
- static inline bitmap may_aliases (const_tree);
  static inline int get_lineno (const_gimple);
  
  /*---------------------------------------------------------------------------
--- 431,436 ----
*************** extern void dump_points_to_info (FILE *)
*** 817,841 ****
  extern void debug_points_to_info (void);
  extern void dump_points_to_info_for (FILE *, tree);
  extern void debug_points_to_info_for (tree);
- extern bool may_be_aliased (tree);
  extern bool may_alias_p (tree, alias_set_type, tree, alias_set_type, bool);
  extern struct ptr_info_def *get_ptr_info (tree);
  extern bool may_point_to_global_var (tree);
- extern void new_type_alias (tree, tree, tree);
  extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *,
  				   unsigned *);
  static inline bool ref_contains_array_ref (const_tree);
  static inline bool array_ref_contains_indirect_ref (const_tree);
  extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
  				     HOST_WIDE_INT *, HOST_WIDE_INT *);
- extern tree create_tag_raw (enum tree_code, tree, const char *);
- extern void delete_mem_ref_stats (struct function *);
- extern void dump_mem_ref_stats (FILE *);
- extern void debug_mem_ref_stats (void);
- extern void debug_memory_partitions (void);
- extern void debug_mem_sym_stats (tree var);
- extern void dump_mem_sym_stats_for_var (FILE *, tree);
- extern void debug_all_mem_sym_stats (void);
  
  /* Call-back function for walk_use_def_chains().  At each reaching
     definition, a function with this prototype is called.  */
--- 706,720 ----
Index: alias-improvements/gcc/tree-into-ssa.c
===================================================================
*** alias-improvements.orig/gcc/tree-into-ssa.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-into-ssa.c	2008-11-26 13:48:08.000000000 +0100
*************** mark_sym_for_renaming (tree sym)
*** 2796,2806 ****
    bitmap_set_bit (syms_to_rename, DECL_UID (sym));
  
    if (!is_gimple_reg (sym))
!     {
!       need_to_update_vops_p = true;
!       if (memory_partition (sym))
! 	bitmap_set_bit (syms_to_rename, DECL_UID (memory_partition (sym)));
!     }
  }
  
  
--- 2796,2802 ----
    bitmap_set_bit (syms_to_rename, DECL_UID (sym));
  
    if (!is_gimple_reg (sym))
!     need_to_update_vops_p = true;
  }
  
  
*************** update_ssa (unsigned update_flags)
*** 3217,3232 ****
  	  tree sym = referenced_var (i);
  	  if (is_gimple_reg (sym))
  	    bitmap_set_bit (regs_to_rename, i);
- 	  else
- 	    {
- 	      /* Memory partitioning information may have been
- 		 computed after the symbol was marked for renaming,
- 		 if SYM is inside a partition also mark the partition
- 		 for renaming.  */
- 	      tree mpt = memory_partition (sym);
- 	      if (mpt)
- 		bitmap_set_bit (syms_to_rename, DECL_UID (mpt));
- 	    }
  	}
  
        /* Memory symbols are those not in REGS_TO_RENAME.  */
--- 3213,3218 ----
Index: alias-improvements/gcc/tree-outof-ssa.c
===================================================================
*** alias-improvements.orig/gcc/tree-outof-ssa.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-outof-ssa.c	2008-11-26 13:48:08.000000000 +0100
*************** create_temp (tree t)
*** 125,131 ****
    /* add_referenced_var will create the annotation and set up some
       of the flags in the annotation.  However, some flags we need to
       inherit from our original variable.  */
-   set_symbol_mem_tag (tmp, symbol_mem_tag (t));
    if (is_call_clobbered (t))
      mark_call_clobbered (tmp, var_ann (t)->escape_mask);
    if (bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (t)))
--- 125,130 ----
Index: alias-improvements/gcc/tree-predcom.c
===================================================================
*** alias-improvements.orig/gcc/tree-predcom.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-predcom.c	2008-11-26 13:48:08.000000000 +0100
*************** try_combine_chains (VEC (chain_p, heap)
*** 2423,2453 ****
      }
  }
  
- /* Sets alias information based on data reference DR for REF,
-    if necessary.  */
- 
- static void
- set_alias_info (tree ref, struct data_reference *dr)
- {
-   tree var;
-   tree tag = DR_SYMBOL_TAG (dr);
- 
-   gcc_assert (tag != NULL_TREE);
- 
-   ref = get_base_address (ref);
-   if (!ref || !INDIRECT_REF_P (ref))
-     return;
- 
-   var = SSA_NAME_VAR (TREE_OPERAND (ref, 0));
-   if (var_ann (var)->symbol_mem_tag)
-     return;
- 
-   if (!MTAG_P (tag))
-     new_type_alias (var, tag, ref);
-   else
-     var_ann (var)->symbol_mem_tag = tag;
- }
- 
  /* Prepare initializers for CHAIN in LOOP.  Returns false if this is
     impossible because one of these initializers may trap, true otherwise.  */
  
--- 2423,2428 ----
*************** prepare_initializers_chain (struct loop
*** 2497,2503 ****
  	  mark_virtual_ops_for_renaming_list (stmts);
  	  gsi_insert_seq_on_edge_immediate (entry, stmts);
  	}
-       set_alias_info (init, dr);
  
        VEC_replace (tree, chain->inits, i, init);
      }
--- 2472,2477 ----
Index: alias-improvements/gcc/tree-pretty-print.c
===================================================================
*** alias-improvements.orig/gcc/tree-pretty-print.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-pretty-print.c	2008-11-26 13:48:08.000000000 +0100
*************** dump_generic_node (pretty_printer *buffe
*** 882,894 ****
  	}
        break;
  
-     case SYMBOL_MEMORY_TAG:
-     case NAME_MEMORY_TAG:
      case VAR_DECL:
      case PARM_DECL:
      case FIELD_DECL:
      case NAMESPACE_DECL:
-     case MEMORY_PARTITION_TAG:
        dump_decl_name (buffer, node, flags);
        break;
  
--- 882,891 ----
Index: alias-improvements/gcc/tree-sra.c
===================================================================
*** alias-improvements.orig/gcc/tree-sra.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-sra.c	2008-11-26 13:48:08.000000000 +0100
*************** sra_walk_function (const struct sra_walk
*** 1056,1066 ****
  	ni = si;
  	gsi_next (&ni);
  
! 	/* If the statement has no virtual operands, then it doesn't
  	   make any structure references that we care about.  */
! 	if (gimple_aliases_computed_p (cfun)
! 	    && ZERO_SSA_OPERANDS (stmt, (SSA_OP_VIRTUAL_DEFS | SSA_OP_VUSE)))
! 	      continue;
  
  	switch (gimple_code (stmt))
  	  {
--- 1056,1065 ----
  	ni = si;
  	gsi_next (&ni);
  
! 	/* If the statement does not reference memory, then it doesn't
  	   make any structure references that we care about.  */
! 	if (!gimple_references_memory_p (stmt))
! 	  continue;
  
  	switch (gimple_code (stmt))
  	  {
Index: alias-improvements/gcc/tree-ssa-ccp.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-ccp.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-ccp.c	2008-11-26 13:48:08.000000000 +0100
*************** tree
*** 273,280 ****
  get_symbol_constant_value (tree sym)
  {
    if (TREE_STATIC (sym)
!       && TREE_READONLY (sym)
!       && !MTAG_P (sym))
      {
        tree val = DECL_INITIAL (sym);
        if (val)
--- 273,279 ----
  get_symbol_constant_value (tree sym)
  {
    if (TREE_STATIC (sym)
!       && TREE_READONLY (sym))
      {
        tree val = DECL_INITIAL (sym);
        if (val)
Index: alias-improvements/gcc/tree-ssa-copy.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-copy.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-copy.c	2008-11-26 13:48:08.000000000 +0100
*************** may_propagate_copy (tree dest, tree orig
*** 72,95 ****
    if (TREE_CODE (dest) == SSA_NAME
        && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
      return false;
- 
-   /* For memory partitions, copies are OK as long as the memory symbol
-      belongs to the partition.  */
-   if (TREE_CODE (dest) == SSA_NAME
-       && TREE_CODE (SSA_NAME_VAR (dest)) == MEMORY_PARTITION_TAG)
-     return (TREE_CODE (orig) == SSA_NAME
-             && !is_gimple_reg (orig)
- 	    && (SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)
- 	        || bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (dest)),
- 	                         DECL_UID (SSA_NAME_VAR (orig)))));
- 
-   if (TREE_CODE (orig) == SSA_NAME
-       && TREE_CODE (SSA_NAME_VAR (orig)) == MEMORY_PARTITION_TAG)
-     return (TREE_CODE (dest) == SSA_NAME
-             && !is_gimple_reg (dest)
- 	    && (SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)
-                 || bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (orig)),
- 	                         DECL_UID (SSA_NAME_VAR (dest)))));
    
    /* Do not copy between types for which we *do* need a conversion.  */
    if (!useless_type_conversion_p (type_d, type_o))
--- 72,77 ----
*************** may_propagate_copy (tree dest, tree orig
*** 136,168 ****
        && POINTER_TYPE_P (type_d)
        && POINTER_TYPE_P (type_o))
      {
!       tree mt_dest = symbol_mem_tag (SSA_NAME_VAR (dest));
!       tree mt_orig = symbol_mem_tag (SSA_NAME_VAR (orig));
!       if (mt_dest && mt_orig && mt_dest != mt_orig)
! 	return false;
!       else if (get_alias_set (TREE_TYPE (type_d)) != 
! 	       get_alias_set (TREE_TYPE (type_o)))
  	return false;
!       else if (!MTAG_P (SSA_NAME_VAR (dest))
! 	       && !MTAG_P (SSA_NAME_VAR (orig))
! 	       && (DECL_NO_TBAA_P (SSA_NAME_VAR (dest))
! 		   != DECL_NO_TBAA_P (SSA_NAME_VAR (orig))))
  	return false;
- 
-       /* Also verify flow-sensitive information is compatible.  */
-       if (SSA_NAME_PTR_INFO (orig) && SSA_NAME_PTR_INFO (dest))
- 	{
- 	  struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig);
- 	  struct ptr_info_def *dest_ptr_info = SSA_NAME_PTR_INFO (dest);
- 
- 	  if (orig_ptr_info->name_mem_tag
- 	      && dest_ptr_info->name_mem_tag
- 	      && orig_ptr_info->pt_vars
- 	      && dest_ptr_info->pt_vars
- 	      && !bitmap_intersect_p (dest_ptr_info->pt_vars,
- 				      orig_ptr_info->pt_vars))
- 	    return false;
- 	}
      }
  
    /* If the destination is a SSA_NAME for a virtual operand, then we have
--- 118,129 ----
        && POINTER_TYPE_P (type_d)
        && POINTER_TYPE_P (type_o))
      {
!       if (get_alias_set (TREE_TYPE (type_d))
! 	  != get_alias_set (TREE_TYPE (type_o)))
  	return false;
!       else if (DECL_NO_TBAA_P (SSA_NAME_VAR (dest))
! 	       != DECL_NO_TBAA_P (SSA_NAME_VAR (orig)))
  	return false;
      }
  
    /* If the destination is a SSA_NAME for a virtual operand, then we have
*************** may_propagate_copy (tree dest, tree orig
*** 176,183 ****
  	return true;
  
        /* We have a "copy" from something like a constant into a virtual
! 	 operand.  Reject these.  */
!       return false;
      }
  
    /* Anything else is OK.  */
--- 137,145 ----
  	return true;
  
        /* We have a "copy" from something like a constant into a virtual
! 	 operand.  Reject these.
! 	 ???  Funny.  We should really never come along here.  */
!       gcc_unreachable ();
      }
  
    /* Anything else is OK.  */
*************** may_propagate_copy_into_stmt (gimple des
*** 211,218 ****
       is much simpler.  */
  
    if (TREE_CODE (orig) == SSA_NAME
!       && (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)
!           ||  TREE_CODE (SSA_NAME_VAR (orig)) == MEMORY_PARTITION_TAG))
      return false;
  
    if (is_gimple_assign (dest))
--- 173,179 ----
       is much simpler.  */
  
    if (TREE_CODE (orig) == SSA_NAME
!       && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
      return false;
  
    if (is_gimple_assign (dest))
*************** may_propagate_copy_into_asm (tree dest)
*** 252,280 ****
  void
  merge_alias_info (tree orig_name, tree new_name)
  {
-   tree new_sym = SSA_NAME_VAR (new_name);
-   tree orig_sym = SSA_NAME_VAR (orig_name);
-   var_ann_t new_ann = var_ann (new_sym);
-   var_ann_t orig_ann = var_ann (orig_sym);
- 
-   /* No merging necessary when memory partitions are involved.  */
-   if (factoring_name_p (new_name))
-     {
-       gcc_assert (!is_gimple_reg (orig_sym));
-       return;
-     }
-   else if (factoring_name_p (orig_name))
-     {
-       gcc_assert (!is_gimple_reg (new_sym));
-       return;
-     }
- 
    gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig_name))
  	      && POINTER_TYPE_P (TREE_TYPE (new_name)));
  
  #if defined ENABLE_CHECKING
    gcc_assert (useless_type_conversion_p (TREE_TYPE (orig_name),
! 					TREE_TYPE (new_name)));
  
    /* Check that flow-sensitive information is compatible.  Notice that
       we may not merge flow-sensitive information here.  This function
--- 213,225 ----
  void
  merge_alias_info (tree orig_name, tree new_name)
  {
    gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig_name))
  	      && POINTER_TYPE_P (TREE_TYPE (new_name)));
  
  #if defined ENABLE_CHECKING
    gcc_assert (useless_type_conversion_p (TREE_TYPE (orig_name),
! 					 TREE_TYPE (new_name)));
! #endif
  
    /* Check that flow-sensitive information is compatible.  Notice that
       we may not merge flow-sensitive information here.  This function
*************** merge_alias_info (tree orig_name, tree n
*** 290,347 ****
       same in every block dominated by the predicate.
  
       Since we cannot distinguish one case from another in this
!      function, we can only make sure that if P_i and Q_j have
!      flow-sensitive information, they should be compatible.
  
!      As callers of merge_alias_info are supposed to call may_propagate_copy
!      first, the following check is redundant.  Thus, only do it if checking
!      is enabled.  */
!   if (SSA_NAME_PTR_INFO (orig_name) && SSA_NAME_PTR_INFO (new_name))
!     {
!       struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
!       struct ptr_info_def *new_ptr_info = SSA_NAME_PTR_INFO (new_name);
! 
!       /* Note that pointer NEW and ORIG may actually have different
! 	 pointed-to variables (e.g., PR 18291 represented in
! 	 testsuite/gcc.c-torture/compile/pr18291.c).  However, since
! 	 NEW is being copy-propagated into ORIG, it must always be
! 	 true that the pointed-to set for pointer NEW is the same, or
! 	 a subset, of the pointed-to set for pointer ORIG.  If this
! 	 isn't the case, we shouldn't have been able to do the
! 	 propagation of NEW into ORIG.  */
!       if (orig_ptr_info->name_mem_tag
! 	  && new_ptr_info->name_mem_tag
! 	  && orig_ptr_info->pt_vars
! 	  && new_ptr_info->pt_vars)
! 	gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars,
! 					orig_ptr_info->pt_vars));
!     }
! #endif
! 
!   /* Synchronize the symbol tags.  If both pointers had a tag and they
!      are different, then something has gone wrong.  Symbol tags can
!      always be merged because they are flow insensitive, all the SSA
!      names of the same base DECL share the same symbol tag.  */
!   if (new_ann->symbol_mem_tag == NULL_TREE)
!     new_ann->symbol_mem_tag = orig_ann->symbol_mem_tag;
!   else if (orig_ann->symbol_mem_tag == NULL_TREE)
!     orig_ann->symbol_mem_tag = new_ann->symbol_mem_tag;
!   else
!     gcc_assert (new_ann->symbol_mem_tag == orig_ann->symbol_mem_tag);
! 
!   /* Copy flow-sensitive alias information in case that NEW_NAME
!      didn't get a NMT but was set to pt_anything for optimization
!      purposes.  In case ORIG_NAME has a NMT we can safely use its
!      flow-sensitive alias information as a conservative estimate.  */
!   if (SSA_NAME_PTR_INFO (orig_name)
!       && SSA_NAME_PTR_INFO (orig_name)->name_mem_tag
!       && (!SSA_NAME_PTR_INFO (new_name)
! 	  || !SSA_NAME_PTR_INFO (new_name)->name_mem_tag))
!     {
!       struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
!       struct ptr_info_def *new_ptr_info = get_ptr_info (new_name);
!       memcpy (new_ptr_info, orig_ptr_info, sizeof (struct ptr_info_def));
!     }
  }
  
  
--- 235,246 ----
       same in every block dominated by the predicate.
  
       Since we cannot distinguish one case from another in this
!      function, we cannot merge flow-sensitive information by
!      intersecting.  Instead the only thing we can do is to _not_
!      merge flow-sensitive information.
  
!      ???  At some point we should enhance this machinery to distinguish
!      both cases in the caller.  */
  }
  
  
*************** copy_prop_visit_phi_node (gimple phi)
*** 864,871 ****
  	 Otherwise, this may move loop variant variables outside of
  	 their loops and prevent coalescing opportunities.  If the
  	 value was loop invariant, it will be hoisted by LICM and
! 	 exposed for copy propagation.  */
!       if (loop_depth_of_name (arg) > loop_depth_of_name (lhs))
  	{
  	  phi_val.value = lhs;
  	  break;
--- 763,772 ----
  	 Otherwise, this may move loop variant variables outside of
  	 their loops and prevent coalescing opportunities.  If the
  	 value was loop invariant, it will be hoisted by LICM and
! 	 exposed for copy propagation.  Not a problem for virtual
! 	 operands though.  */
!       if (is_gimple_reg (lhs)
! 	  && loop_depth_of_name (arg) > loop_depth_of_name (lhs))
  	{
  	  phi_val.value = lhs;
  	  break;
Index: alias-improvements/gcc/tree-ssa-copyrename.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-copyrename.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-copyrename.c	2008-11-26 13:48:08.000000000 +0100
*************** copy_rename_partition_coalesce (var_map
*** 115,121 ****
    int p1, p2, p3;
    tree root1, root2;
    tree rep1, rep2;
-   var_ann_t ann1, ann2, ann3;
    bool ign1, ign2, abnorm;
  
    gcc_assert (TREE_CODE (var1) == SSA_NAME);
--- 115,120 ----
*************** copy_rename_partition_coalesce (var_map
*** 144,152 ****
    root1 = SSA_NAME_VAR (rep1);
    root2 = SSA_NAME_VAR (rep2);
  
-   ann1 = var_ann (root1);
-   ann2 = var_ann (root2);
- 
    if (p1 == p2)
      {
        if (debug)
--- 143,148 ----
*************** copy_rename_partition_coalesce (var_map
*** 207,222 ****
  	}
      }
  
-   /* Don't coalesce if there are two different memory tags.  */
-   if (ann1->symbol_mem_tag
-       && ann2->symbol_mem_tag
-       && ann1->symbol_mem_tag != ann2->symbol_mem_tag)
-     {
-       if (debug)
- 	fprintf (debug, " : 2 memory tags. No coalesce.\n");
-       return false;
-     }
- 
    /* If both values have default defs, we can't coalesce.  If only one has a 
       tag, make sure that variable is the new root partition.  */
    if (gimple_default_def (cfun, root1))
--- 203,208 ----
*************** copy_rename_partition_coalesce (var_map
*** 252,259 ****
        && POINTER_TYPE_P (TREE_TYPE (root2))
        && ((get_alias_set (TREE_TYPE (TREE_TYPE (root1)))
  	   != get_alias_set (TREE_TYPE (TREE_TYPE (root2))))
! 	  || ((DECL_P (root1) && !MTAG_P (root1))
! 	      && (DECL_P (root2) && !MTAG_P (root2))
  	      && DECL_NO_TBAA_P (root1) != DECL_NO_TBAA_P (root2))))
      {
        if (debug)
--- 238,244 ----
        && POINTER_TYPE_P (TREE_TYPE (root2))
        && ((get_alias_set (TREE_TYPE (TREE_TYPE (root1)))
  	   != get_alias_set (TREE_TYPE (TREE_TYPE (root2))))
! 	  || (DECL_P (root1) && DECL_P (root2)
  	      && DECL_NO_TBAA_P (root1) != DECL_NO_TBAA_P (root2))))
      {
        if (debug)
*************** copy_rename_partition_coalesce (var_map
*** 272,284 ****
    else if (!ign1)
      replace_ssa_name_symbol (partition_to_var (map, p3), root1);
  
-   /* Update the various flag widgitry of the current base representative.  */
-   ann3 = var_ann (SSA_NAME_VAR (partition_to_var (map, p3)));
-   if (ann1->symbol_mem_tag)
-     ann3->symbol_mem_tag = ann1->symbol_mem_tag;
-   else
-     ann3->symbol_mem_tag = ann2->symbol_mem_tag;
- 
    if (debug)
      {
        fprintf (debug, " --> P%d ", p3);
--- 257,262 ----
Index: alias-improvements/gcc/tree-ssa-live.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-live.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-live.c	2008-11-26 13:48:08.000000000 +0100
*************** remove_unused_locals (void)
*** 702,712 ****
       pass is performed.  */
    FOR_EACH_REFERENCED_VAR (t, rvi)
      if (!is_global_var (t)
- 	&& !MTAG_P (t)
  	&& TREE_CODE (t) != PARM_DECL
  	&& TREE_CODE (t) != RESULT_DECL
  	&& !(ann = var_ann (t))->used
- 	&& !ann->symbol_mem_tag
  	&& !TREE_ADDRESSABLE (t)
  	&& (optimize || DECL_ARTIFICIAL (t)))
        remove_referenced_var (t);
--- 702,710 ----
Index: alias-improvements/gcc/tree-ssa-loop-ivopts.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-loop-ivopts.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-loop-ivopts.c	2008-11-26 13:48:08.000000000 +0100
*************** unshare_and_remove_ssa_names (tree ref)
*** 5214,5276 ****
    return ref;
  }
  
- /* Extract the alias analysis info for the memory reference REF.  There are
-    several ways how this information may be stored and what precisely is
-    its semantics depending on the type of the reference, but there always is
-    somewhere hidden one _DECL node that is used to determine the set of
-    virtual operands for the reference.  The code below deciphers this jungle
-    and extracts this single useful piece of information.  */
- 
- static tree
- get_ref_tag (tree ref, tree orig)
- {
-   tree var = get_base_address (ref);
-   tree aref = NULL_TREE, tag, sv;
-   HOST_WIDE_INT offset, size, maxsize;
- 
-   for (sv = orig; handled_component_p (sv); sv = TREE_OPERAND (sv, 0))
-     {
-       aref = get_ref_base_and_extent (sv, &offset, &size, &maxsize);
-       if (ref)
- 	break;
-     }
- 
-   if (!var)
-     return NULL_TREE;
- 
-   if (TREE_CODE (var) == INDIRECT_REF)
-     {
-       /* If the base is a dereference of a pointer, first check its name memory
- 	 tag.  If it does not have one, use its symbol memory tag.  */
-       var = TREE_OPERAND (var, 0);
-       if (TREE_CODE (var) != SSA_NAME)
- 	return NULL_TREE;
- 
-       if (SSA_NAME_PTR_INFO (var))
- 	{
- 	  tag = SSA_NAME_PTR_INFO (var)->name_mem_tag;
- 	  if (tag)
- 	    return tag;
- 	}
-  
-       var = SSA_NAME_VAR (var);
-       tag = symbol_mem_tag (var);
-       gcc_assert (tag != NULL_TREE);
-       return tag;
-     }
-   else
-     { 
-       if (!DECL_P (var))
- 	return NULL_TREE;
- 
-       tag = symbol_mem_tag (var);
-       if (tag)
- 	return tag;
- 
-       return var;
-     }
- }
- 
  /* Copies the reference information from OLD_REF to NEW_REF.  */
  
  static void
--- 5214,5219 ----
*************** copy_ref_info (tree new_ref, tree old_re
*** 5279,5288 ****
    if (TREE_CODE (old_ref) == TARGET_MEM_REF)
      copy_mem_ref_info (new_ref, old_ref);
    else
!     {
!       TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
!       TMR_TAG (new_ref) = get_ref_tag (old_ref, TMR_ORIGINAL (new_ref));
!     }
  }
  
  /* Rewrites USE (address that is an iv) using candidate CAND.  */
--- 5222,5228 ----
    if (TREE_CODE (old_ref) == TARGET_MEM_REF)
      copy_mem_ref_info (new_ref, old_ref);
    else
!     TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
  }
  
  /* Rewrites USE (address that is an iv) using candidate CAND.  */
Index: alias-improvements/gcc/tree-ssa-operands.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-operands.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-operands.c	2008-11-26 13:48:08.000000000 +0100
*************** init_ssa_operands (void)
*** 408,414 ****
      }
  
    gcc_assert (gimple_ssa_operands (cfun)->operand_memory == NULL);
-   gcc_assert (gimple_ssa_operands (cfun)->mpt_table == NULL);
    gimple_ssa_operands (cfun)->operand_memory_index
       = gimple_ssa_operands (cfun)->ssa_operand_mem_size;
    gimple_ssa_operands (cfun)->ops_active = true;
--- 408,413 ----
*************** void
*** 425,432 ****
  fini_ssa_operands (void)
  {
    struct ssa_operand_memory_d *ptr;
-   unsigned ix;
-   tree mpt;
  
    if (!--n_initialized)
      {
--- 424,429 ----
*************** fini_ssa_operands (void)
*** 453,468 ****
        ggc_free (ptr);
      }
  
-   for (ix = 0;
-        VEC_iterate (tree, gimple_ssa_operands (cfun)->mpt_table, ix, mpt);
-        ix++)
-     {
-       if (mpt)
- 	BITMAP_FREE (MPT_SYMBOLS (mpt));
-     }
- 
-   VEC_free (tree, heap, gimple_ssa_operands (cfun)->mpt_table);
- 
    gimple_ssa_operands (cfun)->ops_active = false;
  
    if (!n_initialized)
--- 450,455 ----
*************** get_expr_operands (gimple stmt, tree *ex
*** 1419,1426 ****
        return;
  
      case SSA_NAME:
-     case SYMBOL_MEMORY_TAG:
-     case NAME_MEMORY_TAG:
       add_stmt_operand (expr_p, stmt, flags);
       return;
  
--- 1406,1411 ----
Index: alias-improvements/gcc/tree-ssa-operands.h
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-operands.h	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-operands.h	2008-11-26 13:48:08.000000000 +0100
*************** struct ssa_operands GTY(()) {
*** 131,137 ****
     struct def_optype_d * GTY ((skip (""))) free_defs;
     struct use_optype_d * GTY ((skip (""))) free_uses;
     struct voptype_d * GTY ((skip (""))) vop_free_buckets[NUM_VOP_FREE_BUCKETS];
-    VEC(tree,heap) * GTY ((skip (""))) mpt_table;
  };
  
  /* This represents the operand cache for a stmt.  */
--- 131,136 ----
Index: alias-improvements/gcc/tree-ssa-phiprop.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-phiprop.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-phiprop.c	2008-11-26 13:48:08.000000000 +0100
*************** propagate_with_phi (basic_block bb, gimp
*** 229,236 ****
    ssa_op_iter i;
    bool phi_inserted;
  
!   if (MTAG_P (SSA_NAME_VAR (ptr))
!       || !POINTER_TYPE_P (TREE_TYPE (ptr))
        || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
      return false;
  
--- 229,235 ----
    ssa_op_iter i;
    bool phi_inserted;
  
!   if (!POINTER_TYPE_P (TREE_TYPE (ptr))
        || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
      return false;
  
Index: alias-improvements/gcc/tree-ssa-structalias.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-structalias.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-structalias.c	2008-11-26 13:48:08.000000000 +0100
*************** find_func_aliases (gimple origt)
*** 3645,3650 ****
--- 3645,3652 ----
    struct constraint_expr *c;
    enum escape_type stmt_escape_type;
  
+   /* ???  Initialize pi->is_dereferenced here.  */
+ 
    /* Now build constraints expressions.  */
    if (gimple_code (t) == GIMPLE_PHI)
      {
*************** find_func_aliases (gimple origt)
*** 3899,3910 ****
  	}
      }
  
-   /* After promoting variables and computing aliasing we will
-      need to re-scan most statements.  FIXME: Try to minimize the
-      number of statements re-scanned.  It's not really necessary to
-      re-scan *all* statements.  */
-   if (!in_ipa_mode)
-     gimple_set_modified (origt, true);
    VEC_free (ce_s, heap, rhsc);
    VEC_free (ce_s, heap, lhsc);
  }
--- 3901,3906 ----
*************** var_can_have_subvars (const_tree v)
*** 4042,4048 ****
      return false;
  
    /* Non decls or memory tags can never have subvars.  */
!   if (!DECL_P (v) || MTAG_P (v))
      return false;
  
    /* Aggregates without overlapping fields can have subvars.  */
--- 4038,4044 ----
      return false;
  
    /* Non decls or memory tags can never have subvars.  */
!   if (!DECL_P (v))
      return false;
  
    /* Aggregates without overlapping fields can have subvars.  */
*************** shared_bitmap_add (bitmap pt_vars)
*** 4642,4648 ****
     the from set.  */
  
  static void
! set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
  		   bool no_tbaa_pruning)
  {
    unsigned int i;
--- 4638,4645 ----
     the from set.  */
  
  static void
! set_uids_in_ptset (tree ptr, bitmap into, bitmap from,
! 		   struct ptr_info_def *pi,
  		   bool no_tbaa_pruning)
  {
    unsigned int i;
*************** set_uids_in_ptset (tree ptr, bitmap into
*** 4663,4685 ****
  	  || TREE_CODE (vi->decl) == PARM_DECL
  	  || TREE_CODE (vi->decl) == RESULT_DECL)
  	{
! 	  /* Just add VI->DECL to the alias set.
! 	     Don't type prune artificial vars or points-to sets
  	     for pointers that have not been dereferenced or with
  	     type-based pruning disabled.  */
! 	  if (vi->is_artificial_var
! 	      || !is_derefed
! 	      || no_tbaa_pruning)
! 	    bitmap_set_bit (into, DECL_UID (vi->decl));
! 	  else
  	    {
  	      alias_set_type var_alias_set, mem_alias_set;
  	      var_alias_set = get_alias_set (vi->decl);
  	      mem_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (may_alias_p (SSA_NAME_VAR (ptr), mem_alias_set,
! 			       vi->decl, var_alias_set, true))
! 	        bitmap_set_bit (into, DECL_UID (vi->decl));
  	    }
  	}
      }
  }
--- 4660,4685 ----
  	  || TREE_CODE (vi->decl) == PARM_DECL
  	  || TREE_CODE (vi->decl) == RESULT_DECL)
  	{
! 	  /* Don't type prune artificial vars or points-to sets
  	     for pointers that have not been dereferenced or with
  	     type-based pruning disabled.  */
! 	  if (!vi->is_artificial_var
! 	      && pi->is_dereferenced
! 	      && !no_tbaa_pruning)
  	    {
  	      alias_set_type var_alias_set, mem_alias_set;
  	      var_alias_set = get_alias_set (vi->decl);
  	      mem_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (!may_alias_p (SSA_NAME_VAR (ptr), mem_alias_set,
! 				vi->decl, var_alias_set, true))
! 		continue;
  	    }
+ 
+ 	  /* Add the decl to the points-to set.  Note that the points-to
+ 	     set contains global variables.  */
+ 	  bitmap_set_bit (into, DECL_UID (vi->decl));
+ 	  if (is_global_var (vi->decl))
+ 	    pi->pt_global_mem = true;
  	}
      }
  }
*************** find_what_p_points_to (tree p)
*** 4737,4745 ****
  	  bitmap finished_solution;
  	  bitmap result;
  
- 	  if (!pi->memory_tag_needed)
- 	    return false;
- 
  	  /* This variable may have been collapsed, let's get the real
  	     variable.  */
  	  vi = get_varinfo (find (vi->id));
--- 4737,4742 ----
*************** find_what_p_points_to (tree p)
*** 4784,4790 ****
  	  stats.points_to_sets_created++;
  
  	  set_uids_in_ptset (p, finished_solution, vi->solution,
! 			     pi->is_dereferenced,
  			     vi->no_tbaa_pruning);
  	  result = shared_bitmap_lookup (finished_solution);
  
--- 4781,4787 ----
  	  stats.points_to_sets_created++;
  
  	  set_uids_in_ptset (p, finished_solution, vi->solution,
! 			     pi,
  			     vi->no_tbaa_pruning);
  	  result = shared_bitmap_lookup (finished_solution);
  
*************** init_alias_heapvars (void)
*** 5617,5623 ****
  void
  delete_alias_heapvars (void)
  {
!   htab_delete (heapvar_for_stmt);
    heapvar_for_stmt = NULL;
  }
  
--- 5614,5621 ----
  void
  delete_alias_heapvars (void)
  {
!   if (heapvar_for_stmt)
!     htab_delete (heapvar_for_stmt);
    heapvar_for_stmt = NULL;
  }
  
Index: alias-improvements/gcc/tree-ssa-structalias.h
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-structalias.h	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-structalias.h	2008-11-26 13:48:08.000000000 +0100
*************** typedef struct constraint *constraint_t;
*** 26,32 ****
  
  /* In tree-ssa-alias.c.  */
  enum escape_type is_escape_site (gimple);
- void update_mem_sym_stats_from_stmt (tree, gimple, long, long);
  
  /* In tree-ssa-structalias.c.  */
  extern void compute_points_to_sets (void);
--- 26,31 ----
Index: alias-improvements/gcc/tree-ssa.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa.c	2008-11-26 13:48:08.000000000 +0100
*************** error:
*** 511,629 ****
  }
  
  
- static void
- verify_flow_insensitive_alias_info (void)
- {
-   tree var;
-   referenced_var_iterator rvi;
- 
-   FOR_EACH_REFERENCED_VAR (var, rvi)
-     {
-       unsigned int j;
-       bitmap aliases;
-       tree alias;
-       bitmap_iterator bi;
- 
-       if (!MTAG_P (var) || !MTAG_ALIASES (var))
- 	continue;
-       
-       aliases = MTAG_ALIASES (var);
- 
-       EXECUTE_IF_SET_IN_BITMAP (aliases, 0, j, bi)
- 	{
- 	  alias = referenced_var (j);
- 
- 	  if (TREE_CODE (alias) != MEMORY_PARTITION_TAG
- 	      && !may_be_aliased (alias))
- 	    {
- 	      error ("non-addressable variable inside an alias set");
- 	      debug_variable (alias);
- 	      goto err;
- 	    }
- 	}
-     }
- 
-   return;
- 
- err:
-   debug_variable (var);
-   internal_error ("verify_flow_insensitive_alias_info failed");
- }
- 
- 
- static void
- verify_flow_sensitive_alias_info (void)
- {
-   size_t i;
-   tree ptr;
- 
-   for (i = 1; i < num_ssa_names; i++)
-     {
-       tree var;
-       var_ann_t ann;
-       struct ptr_info_def *pi;
-  
- 
-       ptr = ssa_name (i);
-       if (!ptr)
- 	continue;
- 
-       /* We only care for pointers that are actually referenced in the
- 	 program.  */
-       if (!POINTER_TYPE_P (TREE_TYPE (ptr)) || !TREE_VISITED (ptr))
- 	continue;
- 
-       /* RESULT_DECL is special.  If it's a GIMPLE register, then it
- 	 is only written-to only once in the return statement.
- 	 Otherwise, aggregate RESULT_DECLs may be written-to more than
- 	 once in virtual operands.  */
-       var = SSA_NAME_VAR (ptr);
-       if (TREE_CODE (var) == RESULT_DECL
- 	  && is_gimple_reg (ptr))
- 	continue;
- 
-       pi = SSA_NAME_PTR_INFO (ptr);
-       if (pi == NULL)
- 	continue;
- 
-       ann = var_ann (var);
-       if (pi->memory_tag_needed && !pi->name_mem_tag && !ann->symbol_mem_tag)
- 	{
- 	  error ("dereferenced pointers should have a name or a symbol tag");
- 	  goto err;
- 	}
- 
-       if (pi->name_mem_tag
- 	  && (pi->pt_vars == NULL || bitmap_empty_p (pi->pt_vars)))
- 	{
- 	  error ("pointers with a memory tag, should have points-to sets");
- 	  goto err;
- 	}
- 
-       if (pi->value_escapes_p
- 	  && pi->escape_mask & ~ESCAPE_TO_RETURN
- 	  && pi->name_mem_tag)
- 	{
- 	  tree t = memory_partition (pi->name_mem_tag);
- 	  if (t == NULL_TREE)
- 	    t = pi->name_mem_tag;
- 	  
- 	  if (!is_call_clobbered (t))
- 	    {
- 	      error ("pointer escapes but its name tag is not call-clobbered");
- 	      goto err;
- 	    }
- 	}
-     }
- 
-   return;
- 
- err:
-   debug_variable (ptr);
-   internal_error ("verify_flow_sensitive_alias_info failed");
- }
- 
- 
  /* Verify the consistency of call clobbering information.  */
  
  static void
--- 511,516 ----
*************** verify_call_clobbering (void)
*** 632,638 ****
    unsigned int i;
    bitmap_iterator bi;
    tree var;
-   referenced_var_iterator rvi;
  
    /* At all times, the result of the call_clobbered flag should
       match the result of the call_clobbered_vars bitmap.  Verify both
--- 519,524 ----
*************** verify_call_clobbering (void)
*** 642,674 ****
    EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, i, bi)
      {
        var = referenced_var (i);
! 
!       if (memory_partition (var))
! 	var = memory_partition (var);
! 
!       if (!MTAG_P (var) && !var_ann (var)->call_clobbered)
! 	{
! 	  error ("variable in call_clobbered_vars but not marked "
! 	         "call_clobbered");
! 	  debug_variable (var);
! 	  goto err;
! 	}
!     }
! 
!   FOR_EACH_REFERENCED_VAR (var, rvi)
!     {
!       if (is_gimple_reg (var))
! 	continue;
! 
!       if (memory_partition (var))
! 	var = memory_partition (var);
! 
!       if (!MTAG_P (var)
! 	  && var_ann (var)->call_clobbered
! 	  && !bitmap_bit_p (gimple_call_clobbered_vars (cfun), DECL_UID (var)))
  	{
! 	  error ("variable marked call_clobbered but not in "
! 	         "call_clobbered_vars bitmap.");
  	  debug_variable (var);
  	  goto err;
  	}
--- 528,536 ----
    EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, i, bi)
      {
        var = referenced_var (i);
!       if (is_global_var (var))
  	{
! 	  error ("global variable in call_clobbered_vars");
  	  debug_variable (var);
  	  goto err;
  	}
*************** verify_call_clobbering (void)
*** 681,739 ****
  }
  
  
- /* Verify invariants in memory partitions.  */
- 
- static void
- verify_memory_partitions (void)
- {
-   unsigned i;
-   tree mpt;
-   VEC(tree,heap) *mpt_table = gimple_ssa_operands (cfun)->mpt_table;
-   struct pointer_set_t *partitioned_syms = pointer_set_create ();
- 
-   for (i = 0; VEC_iterate (tree, mpt_table, i, mpt); i++)
-     {
-       unsigned j;
-       bitmap_iterator bj;
- 
-       if (MPT_SYMBOLS (mpt) == NULL)
- 	{
- 	  error ("Memory partitions should have at least one symbol");
- 	  debug_variable (mpt);
- 	  goto err;
- 	}
- 
-       EXECUTE_IF_SET_IN_BITMAP (MPT_SYMBOLS (mpt), 0, j, bj)
- 	{
- 	  tree var = referenced_var (j);
- 	  if (pointer_set_insert (partitioned_syms, var))
- 	    {
- 	      error ("Partitioned symbols should belong to exactly one "
- 		     "partition");
- 	      debug_variable (var);
- 	      goto err;
- 	    }
- 	}
-     }
- 
-   pointer_set_destroy (partitioned_syms);
- 
-   return;
- 
- err:
-   internal_error ("verify_memory_partitions failed");
- }
- 
- 
  /* Verify the consistency of aliasing information.  */
  
  static void
  verify_alias_info (void)
  {
-   verify_flow_sensitive_alias_info ();
    verify_call_clobbering ();
-   verify_flow_insensitive_alias_info ();
-   verify_memory_partitions ();
  }
  
  
--- 543,554 ----
*************** verify_ssa (bool check_modified_stmt)
*** 833,841 ****
  	      base_address = get_base_address (lhs);
  
  	      if (base_address
- 		  && gimple_aliases_computed_p (cfun)
  		  && SSA_VAR_P (base_address)
- 		  && !gimple_has_volatile_ops (stmt)
  		  && ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF))
  		{
  		  error ("statement makes a memory store, but has no VDEFS");
--- 648,654 ----
*************** verify_ssa (bool check_modified_stmt)
*** 880,887 ****
      }
  
    /* Finally, verify alias information.  */
!   if (gimple_aliases_computed_p (cfun))
!     verify_alias_info ();
  
    free (definition_block);
  
--- 693,699 ----
      }
  
    /* Finally, verify alias information.  */
!   verify_alias_info ();
  
    free (definition_block);
  
*************** delete_tree_ssa (void)
*** 1029,1041 ****
    /* Remove annotations from every referenced local variable.  */
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
!       if (!MTAG_P (var)
! 	  && (TREE_STATIC (var) || DECL_EXTERNAL (var)))
! 	{
! 	  var_ann (var)->mpt = NULL_TREE;
! 	  var_ann (var)->symbol_mem_tag = NULL_TREE;
! 	  continue;
! 	}
        if (var->base.ann)
          ggc_free (var->base.ann);
        var->base.ann = NULL;
--- 841,848 ----
    /* Remove annotations from every referenced local variable.  */
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
!       if (is_global_var (var))
! 	continue;
        if (var->base.ann)
          ggc_free (var->base.ann);
        var->base.ann = NULL;
*************** delete_tree_ssa (void)
*** 1050,1071 ****
    if (ssa_operands_active ())
      fini_ssa_operands ();
  
!   cfun->gimple_df->global_var = NULL_TREE;
!   
    htab_delete (cfun->gimple_df->default_defs);
    cfun->gimple_df->default_defs = NULL;
    cfun->gimple_df->call_clobbered_vars = NULL;
    cfun->gimple_df->call_used_vars = NULL;
    cfun->gimple_df->addressable_vars = NULL;
    cfun->gimple_df->modified_noreturn_calls = NULL;
-   if (gimple_aliases_computed_p (cfun))
-     {
-       delete_alias_heapvars ();
-       gcc_assert (!need_ssa_update_p ());
-     }
-   cfun->gimple_df->aliases_computed_p = false;
-   delete_mem_ref_stats (cfun);
- 
    cfun->gimple_df = NULL;
  
    /* We no longer need the edge variable maps.  */
--- 857,870 ----
    if (ssa_operands_active ())
      fini_ssa_operands ();
  
!   delete_alias_heapvars ();
! 
    htab_delete (cfun->gimple_df->default_defs);
    cfun->gimple_df->default_defs = NULL;
    cfun->gimple_df->call_clobbered_vars = NULL;
    cfun->gimple_df->call_used_vars = NULL;
    cfun->gimple_df->addressable_vars = NULL;
    cfun->gimple_df->modified_noreturn_calls = NULL;
    cfun->gimple_df = NULL;
  
    /* We no longer need the edge variable maps.  */
*************** warn_uninitialized_var (tree *tp, int *w
*** 1498,1505 ****
  	/* If there is not gimple stmt, 
  	   or alias information has not been computed,
  	   then we cannot check VUSE ops.  */
! 	if (data->stmt == NULL
!             || !gimple_aliases_computed_p (cfun))
  	  return NULL_TREE;
  
  	vuse = SINGLE_SSA_USE_OPERAND (data->stmt, SSA_OP_VUSE);
--- 1297,1303 ----
  	/* If there is not gimple stmt, 
  	   or alias information has not been computed,
  	   then we cannot check VUSE ops.  */
! 	if (data->stmt == NULL)
  	  return NULL_TREE;
  
  	vuse = SINGLE_SSA_USE_OPERAND (data->stmt, SSA_OP_VUSE);
*************** execute_update_addresses_taken (void)
*** 1678,1687 ****
    referenced_var_iterator rvi;
    gimple_stmt_iterator gsi;
    basic_block bb;
!   bitmap addresses_taken = BITMAP_ALLOC (NULL);
    bitmap not_reg_needs = BITMAP_ALLOC (NULL);
    bool update_vops = false;
  
    /* Collect into ADDRESSES_TAKEN all variables whose address is taken within
       the function body.  */
    FOR_EACH_BB (bb)
--- 1476,1489 ----
    referenced_var_iterator rvi;
    gimple_stmt_iterator gsi;
    basic_block bb;
!   bitmap addresses_taken;
    bitmap not_reg_needs = BITMAP_ALLOC (NULL);
    bool update_vops = false;
  
+   /* Reset the addressable vars bitmap.  */
+   addresses_taken = gimple_addressable_vars (cfun);
+   bitmap_clear (addresses_taken);
+ 
    /* Collect into ADDRESSES_TAKEN all variables whose address is taken within
       the function body.  */
    FOR_EACH_BB (bb)
*************** execute_update_addresses_taken (void)
*** 1738,1743 ****
--- 1540,1546 ----
  	
        if (TREE_ADDRESSABLE (var))
  	{
+ 	  clear_call_clobbered (var);
  	  TREE_ADDRESSABLE (var) = 0;
  	  if (is_gimple_reg (var))
  	    mark_sym_for_renaming (var);
*************** execute_update_addresses_taken (void)
*** 1777,1784 ****
  	  if (gimple_references_memory_p (stmt))
  	    update_stmt (stmt);
  	}
    BITMAP_FREE (not_reg_needs);
!   BITMAP_FREE (addresses_taken);
    return 0;
  }
  
--- 1580,1588 ----
  	  if (gimple_references_memory_p (stmt))
  	    update_stmt (stmt);
  	}
+ 
    BITMAP_FREE (not_reg_needs);
! 
    return 0;
  }
  
Index: alias-improvements/gcc/tree-tailcall.c
===================================================================
*** alias-improvements.orig/gcc/tree-tailcall.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-tailcall.c	2008-11-26 13:48:08.000000000 +0100
*************** suitable_for_tail_opt_p (void)
*** 135,149 ****
    if (cfun->stdarg)
      return false;
  
!   /* No local variable nor structure field should be call-used.  We
!      ignore any kind of memory tag, as these are not real variables.  */
! 
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (!is_global_var (var)
! 	  && !MTAG_P (var)
! 	  && (gimple_aliases_computed_p (cfun)? is_call_used (var)
! 	      : TREE_ADDRESSABLE (var)))
  	return false;
      }
  
--- 135,145 ----
    if (cfun->stdarg)
      return false;
  
!   /* No local variable nor structure field should be call-used.  */
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (!is_global_var (var)
! 	  && is_call_used (var))
  	return false;
      }
  
*************** find_tail_calls (basic_block bb, struct
*** 409,419 ****
  	  break;
  	}
  
!       /* If the statement has virtual or volatile operands, fail.  */
!       if (!ZERO_SSA_OPERANDS (stmt, (SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS))
! 	  || gimple_has_volatile_ops (stmt)
! 	  || (!gimple_aliases_computed_p (cfun)
! 	      && gimple_references_memory_p (stmt)))
  	return;
      }
  
--- 405,413 ----
  	  break;
  	}
  
!       /* If the statement references memory or volatile operands, fail.  */
!       if (gimple_references_memory_p (stmt)
! 	  || gimple_has_volatile_ops (stmt))
  	return;
      }
  
Index: alias-improvements/gcc/tree-vect-transform.c
===================================================================
*** alias-improvements.orig/gcc/tree-vect-transform.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-vect-transform.c	2008-11-26 13:48:08.000000000 +0100
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 1024,1030 ****
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree vect_ptr_type;
    tree vect_ptr;
-   tree tag;
    tree new_temp;
    gimple vec_stmt;
    gimple_seq new_stmt_list = NULL;
--- 1024,1029 ----
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 1092,1110 ****
  
    add_referenced_var (vect_ptr);
  
-   /** (2) Add aliasing information to the new vector-pointer:
-           (The points-to info (DR_PTR_INFO) may be defined later.)  **/
-   
-   tag = DR_SYMBOL_TAG (dr);
-   gcc_assert (tag);
- 
-   /* If tag is a variable (and NOT_A_TAG) than a new symbol memory
-      tag must be created with tag added to its may alias list.  */
-   if (!MTAG_P (tag))
-     new_type_alias (vect_ptr, tag, DR_REF (dr));
-   else
-     set_symbol_mem_tag (vect_ptr, tag);
- 
    /** Note: If the dataref is in an inner-loop nested in LOOP, and we are
        vectorizing LOOP (i.e. outer-loop vectorization), we need to create two
        def-use update cycles for the pointer: One relative to the outer-loop
--- 1091,1096 ----
Index: alias-improvements/gcc/tree.c
===================================================================
*** alias-improvements.orig/gcc/tree.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree.c	2008-11-26 13:48:08.000000000 +0100
*************** init_ttree (void)
*** 320,334 ****
    tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1;
    tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1;
    tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1;
-   tree_contains_struct[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
-   tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
-   tree_contains_struct[MEMORY_PARTITION_TAG][TS_DECL_MINIMAL] = 1;
- 
-   tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1;
-   tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1;
-   tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1;
- 
-   tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1;
  
    tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
    tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1;
--- 320,325 ----
*************** tree_code_size (enum tree_code code)
*** 465,475 ****
  	    return sizeof (struct tree_type_decl);
  	  case FUNCTION_DECL:
  	    return sizeof (struct tree_function_decl);
- 	  case NAME_MEMORY_TAG:
- 	  case SYMBOL_MEMORY_TAG:
- 	    return sizeof (struct tree_memory_tag);
- 	  case MEMORY_PARTITION_TAG:
- 	    return sizeof (struct tree_memory_partition_tag);
  	  default:
  	    return sizeof (struct tree_decl_non_common);
  	  }
--- 456,461 ----
*************** tree_node_structure (const_tree t)
*** 2399,2408 ****
  	    return TS_TYPE_DECL;
  	  case FUNCTION_DECL:
  	    return TS_FUNCTION_DECL;
- 	  case SYMBOL_MEMORY_TAG:
- 	  case NAME_MEMORY_TAG:
- 	  case MEMORY_PARTITION_TAG:
- 	    return TS_MEMORY_TAG;
  	  default:
  	    return TS_DECL_NON_COMMON;
  	  }
--- 2385,2390 ----
*************** build5_stat (enum tree_code code, tree t
*** 3423,3431 ****
  }
  
  tree
! build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
! 	     tree arg2, tree arg3, tree arg4, tree arg5,
! 	     tree arg6 MEM_STAT_DECL)
  {
    bool constant, read_only, side_effects;
    tree t;
--- 3405,3412 ----
  }
  
  tree
! build6_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
! 	     tree arg2, tree arg3, tree arg4, tree arg5 MEM_STAT_DECL)
  {
    bool constant, read_only, side_effects;
    tree t;
*************** build7_stat (enum tree_code code, tree t
*** 3443,3449 ****
    PROCESS_ARG(3);
    PROCESS_ARG(4);
    PROCESS_ARG(5);
-   PROCESS_ARG(6);
  
    TREE_SIDE_EFFECTS (t) = side_effects;
    TREE_THIS_VOLATILE (t) = 0;
--- 3424,3429 ----
Index: alias-improvements/gcc/tree.h
===================================================================
*** alias-improvements.orig/gcc/tree.h	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree.h	2008-11-26 13:48:08.000000000 +0100
*************** extern const enum tree_code_class tree_c
*** 105,118 ****
  #define DECL_P(CODE)\
          (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_declaration)
  
- /* Nonzero if CODE represents a memory tag.  */
- 
- #define MTAG_P(CODE) \
-   (TREE_CODE (CODE) == NAME_MEMORY_TAG		\
-    || TREE_CODE (CODE) == SYMBOL_MEMORY_TAG	\
-    || TREE_CODE (CODE) == MEMORY_PARTITION_TAG)
- 
- 
  /* Nonzero if DECL represents a VAR_DECL or FUNCTION_DECL.  */
  
  #define VAR_OR_FUNCTION_DECL_P(DECL)\
--- 105,110 ----
*************** extern void omp_clause_range_check_faile
*** 933,939 ****
  
  #define TYPE_CHECK(T)		TREE_CLASS_CHECK (T, tcc_type)
  #define DECL_MINIMAL_CHECK(T)   CONTAINS_STRUCT_CHECK (T, TS_DECL_MINIMAL)
- #define TREE_MEMORY_TAG_CHECK(T)       CONTAINS_STRUCT_CHECK (T, TS_MEMORY_TAG)
  #define DECL_COMMON_CHECK(T)    CONTAINS_STRUCT_CHECK (T, TS_DECL_COMMON)
  #define DECL_WRTL_CHECK(T)      CONTAINS_STRUCT_CHECK (T, TS_DECL_WRTL)
  #define DECL_WITH_VIS_CHECK(T)  CONTAINS_STRUCT_CHECK (T, TS_DECL_WITH_VIS)
--- 925,930 ----
*************** extern void protected_set_expr_location
*** 1611,1617 ****
  #define TMR_STEP(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 3))
  #define TMR_OFFSET(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 4))
  #define TMR_ORIGINAL(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 5))
- #define TMR_TAG(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 6))
  
  /* The operands of a BIND_EXPR.  */
  #define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))
--- 1602,1607 ----
*************** struct tree_binfo GTY (())
*** 2430,2441 ****
  	(TREE_CODE (DECL) == VAR_DECL					\
  	 || TREE_CODE (DECL) == PARM_DECL				\
  	 || TREE_CODE (DECL) == RESULT_DECL				\
- 	 || MTAG_P (DECL)						\
  	 || (TREE_CODE (DECL) == SSA_NAME				\
  	     && (TREE_CODE (SSA_NAME_VAR (DECL)) == VAR_DECL		\
  		 || TREE_CODE (SSA_NAME_VAR (DECL)) == PARM_DECL	\
! 		 || TREE_CODE (SSA_NAME_VAR (DECL)) == RESULT_DECL	\
! 		 || MTAG_P (SSA_NAME_VAR (DECL)))))
  
  
  
--- 2420,2429 ----
  	(TREE_CODE (DECL) == VAR_DECL					\
  	 || TREE_CODE (DECL) == PARM_DECL				\
  	 || TREE_CODE (DECL) == RESULT_DECL				\
  	 || (TREE_CODE (DECL) == SSA_NAME				\
  	     && (TREE_CODE (SSA_NAME_VAR (DECL)) == VAR_DECL		\
  		 || TREE_CODE (SSA_NAME_VAR (DECL)) == PARM_DECL	\
! 		 || TREE_CODE (SSA_NAME_VAR (DECL)) == RESULT_DECL)))
  
  
  
*************** struct tree_decl_minimal GTY(())
*** 2490,2538 ****
    tree context;
  };
  
- /* When computing aliasing information, we represent the memory pointed-to
-    by pointers with artificial variables called "memory tags" (MT).  There
-    are two kinds of tags, namely symbol and name:
- 
-    Symbol tags (SMT) are used in flow-insensitive alias analysis, they
-    represent all the pointed-to locations and variables pointed-to by
-    the same pointer symbol.  Usually, this set is computed using
-    type-based analysis (i.e., alias set classes), but this may not
-    always be the case.
- 
-    Name tags (NMT) are used in flow-sensitive points-to alias
-    analysis, they represent the variables and memory locations
-    pointed-to by a specific SSA_NAME pointer.
- 
-    In general, given a pointer P with a symbol tag SMT, the alias set
-    of SMT should be the union of all the alias sets of the NMTs of
-    every SSA_NAME for P.  */
- struct tree_memory_tag GTY(())
- {
-   struct tree_decl_minimal common;
- 
-   bitmap GTY ((skip)) aliases;
- 
-   /* True if this tag has global scope.  */
-   unsigned int is_global : 1;
- };
- 
- #define MTAG_GLOBAL(NODE) (TREE_MEMORY_TAG_CHECK (NODE)->mtag.is_global)
- #define MTAG_ALIASES(NODE) (TREE_MEMORY_TAG_CHECK (NODE)->mtag.aliases)
- 
- /* Memory Partition Tags (MPTs) group memory symbols under one
-    common name for the purposes of placing memory PHI nodes.  */
- 
- struct tree_memory_partition_tag GTY(())
- {
-   struct tree_memory_tag common;
-   
-   /* Set of symbols grouped under this MPT.  */
-   bitmap symbols;
- };
- 
- #define MPT_SYMBOLS(NODE)	(MEMORY_PARTITION_TAG_CHECK (NODE)->mpt.symbols)
- 
  
  /* For any sort of a ..._DECL node, this points to the original (abstract)
     decl node which this decl is an instance of, or else it is NULL indicating
--- 2478,2483 ----
*************** union tree_node GTY ((ptr_alias (union l
*** 3444,3452 ****
    struct tree_binfo GTY ((tag ("TS_BINFO"))) binfo;
    struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list;
    struct tree_constructor GTY ((tag ("TS_CONSTRUCTOR"))) constructor;
-   struct tree_memory_tag GTY ((tag ("TS_MEMORY_TAG"))) mtag;
    struct tree_omp_clause GTY ((tag ("TS_OMP_CLAUSE"))) omp_clause;
-   struct tree_memory_partition_tag GTY ((tag ("TS_MEMORY_PARTITION_TAG"))) mpt;
    struct tree_optimization_option GTY ((tag ("TS_OPTIMIZATION"))) optimization;
    struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option;
  };
--- 3389,3395 ----
*************** extern tree build4_stat (enum tree_code,
*** 3938,3947 ****
  extern tree build5_stat (enum tree_code, tree, tree, tree, tree, tree,
  			 tree MEM_STAT_DECL);
  #define build5(c,t1,t2,t3,t4,t5,t6) build5_stat (c,t1,t2,t3,t4,t5,t6 MEM_STAT_INFO)
! extern tree build7_stat (enum tree_code, tree, tree, tree, tree, tree,
! 			 tree, tree, tree MEM_STAT_DECL);
! #define build7(c,t1,t2,t3,t4,t5,t6,t7,t8) \
!   build7_stat (c,t1,t2,t3,t4,t5,t6,t7,t8 MEM_STAT_INFO)
  
  extern tree build_int_cst (tree, HOST_WIDE_INT);
  extern tree build_int_cst_type (tree, HOST_WIDE_INT);
--- 3881,3890 ----
  extern tree build5_stat (enum tree_code, tree, tree, tree, tree, tree,
  			 tree MEM_STAT_DECL);
  #define build5(c,t1,t2,t3,t4,t5,t6) build5_stat (c,t1,t2,t3,t4,t5,t6 MEM_STAT_INFO)
! extern tree build6_stat (enum tree_code, tree, tree, tree, tree, tree,
! 			 tree, tree MEM_STAT_DECL);
! #define build6(c,t1,t2,t3,t4,t5,t6,t7) \
!   build6_stat (c,t1,t2,t3,t4,t5,t6,t7 MEM_STAT_INFO)
  
  extern tree build_int_cst (tree, HOST_WIDE_INT);
  extern tree build_int_cst_type (tree, HOST_WIDE_INT);
Index: alias-improvements/gcc/treestruct.def
===================================================================
*** alias-improvements.orig/gcc/treestruct.def	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/treestruct.def	2008-11-26 13:48:08.000000000 +0100
*************** DEFTREESTRUCT(TS_BINFO, "binfo")
*** 60,68 ****
  DEFTREESTRUCT(TS_STATEMENT_LIST, "statement list")
  DEFTREESTRUCT(TS_GIMPLE_STATEMENT, "gimple statement")
  DEFTREESTRUCT(TS_CONSTRUCTOR, "constructor")
- DEFTREESTRUCT(TS_MEMORY_TAG, "memory tag")
  DEFTREESTRUCT(TS_OMP_CLAUSE, "omp clause")
- DEFTREESTRUCT(TS_MEMORY_PARTITION_TAG, "memory partition tag")
  DEFTREESTRUCT(TS_OPTIMIZATION, "optimization options")
  DEFTREESTRUCT(TS_TARGET_OPTION, "target options")
  
--- 60,66 ----
Index: alias-improvements/gcc/tree-ssa-alias-warnings.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-alias-warnings.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-alias-warnings.c	2008-11-26 13:48:08.000000000 +0100
*************** build_reference_table (void)
*** 475,496 ****
  
        pi = SSA_NAME_PTR_INFO (ptr);
  
!       if (!SSA_NAME_IN_FREE_LIST (ptr) && pi && pi->name_mem_tag)
  	{
  	  /* Add pointer to the interesting dereference list.  */
  	  add_key (ref_table->ptrs, ptr, references_pool);
  
  	  /* Add all aliased names to the interesting reference list.  */
! 	  if (pi->pt_vars)
  	    {
! 	      unsigned ix;
! 	      bitmap_iterator bi;
! 
! 	      EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix, bi)
! 		{
! 		  tree alias = referenced_var (ix);
! 		  add_key (ref_table->objs, alias, references_pool);
! 		}
  	    }
  	}
      }
--- 475,494 ----
  
        pi = SSA_NAME_PTR_INFO (ptr);
  
!       if (!SSA_NAME_IN_FREE_LIST (ptr)
! 	  && pi && pi->pt_vars)
  	{
+ 	  unsigned ix;
+ 	  bitmap_iterator bi;
+ 
  	  /* Add pointer to the interesting dereference list.  */
  	  add_key (ref_table->ptrs, ptr, references_pool);
  
  	  /* Add all aliased names to the interesting reference list.  */
! 	  EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix, bi)
  	    {
! 	      tree alias = referenced_var (ix);
! 	      add_key (ref_table->objs, alias, references_pool);
  	    }
  	}
      }
*************** ffan_walker (tree *t,
*** 670,676 ****
               int *go_below ATTRIBUTE_UNUSED,
               void *data ATTRIBUTE_UNUSED)
  {
!   if (DECL_P (*t) && !MTAG_P (*t) && DECL_ARTIFICIAL (*t))
      return *t;
    else
      return NULL_TREE;
--- 668,674 ----
               int *go_below ATTRIBUTE_UNUSED,
               void *data ATTRIBUTE_UNUSED)
  {
!   if (DECL_P (*t) && DECL_ARTIFICIAL (*t))
      return *t;
    else
      return NULL_TREE;
*************** detect_strict_aliasing_named (void)
*** 990,996 ****
  
        pi = SSA_NAME_PTR_INFO (ptr);
  
!       if (!SSA_NAME_IN_FREE_LIST (ptr) && pi && pi->name_mem_tag)
  	dsa_named_for (ptr);
      }
  }
--- 988,994 ----
  
        pi = SSA_NAME_PTR_INFO (ptr);
  
!       if (!SSA_NAME_IN_FREE_LIST (ptr) && pi && pi->pt_vars)
  	dsa_named_for (ptr);
      }
  }
Index: alias-improvements/gcc/tree-data-ref.h
===================================================================
*** alias-improvements.orig/gcc/tree-data-ref.h	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-data-ref.h	2008-11-26 13:48:08.000000000 +0100
*************** struct dr_alias
*** 87,93 ****
  {
    /* The alias information that should be used for new pointers to this
       location.  SYMBOL_TAG is either a DECL or a SYMBOL_MEMORY_TAG.  */
-   tree symbol_tag;
    struct ptr_info_def *ptr_info;
  
    /* The set of virtual operands corresponding to this memory reference,
--- 87,92 ----
*************** struct data_reference
*** 203,211 ****
  #define DR_OFFSET(DR)              (DR)->innermost.offset
  #define DR_INIT(DR)                (DR)->innermost.init
  #define DR_STEP(DR)                (DR)->innermost.step
- #define DR_SYMBOL_TAG(DR)          (DR)->alias.symbol_tag
  #define DR_PTR_INFO(DR)            (DR)->alias.ptr_info
- #define DR_VOPS(DR)		   (DR)->alias.vops
  #define DR_ALIGNED_TO(DR)          (DR)->innermost.aligned_to
  #define DR_ACCESS_MATRIX(DR)       (DR)->access_matrix
  
--- 202,208 ----
Index: alias-improvements/gcc/tree-ssa-address.c
===================================================================
*** alias-improvements.orig/gcc/tree-ssa-address.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-ssa-address.c	2008-11-26 13:48:08.000000000 +0100
*************** create_mem_ref_raw (tree type, struct me
*** 333,341 ****
    if (addr->offset && integer_zerop (addr->offset))
      addr->offset = NULL_TREE;
  
!   return build7 (TARGET_MEM_REF, type,
  		 addr->symbol, addr->base, addr->index,
! 		 addr->step, addr->offset, NULL, NULL);
  }
  
  /* Returns true if OBJ is an object whose address is a link time constant.  */
--- 333,341 ----
    if (addr->offset && integer_zerop (addr->offset))
      addr->offset = NULL_TREE;
  
!   return build6 (TARGET_MEM_REF, type,
  		 addr->symbol, addr->base, addr->index,
! 		 addr->step, addr->offset, NULL);
  }
  
  /* Returns true if OBJ is an object whose address is a link time constant.  */
*************** get_address_description (tree op, struct
*** 709,717 ****
  void
  copy_mem_ref_info (tree to, tree from)
  {
-   /* Copy the annotation, to preserve the aliasing information.  */
-   TMR_TAG (to) = TMR_TAG (from);
- 
    /* And the info about the original reference.  */
    TMR_ORIGINAL (to) = TMR_ORIGINAL (from);
  }
--- 709,714 ----
Index: alias-improvements/gcc/tree-vect-analyze.c
===================================================================
*** alias-improvements.orig/gcc/tree-vect-analyze.c	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree-vect-analyze.c	2008-11-26 13:48:08.000000000 +0100
*************** vect_analyze_data_refs (loop_vec_info lo
*** 3563,3578 ****
            return false;
          }
  
-       if (!DR_SYMBOL_TAG (dr))
-         {
-           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
-             {
-               fprintf (vect_dump, "not vectorized: no memory tag for ");
-               print_generic_expr (vect_dump, DR_REF (dr), TDF_SLIM);
-             }
-           return false;
-         }
- 
        base = unshare_expr (DR_BASE_ADDRESS (dr));
        offset = unshare_expr (DR_OFFSET (dr));
        init = unshare_expr (DR_INIT (dr));
--- 3563,3568 ----
Index: alias-improvements/gcc/tree.def
===================================================================
*** alias-improvements.orig/gcc/tree.def	2008-11-26 13:47:02.000000000 +0100
--- alias-improvements/gcc/tree.def	2008-11-26 13:48:08.000000000 +0100
*************** DEFTREECODE (PARM_DECL, "parm_decl", tcc
*** 362,373 ****
  DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
  DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
  
- /* Memory tags used in tree-ssa to represent memory locations in
-    virtual SSA.  */
- DEFTREECODE (NAME_MEMORY_TAG, "name_memory_tag", tcc_declaration, 0)
- DEFTREECODE (SYMBOL_MEMORY_TAG, "symbol_memory_tag", tcc_declaration, 0)
- DEFTREECODE (MEMORY_PARTITION_TAG, "memory_partition_tag", tcc_declaration, 0)
- 
  /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
     _DECLs, providing a hierarchy of names.  */
  DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
--- 362,367 ----
*************** DEFTREECODE (REALIGN_LOAD_EXPR, "realign
*** 980,989 ****
     sizetype or a pointer type (if SYMBOL is NULL).
     
     The sixth argument is the reference to the original memory access, which
!    is preserved for the purposes of the RTL alias analysis.  The seventh
!    argument is a tag representing results of the tree level alias analysis.  */
  
! DEFTREECODE (TARGET_MEM_REF, "target_mem_ref", tcc_reference, 7)
  
  /* The ordering of the codes between OMP_PARALLEL and OMP_CRITICAL is
     exposed to TREE_RANGE_CHECK.  */
--- 974,982 ----
     sizetype or a pointer type (if SYMBOL is NULL).
     
     The sixth argument is the reference to the original memory access, which
!    is preserved for the purposes of the RTL alias analysis.  */
  
! DEFTREECODE (TARGET_MEM_REF, "target_mem_ref", tcc_reference, 6)
  
  /* The ordering of the codes between OMP_PARALLEL and OMP_CRITICAL is
     exposed to TREE_RANGE_CHECK.  */


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