[PATCH] Remove SFT code.

Richard Guenther rguenther@suse.de
Wed May 7 10:12:00 GMT 2008


This removes all traces of SFTs from the compiler.  It retains the
field-sensitive capabilities of PTA, as that is more difficult to
remove and still might be useful for IPA-PTA.

Bootstrapped and tested on x86-64-unknown-linux-gnu, ok for trunk?

I'll remove the salias pass itself in a followup (it needs some
testcase adjustments).

Thanks,
Richard.

2008-05-07  Richard Guenther  <rguenther@suse.de>

	* tree-data-ref.c (dr_analyze_alias): Do not set DR_SUBVARS.
	* tree-data-ref.h (struct dr_alias): Remove subvars field.
	(DR_SUBVARS): Remove.
	* tree-dfa.c (dump_subvars_for): Remove.
	(debug_subvars_for): Likewise.
	(dump_variable): Do not dump subvars.
	(remove_referenced_var): Do not remove subvars.
	* tree-flow-inline.h (clear_call_clobbered): SFTs no longer exist.
	(lookup_subvars_for_var): Remove.
	(get_subvars_for_var): Likewise.
	(get_subvars_at): Likewise.
	(get_first_overlapping_subvar): Likewise.
	(overlap_subvar): Likewise.
	* tree-flow.h (subvar_t): Remove.
	(struct var_ann_d): Remove subvars field.
	* tree-ssa-alias.c (mark_aliases_call_clobbered): Remove queued
	argument.  Remove special handling of SFTs.
	(compute_tag_properties): Likewise.
	(set_initial_properties): Likewise.
	(compute_call_clobbered): Likewise.
	(count_mem_refs): Likewise.
	(compute_memory_partitions): Likewise.
	(compute_flow_insensitive_aliasing): Likewise.
	(setup_pointers_and_addressables): Likewise.
	(new_type_alias): Likewise.
	(struct used_part): Remove.
	(used_portions): Likewise.
	(struct used_part_map): Likewise.
	(used_part_map_eq): Likewise.
	(used_part_map_hash): Likewise.
	(free_used_part_map): Likewise.
	(up_lookup): Likewise.
	(up_insert): Likewise.
	(get_or_create_used_part_for): Likewise.
	(create_sft): Likewise.
	(create_overlap_variables_for): Likewise.
	(find_used_portions): Likewise.
	(create_structure_vars): Likewise.
	* tree.def (STRUCT_FIELD_TAG): Remove.
	* tree.h (MTAG_P): Adjust.
	(struct tree_memory_tag): Remove base_for_components and
	unpartitionable flags.
	(struct tree_struct_field_tag): Remove.
	(SFT_PARENT_VAR): Likewise.
	(SFT_OFFSET): Likewise.
	(SFT_SIZE): Likewise.
	(SFT_NONADDRESSABLE_P): Likewise.
	(SFT_ALIAS_SET): Likewise.
	(SFT_UNPARTITIONABLE_P): Likewise.
	(SFT_BASE_FOR_COMPONENTS_P): Likewise.
	(union tree_node): Remove sft field.
	* alias.c (get_alias_set): Remove special handling of SFTs.
	* print-tree.c (print_node): Remove handling of SFTs.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-into-ssa.c (mark_sym_for_renaming): Likewise.
	* tree-nrv.c (dest_safe_for_nrv_p): Remove special handling of SFTs.
	* tree-predcom.c (set_alias_info): Do not set subvars.
	* tree-pretty-print.c (dump_generic_node): Do not handle SFTs.
	* tree-ssa-loop-ivopts.c (get_ref_tag): Likewise.
	* tree-ssa-operands.c (access_can_touch_variable): Likewise.
	(add_vars_for_offset): Remove.
	(add_virtual_operand): Remove special handling of SFTs.
	(add_call_clobber_ops): Likewise.
	(add_call_read_ops): Likewise.
	(get_asm_expr_operands): Likewise.
	(get_modify_stmt_operands): Likewise.
	(get_expr_operands): Likewise.
	(add_to_addressable_set): Likewise.
	* tree-ssa.c (verify_ssa_name): Do not handle SFTs.
	* tree-tailcall.c (suitable_for_tail_opt_p): Likewise.
	* tree-vect-transform.c (vect_create_data_ref_ptr): Do not
	set subvars.
	* tree.c (init_ttree): Remove STRUCT_FIELD_TAG initialization.
	(tree_code_size): Remove STRUCT_FIELD_TAG handling.
	(tree_node_structure): Likewise.
	* tree-ssa-structalias.c (set_uids_in_ptset): Remove special
	handling of SFTs.
	(find_what_p_points_to): Likewise.

Index: trunk/gcc/tree-data-ref.c
===================================================================
*** trunk.orig/gcc/tree-data-ref.c
--- trunk/gcc/tree-data-ref.c
*************** dr_analyze_alias (struct data_reference 
*** 793,800 ****
      }
  
    DR_SYMBOL_TAG (dr) = smt;
-   if (smt && var_can_have_subvars (smt))
-     DR_SUBVARS (dr) = get_subvars_for_var (smt);
  
    vops = BITMAP_ALLOC (NULL);
    FOR_EACH_SSA_TREE_OPERAND (op, stmt, it, SSA_OP_VIRTUAL_USES)
--- 793,798 ----
Index: trunk/gcc/tree-data-ref.h
===================================================================
*** trunk.orig/gcc/tree-data-ref.h
--- trunk/gcc/tree-data-ref.h
*************** struct dr_alias
*** 88,94 ****
    /* 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;
-   subvar_t subvars;
    struct ptr_info_def *ptr_info;
  
    /* The set of virtual operands corresponding to this memory reference,
--- 88,93 ----
*************** DEF_VEC_ALLOC_P (data_reference_p, heap)
*** 138,144 ****
  #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_SUBVARS(DR)             (DR)->alias.subvars
  #define DR_VOPS(DR)		   (DR)->alias.vops
  #define DR_ALIGNED_TO(DR)          (DR)->innermost.aligned_to
  
--- 137,142 ----
Index: trunk/gcc/tree-dfa.c
===================================================================
*** trunk.orig/gcc/tree-dfa.c
--- trunk/gcc/tree-dfa.c
*************** debug_referenced_vars (void)
*** 272,313 ****
  }
  
  
- /* Dump sub-variables for VAR to FILE.  */
- 
- void
- dump_subvars_for (FILE *file, tree var)
- {
-   subvar_t sv = get_subvars_for_var (var);
-   tree subvar;
-   unsigned int i;
- 
-   if (!sv)
-     return;
- 
-   fprintf (file, "{ ");
- 
-   for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
-     {
-       print_generic_expr (file, subvar, dump_flags);
-       fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar));
-       if (SFT_BASE_FOR_COMPONENTS_P (subvar))
-         fprintf (file, "[B]");
-       fprintf (file, " ");
-     }
- 
-   fprintf (file, "}");
- }
- 
- 
- /* Dumb sub-variables for VAR to stderr.  */
- 
- void
- debug_subvars_for (tree var)
- {
-   dump_subvars_for (stderr, var);
- }
- 
- 
  /* Dump variable VAR and its may-aliases to FILE.  */
  
  void
--- 272,277 ----
*************** dump_variable (FILE *file, tree var)
*** 403,414 ****
        dump_may_aliases_for (file, var);
      }
  
-   if (get_subvars_for_var (var))
-     {
-       fprintf (file, ", sub-vars: ");
-       dump_subvars_for (file, var);
-     }
- 
    if (!is_gimple_reg (var))
      {
        if (memory_partition (var))
--- 367,372 ----
*************** dump_variable (FILE *file, tree var)
*** 422,437 ****
  	  fprintf (file, ", partition symbols: ");
  	  dump_decl_set (file, MPT_SYMBOLS (var));
  	}
- 
-       if (TREE_CODE (var) == STRUCT_FIELD_TAG)
- 	{
- 	  fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED,
- 		   SFT_OFFSET (var));
- 	  fprintf (file, ", base for components: %s",
- 		   SFT_BASE_FOR_COMPONENTS_P (var) ? "NO" : "YES");
- 	  fprintf (file, ", partitionable: %s",
- 		   SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES");
- 	}
      }
  
    fprintf (file, "\n");
--- 380,385 ----
*************** remove_referenced_var (tree var)
*** 766,783 ****
    struct tree_decl_minimal in;
    void **loc;
    unsigned int uid = DECL_UID (var);
-   subvar_t sv;
- 
-   /* If we remove a var, we should also remove its subvars, as we kill
-      their parent var and its annotation.  */
-   if (var_can_have_subvars (var)
-       && (sv = get_subvars_for_var (var)))
-     {
-       unsigned int i;
-       tree subvar;
-       for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
-         remove_referenced_var (subvar);
-     }
  
    clear_call_clobbered (var);
    if ((v_ann = var_ann (var)))
--- 714,719 ----
Index: trunk/gcc/tree-flow-inline.h
===================================================================
*** trunk.orig/gcc/tree-flow-inline.h
--- trunk/gcc/tree-flow-inline.h
*************** clear_call_clobbered (tree var)
*** 883,889 ****
  {
    var_ann_t ann = var_ann (var);
    ann->escape_mask = 0;
!   if (MTAG_P (var) && TREE_CODE (var) != STRUCT_FIELD_TAG)
      MTAG_GLOBAL (var) = 0;
    if (!MTAG_P (var))
      var_ann (var)->call_clobbered = false;
--- 883,889 ----
  {
    var_ann_t ann = var_ann (var);
    ann->escape_mask = 0;
!   if (MTAG_P (var))
      MTAG_GLOBAL (var) = 0;
    if (!MTAG_P (var))
      var_ann (var)->call_clobbered = false;
*************** ref_contains_array_ref (const_tree ref)
*** 1581,1701 ****
    return false;
  }
  
- /* Given a variable VAR, lookup and return a pointer to the list of
-    subvariables for it.  */
- 
- static inline subvar_t *
- lookup_subvars_for_var (const_tree var)
- {
-   var_ann_t ann = var_ann (var);
-   gcc_assert (ann);
-   return &ann->subvars;
- }
- 
- /* Given a variable VAR, return a linked list of subvariables for VAR, or
-    NULL, if there are no subvariables.  */
- 
- static inline subvar_t
- get_subvars_for_var (tree var)
- {
-   subvar_t subvars;
- 
-   gcc_assert (SSA_VAR_P (var));  
-   
-   if (TREE_CODE (var) == SSA_NAME)
-     subvars = *(lookup_subvars_for_var (SSA_NAME_VAR (var)));
-   else
-     subvars = *(lookup_subvars_for_var (var));
-   return subvars;
- }
- 
- /* Return the subvariable of VAR at offset OFFSET.  */
- 
- static inline tree
- get_subvar_at (tree var, unsigned HOST_WIDE_INT offset)
- {
-   subvar_t sv = get_subvars_for_var (var);
-   int low, high;
- 
-   low = 0;
-   high = VEC_length (tree, sv) - 1;
-   while (low <= high)
-     {
-       int mid = (low + high) / 2;
-       tree subvar = VEC_index (tree, sv, mid);
-       if (SFT_OFFSET (subvar) == offset)
- 	return subvar;
-       else if (SFT_OFFSET (subvar) < offset)
- 	low = mid + 1;
-       else
- 	high = mid - 1;
-     }
- 
-   return NULL_TREE;
- }
- 
- 
- /* Return the first subvariable in SV that overlaps [offset, offset + size[.
-    NULL_TREE is returned, if there is no overlapping subvariable, else *I
-    is set to the index in the SV vector of the first overlap.  */
- 
- static inline tree
- get_first_overlapping_subvar (subvar_t sv, unsigned HOST_WIDE_INT offset,
- 			      unsigned HOST_WIDE_INT size, unsigned int *i)
- {
-   int low = 0;
-   int high = VEC_length (tree, sv) - 1;
-   int mid;
-   tree subvar;
- 
-   if (low > high)
-     return NULL_TREE;
- 
-   /* Binary search for offset.  */
-   do
-     {
-       mid = (low + high) / 2;
-       subvar = VEC_index (tree, sv, mid);
-       if (SFT_OFFSET (subvar) == offset)
- 	{
- 	  *i = mid;
- 	  return subvar;
- 	}
-       else if (SFT_OFFSET (subvar) < offset)
- 	low = mid + 1;
-       else
- 	high = mid - 1;
-     }
-   while (low <= high);
- 
-   /* As we didn't find a subvar with offset, adjust to return the
-      first overlapping one.  */
-   if (SFT_OFFSET (subvar) < offset
-       && SFT_OFFSET (subvar) + SFT_SIZE (subvar) <= offset)
-     {
-       mid += 1;
-       if ((unsigned)mid >= VEC_length (tree, sv))
- 	return NULL_TREE;
-       subvar = VEC_index (tree, sv, mid);
-     }
-   else if (SFT_OFFSET (subvar) > offset
- 	   && size <= SFT_OFFSET (subvar) - offset)
-     {
-       mid -= 1;
-       if (mid < 0)
- 	return NULL_TREE;
-       subvar = VEC_index (tree, sv, mid);
-     }
- 
-   if (overlap_subvar (offset, size, subvar, NULL))
-     {
-       *i = mid;
-       return subvar;
-     }
- 
-   return NULL_TREE;
- }
- 
  
  /* Return true if V is a tree that we can have subvars for.
     Normally, this is any aggregate type.  Also complex
--- 1581,1586 ----
*************** ranges_overlap_p (unsigned HOST_WIDE_INT
*** 1748,1800 ****
    return false;
  }
  
- 
- /* Return true if OFFSET and SIZE define a range that overlaps with some
-    portion of the range of SV, a subvar.  If there was an exact overlap,
-    *EXACT will be set to true upon return. */
- 
- static inline bool
- overlap_subvar (unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size,
- 		const_tree sv,  bool *exact)
- {
-   /* There are three possible cases of overlap.
-      1. We can have an exact overlap, like so:   
-      |offset, offset + size             |
-      |sv->offset, sv->offset + sv->size |
-      
-      2. We can have offset starting after sv->offset, like so:
-      
-            |offset, offset + size              |
-      |sv->offset, sv->offset + sv->size  |
- 
-      3. We can have offset starting before sv->offset, like so:
-      
-      |offset, offset + size    |
-        |sv->offset, sv->offset + sv->size|
-   */
- 
-   if (exact)
-     *exact = false;
-   if (offset == SFT_OFFSET (sv) && size == SFT_SIZE (sv))
-     {
-       if (exact)
- 	*exact = true;
-       return true;
-     }
-   else if (offset >= SFT_OFFSET (sv) 
- 	   && offset < (SFT_OFFSET (sv) + SFT_SIZE (sv)))
-     {
-       return true;
-     }
-   else if (offset < SFT_OFFSET (sv) 
- 	   && (size > SFT_OFFSET (sv) - offset))
-     {
-       return true;
-     }
-   return false;
- 
- }
- 
  /* Return the memory tag associated with symbol SYM.  */
  
  static inline tree
--- 1633,1638 ----
Index: trunk/gcc/tree-flow.h
===================================================================
*** trunk.orig/gcc/tree-flow.h
--- trunk/gcc/tree-flow.h
*************** enum noalias_state {
*** 327,334 ****
  };
  
  
- typedef VEC(tree,gc) *subvar_t;
- 
  struct var_ann_d GTY(())
  {
    struct tree_ann_common_d common;
--- 327,332 ----
*************** struct var_ann_d GTY(())
*** 395,404 ****
    /* During into-ssa and the dominator optimizer, this field holds the
       current version of this variable (an SSA_NAME).  */
    tree current_def;
- 
-   /* If this variable is a structure, this fields holds an array
-      of symbols representing each of the fields of the structure.  */
-   VEC(tree,gc) *subvars;
  };
  
  /* Container for variable annotation used by hashtable for annotations for
--- 393,398 ----
*************** extern void debug_referenced_vars (void)
*** 815,822 ****
  extern void dump_referenced_vars (FILE *);
  extern void dump_variable (FILE *, tree);
  extern void debug_variable (tree);
- extern void dump_subvars_for (FILE *, tree);
- extern void debug_subvars_for (tree);
  extern tree get_virtual_var (tree);
  extern void add_referenced_var (tree);
  extern void remove_referenced_var (tree);
--- 809,814 ----
*************** extern struct ptr_info_def *get_ptr_info
*** 859,874 ****
  extern void new_type_alias (tree, tree, tree);
  extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *,
  				   unsigned *);
- static inline subvar_t get_subvars_for_var (tree);
- static inline tree get_subvar_at (tree, unsigned HOST_WIDE_INT);
  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 *);
  static inline bool var_can_have_subvars (const_tree);
- static inline bool overlap_subvar (unsigned HOST_WIDE_INT,
- 				   unsigned HOST_WIDE_INT,
- 				   const_tree, bool *);
  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 *);
--- 851,861 ----
Index: trunk/gcc/tree-ssa-alias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias.c
--- trunk/gcc/tree-ssa-alias.c
*************** add_to_worklist (tree alias, VEC (tree, 
*** 385,392 ****
  
  static void
  mark_aliases_call_clobbered (tree tag, VEC (tree, heap) **worklist,
! 			     VEC (int, heap) **worklist2,
! 			     bitmap on_worklist, bitmap queued)
  {
    bitmap aliases;
    bitmap_iterator bi;
--- 385,391 ----
  
  static void
  mark_aliases_call_clobbered (tree tag, VEC (tree, heap) **worklist,
! 			     VEC (int, heap) **worklist2, bitmap on_worklist)
  {
    bitmap aliases;
    bitmap_iterator bi;
*************** mark_aliases_call_clobbered (tree tag, V
*** 408,436 ****
  	 the world a particularly nice place, it is necessary
  	 in order to allow C/C++ tricks that involve
  	 pointer arithmetic to work.  */
!       if (TREE_CODE (entry) == STRUCT_FIELD_TAG)
! 	bitmap_set_bit (queued, DECL_UID (SFT_PARENT_VAR (entry)));
!       else if (!unmodifiable_var_p (entry))
  	{
  	  add_to_worklist (entry, worklist, worklist2, ta->escape_mask,
  			   on_worklist);
  	  mark_call_clobbered (entry, ta->escape_mask);
  	}
      }
-   if (!bitmap_empty_p (queued))
-     {
-       EXECUTE_IF_SET_IN_BITMAP (queued, 0, i, bi)
- 	{
- 	  subvar_t svars = get_subvars_for_var (referenced_var (i));
- 	  unsigned int i;
- 	  tree subvar;
- 
- 	  for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
- 	    if (!unmodifiable_var_p (subvar))
- 	       mark_call_clobbered (subvar, ta->escape_mask);
- 	}
-       bitmap_clear (queued);
-     }
  }
  
  /* Tags containing global vars need to be marked as global.
--- 407,419 ----
  	 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.
*************** compute_tag_properties (void)
*** 447,453 ****
  
    FOR_EACH_REFERENCED_VAR (tag, rvi)
      {
!       if (!MTAG_P (tag) || TREE_CODE (tag) == STRUCT_FIELD_TAG)
  	continue;
        VEC_safe_push (tree, heap, taglist, tag);
      }
--- 430,436 ----
  
    FOR_EACH_REFERENCED_VAR (tag, rvi)
      {
!       if (!MTAG_P (tag))
  	continue;
        VEC_safe_push (tree, heap, taglist, tag);
      }
*************** set_initial_properties (struct alias_inf
*** 538,554 ****
    referenced_var_iterator rvi;
    tree var;
    tree ptr;
-   bitmap queued;
- 
-   /* Temporary bitmap to avoid quadratic behavior in marking
-      call clobbers.  */
-   queued = BITMAP_ALLOC (&alias_bitmap_obstack);
  
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
!       if (is_global_var (var) 
! 	  && (!var_can_have_subvars (var)
! 	      || get_subvars_for_var (var) == NULL))
  	{
  	  if (!unmodifiable_var_p (var))
  	    mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
--- 521,530 ----
    referenced_var_iterator rvi;
    tree var;
    tree ptr;
  
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
!       if (is_global_var (var))
  	{
  	  if (!unmodifiable_var_p (var))
  	    mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
*************** set_initial_properties (struct alias_inf
*** 591,616 ****
  		     the world a particularly nice place, it is necessary
  		     in order to allow C/C++ tricks that involve
  		     pointer arithmetic to work.  */
! 		  if (TREE_CODE (alias) == STRUCT_FIELD_TAG)
! 		    bitmap_set_bit (queued, DECL_UID (SFT_PARENT_VAR (alias)));
! 		  else if (!unmodifiable_var_p (alias))
  		    mark_call_clobbered (alias, pi->escape_mask);
  		}
- 	      /* Process variables we need to clobber all parts of.  */
- 	      if (!bitmap_empty_p (queued))
- 		{
- 		  EXECUTE_IF_SET_IN_BITMAP (queued, 0, j, bi)
- 		    {
- 		      subvar_t svars = get_subvars_for_var (referenced_var (j));
- 		      unsigned int i;
- 		      tree subvar;
- 
- 		      for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
- 			if (!unmodifiable_var_p (subvar))
- 			  mark_call_clobbered (subvar, pi->escape_mask);
- 		    }
- 		  bitmap_clear (queued);
- 		}
  	    }
  	}
  
--- 567,575 ----
  		     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 (alias))
  		    mark_call_clobbered (alias, pi->escape_mask);
  		}
  	    }
  	}
  
*************** set_initial_properties (struct alias_inf
*** 644,651 ****
  	  MTAG_GLOBAL (tag) = true;
  	}
      }
- 
-   BITMAP_FREE (queued);
  }
  
  /* Compute which variables need to be marked call clobbered because
--- 603,608 ----
*************** compute_call_clobbered (struct alias_inf
*** 657,667 ****
  {
    VEC (tree, heap) *worklist = NULL;
    VEC (int,heap) *worklist2 = NULL;
!   bitmap on_worklist, queued;
  
    timevar_push (TV_CALL_CLOBBER);
    on_worklist = BITMAP_ALLOC (NULL);
-   queued = BITMAP_ALLOC (NULL);
      
    set_initial_properties (ai);
    init_transitive_clobber_worklist (&worklist, &worklist2, on_worklist);
--- 614,623 ----
  {
    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);
*************** compute_call_clobbered (struct alias_inf
*** 672,684 ****
  
        bitmap_clear_bit (on_worklist, DECL_UID (curr));
        mark_call_clobbered (curr, reason);
!       mark_aliases_call_clobbered (curr, &worklist, &worklist2,
! 				   on_worklist, queued);
      }
    VEC_free (tree, heap, worklist);
    VEC_free (int, heap, worklist2);
    BITMAP_FREE (on_worklist);
-   BITMAP_FREE (queued);
    compute_tag_properties ();
    timevar_pop (TV_CALL_CLOBBER);
  }
--- 628,638 ----
  
        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);
  }
*************** count_mem_refs (long *num_vuses_p, long 
*** 827,839 ****
  static inline long
  mem_sym_score (mem_sym_stats_t mp)
  {
-   /* Unpartitionable SFTs are automatically thrown to the bottom of
-      the list.  They are not stored in partitions, but they are used
-      for computing overall statistics.  */
-   if (TREE_CODE (mp->var) == STRUCT_FIELD_TAG
-       && SFT_UNPARTITIONABLE_P (mp->var))
-     return LONG_MAX;
- 
    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
--- 781,786 ----
*************** compute_memory_partitions (void)
*** 1597,1611 ****
        if (!need_to_partition_p (mem_ref_stats))
  	break;
  
-       /* SFTs that are marked unpartitionable should not be added to
- 	 partitions.  These SFTs are special because they mark the
- 	 first SFT into a structure where a pointer is pointing to.
- 	 This is needed by the operand scanner to find adjacent
- 	 fields.  See add_vars_for_offset for details.  */
-       if (TREE_CODE (mp_p->var) == STRUCT_FIELD_TAG
- 	  && SFT_UNPARTITIONABLE_P (mp_p->var))
- 	continue;
- 
        mpt = find_partition_for (mp_p);
        estimate_vop_reduction (mem_ref_stats, mp_p, mpt);
      }
--- 1544,1549 ----
*************** compute_flow_insensitive_aliasing (struc
*** 2424,2434 ****
  	     
  	  if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
  	    {
- 	      /* We should never have a var with subvars here, because
- 	         they shouldn't get into the set of addressable vars */
- 	      gcc_assert (!var_can_have_subvars (var)
- 			  || get_subvars_for_var (var) == NULL);
- 
  	      /* Add VAR to TAG's may-aliases set.  */
  	      add_may_alias (tag, var);
  	    }
--- 2362,2367 ----
*************** setup_pointers_and_addressables (struct 
*** 2547,2554 ****
  
    FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, srvi)
      {
-       subvar_t svars;
- 
        /* Name memory tags already have flow-sensitive aliasing
  	 information, so they need not be processed by
  	 compute_flow_insensitive_aliasing.  Similarly, symbol memory
--- 2480,2485 ----
*************** setup_pointers_and_addressables (struct 
*** 2558,2564 ****
           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) && TREE_CODE (var) != STRUCT_FIELD_TAG)
  	continue;
  
        /* Remove the ADDRESSABLE flag from every addressable variable whose
--- 2489,2495 ----
           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
*************** setup_pointers_and_addressables (struct 
*** 2578,2601 ****
  		 to rename VAR into SSA afterwards.  */
  	      mark_sym_for_renaming (var);
  
- 	      /* If VAR can have sub-variables, and any of its
- 		 sub-variables has its address taken, then we cannot
- 		 remove the addressable flag from VAR.  */
- 	      if (var_can_have_subvars (var)
- 		  && (svars = get_subvars_for_var (var)))
- 		{
- 		  unsigned int i;
- 		  tree subvar;
- 
- 		  for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
- 		    {	      
- 		      if (bitmap_bit_p (gimple_addressable_vars (cfun),
- 					DECL_UID (subvar)))
- 			okay_to_mark = false;
- 		      mark_sym_for_renaming (subvar);
- 		    }
- 		}
- 
  	      /* The address of VAR is not needed, remove the
  		 addressable bit, so that it can be optimized as a
  		 regular variable.  */
--- 2509,2514 ----
*************** setup_pointers_and_addressables (struct 
*** 2616,2625 ****
           entry in ADDRESSABLE_VARS for VAR.  */
        if (may_be_aliased (var))
  	{
! 	  if (!var_can_have_subvars (var)
! 	      || get_subvars_for_var (var) == NULL)
! 	    create_alias_map_for (var, ai);
! 
  	  mark_sym_for_renaming (var);
  	}
  
--- 2529,2535 ----
           entry in ADDRESSABLE_VARS for VAR.  */
        if (may_be_aliased (var))
  	{
! 	  create_alias_map_for (var, ai);
  	  mark_sym_for_renaming (var);
  	}
  
*************** new_type_alias (tree ptr, tree var, tree
*** 3508,3521 ****
  {
    tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
    tree tag;
-   subvar_t svars;
    tree ali = NULL_TREE;
    HOST_WIDE_INT offset, size, maxsize;
    tree ref;
-   VEC (tree, heap) *overlaps = NULL;
-   unsigned int len, i;
-   tree subvar;
- 
  
    gcc_assert (symbol_mem_tag (ptr) == NULL_TREE);
    gcc_assert (!MTAG_P (var));
--- 3418,3426 ----
*************** new_type_alias (tree ptr, tree var, tree
*** 3526,4118 ****
    tag = create_memory_tag (tag_type, true);
    set_symbol_mem_tag (ptr, tag);
  
!   /* Add VAR to the may-alias set of PTR's new symbol tag.  If VAR has
!      subvars, add the subvars to the tag instead of the actual var.  */
!   if (var_can_have_subvars (ref)
!       && (svars = get_subvars_for_var (ref)))
!     {
!       for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
! 	{
!           bool exact;
! 
!           if (overlap_subvar (offset, maxsize, subvar, &exact))
!             VEC_safe_push (tree, heap, overlaps, subvar);
!         }
!       gcc_assert (overlaps != NULL);
!     }
!   else if (var_can_have_subvars (var)
! 	   && (svars = get_subvars_for_var (var)))
!     {
!       /* If the REF is not a direct access to VAR (e.g., it is a dereference
! 	 of a pointer), we should scan the virtual operands of REF the same
! 	 way as tree-ssa-operands do.  At the moment, this is somewhat
! 	 difficult, so we just give up and add all the subvars of VAR.
! 	 On mem-ssa branch, the scanning for virtual operands have been
! 	 split from the rest of tree-ssa-operands, so it should be much
! 	 easier to fix this problem correctly once mem-ssa is merged.  */
!       for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
! 	VEC_safe_push (tree, heap, overlaps, subvar);
! 
!       gcc_assert (overlaps != NULL);
!     }
!   else
!     ali = add_may_alias_for_new_tag (tag, var);
! 
!   len = VEC_length (tree, overlaps);
!   if (len > 0)
!     {
!       if (dump_file && (dump_flags & TDF_DETAILS))
! 	fprintf (dump_file, "\nnumber of overlapping subvars = %u\n", len);
! 
!       if (len == 1)
! 	ali = add_may_alias_for_new_tag (tag, VEC_index (tree, overlaps, 0));
!       else if (len > 1)
! 	{
! 	  unsigned int k;
! 	  tree sv_var;
! 
! 	  for (k = 0; VEC_iterate (tree, overlaps, k, sv_var); k++)
! 	    {
! 	      ali = add_may_alias_for_new_tag (tag, sv_var);
! 
! 	      if (ali != tag)
! 		{
! 		  /* Can happen only if 'Case 1' of add_may_alias_for_new_tag
! 		     took place.  Since more than one svar was found, we add 
! 		     'ali' as one of the may_aliases of the new tag.  */ 
! 		  add_may_alias (tag, ali);
! 		  ali = tag;
! 		}
! 	    }
! 	}
!       VEC_free (tree, heap, overlaps);
!     }
  
    set_symbol_mem_tag (ptr, ali);
    TREE_READONLY (tag) = TREE_READONLY (var);
    MTAG_GLOBAL (tag) = is_global_var (var);
  }
  
! /* This represents the used range of a variable.  */
! 
! typedef struct used_part
! {
!   HOST_WIDE_INT minused;
!   HOST_WIDE_INT maxused;
!   /* True if we have an explicit use/def of some portion of this variable,
!      even if it is all of it. i.e. a.b = 5 or temp = a.b.  */
!   bool explicit_uses;
!   /* True if we have an implicit use/def of some portion of this
!      variable.  Implicit uses occur when we can't tell what part we
!      are referencing, and have to make conservative assumptions.  */
!   bool implicit_uses;
!   /* True if the structure is only written to or taken its address.  */
!   bool write_only;
! } *used_part_t;
! 
! /* An array of used_part structures, indexed by variable uid.  */
! 
! static htab_t used_portions;
! 
! struct used_part_map
! {
!   unsigned int uid;
!   used_part_t to;
! };
! 
! /* Return true if the uid in the two used part maps are equal.  */
! 
! static int
! used_part_map_eq (const void *va, const void *vb)
! {
!   const struct used_part_map *a = (const struct used_part_map *) va;
!   const struct used_part_map *b = (const struct used_part_map *) vb;
!   return (a->uid == b->uid);
! }
! 
! /* Hash a from uid in a used_part_map.  */
! 
! static unsigned int
! used_part_map_hash (const void *item)
! {
!   return ((const struct used_part_map *)item)->uid;
! }
! 
! /* Free a used part map element.  */
! 
! static void 
! free_used_part_map (void *item)
! {
!   free (((struct used_part_map *)item)->to);
!   free (item);
! }
! 
! /* Lookup a used_part structure for a UID.  */
! 
! static used_part_t
! up_lookup (unsigned int uid)
! {
!   struct used_part_map *h, in;
!   in.uid = uid;
!   h = (struct used_part_map *) htab_find_with_hash (used_portions, &in, uid);
!   if (!h)
!     return NULL;
!   return h->to;
! }
! 
! /* Insert the pair UID, TO into the used part hashtable.  */
!  
! static void 
! up_insert (unsigned int uid, used_part_t to)
! { 
!   struct used_part_map *h;
!   void **loc;
! 
!   h = XNEW (struct used_part_map);
!   h->uid = uid;
!   h->to = to;
!   loc = htab_find_slot_with_hash (used_portions, h,
! 				  uid, INSERT);
!   if (*loc != NULL)
!     free (*loc);
!   *(struct used_part_map **)  loc = h;
! }
! 
! 
! /* Given a variable uid, UID, get or create the entry in the used portions
!    table for the variable.  */
! 
! static used_part_t
! get_or_create_used_part_for (size_t uid)
! {
!   used_part_t up;
!   if ((up = up_lookup (uid)) == NULL)
!     {
!       up = XCNEW (struct used_part);
!       up->minused = INT_MAX;
!       up->maxused = 0;
!       up->explicit_uses = false;
!       up->implicit_uses = false;
!       up->write_only = true;
!     }
! 
!   return up;
! }
! 
! 
! /* Create and return a structure sub-variable for field type FIELD at
!    offset OFFSET, with size SIZE, of variable VAR.  If ALIAS_SET not
!    -1 this field is non-addressable and we should use this alias set
!    with this field.  */
! 
! static tree
! create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
! 	    unsigned HOST_WIDE_INT size, alias_set_type alias_set,
! 	    bool base_for_components)
! {
!   tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
! 
!   /* We need to copy the various flags from VAR to SUBVAR, so that
!      they are is_global_var iff the original variable was.  */
!   DECL_CONTEXT (subvar) = DECL_CONTEXT (var);
!   MTAG_GLOBAL (subvar) = DECL_EXTERNAL (var);
!   TREE_PUBLIC  (subvar) = TREE_PUBLIC (var);
!   TREE_STATIC (subvar) = TREE_STATIC (var);
!   TREE_READONLY (subvar) = TREE_READONLY (var);
!   TREE_ADDRESSABLE (subvar) = TREE_ADDRESSABLE (var);
! 
!   /* Add the new variable to REFERENCED_VARS.  */
!   set_symbol_mem_tag (subvar, NULL);
!   add_referenced_var (subvar);
!   SFT_PARENT_VAR (subvar) = var;
!   SFT_OFFSET (subvar) = offset;
!   SFT_SIZE (subvar) = size;
!   SFT_ALIAS_SET (subvar) = alias_set;
!   SFT_BASE_FOR_COMPONENTS_P (subvar) = base_for_components;
!   SFT_UNPARTITIONABLE_P (subvar) = false;
! 
!   return subvar;
! }
! 
! 
! /* Given an aggregate VAR, create the subvariables that represent its
!    fields.  */
! 
! static void
! create_overlap_variables_for (tree var)
! {
!   VEC(fieldoff_s,heap) *fieldstack = NULL;
!   used_part_t up;
!   size_t uid = DECL_UID (var);
! 
!   up = up_lookup (uid);
!   if (!up
!       || up->write_only)
!     return;
! 
!   push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL,
! 			       TREE_TYPE (var));
!   /* Make sure to not create SFTs for structs we won't generate variable
!      infos for.  See tree-ssa-structalias.c:create_variable_info_for ().  */
!   if (VEC_length (fieldoff_s, fieldstack) > 1
!       && VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE)
!     {
!       subvar_t *subvars;
!       fieldoff_s *fo;
!       bool notokay = false;
!       int fieldcount = 0;
!       int i;
!       HOST_WIDE_INT lastfooffset = -1;
!       HOST_WIDE_INT lastfosize = -1;
!       tree lastfotype = NULL_TREE;
! 
!       /* Not all fields have DECL_SIZE set, and those that don't, we don't
! 	 know their size, and thus, can't handle.
! 	 The same is true of fields with DECL_SIZE that is not an integer
! 	 constant (such as variable sized fields).
! 	 Fields with offsets which are not constant will have an offset < 0 
! 	 We *could* handle fields that are constant sized arrays, but
! 	 currently don't.  Doing so would require some extra changes to
! 	 tree-ssa-operands.c.  */
! 
!       for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
! 	{
! 	  if (!fo->size
! 	      || TREE_CODE (fo->size) != INTEGER_CST
! 	      || fo->offset < 0)
! 	    {
! 	      notokay = true;
! 	      break;
! 	    }
!           fieldcount++;
! 	}
! 
!       /* The current heuristic we use is as follows:
! 	 If the variable has no used portions in this function, no
! 	 structure vars are created for it.
! 	 Otherwise,
!          If the variable has less than SALIAS_MAX_IMPLICIT_FIELDS,
! 	 we always create structure vars for them.
! 	 If the variable has more than SALIAS_MAX_IMPLICIT_FIELDS, and
! 	 some explicit uses, we create structure vars for them.
! 	 If the variable has more than SALIAS_MAX_IMPLICIT_FIELDS, and
! 	 no explicit uses, we do not create structure vars for them.
!       */
!       
!       if (fieldcount >= SALIAS_MAX_IMPLICIT_FIELDS
! 	  && !up->explicit_uses)
! 	{
! 	  if (dump_file && (dump_flags & TDF_DETAILS))
! 	    {
! 	      fprintf (dump_file, "Variable ");
! 	      print_generic_expr (dump_file, var, 0);
! 	      fprintf (dump_file, " has no explicit uses in this function, and is > SALIAS_MAX_IMPLICIT_FIELDS, so skipping\n");
! 	    }
! 	  notokay = true;
! 	}
!       
!       /* Bail out, if we can't create overlap variables.  */
!       if (notokay)
! 	{
! 	  VEC_free (fieldoff_s, heap, fieldstack);
! 	  return;
! 	}
!       
!       /* Otherwise, create the variables.  */
!       subvars = lookup_subvars_for_var (var);
!       *subvars = VEC_alloc (tree, gc, VEC_length (fieldoff_s, fieldstack));
!  
!       sort_fieldstack (fieldstack);
! 
!       for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); ++i)
! 	{
! 	  HOST_WIDE_INT fosize;
! 	  tree currfotype, subvar;
! 
! 	  fosize = TREE_INT_CST_LOW (fo->size);
! 	  currfotype = fo->type;
! 
! 	  /* If this field isn't in the used portion,
! 	     or it has the exact same offset and size as the last
! 	     field, skip it.  Note that we always need the field at
! 	     offset 0 so we can properly handle pointers to the
! 	     structure.  */
! 
! 	  if ((fo->offset != 0
! 	       && ((fo->offset <= up->minused
! 		    && fo->offset + fosize <= up->minused)
! 		   || fo->offset >= up->maxused))
! 	      || (fo->offset == lastfooffset
! 		  && fosize == lastfosize
! 		  && currfotype == lastfotype))
! 	    continue;
! 	  subvar = create_sft (var, fo->type, fo->offset,
! 			       fosize, fo->alias_set, fo->base_for_components);
! 	  VEC_quick_push (tree, *subvars, subvar);
! 
! 	  if (dump_file)
! 	    {
! 	      fprintf (dump_file, "structure field tag %s created for var %s",
! 		       get_name (subvar), get_name (var));
! 	      fprintf (dump_file, " offset " HOST_WIDE_INT_PRINT_DEC,
! 		       SFT_OFFSET (subvar));
! 	      fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
! 		       SFT_SIZE (subvar));
! 	      fprintf (dump_file, "\n");
! 	    }
! 	  
! 	  lastfotype = currfotype;
! 	  lastfooffset = fo->offset;
! 	  lastfosize = fosize;
! 	}
! 
!       /* Once we have created subvars, the original is no longer call
! 	 clobbered on its own.  Its call clobbered status depends
! 	 completely on the call clobbered status of the subvars.
! 
! 	 add_referenced_var in the above loop will take care of
! 	 marking subvars of global variables as call clobbered for us
! 	 to start, since they are global as well.  */
!       clear_call_clobbered (var);
!     }
! 
!   VEC_free (fieldoff_s, heap, fieldstack);
! }
! 
! 
! /* Find the conservative answer to the question of what portions of what 
!    structures are used by this statement.  We assume that if we have a
!    component ref with a known size + offset, that we only need that part
!    of the structure.  For unknown cases, or cases where we do something
!    to the whole structure, we assume we need to create fields for the 
!    entire structure.  */
! 
! static tree
! find_used_portions (tree *tp, int *walk_subtrees, void *lhs_p)
! {
!   switch (TREE_CODE (*tp))
!     {
!     case GIMPLE_MODIFY_STMT:
!       /* Recurse manually here to track whether the use is in the
! 	 LHS of an assignment.  */
!       find_used_portions (&GIMPLE_STMT_OPERAND (*tp, 0), walk_subtrees, tp);
!       return find_used_portions (&GIMPLE_STMT_OPERAND (*tp, 1),
! 	  			 walk_subtrees, NULL);
!     case REALPART_EXPR:
!     case IMAGPART_EXPR:
!     case COMPONENT_REF:
!     case ARRAY_REF:
!       {
! 	HOST_WIDE_INT bitsize;
! 	HOST_WIDE_INT bitmaxsize;
! 	HOST_WIDE_INT bitpos;
! 	tree ref;
! 	ref = get_ref_base_and_extent (*tp, &bitpos, &bitsize, &bitmaxsize);
! 	if (DECL_P (ref)
! 	    && var_can_have_subvars (ref)
! 	    && bitmaxsize != -1)
! 	  {
! 	    size_t uid = DECL_UID (ref);
! 	    used_part_t up;
! 
! 	    up = get_or_create_used_part_for (uid);	    
! 
! 	    if (bitpos <= up->minused)
! 	      up->minused = bitpos;
! 	    if ((bitpos + bitmaxsize >= up->maxused))
! 	      up->maxused = bitpos + bitmaxsize;
! 
! 	    if (bitsize == bitmaxsize)
! 	      up->explicit_uses = true;
! 	    else
! 	      up->implicit_uses = true;
! 	    if (!lhs_p)
! 	      up->write_only = false;
! 	    up_insert (uid, up);
! 
! 	    *walk_subtrees = 0;
! 	    return NULL_TREE;
! 	  }
!       }
!       break;
!       /* This is here to make sure we mark the entire base variable as used
! 	 when you take its address.  Because our used portion analysis is
! 	 simple, we aren't looking at casts or pointer arithmetic to see what
! 	 happens when you take the address.  */
!     case ADDR_EXPR:
!       {
! 	tree var = get_base_address (TREE_OPERAND (*tp, 0));
! 
! 	if (var 
! 	    && DECL_P (var)
! 	    && DECL_SIZE (var)
! 	    && var_can_have_subvars (var)
! 	    && TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
! 	  {
! 	    used_part_t up;
! 	    size_t uid = DECL_UID (var);
! 	    
! 	    up = get_or_create_used_part_for (uid);
!  
! 	    up->minused = 0;
! 	    up->maxused = TREE_INT_CST_LOW (DECL_SIZE (var));
! 	    up->implicit_uses = true;
! 	    if (!lhs_p)
! 	      up->write_only = false;
! 
! 	    up_insert (uid, up);
! 	    *walk_subtrees = 0;
! 	    return NULL_TREE;
! 	  }
!       }
!       break;
!     case CALL_EXPR:
!       {
! 	int i;
! 	int nargs = call_expr_nargs (*tp);
! 	for (i = 0; i < nargs; i++)
! 	  {
! 	    tree *arg = &CALL_EXPR_ARG (*tp, i);
! 	    if (TREE_CODE (*arg) == ADDR_EXPR)
!               find_used_portions (arg, walk_subtrees, NULL);
! 	  }
! 	*walk_subtrees = 0;
! 	return NULL_TREE;
!       }
!     case VAR_DECL:
!     case PARM_DECL:
!     case RESULT_DECL:
!       {
! 	tree var = *tp;
! 	if (DECL_SIZE (var)
! 	    && var_can_have_subvars (var)
! 	    && TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
! 	  {
! 	    used_part_t up;
! 	    size_t uid = DECL_UID (var);
! 	    
! 	    up = get_or_create_used_part_for (uid);
!  
! 	    up->minused = 0;
! 	    up->maxused = TREE_INT_CST_LOW (DECL_SIZE (var));
! 	    up->implicit_uses = true;
! 
! 	    up_insert (uid, up);
! 	    *walk_subtrees = 0;
! 	    return NULL_TREE;
! 	  }
!       }
!       break;
!       
!     default:
!       break;
!       
!     }
!   return NULL_TREE;
! }
! 
! /* Create structure field variables for structures used in this function.  */
  
  static unsigned int
  create_structure_vars (void)
  {
-   basic_block bb;
-   safe_referenced_var_iterator rvi;
-   VEC (tree, heap) *varvec = NULL;
-   tree var;
- 
-   used_portions = htab_create (10, used_part_map_hash, used_part_map_eq, 
-                                free_used_part_map);
-   
-   FOR_EACH_BB (bb)
-     {
-       block_stmt_iterator bsi;
-       tree phi;
-       
-       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- 	{
- 	  use_operand_p use;
- 	  ssa_op_iter iter;
- 
- 	  FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
- 	    {
- 	      tree op = USE_FROM_PTR (use);
- 	      walk_tree_without_duplicates (&op, find_used_portions,
- 					    NULL);
- 	    }
- 	}
- 
-       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- 	{
- 	  walk_tree_without_duplicates (bsi_stmt_ptr (bsi), 
- 					find_used_portions,
- 					NULL);
- 	}
-     }
-   FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, rvi)
-     {
-       /* The C++ FE creates vars without DECL_SIZE set, for some reason.  */
-       if (var 	  
- 	  && DECL_SIZE (var)
- 	  && var_can_have_subvars (var)
- 	  && !MTAG_P (var)
- 	  && TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
- 	create_overlap_variables_for (var);
-     }
-   htab_delete (used_portions);
-   VEC_free (tree, heap, varvec);
- 
-   /* Update SSA operands of statements mentioning variables we split.  */
-   if (gimple_in_ssa_p (cfun))
-     FOR_EACH_BB (bb)
-       {
- 	block_stmt_iterator bsi;
- 	for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- 	  {
- 	    tree stmt = bsi_stmt (bsi);
- 	    bool update = false;
- 	    unsigned int i;
- 	    bitmap_iterator bi;
- 
- 	    if (STORED_SYMS (stmt))
- 	       EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
- 		{
- 		  tree sym = referenced_var_lookup (i);
- 		  if (get_subvars_for_var (sym))
- 		    {
- 		      update = true;
- 		      break;
- 		    }
- 		}
- 
- 	    if (LOADED_SYMS (stmt) && !update)
- 	       EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi)
- 		{
- 		  tree sym = referenced_var_lookup (i);
- 		  if (get_subvars_for_var (sym))
- 		    {
- 		      update = true;
- 		      break;
- 		    }
- 		}
- 
- 	    if (stmt_ann (stmt)->addresses_taken && !update)
- 	       EXECUTE_IF_SET_IN_BITMAP (stmt_ann (stmt)->addresses_taken,
- 					 0, i, bi)
- 		{
- 		  tree sym = referenced_var_lookup (i);
- 		  if (get_subvars_for_var (sym))
- 		    {
- 		      update = true;
- 		      break;
- 		    }
- 		}
- 
- 	    if (update)
- 	      update_stmt (stmt);
- 	  }
-       }
- 
    return TODO_rebuild_alias;
  }
  
--- 3431,3448 ----
    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);
    TREE_READONLY (tag) = TREE_READONLY (var);
    MTAG_GLOBAL (tag) = is_global_var (var);
  }
  
! /* ???  Stub.  */
  
  static unsigned int
  create_structure_vars (void)
  {
    return TODO_rebuild_alias;
  }
  
Index: trunk/gcc/tree.def
===================================================================
*** trunk.orig/gcc/tree.def
--- trunk/gcc/tree.def
*************** DEFTREECODE (RESULT_DECL, "result_decl",
*** 363,369 ****
  
  /* Memory tags used in tree-ssa to represent memory locations in
     virtual SSA.  */
- DEFTREECODE (STRUCT_FIELD_TAG, "struct_field_tag", tcc_declaration, 0)
  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)
--- 363,368 ----
Index: trunk/gcc/tree.h
===================================================================
*** trunk.orig/gcc/tree.h
--- trunk/gcc/tree.h
*************** extern const enum tree_code_class tree_c
*** 109,116 ****
  /* Nonzero if CODE represents a memory tag.  */
  
  #define MTAG_P(CODE) \
!   (TREE_CODE (CODE) == STRUCT_FIELD_TAG		\
!    || TREE_CODE (CODE) == NAME_MEMORY_TAG	\
     || TREE_CODE (CODE) == SYMBOL_MEMORY_TAG	\
     || TREE_CODE (CODE) == MEMORY_PARTITION_TAG)
  
--- 109,115 ----
  /* 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)
  
*************** struct tree_memory_tag GTY(())
*** 2546,2590 ****
  
    /* True if this tag has global scope.  */
    unsigned int is_global : 1;
- 
-   /* True if this tag is the first field of an aggregate type that
-      can be used to find adjacent SFTs belonging to the same aggregate.  */
-   unsigned int base_for_components : 1;
- 
-   /* True if this tag should not be grouped into a memory partition.  */
-   unsigned int unpartitionable : 1;
  };
  
  #define MTAG_GLOBAL(NODE) (TREE_MEMORY_TAG_CHECK (NODE)->mtag.is_global)
  #define MTAG_ALIASES(NODE) (TREE_MEMORY_TAG_CHECK (NODE)->mtag.aliases)
  
- struct tree_struct_field_tag GTY(())
- {
-   struct tree_memory_tag common;
- 
-   /* Parent variable.  */
-   tree parent_var;
- 
-   /* Offset inside structure.  */
-   unsigned HOST_WIDE_INT offset;
- 
-   /* Size of the field.  */
-   unsigned HOST_WIDE_INT size;
- 
-   /* Alias set for a DECL_NONADDRESSABLE_P field.  Otherwise -1.  */
-   alias_set_type alias_set;
- };
- #define SFT_PARENT_VAR(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.parent_var)
- #define SFT_OFFSET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.offset)
- #define SFT_SIZE(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.size)
- #define SFT_NONADDRESSABLE_P(NODE) \
-   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set != -1)
- #define SFT_ALIAS_SET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set)
- #define SFT_UNPARTITIONABLE_P(NODE) \
-   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.unpartitionable)
- #define SFT_BASE_FOR_COMPONENTS_P(NODE) \
-   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.base_for_components)
- 
  /* Memory Partition Tags (MPTs) group memory symbols under one
     common name for the purposes of placing memory PHI nodes.  */
  
--- 2545,2555 ----
*************** union tree_node GTY ((ptr_alias (union l
*** 3471,3477 ****
    struct tree_value_handle GTY ((tag ("TS_VALUE_HANDLE"))) value_handle;
    struct tree_constructor GTY ((tag ("TS_CONSTRUCTOR"))) constructor;
    struct tree_memory_tag GTY ((tag ("TS_MEMORY_TAG"))) mtag;
-   struct tree_struct_field_tag GTY ((tag ("TS_STRUCT_FIELD_TAG"))) sft;
    struct tree_omp_clause GTY ((tag ("TS_OMP_CLAUSE"))) omp_clause;
    struct tree_memory_partition_tag GTY ((tag ("TS_MEMORY_PARTITION_TAG"))) mpt;
  };
--- 3436,3441 ----
Index: trunk/gcc/alias.c
===================================================================
*** trunk.orig/gcc/alias.c
--- trunk/gcc/alias.c
*************** get_alias_set (tree t)
*** 584,596 ****
  	    return 0;
  	}
  
-       /* For non-addressable fields we return the alias set of the
- 	 outermost object that could have its address taken.  If this
- 	 is an SFT use the precomputed value.  */
-       if (TREE_CODE (t) == STRUCT_FIELD_TAG
- 	  && SFT_NONADDRESSABLE_P (t))
- 	return SFT_ALIAS_SET (t);
- 
        /* Otherwise, pick up the outermost object that we could have a pointer
  	 to, processing conversions as above.  */
        while (component_uses_parent_alias_set (t))
--- 584,589 ----
Index: trunk/gcc/print-tree.c
===================================================================
*** trunk.orig/gcc/print-tree.c
--- trunk/gcc/print-tree.c
*************** print_node (FILE *file, const char *pref
*** 534,548 ****
  	  && DECL_HAS_VALUE_EXPR_P (node))
  	print_node (file, "value-expr", DECL_VALUE_EXPR (node), indent + 4);
  
-       if (TREE_CODE (node) == STRUCT_FIELD_TAG)
- 	{
- 	  fprintf (file, " sft size " HOST_WIDE_INT_PRINT_DEC, 
- 		   SFT_SIZE (node));
- 	  fprintf (file, " sft offset " HOST_WIDE_INT_PRINT_DEC,
- 		   SFT_OFFSET (node));
- 	  print_node_brief (file, "parent var", SFT_PARENT_VAR (node), 
- 			    indent + 4);
- 	}
        /* Print the decl chain only if decl is at second level.  */
        if (indent == 4)
  	print_node (file, "chain", TREE_CHAIN (node), indent + 4);
--- 534,539 ----
Index: trunk/gcc/tree-dump.c
===================================================================
*** trunk.orig/gcc/tree-dump.c
--- trunk/gcc/tree-dump.c
*************** dequeue_and_dump (dump_info_p di)
*** 513,519 ****
        
      case SYMBOL_MEMORY_TAG:
      case NAME_MEMORY_TAG:
-     case STRUCT_FIELD_TAG:
        break;
  
      case VAR_DECL:
--- 513,518 ----
Index: trunk/gcc/tree-into-ssa.c
===================================================================
*** trunk.orig/gcc/tree-into-ssa.c
--- trunk/gcc/tree-into-ssa.c
*************** mark_sym_for_renaming (tree sym)
*** 2790,2808 ****
    if (need_to_initialize_update_ssa_p)
      init_update_ssa ();
  
-   /* FIXME.  Why do we need this?  */
-   {
-     subvar_t svars;
-     if (var_can_have_subvars (sym) && (svars = get_subvars_for_var (sym)))
-       {
-         unsigned int i;
- 	tree subvar;
- 
- 	for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
- 	  mark_sym_for_renaming (subvar);
-       }
-   }
- 
    bitmap_set_bit (syms_to_rename, DECL_UID (sym));
  
    if (!is_gimple_reg (sym))
--- 2790,2795 ----
Index: trunk/gcc/tree-nrv.c
===================================================================
*** trunk.orig/gcc/tree-nrv.c
--- trunk/gcc/tree-nrv.c
*************** struct gimple_opt_pass pass_nrv = 
*** 249,265 ****
     optimization, where DEST is expected to be the LHS of a modify
     expression where the RHS is a function returning an aggregate.
  
!    We search for a base VAR_DECL and look to see if it, or any of its
!    subvars are clobbered.  Note that we could do better, for example, by
     attempting to doing points-to analysis on INDIRECT_REFs.  */
  
  static bool
  dest_safe_for_nrv_p (tree dest)
  {
-   subvar_t sv;
-   unsigned int i;
-   tree subvar;
- 
    while (handled_component_p (dest))
      dest = TREE_OPERAND (dest, 0);
  
--- 249,261 ----
     optimization, where DEST is expected to be the LHS of a modify
     expression where the RHS is a function returning an aggregate.
  
!    We search for a base VAR_DECL and look to see if it is call clobbered.
!    Note that we could do better, for example, by
     attempting to doing points-to analysis on INDIRECT_REFs.  */
  
  static bool
  dest_safe_for_nrv_p (tree dest)
  {
    while (handled_component_p (dest))
      dest = TREE_OPERAND (dest, 0);
  
*************** dest_safe_for_nrv_p (tree dest)
*** 272,282 ****
    if (is_call_clobbered (dest))
      return false;
  
-   sv = get_subvars_for_var (dest);
-   for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
-     if (is_call_clobbered (subvar))
-       return false;
- 
    return true;
  }
  
--- 268,273 ----
Index: trunk/gcc/tree-predcom.c
===================================================================
*** trunk.orig/gcc/tree-predcom.c
--- trunk/gcc/tree-predcom.c
*************** set_alias_info (tree ref, struct data_re
*** 2389,2396 ****
      new_type_alias (var, tag, ref);
    else
      var_ann (var)->symbol_mem_tag = tag;
- 
-   var_ann (var)->subvars = DR_SUBVARS (dr);
  }
  
  /* Prepare initializers for CHAIN in LOOP.  Returns false if this is
--- 2389,2394 ----
Index: trunk/gcc/tree-pretty-print.c
===================================================================
*** trunk.orig/gcc/tree-pretty-print.c
--- trunk/gcc/tree-pretty-print.c
*************** dump_generic_node (pretty_printer *buffe
*** 907,913 ****
  
      case SYMBOL_MEMORY_TAG:
      case NAME_MEMORY_TAG:
-     case STRUCT_FIELD_TAG:
      case VAR_DECL:
      case PARM_DECL:
      case FIELD_DECL:
--- 907,912 ----
Index: trunk/gcc/tree-ssa-loop-ivopts.c
===================================================================
*** trunk.orig/gcc/tree-ssa-loop-ivopts.c
--- trunk/gcc/tree-ssa-loop-ivopts.c
*************** get_ref_tag (tree ref, tree orig)
*** 5155,5163 ****
  	break;
      }
  
-   if (aref && SSA_VAR_P (aref) && get_subvars_for_var (aref))
-     return aref;
- 
    if (!var)
      return NULL_TREE;
  
--- 5155,5160 ----
Index: trunk/gcc/tree-ssa-operands.c
===================================================================
*** trunk.orig/gcc/tree-ssa-operands.c
--- trunk/gcc/tree-ssa-operands.c
*************** access_can_touch_variable (tree ref, tre
*** 1210,1258 ****
    if (ref && TREE_CODE (ref) == TARGET_MEM_REF)
      return true;
    
-   /* If ALIAS is an SFT, it can't be touched if the offset     
-      and size of the access is not overlapping with the SFT offset and
-      size.  This is only true if we are accessing through a pointer
-      to a type that is the same as SFT_PARENT_VAR.  Otherwise, we may
-      be accessing through a pointer to some substruct of the
-      structure, and if we try to prune there, we will have the wrong
-      offset, and get the wrong answer.
-      i.e., we can't prune without more work if we have something like
- 
-      struct gcc_target
-      {
-        struct asm_out
-        {
-          const char *byte_op;
- 	 struct asm_int_op
- 	 {    
- 	   const char *hi;
- 	 } aligned_op;
-        } asm_out;
-      } targetm;
-      
-      foo = &targetm.asm_out.aligned_op;
-      return foo->hi;
- 
-      SFT.1, which represents hi, will have SFT_OFFSET=32 because in
-      terms of SFT_PARENT_VAR, that is where it is.
-      However, the access through the foo pointer will be at offset 0.  */
-   if (size != -1
-       && TREE_CODE (alias) == STRUCT_FIELD_TAG
-       && base
-       && TREE_TYPE (base) == TREE_TYPE (SFT_PARENT_VAR (alias))
-       && !overlap_subvar (offset, size, alias, NULL))
-     {
- #ifdef ACCESS_DEBUGGING
-       fprintf (stderr, "Access to ");
-       print_generic_expr (stderr, ref, 0);
-       fprintf (stderr, " may not touch ");
-       print_generic_expr (stderr, alias, 0);
-       fprintf (stderr, " in function %s\n", get_name (current_function_decl));
- #endif
-       return false;
-     }
- 
    /* Without strict aliasing, it is impossible for a component access
       through a pointer to touch a random variable, unless that
       variable *is* a structure or a pointer.
--- 1210,1215 ----
*************** access_can_touch_variable (tree ref, tre
*** 1308,1314 ****
       my_char_ref_1 = (char[1:1] &) &my_char;
       D.874_2 = (*my_char_ref_1)[1]{lb: 1 sz: 1};
    */
!   else if (ref 
  	   && flag_strict_aliasing
  	   && TREE_CODE (ref) != INDIRECT_REF
  	   && !MTAG_P (alias)
--- 1265,1271 ----
       my_char_ref_1 = (char[1:1] &) &my_char;
       D.874_2 = (*my_char_ref_1)[1]{lb: 1 sz: 1};
    */
!   if (ref 
  	   && flag_strict_aliasing
  	   && TREE_CODE (ref) != INDIRECT_REF
  	   && !MTAG_P (alias)
*************** access_can_touch_variable (tree ref, tre
*** 1366,1426 ****
    return true;
  }
  
- /* Add the actual variables accessed, given a member of a points-to set
-    that is the SFT VAR, where the access is of SIZE at OFFSET from VAR.
-    IS_CALL_SITE is true if this is a call, and IS_DEF is true if this is
-    supposed to be a vdef, and false if this should be a VUSE.
- 
-    The real purpose of this function is to take a points-to set for a
-    pointer to a structure, say
- 
-    struct s {
-      int a;
-      int b;
-    } foo, *foop = &foo;
- 
-    and discover which variables an access, such as foop->b, can alias.
-    
-    This is necessary because foop only actually points to foo's first
-    member, so that is all the points-to set contains.  However, an access
-    to foop->a may be touching some single SFT if we have created some
-    SFT's for a structure.  */
- 
- static bool
- add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset,
- 		     unsigned HOST_WIDE_INT size, bool is_def)
- {
-   bool added = false;
-   tree subvar;
-   subvar_t sv;
-   unsigned int i;
- 
-   /* Adjust offset by the pointed-to location.  */
-   offset += SFT_OFFSET (var);
- 
-   /* Add all subvars of var that overlap with the access.
-      Binary search for the first relevant SFT.  */
-   sv = get_subvars_for_var (SFT_PARENT_VAR (var));
-   if (!get_first_overlapping_subvar (sv, offset, size, &i))
-     return false;
- 
-   for (; VEC_iterate (tree, sv, i, subvar); ++i)
-     {
-       if (SFT_OFFSET (subvar) > offset
- 	  && size <= SFT_OFFSET (subvar) - offset)
- 	break;
- 
-       if (is_def)
- 	append_vdef (subvar);
-       else
- 	append_vuse (subvar);
-       added = true;
-     }
- 
-   return added;
- }
- 
- 
  /* Add VAR to the virtual operands array.  FLAGS is as in
     get_expr_operands.  FULL_REF is a tree that contains the entire
     pointer dereference expression, if available, or NULL otherwise.
--- 1323,1328 ----
*************** add_virtual_operand (tree var, stmt_ann_
*** 1495,1544 ****
  	{
  	  tree al = referenced_var (i);
  
! 	  /* For SFTs we have to consider all subvariables of the parent var
! 	     if it is a potential points-to location.  */
! 	  if (TREE_CODE (al) == STRUCT_FIELD_TAG
! 	      && TREE_CODE (var) == NAME_MEMORY_TAG)
! 	    {
! 	      if (SFT_BASE_FOR_COMPONENTS_P (al))
! 		{
! 		  /* If AL is the first SFT of a component, it can be used
! 		     to find other SFTs at [offset, size] adjacent to it.  */
! 		  none_added &= !add_vars_for_offset (al, offset, size,
! 						      flags & opf_def);
! 		}
! 	      else if ((unsigned HOST_WIDE_INT)offset < SFT_SIZE (al))
! 		{
! 		  /* Otherwise, we only need to consider it if
! 		     [offset, size] overlaps with AL.  */
! 		  if (flags & opf_def)
! 		    append_vdef (al);
! 		  else
! 		    append_vuse (al);
! 		  none_added = false;
! 		}
! 	    }
  	  else
! 	    {
! 	      /* Call-clobbered tags may have non-call-clobbered
! 		 symbols in their alias sets.  Ignore them if we are
! 		 adding VOPs for a call site.  */
! 	      if (is_call_site && !is_call_clobbered (al))
! 		 continue;
! 
! 	      /* If we do not know the full reference tree or if the access is
! 		 unspecified [0, -1], we cannot prune it.  Otherwise try doing
! 		 so using access_can_touch_variable.  */
! 	      if (full_ref
! 		  && !access_can_touch_variable (full_ref, al, offset, size))
! 		continue;
! 
! 	      if (flags & opf_def)
! 		append_vdef (al);
! 	      else
! 		append_vuse (al);
! 	      none_added = false;
! 	    }
  	}
  
        if (flags & opf_def)
--- 1397,1420 ----
  	{
  	  tree al = referenced_var (i);
  
! 	  /* Call-clobbered tags may have non-call-clobbered
! 	     symbols in their alias sets.  Ignore them if we are
! 	     adding VOPs for a call site.  */
! 	  if (is_call_site && !is_call_clobbered (al))
! 	    continue;
! 
! 	  /* If we do not know the full reference tree or if the access is
! 	     unspecified [0, -1], we cannot prune it.  Otherwise try doing
! 	     so using access_can_touch_variable.  */
! 	  if (full_ref
! 	      && !access_can_touch_variable (full_ref, al, offset, size))
! 	    continue;
! 
! 	  if (flags & opf_def)
! 	    append_vdef (al);
  	  else
! 	    append_vuse (al);
! 	  none_added = false;
  	}
  
        if (flags & opf_def)
*************** add_call_clobber_ops (tree stmt, tree ca
*** 1806,1816 ****
        tree real_var = var;
        bool not_read;
        bool not_written;
-       
-       /* Not read and not written are computed on regular vars, not
- 	 subvars, so look at the parent var if this is an SFT. */
-       if (TREE_CODE (var) == STRUCT_FIELD_TAG)
- 	real_var = SFT_PARENT_VAR (var);
  
        not_read = not_read_b
  	         ? bitmap_bit_p (not_read_b, DECL_UID (real_var))
--- 1682,1687 ----
*************** add_call_read_ops (tree stmt, tree calle
*** 1889,1900 ****
        
        clobber_stats.readonly_clobbers++;
  
-       /* Not read and not written are computed on regular vars, not
- 	 subvars, so look at the parent var if this is an SFT. */
- 
-       if (TREE_CODE (var) == STRUCT_FIELD_TAG)
- 	real_var = SFT_PARENT_VAR (var);
- 
        not_read = not_read_b ? bitmap_bit_p (not_read_b, DECL_UID (real_var))
  	                    : false;
        
--- 1760,1765 ----
*************** get_asm_expr_operands (tree stmt)
*** 2022,2037 ****
  	EXECUTE_IF_SET_IN_BITMAP (gimple_addressable_vars (cfun), 0, i, bi)
  	  {
  	    tree var = referenced_var (i);
- 
- 	    /* Subvars are explicitly represented in this list, so we
- 	       don't need the original to be added to the clobber ops,
- 	       but the original *will* be in this list because we keep
- 	       the addressability of the original variable up-to-date
- 	       to avoid confusing the back-end.  */
- 	    if (var_can_have_subvars (var)
- 		&& get_subvars_for_var (var) != NULL)
- 	      continue;		
- 
  	    add_stmt_operand (&var, s_ann, opf_def | opf_implicit);
  	  }
  	break;
--- 1887,1892 ----
*************** get_modify_stmt_operands (tree stmt, tre
*** 2052,2060 ****
       a preserving definition (VDEF).
  
       Preserving definitions are those that modify a part of an
!      aggregate object for which no subvars have been computed (or the
!      reference does not correspond exactly to one of them). Stores
!      through a pointer are also represented with VDEF operators.
  
       We used to distinguish between preserving and killing definitions.
       We always emit preserving definitions now.  */
--- 1907,1914 ----
       a preserving definition (VDEF).
  
       Preserving definitions are those that modify a part of an
!      aggregate object. Stores through a pointer are also represented
!      with VDEF operators.
  
       We used to distinguish between preserving and killing definitions.
       We always emit preserving definitions now.  */
*************** get_expr_operands (tree stmt, tree *expr
*** 2104,2110 ****
        return;
  
      case SSA_NAME:
-     case STRUCT_FIELD_TAG:
      case SYMBOL_MEMORY_TAG:
      case NAME_MEMORY_TAG:
       add_stmt_operand (expr_p, s_ann, flags);
--- 1958,1963 ----
*************** get_expr_operands (tree stmt, tree *expr
*** 2113,2137 ****
      case VAR_DECL:
      case PARM_DECL:
      case RESULT_DECL:
!       {
! 	subvar_t svars;
! 	
! 	/* Add the subvars for a variable, if it has subvars, to DEFS
! 	   or USES.  Otherwise, add the variable itself.  Whether it
! 	   goes to USES or DEFS depends on the operand flags.  */
! 	if (var_can_have_subvars (expr)
! 	    && (svars = get_subvars_for_var (expr)))
! 	  {
! 	    unsigned int i;
! 	    tree subvar;
! 	    for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
! 	      add_stmt_operand (&subvar, s_ann, flags);
! 	  }
! 	else
! 	  add_stmt_operand (expr_p, s_ann, flags);
! 
! 	return;
!       }
  
      case MISALIGNED_INDIRECT_REF:
        get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
--- 1966,1973 ----
      case VAR_DECL:
      case PARM_DECL:
      case RESULT_DECL:
!       add_stmt_operand (expr_p, s_ann, flags);
!       return;
  
      case MISALIGNED_INDIRECT_REF:
        get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
*************** get_expr_operands (tree stmt, tree *expr
*** 2154,2207 ****
        {
  	tree ref;
  	HOST_WIDE_INT offset, size, maxsize;
- 	bool none = true;
  
  	if (TREE_THIS_VOLATILE (expr))
  	  s_ann->has_volatile_ops = true;
  
- 	/* This component reference becomes an access to all of the
- 	   subvariables it can touch, if we can determine that, but
- 	   *NOT* the real one.  If we can't determine which fields we
- 	   could touch, the recursion will eventually get to a
- 	   variable and add *all* of its subvars, or whatever is the
- 	   minimum correct subset.  */
  	ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
! 	if (SSA_VAR_P (ref) && get_subvars_for_var (ref))
! 	  {
! 	    subvar_t svars = get_subvars_for_var (ref);
! 	    unsigned int i;
! 	    tree subvar;
! 
! 	    for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
! 	      {
! 		bool exact;		
! 
! 		if (overlap_subvar (offset, maxsize, subvar, &exact))
! 		  {
! 	            int subvar_flags = flags;
! 		    none = false;
! 		    add_stmt_operand (&subvar, s_ann, subvar_flags);
! 		  }
! 	      }
! 
! 	    if (!none)
! 	      flags |= opf_no_vops;
! 
! 	    if ((DECL_P (ref) && TREE_THIS_VOLATILE (ref))
! 		|| (TREE_CODE (ref) == SSA_NAME
! 		    && TREE_THIS_VOLATILE (SSA_NAME_VAR (ref))))
! 	      s_ann->has_volatile_ops = true;
! 	  }
! 	else if (TREE_CODE (ref) == INDIRECT_REF)
  	  {
  	    get_indirect_ref_operands (stmt, ref, flags, expr, offset,
  		                       maxsize, false);
  	    flags |= opf_no_vops;
  	  }
  
- 	/* Even if we found subvars above we need to ensure to see
- 	   immediate uses for d in s.a[d].  In case of s.a having
- 	   a subvar or we would miss it otherwise.  */
  	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
  	
  	if (code == COMPONENT_REF)
--- 1990,2007 ----
        {
  	tree ref;
  	HOST_WIDE_INT offset, size, maxsize;
  
  	if (TREE_THIS_VOLATILE (expr))
  	  s_ann->has_volatile_ops = true;
  
  	ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
! 	if (TREE_CODE (ref) == INDIRECT_REF)
  	  {
  	    get_indirect_ref_operands (stmt, ref, flags, expr, offset,
  		                       maxsize, false);
  	    flags |= opf_no_vops;
  	  }
  
  	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
  	
  	if (code == COMPONENT_REF)
*************** void
*** 2759,2765 ****
  add_to_addressable_set (tree ref, bitmap *addresses_taken)
  {
    tree var;
-   subvar_t svars;
  
    gcc_assert (addresses_taken);
  
--- 2559,2564 ----
*************** add_to_addressable_set (tree ref, bitmap
*** 2773,2795 ****
      {
        if (*addresses_taken == NULL)
  	*addresses_taken = BITMAP_GGC_ALLOC ();      
!       
!       if (var_can_have_subvars (var)
! 	  && (svars = get_subvars_for_var (var)))
! 	{
! 	  unsigned int i;
! 	  tree subvar;
! 	  for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
! 	    {
! 	      bitmap_set_bit (*addresses_taken, DECL_UID (subvar));
! 	      TREE_ADDRESSABLE (subvar) = 1;
! 	    }
! 	}
!       else
! 	{
! 	  bitmap_set_bit (*addresses_taken, DECL_UID (var));
! 	  TREE_ADDRESSABLE (var) = 1;
! 	}
      }
  }
  
--- 2572,2579 ----
      {
        if (*addresses_taken == NULL)
  	*addresses_taken = BITMAP_GGC_ALLOC ();      
!       bitmap_set_bit (*addresses_taken, DECL_UID (var));
!       TREE_ADDRESSABLE (var) = 1;
      }
  }
  
Index: trunk/gcc/tree-ssa.c
===================================================================
*** trunk.orig/gcc/tree-ssa.c
--- trunk/gcc/tree-ssa.c
*************** verify_ssa_name (tree ssa_name, bool is_
*** 254,266 ****
        return true;
      }
  
-   if (is_virtual && var_ann (SSA_NAME_VAR (ssa_name)) 
-       && get_subvars_for_var (SSA_NAME_VAR (ssa_name)) != NULL)
-     {
-       error ("found real variable when subvariables should have appeared");
-       return true;
-     }
- 
    if (SSA_NAME_IS_DEFAULT_DEF (ssa_name)
        && !IS_EMPTY_STMT (SSA_NAME_DEF_STMT (ssa_name)))
      {
--- 254,259 ----
Index: trunk/gcc/tree-tailcall.c
===================================================================
*** trunk.orig/gcc/tree-tailcall.c
--- trunk/gcc/tree-tailcall.c
*************** suitable_for_tail_opt_p (void)
*** 144,150 ****
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (!is_global_var (var)
! 	  && (!MTAG_P (var) || TREE_CODE (var) == STRUCT_FIELD_TAG)
  	  && (gimple_aliases_computed_p (cfun) ? is_call_clobbered (var)
  	      : TREE_ADDRESSABLE (var)))
  	return false;
--- 144,150 ----
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (!is_global_var (var)
! 	  && !MTAG_P (var)
  	  && (gimple_aliases_computed_p (cfun) ? is_call_clobbered (var)
  	      : TREE_ADDRESSABLE (var)))
  	return false;
Index: trunk/gcc/tree-vect-transform.c
===================================================================
*** trunk.orig/gcc/tree-vect-transform.c
--- trunk/gcc/tree-vect-transform.c
*************** vect_create_data_ref_ptr (tree stmt, str
*** 1061,1068 ****
    else
      set_symbol_mem_tag (vect_ptr, tag);
  
-   var_ann (vect_ptr)->subvars = DR_SUBVARS (dr);
- 
    /** 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
--- 1061,1066 ----
Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c
--- trunk/gcc/tree.c
*************** init_ttree (void)
*** 263,279 ****
    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[STRUCT_FIELD_TAG][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[STRUCT_FIELD_TAG][TS_MEMORY_TAG] = 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[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 1;
    tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1;
  
    tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
--- 263,276 ----
*************** tree_code_size (enum tree_code code)
*** 370,377 ****
  	  case NAME_MEMORY_TAG:
  	  case SYMBOL_MEMORY_TAG:
  	    return sizeof (struct tree_memory_tag);
- 	  case STRUCT_FIELD_TAG:
- 	    return sizeof (struct tree_struct_field_tag);
  	  case MEMORY_PARTITION_TAG:
  	    return sizeof (struct tree_memory_partition_tag);
  	  default:
--- 367,372 ----
*************** tree_node_structure (const_tree t)
*** 2289,2295 ****
  	    return TS_FUNCTION_DECL;
  	  case SYMBOL_MEMORY_TAG:
  	  case NAME_MEMORY_TAG:
- 	  case STRUCT_FIELD_TAG:
  	  case MEMORY_PARTITION_TAG:
  	    return TS_MEMORY_TAG;
  	  default:
--- 2284,2289 ----
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c
--- trunk/gcc/tree-ssa-structalias.c
*************** set_uids_in_ptset (tree ptr, bitmap into
*** 4709,4796 ****
  {
    unsigned int i;
    bitmap_iterator bi;
-   alias_set_type ptr_alias_set;
  
    gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
-   ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
  
    EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
      {
        varinfo_t vi = get_varinfo (i);
-       alias_set_type var_alias_set;
  
        /* The only artificial variables that are allowed in a may-alias
  	 set are heap variables.  */
        if (vi->is_artificial_var && !vi->is_heap_var)
  	continue;
  
!       if (vi->has_union && get_subvars_for_var (vi->decl) != NULL)
! 	{
! 	  unsigned int i;
! 	  tree subvar;
! 	  subvar_t sv = get_subvars_for_var (vi->decl);
! 
! 	  /* Variables containing unions may need to be converted to
! 	     their SFT's, because SFT's can have unions and we cannot.  */
! 	  for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i)
! 	    bitmap_set_bit (into, DECL_UID (subvar));
! 	}
!       else if (TREE_CODE (vi->decl) == VAR_DECL
! 	       || TREE_CODE (vi->decl) == PARM_DECL
! 	       || TREE_CODE (vi->decl) == RESULT_DECL)
! 	{
! 	  subvar_t sv;
! 	  if (var_can_have_subvars (vi->decl)
! 	      && (sv = get_subvars_for_var (vi->decl)))
! 	    {
! 	      /* If VI->DECL is an aggregate for which we created
! 		 SFTs, add the SFT corresponding to VI->OFFSET.
! 		 If we didn't do field-sensitive PTA we need to to
! 		 add all overlapping SFTs.  */
! 	      unsigned int j;
! 	      tree sft = get_first_overlapping_subvar (sv, vi->offset,
! 						       vi->size, &j);
! 	      gcc_assert (sft);
! 	      for (; VEC_iterate (tree, sv, j, sft); ++j)
! 		{
! 		  if (SFT_OFFSET (sft) > vi->offset
! 		      && vi->size <= SFT_OFFSET (sft) - vi->offset)
! 		    break;
! 
! 		  var_alias_set = get_alias_set (sft);
! 		  if (no_tbaa_pruning
! 		      || (!is_derefed && !vi->directly_dereferenced)
! 		      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
! 		    {
! 		      bitmap_set_bit (into, DECL_UID (sft));
! 		      
! 		      /* Pointed-to SFTs are needed by the operand scanner
! 			 to adjust offsets when adding operands to memory
! 			 expressions that dereference PTR.  This means
! 			 that memory partitioning may not partition
! 			 this SFT because the operand scanner will not
! 			 be able to find the other SFTs next to this
! 			 one.  But we only need to do this if the pointed
! 			 to type is aggregate.  */
! 		      if (SFT_BASE_FOR_COMPONENTS_P (sft))
! 			SFT_UNPARTITIONABLE_P (sft) = true;
! 		    }
! 		}
! 	    }
  	  else
  	    {
! 	      /* Otherwise, just add VI->DECL to the alias set.
! 		 Don't type prune artificial vars.  */
! 	      if (vi->is_artificial_var)
! 		bitmap_set_bit (into, DECL_UID (vi->decl));
! 	      else
! 		{
! 		  var_alias_set = get_alias_set (vi->decl);
! 		  if (no_tbaa_pruning
! 		      || (!is_derefed && !vi->directly_dereferenced)
! 		      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
! 		    bitmap_set_bit (into, DECL_UID (vi->decl));
! 		}
  	    }
  	}
      }
--- 4709,4743 ----
  {
    unsigned int i;
    bitmap_iterator bi;
  
    gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
  
    EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
      {
        varinfo_t vi = get_varinfo (i);
  
        /* The only artificial variables that are allowed in a may-alias
  	 set are heap variables.  */
        if (vi->is_artificial_var && !vi->is_heap_var)
  	continue;
  
!       if (TREE_CODE (vi->decl) == VAR_DECL
! 	  || 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.  */
! 	  if (vi->is_artificial_var)
! 	    bitmap_set_bit (into, DECL_UID (vi->decl));
  	  else
  	    {
! 	      alias_set_type var_alias_set, ptr_alias_set;
! 	      var_alias_set = get_alias_set (vi->decl);
! 	      ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (no_tbaa_pruning
! 		  || (!is_derefed && !vi->directly_dereferenced)
! 		  || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
! 	        bitmap_set_bit (into, DECL_UID (vi->decl));
  	    }
  	}
      }
*************** find_what_p_points_to (tree p)
*** 4919,4927 ****
  	  /* Nothing currently asks about structure fields directly,
  	     but when they do, we need code here to hand back the
  	     points-to set.  */
! 	  if (!var_can_have_subvars (vi->decl)
! 	      || get_subvars_for_var (vi->decl) == NULL)
! 	    return false;
  	}
        else
  	{
--- 4866,4872 ----
  	  /* Nothing currently asks about structure fields directly,
  	     but when they do, we need code here to hand back the
  	     points-to set.  */
! 	  return false;
  	}
        else
  	{



More information about the Gcc-patches mailing list