OSDN Git Service

* tree-ssa-alias.c (add_type_alias): Fix typo. Test whether
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-alias.c
index c65fe8d..6676303 100644 (file)
@@ -344,12 +344,20 @@ struct count_ptr_d
    (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
 
 static tree
-count_ptr_derefs (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
+count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
 {
   struct count_ptr_d *count_p = (struct count_ptr_d *) data;
 
+  /* 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)
-/*       || (TREE_CODE (*tp) == MEM_REF && MEM_REF_SYMBOL (*tp) == count_p->ptr)) */
     count_p->count++;
 
   return NULL_TREE;
@@ -447,7 +455,7 @@ init_alias_info (void)
   tree var;
 
   bitmap_obstack_initialize (&alias_obstack);
-  ai = xcalloc (1, sizeof (struct alias_info));
+  ai = XCNEW (struct alias_info);
   ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
   sbitmap_zero (ai->ssa_names_visited);
   VARRAY_TREE_INIT (ai->processed_ptrs, 50, "processed_ptrs");
@@ -484,8 +492,8 @@ init_alias_info (void)
             a global variable, so we *don't* clear their call clobberedness
             just because they are tags, though we will clear it if they
             aren't for global variables.  */
-         if (ann->mem_tag_kind == NAME_TAG 
-             || ann->mem_tag_kind == TYPE_TAG 
+         if (TREE_CODE (var) == NAME_MEMORY_TAG
+             || TREE_CODE (var) == TYPE_MEMORY_TAG
              || !is_global_var (var))
            clear_call_clobbered (var);
        }
@@ -560,7 +568,6 @@ delete_alias_info (struct alias_info *ai)
   delete_points_to_sets ();
 }
 
-
 /* 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
@@ -574,7 +581,10 @@ static void
 create_name_tags (void)
 {
   size_t i;
+  VEC (tree, heap) *with_ptvars = NULL;
+  tree ptr;
 
+  /* 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);
@@ -595,68 +605,71 @@ create_name_tags (void)
          continue;
        }
 
-      if (pi->pt_vars && !bitmap_empty_p (pi->pt_vars))
+      /* Set pt_anything on the pointers without pt_vars filled in so
+        that they are assigned a type 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;
+
+  /* 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);
+      size_t j;
+      tree ptr2;
+      tree old_name_tag = pi->name_mem_tag;
+      
+      /* 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).  */
+      for (j = 0; j < i && VEC_iterate (tree, with_ptvars, j, ptr2); j++)
        {
-         size_t j;
-         tree old_name_tag = pi->name_mem_tag;
-
-         /* 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).  */
-         for (j = 1; j < i; j++)
+         struct ptr_info_def *qi = SSA_NAME_PTR_INFO (ptr2);
+         
+         if (bitmap_equal_p (pi->pt_vars, qi->pt_vars))
            {
-             tree q = ssa_name (j);
-             struct ptr_info_def *qi;
-
-             if (!q || !POINTER_TYPE_P (TREE_TYPE (q)))
-               continue;
-
-             qi = SSA_NAME_PTR_INFO (q);
-
-             if (qi
-                 && qi->pt_vars
-                 && qi->name_mem_tag
-                 && bitmap_equal_p (pi->pt_vars, qi->pt_vars))
-               {
-                 pi->name_mem_tag = qi->name_mem_tag;
-                 break;
-               }
+             pi->name_mem_tag = qi->name_mem_tag;
+             break;
            }
-
-         /* 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);
-       }
-      else
-       {
-         /* If the pointer does not point to a known spot, we should
-            use type tags.  */
-         set_pt_anything (ptr);
-         continue;
        }
-
+      
+      /* 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);
+      
       TREE_THIS_VOLATILE (pi->name_mem_tag)
-         |= TREE_THIS_VOLATILE (TREE_TYPE (TREE_TYPE (ptr)));
-
+       |= TREE_THIS_VOLATILE (TREE_TYPE (TREE_TYPE (ptr)));
+      
       /* Mark the new name tag for renaming.  */
       mark_sym_for_renaming (pi->name_mem_tag);
     }
+
+  VEC_free (tree, heap, with_ptvars);
 }
 
 
@@ -786,7 +799,6 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
             
          if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
            {
-             subvar_t svars;
              size_t num_tag_refs, num_var_refs;
 
              num_tag_refs = NUM_REFERENCES (tag_ann);
@@ -794,28 +806,15 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
 
              /* Add VAR to TAG's may-aliases set.  */
 
-             /* If this is an aggregate, we may have subvariables for it
-                that need to be pointed to.  */
-             if (var_can_have_subvars (var)
-                 && (svars = get_subvars_for_var (var)))
-               {
-                 subvar_t sv;
+             /* 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);
 
-                 for (sv = svars; sv; sv = sv->next)
-                   {
-                     add_may_alias (tag, sv->var);
-                     /* Update the bitmap used to represent TAG's alias set
-                        in case we need to group aliases.  */
-                     bitmap_set_bit (p_map->may_aliases, DECL_UID (sv->var));
-                   }
-               }
-             else
-               {
-                 add_may_alias (tag, var);
-                 /* Update the bitmap used to represent TAG's alias set
-                    in case we need to group aliases.  */
-                 bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
-               }
+             add_may_alias (tag, var);
+             /* Update the bitmap used to represent TAG's alias set
+                in case we need to group aliases.  */
+             bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
 
              /* Update the total number of virtual operands due to
                 aliasing.  Since we are adding one more alias to TAG's
@@ -1109,26 +1108,26 @@ group_aliases (struct alias_info *ai)
       size_t j;
       tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
       tree name_tag = SSA_NAME_PTR_INFO (ptr)->name_mem_tag;
-      varray_type aliases;
+      VEC(tree,gc) *aliases;
+      tree alias;
       
       if (name_tag == NULL_TREE)
        continue;
 
       aliases = var_ann (name_tag)->may_aliases;
-      for (j = 0; aliases && j < VARRAY_ACTIVE_SIZE (aliases); j++)
+      for (j = 0; VEC_iterate (tree, aliases, j, alias); j++)
        {
-         tree alias = VARRAY_TREE (aliases, j);
          var_ann_t ann = var_ann (alias);
 
-         if ((ann->mem_tag_kind == NOT_A_TAG 
-              || ann->mem_tag_kind == STRUCT_FIELD)
+         if ((!MTAG_P (alias)
+              || TREE_CODE (alias) == STRUCT_FIELD_TAG)
              && ann->may_aliases)
            {
              tree new_alias;
 
-             gcc_assert (VARRAY_ACTIVE_SIZE (ann->may_aliases) == 1);
+             gcc_assert (VEC_length (tree, ann->may_aliases) == 1);
 
-             new_alias = VARRAY_TREE (ann->may_aliases, 0);
+             new_alias = VEC_index (tree, ann->may_aliases, 0);
              replace_may_alias (name_tag, j, new_alias);
            }
        }
@@ -1149,7 +1148,7 @@ static void
 create_alias_map_for (tree var, struct alias_info *ai)
 {
   struct alias_map_d *alias_map;
-  alias_map = xcalloc (1, sizeof (*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;
@@ -1195,9 +1194,8 @@ setup_pointers_and_addressables (struct alias_info *ai)
      because some TREE_ADDRESSABLE variables will be marked
      non-addressable below and only pointers with unique type tags are
      going to be added to POINTERS.  */
-  ai->addressable_vars = xcalloc (num_addressable_vars,
-                                 sizeof (struct alias_map_d *));
-  ai->pointers = xcalloc (num_pointers, sizeof (struct alias_map_d *));
+  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;
 
@@ -1220,8 +1218,7 @@ setup_pointers_and_addressables (struct alias_info *ai)
          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 (v_ann->mem_tag_kind != NOT_A_TAG
-         && v_ann->mem_tag_kind != STRUCT_FIELD) 
+      if (MTAG_P (var) && TREE_CODE (var) != STRUCT_FIELD_TAG)
        continue;
 
       /* Remove the ADDRESSABLE flag from every addressable variable whose
@@ -1267,7 +1264,9 @@ setup_pointers_and_addressables (struct alias_info *ai)
 
       /* Global variables and addressable locals may be aliased.  Create an
          entry in ADDRESSABLE_VARS for VAR.  */
-      if (may_be_aliased (var))
+      if (may_be_aliased (var)   
+         && (!var_can_have_subvars (var) 
+             || get_subvars_for_var (var) == NULL))
        {
          create_alias_map_for (var, ai);
          mark_sym_for_renaming (var);
@@ -1463,7 +1462,6 @@ may_alias_p (tree ptr, HOST_WIDE_INT mem_alias_set,
             bool alias_set_only)
 {
   tree mem;
-  var_ann_t m_ann;
 
   alias_stats.alias_queries++;
   alias_stats.simple_queries++;
@@ -1497,29 +1495,10 @@ may_alias_p (tree ptr, HOST_WIDE_INT mem_alias_set,
       return false;
     }
 
-  m_ann = var_ann (mem);
-
-  gcc_assert (m_ann->mem_tag_kind == TYPE_TAG);
+  gcc_assert (TREE_CODE (mem) == TYPE_MEMORY_TAG);
 
   alias_stats.tbaa_queries++;
 
-  /* If VAR is a pointer with the same alias set as PTR, then dereferencing
-     PTR can't possibly affect VAR.  Note, that we are specifically testing
-     for PTR's alias set here, not its pointed-to type.  We also can't
-     do this check with relaxed aliasing enabled.  */
-  if (POINTER_TYPE_P (TREE_TYPE (var))
-      && var_alias_set != 0
-      && mem_alias_set != 0)
-    {
-      HOST_WIDE_INT ptr_alias_set = get_alias_set (ptr);
-      if (ptr_alias_set == var_alias_set)
-       {
-         alias_stats.alias_noalias++;
-         alias_stats.tbaa_resolved++;
-         return false;
-       }
-    }
-
   /* If the alias sets don't conflict then MEM cannot alias VAR.  */
   if (!alias_sets_conflict_p (mem_alias_set, var_alias_set))
     {
@@ -1599,6 +1578,7 @@ add_may_alias (tree var, tree alias)
   size_t i;
   var_ann_t v_ann = get_var_ann (var);
   var_ann_t a_ann = get_var_ann (alias);
+  tree al;
 
   /* Don't allow self-referential aliases.  */
   gcc_assert (var != alias);
@@ -1611,11 +1591,11 @@ add_may_alias (tree var, tree alias)
 #endif
 
   if (v_ann->may_aliases == NULL)
-    VARRAY_TREE_INIT (v_ann->may_aliases, 2, "aliases");
+    v_ann->may_aliases = VEC_alloc (tree, gc, 2);
 
   /* Avoid adding duplicates.  */
-  for (i = 0; i < VARRAY_ACTIVE_SIZE (v_ann->may_aliases); i++)
-    if (alias == VARRAY_TREE (v_ann->may_aliases, i))
+  for (i = 0; VEC_iterate (tree, v_ann->may_aliases, i, al); i++)
+    if (alias == al)
       return;
 
   /* If VAR is a call-clobbered variable, so is its new ALIAS.
@@ -1628,7 +1608,7 @@ add_may_alias (tree var, tree alias)
   else if (is_call_clobbered (alias))
     mark_call_clobbered (var);
 
-  VARRAY_PUSH_TREE (v_ann->may_aliases, alias);
+  VEC_safe_push (tree, gc, v_ann->may_aliases, alias);
   a_ann->is_alias_tag = 1;
 }
 
@@ -1639,7 +1619,7 @@ static void
 replace_may_alias (tree var, size_t i, tree new_alias)
 {
   var_ann_t v_ann = var_ann (var);
-  VARRAY_TREE (v_ann->may_aliases, i) = new_alias;
+  VEC_replace (tree, v_ann->may_aliases, i, new_alias);
 
   /* If VAR is a call-clobbered variable, so is NEW_ALIAS.
      FIXME, call-clobbering should only depend on whether an address
@@ -1745,6 +1725,31 @@ is_escape_site (tree stmt, struct alias_info *ai)
   return false;
 }
 
+/* Create a new memory tag of type TYPE.
+   Does NOT push it into the current binding.  */
+
+static tree
+create_tag_raw (enum tree_code code, tree type, const char *prefix)
+{
+  tree tmp_var;
+  tree new_type;
+
+  /* Make the type of the variable writable.  */
+  new_type = build_type_variant (type, 0, 0);
+  TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
+
+  tmp_var = build_decl (code, create_tmp_var_name (prefix),
+                       type);
+  /* Make the variable writable.  */
+  TREE_READONLY (tmp_var) = 0;
+
+  /* It doesn't start out global.  */
+  MTAG_GLOBAL (tmp_var) = 0;
+  TREE_STATIC (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
@@ -1755,7 +1760,8 @@ static tree
 create_memory_tag (tree type, bool is_type_tag)
 {
   var_ann_t ann;
-  tree tag = create_tmp_var_raw (type, (is_type_tag) ? "TMT" : "NMT");
+  tree tag = create_tag_raw (is_type_tag ? TYPE_MEMORY_TAG : NAME_MEMORY_TAG,
+                            type, (is_type_tag) ? "TMT" : "NMT");
 
   /* By default, memory tags are local variables.  Alias analysis will
      determine whether they should be considered globals.  */
@@ -1765,7 +1771,6 @@ create_memory_tag (tree type, bool is_type_tag)
   TREE_ADDRESSABLE (tag) = 1;
 
   ann = get_var_ann (tag);
-  ann->mem_tag_kind = (is_type_tag) ? TYPE_TAG : NAME_TAG;
   ann->type_mem_tag = NULL_TREE;
 
   /* Add the tag to the symbol table.  */
@@ -1852,7 +1857,7 @@ get_tmt_for (tree ptr, struct alias_info *ai)
       /* 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 = xcalloc (1, sizeof (*alias_map));
+      alias_map = XCNEW (struct alias_map_d);
       alias_map->var = ptr;
       alias_map->set = tag_set;
       ai->pointers[ai->num_pointers++] = alias_map;
@@ -1958,8 +1963,7 @@ dump_alias_info (FILE *file)
   
   FOR_EACH_REFERENCED_VAR (var, rvi)
     {
-      var_ann_t ann = var_ann (var);
-      if (ann->mem_tag_kind == TYPE_TAG)
+      if (TREE_CODE (var) == TYPE_MEMORY_TAG)
        dump_variable (file, var);
     }
 
@@ -1985,8 +1989,7 @@ dump_alias_info (FILE *file)
   
   FOR_EACH_REFERENCED_VAR (var, rvi)
     {
-      var_ann_t ann = var_ann (var);
-      if (ann->mem_tag_kind == NAME_TAG)
+      if (TREE_CODE (var) == NAME_MEMORY_TAG)
        dump_variable (file, var);
     }
 
@@ -2016,7 +2019,7 @@ get_ptr_info (tree t)
   pi = SSA_NAME_PTR_INFO (t);
   if (pi == NULL)
     {
-      pi = ggc_alloc (sizeof (*pi));
+      pi = GGC_NEW (struct ptr_info_def);
       memset ((void *)pi, 0, sizeof (*pi));
       SSA_NAME_PTR_INFO (t) = pi;
     }
@@ -2137,7 +2140,7 @@ dump_points_to_info (FILE *file)
 }
 
 
-/* Dump points-to info pointed by PTO into STDERR.  */
+/* Dump points-to info pointed to by PTO into STDERR.  */
 
 void
 debug_points_to_info (void)
@@ -2150,7 +2153,7 @@ debug_points_to_info (void)
 void
 dump_may_aliases_for (FILE *file, tree var)
 {
-  varray_type aliases;
+  VEC(tree, gc) *aliases;
   
   if (TREE_CODE (var) == SSA_NAME)
     var = SSA_NAME_VAR (var);
@@ -2159,10 +2162,11 @@ dump_may_aliases_for (FILE *file, tree var)
   if (aliases)
     {
       size_t i;
+      tree al;
       fprintf (file, "{ ");
-      for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
+      for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
        {
-         print_generic_expr (file, VARRAY_TREE (aliases, i), dump_flags);
+         print_generic_expr (file, al, dump_flags);
          fprintf (file, " ");
        }
       fprintf (file, "}");
@@ -2189,7 +2193,12 @@ may_be_aliased (tree var)
 
   /* Globally visible variables can have their addresses taken by other
      translation units.  */
-  if (DECL_EXTERNAL (var) || TREE_PUBLIC (var))
+
+  if (MTAG_P (var)
+      && (MTAG_GLOBAL (var) || TREE_PUBLIC (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.
@@ -2211,17 +2220,53 @@ may_be_aliased (tree var)
 }
 
 
+/* Given two symbols return TRUE if one is in the alias set of the other.  */
+bool
+is_aliased_with (tree tag, tree sym)
+{
+  size_t i;
+  VEC(tree,gc) *aliases;
+  tree al;
+
+  if (var_ann (sym)->is_alias_tag)
+    {
+      aliases = var_ann (tag)->may_aliases;
+
+      if (aliases == NULL)
+       return false;
+
+      for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+       if (al == sym)
+         return true;
+    }
+  else
+    {
+      aliases = var_ann (sym)->may_aliases;
+
+      if (aliases == NULL)
+       return false;
+
+      for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+       if (al == tag)
+         return true;
+    }
+
+  return false;
+}
+
+
 /* Add VAR to the list of may-aliases of PTR's type tag.  If PTR
    doesn't already have a type tag, create one.  */
 
 void
 add_type_alias (tree ptr, tree var)
 {
-  varray_type aliases;
-  tree tag;
+  VEC(tree, gc) *aliases;
+  tree tag, al;
   var_ann_t ann = var_ann (ptr);
   subvar_t svars;
   VEC (tree, heap) *varvec = NULL;  
+  unsigned i;
 
   if (ann->type_mem_tag == NULL_TREE)
     {
@@ -2262,7 +2307,7 @@ add_type_alias (tree ptr, tree var)
 found_tag:
   /* If VAR is not already PTR's type tag, add it to the may-alias set
      for PTR's type tag.  */
-  gcc_assert (var_ann (var)->type_mem_tag == NOT_A_TAG);
+  gcc_assert (!MTAG_P (var));
   tag = ann->type_mem_tag;
 
   /* If VAR has subvars, add the subvars to the tag instead of the
@@ -2281,9 +2326,8 @@ found_tag:
   mark_sym_for_renaming (tag);
   if ((aliases = var_ann (tag)->may_aliases) != NULL)
     {
-      size_t i;
-      for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
-       mark_sym_for_renaming (VARRAY_TREE (aliases, i));
+      for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+       mark_sym_for_renaming (al);
     }
 
   /* If we had grouped aliases, VAR may have aliases of its own.  Mark
@@ -2291,9 +2335,8 @@ found_tag:
      aliases of VAR will need to be updated.  */
   if ((aliases = var_ann (var)->may_aliases) != NULL)
     {
-      size_t i;
-      for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
-       mark_sym_for_renaming (VARRAY_TREE (aliases, i));
+      for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+       mark_sym_for_renaming (al);
     }
   VEC_free (tree, heap, varvec);
 }
@@ -2315,7 +2358,7 @@ new_type_alias (tree ptr, tree var)
   subvar_t svars;
 
   gcc_assert (p_ann->type_mem_tag == NULL_TREE);
-  gcc_assert (v_ann->mem_tag_kind == NOT_A_TAG);
+  gcc_assert (!MTAG_P (var));
 
   /* Add VAR to the may-alias set of PTR's new type tag.  If VAR has
      subvars, add the subvars to the tag instead of the actual var.  */
@@ -2336,14 +2379,14 @@ new_type_alias (tree ptr, tree var)
         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.  */
-      varray_type aliases = v_ann->may_aliases;
+      VEC(tree, gc) *aliases = v_ann->may_aliases;
 
       if ((aliases != NULL)
-         && (VARRAY_ACTIVE_SIZE (aliases) == 1))
+         && (VEC_length (tree, aliases) == 1))
        {
-         tree ali = VARRAY_TREE (aliases, 0);
+         tree ali = VEC_index (tree, aliases, 0);
 
-         if (get_var_ann (ali)->mem_tag_kind == TYPE_TAG)
+         if (TREE_CODE (ali) == TYPE_MEMORY_TAG)
            {
              p_ann->type_mem_tag = ali;
              return;
@@ -2357,10 +2400,11 @@ new_type_alias (tree ptr, tree var)
        add_may_alias (tag, var);
       else
        {
-         size_t i;
+         unsigned i;
+         tree al;
 
-         for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
-           add_may_alias (tag, VARRAY_TREE (aliases, i));
+         for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+           add_may_alias (tag, al);
        }
     }    
 }
@@ -2397,7 +2441,8 @@ struct used_part_map
 static int
 used_part_map_eq (const void *va, const void *vb)
 {
-  const struct used_part_map  *a = va, *b = 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);
 }
 
@@ -2425,7 +2470,7 @@ up_lookup (unsigned int uid)
 {
   struct used_part_map *h, in;
   in.uid = uid;
-  h = htab_find_with_hash (used_portions, &in, uid);
+  h = (struct used_part_map *) htab_find_with_hash (used_portions, &in, uid);
   if (!h)
     return NULL;
   return h->to;
@@ -2439,7 +2484,7 @@ up_insert (unsigned int uid, used_part_t to)
   struct used_part_map *h;
   void **loc;
 
-  h = xmalloc (sizeof (struct used_part_map));
+  h = XNEW (struct used_part_map);
   h->uid = uid;
   h->to = to;
   loc = htab_find_slot_with_hash (used_portions, h,
@@ -2459,7 +2504,7 @@ get_or_create_used_part_for (size_t uid)
   used_part_t up;
   if ((up = up_lookup (uid)) == NULL)
     {
-      up = xcalloc (1, sizeof (struct used_part));
+      up = XCNEW (struct used_part);
       up->minused = INT_MAX;
       up->maxused = 0;
       up->explicit_uses = false;
@@ -2470,28 +2515,28 @@ get_or_create_used_part_for (size_t uid)
 }
 
 
-/* Create and return a structure sub-variable for field FIELD of
+/* Create and return a structure sub-variable for field type FIELD of
    variable VAR.  */
 
 static tree
 create_sft (tree var, tree field)
 {
   var_ann_t ann;
-  tree subvar = create_tmp_var_raw (TREE_TYPE (field), "SFT");
+  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);
-  DECL_EXTERNAL (subvar) = DECL_EXTERNAL (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);
 
   /* Add the new variable to REFERENCED_VARS.  */
   ann = get_var_ann (subvar);
-  ann->mem_tag_kind = STRUCT_FIELD; 
   ann->type_mem_tag = NULL;    
   add_referenced_tmp_var (subvar);
+  SFT_PARENT_VAR (subvar) = var;
 
   return subvar;
 }
@@ -2534,9 +2579,8 @@ create_overlap_variables_for (tree var)
 
       for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
        {
-         if (!DECL_SIZE (fo->field) 
-             || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
-             || TREE_CODE (TREE_TYPE (fo->field)) == ARRAY_TYPE
+         if (!fo->size
+             || TREE_CODE (fo->size) != INTEGER_CST
              || fo->offset < 0)
            {
              notokay = true;
@@ -2588,8 +2632,8 @@ create_overlap_variables_for (tree var)
          HOST_WIDE_INT fosize;
          tree currfotype;
 
-         fosize = TREE_INT_CST_LOW (DECL_SIZE (fo->field));
-         currfotype = TREE_TYPE (fo->field);
+         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
@@ -2602,11 +2646,11 @@ create_overlap_variables_for (tree var)
                  && fosize == lastfosize
                  && currfotype == lastfotype))
            continue;
-         sv = ggc_alloc (sizeof (struct subvar));
+         sv = GGC_NEW (struct subvar);
          sv->offset = fo->offset;
          sv->size = fosize;
          sv->next = *subvars;
-         sv->var = create_sft (var, fo->field);
+         sv->var = create_sft (var, fo->type);
 
          if (dump_file)
            {
@@ -2651,19 +2695,19 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 {
   switch (TREE_CODE (*tp))
     {
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
     case COMPONENT_REF:
       {
        HOST_WIDE_INT bitsize;
+       HOST_WIDE_INT bitmaxsize;
        HOST_WIDE_INT bitpos;
-       tree offset;
-       enum machine_mode mode;
-       int unsignedp;
-       int volatilep;  
        tree ref;
-       ref = get_inner_reference (*tp, &bitsize, &bitpos, &offset, &mode,
-                                  &unsignedp, &volatilep, false);
-       if (DECL_P (ref) && offset == NULL && bitsize != -1)
-         {         
+       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;
 
@@ -2671,37 +2715,18 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 
            if (bitpos <= up->minused)
              up->minused = bitpos;
-           if ((bitpos + bitsize >= up->maxused))
-             up->maxused = bitpos + bitsize;       
+           if ((bitpos + bitmaxsize >= up->maxused))
+             up->maxused = bitpos + bitmaxsize;
 
-           up->explicit_uses = true;
+           if (bitsize == bitmaxsize)
+             up->explicit_uses = true;
+           else
+             up->implicit_uses = true;
            up_insert (uid, up);
 
            *walk_subtrees = 0;
            return NULL_TREE;
          }
-       else if (DECL_P (ref))
-         {
-           if (DECL_SIZE (ref)
-               && var_can_have_subvars (ref)
-               && TREE_CODE (DECL_SIZE (ref)) == INTEGER_CST)
-             {
-               used_part_t up;
-               size_t uid = DECL_UID (ref);
-
-               up = get_or_create_used_part_for (uid);
-
-               up->minused = 0;
-               up->maxused = TREE_INT_CST_LOW (DECL_SIZE (ref));
-
-               up->implicit_uses = true;
-
-               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
@@ -2735,6 +2760,7 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       break;
     case VAR_DECL:
     case PARM_DECL:
+    case RESULT_DECL:
       {
        tree var = *tp;
        if (DECL_SIZE (var)
@@ -2793,7 +2819,7 @@ create_structure_vars (void)
       if (var    
          && DECL_SIZE (var)
          && var_can_have_subvars (var)
-         && var_ann (var)->mem_tag_kind == NOT_A_TAG
+         && !MTAG_P (var)
          && TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
        create_overlap_variables_for (var);
     }