OSDN Git Service

* Makefile.in (tree-ssa-alias.o): Depend on tree-ssa-structalias.h
authordnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 Jul 2005 00:28:01 +0000 (00:28 +0000)
committerdnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 Jul 2005 00:28:01 +0000 (00:28 +0000)
* tree-cfg.c (CHECK_OP): Only test for is_gimple_val.
* tree-dfa.c (dump_subvars_for): New.
(debug_subvars_for): New.
(dump_variable): Show subvariables if VAR has them.
* tree-flow-inline.h (get_subvar_at): New.
(overlap_subvar): Change offset and size to unsigned HOST_WIDE_INT.
* tree-flow.h (struct ptr_info_def): Remove field pt_malloc.
Update all users.
(struct subvar): Change fields offset and size to unsigned
HOST_WIDE_INT.
(dump_subvars_for): Declare.
(debug_subvars_for): Declare.
(get_subvar_at): Declare.
(okay_component_ref_for_subvars): Change 2nd and 3rd argument
to unsigned HOST_WIDE_INT *.
(overlap_subvar): Likewise.
* tree-gimple.c (is_gimple_reg): Always return false for
SFTs and memory tags.
* tree-pass.h (pass_build_pta, pass_del_pta): Remove.
Update all callers.
* tree-ssa-alias.c: Include tree-ssa-structalias.h.
(compute_may_aliases): Call compute_points_to_sets.
(collect_points_to_info_for): Remove.
(compute_points_to_and_addr_escape): Remove.
(delete_alias_info): Call delete_points_to_sets.
(compute_flow_sensitive_aliasing): If the call to
find_what_p_points_to returns false, call set_pt_anything.
(add_may_alias): Set TREE_ADDRESSABLE when adding a new alias.
(set_pt_anything): Clear pi->pt_vars.
(set_pt_malloc): Remove.
(merge_pointed_to_info): Remove.
(add_pointed_to_expr): Remove.
(add_pointed_to_var): Remove.
(collect_points_to_info_r): Remove.
(is_escape_site): Make extern.
(create_sft): New.
(create_overlap_variables_for): Call it.
* tree-ssa-copy.c (merge_alias_info): Never merge
flow-sensitive alias information.
* tree-ssa-operands.c (get_expr_operands): Adjust variables
offset and size to be unsigned HOST_WIDE_INT.
(add_to_addressable_set): Rename from note_addressable.
Set TREE_ADDRESSABLE as the variables are added to the set.
Update all users.
(add_stmt_operand): Do not try to micro-optimize unmodifiable
operands into VUSEs when adding V_MAY_DEFs for members in an
alias set.
* tree-ssa-operands.h (add_to_addressable_set): Declare.
* tree-ssa-structalias.c: Include tree-ssa-structalias.h last.
(struct variable_info): Add bitfield is_heap_var.
(var_anyoffset, anyoffset_tree, anyoffset_id): Declare.
(new_var_info): Initialize is_heap_var.
(get_constraint_for): Add HEAP variables to the symbol table.
Mark them with is_heap_var.
(update_alias_info): New.  Taken mostly from the old
compute_points_to_and_addr_escape.
(handle_ptr_arith): New.
(find_func_aliases): Call update_alias_info.
Call handle_ptr_info for tcc_binary expressions.
Call mark_stmt_modified.
(create_variable_info_for): If DECL has subvars, do not create
variables for its subvars.  Always add all the fields.
(set_uids_in_ptset): If the solution includes ANYOFFSET and
SFTs, then add all the SFTs of the structure.
If VI->DECL is an aggregate with subvariables, add the SFT at
VI->OFFSET.
(find_what_p_points_to): If VI is an artificial variable,
translate to bitfields in SSA_NAME_PTR_INFO.
If the solution is empty, set pi->pt_vars to NULL
(init_base_vars): Create ANYOFFSET.
(compute_points_to_sets): Rename from create_alias_vars.
Make extern.
(pass_build_pta): Remove.
(delete_points_to_sets): Rename from delete_alias_vars.
(pass_del_pta): Remove.
* tree-ssa-structalias.h (struct alias_info): Move from
tree-ssa-alias.h.
(NUM_REFERENCES, NUM_REFERENCES_CLEAR, NUM_REFERENCES_INC,
NUM_REFERENCES_SET): Likewise.
(compute_points_to_sets, delete_points_to_sets): Declare.

testsuite/ChangeLog

* gcc.dg/tree-ssa/pta-fp.c: Use -fdump-tree-alias1.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101841 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pta-fp.c
gcc/tree-cfg.c
gcc/tree-dfa.c
gcc/tree-flow-inline.h
gcc/tree-flow.h
gcc/tree-gimple.c
gcc/tree-pass.h
gcc/tree-ssa-alias.c
gcc/tree-ssa-copy.c
gcc/tree-ssa-operands.c
gcc/tree-ssa-operands.h
gcc/tree-ssa-structalias.c
gcc/tree-ssa-structalias.h
gcc/tree-ssa.c

index f6a729a..2217625 100644 (file)
@@ -1,3 +1,87 @@
+2005-07-09  Diego Novillo  <dnovillo@redhat.com>
+
+       * Makefile.in (tree-ssa-alias.o): Depend on tree-ssa-structalias.h
+       * tree-cfg.c (CHECK_OP): Only test for is_gimple_val.
+       * tree-dfa.c (dump_subvars_for): New.
+       (debug_subvars_for): New.
+       (dump_variable): Show subvariables if VAR has them.
+       * tree-flow-inline.h (get_subvar_at): New.
+       (overlap_subvar): Change offset and size to unsigned HOST_WIDE_INT.
+       * tree-flow.h (struct ptr_info_def): Remove field pt_malloc.
+       Update all users.
+       (struct subvar): Change fields offset and size to unsigned
+       HOST_WIDE_INT.
+       (dump_subvars_for): Declare.
+       (debug_subvars_for): Declare.
+       (get_subvar_at): Declare.
+       (okay_component_ref_for_subvars): Change 2nd and 3rd argument
+       to unsigned HOST_WIDE_INT *.
+       (overlap_subvar): Likewise.
+       * tree-gimple.c (is_gimple_reg): Always return false for
+       SFTs and memory tags.
+       * tree-pass.h (pass_build_pta, pass_del_pta): Remove.
+       Update all callers.
+       * tree-ssa-alias.c: Include tree-ssa-structalias.h.
+       (compute_may_aliases): Call compute_points_to_sets.
+       (collect_points_to_info_for): Remove.
+       (compute_points_to_and_addr_escape): Remove.
+       (delete_alias_info): Call delete_points_to_sets.
+       (compute_flow_sensitive_aliasing): If the call to
+       find_what_p_points_to returns false, call set_pt_anything.
+       (add_may_alias): Set TREE_ADDRESSABLE when adding a new alias.
+       (set_pt_anything): Clear pi->pt_vars.
+       (set_pt_malloc): Remove.
+       (merge_pointed_to_info): Remove.
+       (add_pointed_to_expr): Remove.
+       (add_pointed_to_var): Remove.
+       (collect_points_to_info_r): Remove.
+       (is_escape_site): Make extern.
+       (create_sft): New.
+       (create_overlap_variables_for): Call it.
+       * tree-ssa-copy.c (merge_alias_info): Never merge
+       flow-sensitive alias information.
+       * tree-ssa-operands.c (get_expr_operands): Adjust variables
+       offset and size to be unsigned HOST_WIDE_INT.
+       (add_to_addressable_set): Rename from note_addressable.
+       Set TREE_ADDRESSABLE as the variables are added to the set.
+       Update all users.
+       (add_stmt_operand): Do not try to micro-optimize unmodifiable
+       operands into VUSEs when adding V_MAY_DEFs for members in an
+       alias set.
+       * tree-ssa-operands.h (add_to_addressable_set): Declare.
+       * tree-ssa-structalias.c: Include tree-ssa-structalias.h last.
+       (struct variable_info): Add bitfield is_heap_var.
+       (var_anyoffset, anyoffset_tree, anyoffset_id): Declare.
+       (new_var_info): Initialize is_heap_var.
+       (get_constraint_for): Add HEAP variables to the symbol table.
+       Mark them with is_heap_var.
+       (update_alias_info): New.  Taken mostly from the old
+       compute_points_to_and_addr_escape.
+       (handle_ptr_arith): New.
+       (find_func_aliases): Call update_alias_info.
+       Call handle_ptr_info for tcc_binary expressions.
+       Call mark_stmt_modified.
+       (create_variable_info_for): If DECL has subvars, do not create
+       variables for its subvars.  Always add all the fields.
+       (set_uids_in_ptset): If the solution includes ANYOFFSET and
+       SFTs, then add all the SFTs of the structure.
+       If VI->DECL is an aggregate with subvariables, add the SFT at
+       VI->OFFSET.
+       (find_what_p_points_to): If VI is an artificial variable,
+       translate to bitfields in SSA_NAME_PTR_INFO.
+       If the solution is empty, set pi->pt_vars to NULL
+       (init_base_vars): Create ANYOFFSET.
+       (compute_points_to_sets): Rename from create_alias_vars.
+       Make extern.
+       (pass_build_pta): Remove.
+       (delete_points_to_sets): Rename from delete_alias_vars.
+       (pass_del_pta): Remove.
+       * tree-ssa-structalias.h (struct alias_info): Move from
+       tree-ssa-alias.h.
+       (NUM_REFERENCES, NUM_REFERENCES_CLEAR, NUM_REFERENCES_INC,
+       NUM_REFERENCES_SET): Likewise.
+       (compute_points_to_sets, delete_points_to_sets): Declare.
+
 2005-07-09  Richard Henderson  <rth@redhat.com>
 
        * config/alpha/alpha.c (emit_insxl, alpha_expand_compare_and_swap_12,
index 244643c..1c70c7a 100644 (file)
@@ -1895,7 +1895,7 @@ tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) tree-inline.h $(FLAGS_H) \
    function.h $(TIMEVAR_H) convert.h $(TM_H) coretypes.h langhooks.h \
    $(TREE_DUMP_H) tree-pass.h $(PARAMS_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \
-   hard-reg-set.h $(TREE_GIMPLE_H) vec.h
+   hard-reg-set.h $(TREE_GIMPLE_H) vec.h tree-ssa-structalias.h
 tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TIMEVAR_H) \
    $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) tree-iterator.h\
index abc44e4..04c60a5 100644 (file)
@@ -471,10 +471,8 @@ init_optimization_passes (void)
   NEXT_PASS (pass_referenced_vars);
   NEXT_PASS (pass_create_structure_vars);
   NEXT_PASS (pass_build_ssa);
-  NEXT_PASS (pass_build_pta);
   NEXT_PASS (pass_may_alias);
   NEXT_PASS (pass_return_slot);
-  NEXT_PASS (pass_del_pta);
   NEXT_PASS (pass_rename_ssa_copies);
   NEXT_PASS (pass_early_warn_uninitialized);
 
@@ -490,9 +488,7 @@ init_optimization_passes (void)
   NEXT_PASS (pass_dominator);
 
   NEXT_PASS (pass_phiopt);
-  NEXT_PASS (pass_build_pta);
   NEXT_PASS (pass_may_alias);
-  NEXT_PASS (pass_del_pta);
   NEXT_PASS (pass_tail_recursion);
   NEXT_PASS (pass_profile);
   NEXT_PASS (pass_ch);
index 9a982a7..96d0a0b 100644 (file)
@@ -1,3 +1,7 @@
+2005-07-09  Diego Novillo  <dnovillo@redhat.com>
+
+       * gcc.dg/tree-ssa/pta-fp.c: Use -fdump-tree-alias1.
+
 2005-07-09  Richard Henderson  <rth@redhat.com>
 
        * lib/target-supports.exp (check_effective_target_sync_char_short):
index e835399..4cebcbb 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */ 
-/* { dg-options "-O2 -fdump-tree-pta1" } */
+/* { dg-options "-O2 -fdump-tree-alias1" } */
 extern double cos (double);
 extern double sin (double);
 double f(double a)
@@ -22,5 +22,5 @@ double f(double a)
 }
 /* The points-to set of the final function pointer should be "sin cos" */
 
-/* { dg-final { scan-tree-dump-times "sin cos" 1 "pta1"} } */
-/* { dg-final { cleanup-tree-dump "pta1" } } */
+/* { dg-final { scan-tree-dump-times "sin cos" 1 "alias1"} } */
+/* { dg-final { cleanup-tree-dump "alias1" } } */
index bfbf5a5..dd8ad08 100644 (file)
@@ -3083,12 +3083,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
   if (TYPE_P (t))
     *walk_subtrees = 0;
   
-  /* Check operand N for being valid GIMPLE and give error MSG if not. 
-     We check for constants explicitly since they are not considered
-     gimple invariants if they overflowed.  */
+  /* Check operand N for being valid GIMPLE and give error MSG if not.  */
 #define CHECK_OP(N, MSG) \
-  do { if (!CONSTANT_CLASS_P (TREE_OPERAND (t, N))             \
-         && !is_gimple_val (TREE_OPERAND (t, N)))              \
+  do { if (!is_gimple_val (TREE_OPERAND (t, N)))               \
        { error (MSG); return TREE_OPERAND (t, N); }} while (0)
 
   switch (TREE_CODE (t))
index 5cfbe1c..f065f5d 100644 (file)
@@ -254,6 +254,37 @@ debug_referenced_vars (void)
 }
 
 
+/* Dump sub-variables for VAR to FILE.  */
+
+void
+dump_subvars_for (FILE *file, tree var)
+{
+  subvar_t sv = get_subvars_for_var (var);
+
+  if (!sv)
+    return;
+
+  fprintf (file, "{ ");
+
+  for (; sv; sv = sv->next)
+    {
+      print_generic_expr (file, sv->var, dump_flags);
+      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
@@ -316,6 +347,12 @@ dump_variable (FILE *file, tree var)
       dump_may_aliases_for (file, var);
     }
 
+  if (get_subvars_for_var (var))
+    {
+      fprintf (file, ", sub-vars: ");
+      dump_subvars_for (file, var);
+    }
+
   fprintf (file, "\n");
 }
 
@@ -741,8 +778,8 @@ find_new_referenced_vars (tree *stmt_p)
    size, in bits, of REF inside the return value.  */
 
 tree
-okay_component_ref_for_subvars (tree ref, HOST_WIDE_INT *poffset,
-                               HOST_WIDE_INT *psize)
+okay_component_ref_for_subvars (tree ref, unsigned HOST_WIDE_INT *poffset,
+                               unsigned HOST_WIDE_INT *psize)
 {
   tree result = NULL;
   HOST_WIDE_INT bitsize;
index 13f94ac..4874c77 100644 (file)
@@ -1444,6 +1444,20 @@ get_subvars_for_var (tree 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;
+
+  for (sv = get_subvars_for_var (var); sv; sv = sv->next)
+    if (sv->offset == offset)
+      return sv->var;
+
+  return NULL_TREE;
+}
+
 /* Return true if V is a tree that we can have subvars for.
    Normally, this is any aggregate type, however, due to implementation
    limitations ATM, we exclude array types as well.  */
@@ -1461,7 +1475,7 @@ var_can_have_subvars (tree v)
    *EXACT will be set to true upon return. */
 
 static inline bool
-overlap_subvar (HOST_WIDE_INT offset, HOST_WIDE_INT size,
+overlap_subvar (unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size,
                subvar_t sv,  bool *exact)
 {
   /* There are three possible cases of overlap.
index 773a76f..c28de1c 100644 (file)
@@ -71,9 +71,6 @@ struct ptr_info_def GTY(())
      is pointing to.  */
   unsigned int pt_anything : 1;
 
-  /* Nonzero if this pointer is the result of a call to malloc.  */
-  unsigned int pt_malloc : 1;
-
   /* Nonzero if the value of this pointer escapes the current function.  */
   unsigned int value_escapes_p : 1;
 
@@ -160,19 +157,22 @@ enum mem_tag_kind {
   /* This variable represents a structure field.  */
   STRUCT_FIELD
 };
+
 struct subvar;
 typedef struct subvar *subvar_t;
 
 /* This structure represents a fake sub-variable for a structure field.  */
-
 struct subvar GTY(())
 {
-  /* Fake variable name */
+  /* Fake variable */
   tree var;
+
   /* Offset inside structure.  */
-  HOST_WIDE_INT offset;
-  /* Size of field.  */
-  HOST_WIDE_INT size;
+  unsigned HOST_WIDE_INT offset;
+
+  /* Size of the field.  */
+  unsigned HOST_WIDE_INT size;
+
   /* Next subvar for this structure.  */
   subvar_t next;
 };
@@ -552,6 +552,8 @@ extern void debug_referenced_vars (void);
 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_tmp_var (tree);
 extern void mark_new_vars_to_rename (tree);
@@ -578,11 +580,13 @@ extern void add_type_alias (tree, tree);
 extern void new_type_alias (tree, tree);
 extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *, bool *);
 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 (tree);
-extern tree okay_component_ref_for_subvars (tree, HOST_WIDE_INT *,
-                                           HOST_WIDE_INT *);
+extern tree okay_component_ref_for_subvars (tree, unsigned HOST_WIDE_INT *,
+                                           unsigned HOST_WIDE_INT *);
 static inline bool var_can_have_subvars (tree);
-static inline bool overlap_subvar (HOST_WIDE_INT, HOST_WIDE_INT,
+static inline bool overlap_subvar (unsigned HOST_WIDE_INT,
+                                  unsigned HOST_WIDE_INT,
                                   subvar_t, bool *);
 
 /* Call-back function for walk_use_def_chains().  At each reaching
index 2a62aeb..284f577 100644 (file)
@@ -268,6 +268,8 @@ is_gimple_reg_type (tree type)
 bool
 is_gimple_reg (tree t)
 {
+  var_ann_t ann;
+
   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
 
@@ -305,9 +307,16 @@ is_gimple_reg (tree t)
   if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
     return DECL_COMPLEX_GIMPLE_REG_P (t);
 
+  /* Some compiler temporaries are created to be used exclusively in
+     virtual operands (currently memory tags and sub-variables).
+     These variables should never be considered GIMPLE registers.  */
+  if (DECL_ARTIFICIAL (t) && (ann = var_ann (t)) != NULL)
+    return ann->mem_tag_kind == NOT_A_TAG;
+
   return true;
 }
 
+
 /* Returns true if T is a GIMPLE formal temporary variable.  */
 
 bool
index 80f4a05..d420b1b 100644 (file)
@@ -276,8 +276,6 @@ extern struct tree_opt_pass pass_store_ccp;
 extern struct tree_opt_pass pass_store_copy_prop;
 extern struct tree_opt_pass pass_vrp;
 extern struct tree_opt_pass pass_create_structure_vars;
-extern struct tree_opt_pass pass_build_pta;
-extern struct tree_opt_pass pass_del_pta;
 extern struct tree_opt_pass pass_uncprop;
 extern struct tree_opt_pass pass_return_slot;
 extern struct tree_opt_pass pass_reassoc;
index 39d9fde..f55e2d2 100644 (file)
@@ -40,19 +40,12 @@ Boston, MA 02110-1301, USA.  */
 #include "tree-flow.h"
 #include "tree-inline.h"
 #include "tree-pass.h"
+#include "tree-ssa-structalias.h"
 #include "convert.h"
 #include "params.h"
 #include "vec.h"
 #include "bitmap.h"
 
-/* Keep track of how many times each pointer has been dereferenced in
-   the program using the aux variable.  This is used by the alias
-   grouping heuristic in compute_flow_insensitive_aliasing.  */
-#define NUM_REFERENCES(ANN) ((size_t)((ANN)->common.aux))
-#define NUM_REFERENCES_CLEAR(ANN) ((ANN)->common.aux) = 0
-#define NUM_REFERENCES_INC(ANN) (ANN)->common.aux = (void*) (((size_t)((ANN)->common.aux)) + 1)
-#define NUM_REFERENCES_SET(ANN, VAL) (ANN)->common.aux = (void*) ((void *)(VAL))
-
 /* Obstack used to hold grouping bitmaps and other temporary bitmaps used by
    aliasing  */
 static bitmap_obstack alias_obstack;
@@ -83,51 +76,6 @@ struct alias_map_d
 };
 
 
-/* Alias information used by compute_may_aliases and its helpers.  */
-struct alias_info
-{
-  /* SSA names visited while collecting points-to information.  If bit I
-     is set, it means that SSA variable with version I has already been
-     visited.  */
-  sbitmap ssa_names_visited;
-
-  /* Array of SSA_NAME pointers processed by the points-to collector.  */
-  varray_type processed_ptrs;
-
-  /* Variables whose address is still needed.  */
-  bitmap addresses_needed;
-
-  /* ADDRESSABLE_VARS contains all the global variables and locals that
-     have had their address taken.  */
-  struct alias_map_d **addressable_vars;
-  size_t num_addressable_vars;
-
-  /* POINTERS contains all the _DECL pointers with unique memory tags
-     that have been referenced in the program.  */
-  struct alias_map_d **pointers;
-  size_t num_pointers;
-
-  /* Number of function calls found in the program.  */
-  size_t num_calls_found;
-
-  /* Number of const/pure function calls found in the program.  */
-  size_t num_pure_const_calls_found;
-
-  /* Total number of virtual operands that will be needed to represent
-     all the aliases of all the pointers found in the program.  */
-  long total_alias_vops;
-
-  /* Variables that have been written to.  */
-  bitmap written_vars;
-
-  /* Pointers that have been used in an indirect store operation.  */
-  bitmap dereferenced_ptrs_store;
-
-  /* Pointers that have been used in an indirect load operation.  */
-  bitmap dereferenced_ptrs_load;
-};
-
-
 /* Counters used to display statistics on alias analysis.  */
 struct alias_stats_d
 {
@@ -155,18 +103,12 @@ static void add_may_alias (tree, tree);
 static void replace_may_alias (tree, size_t, tree);
 static struct alias_info *init_alias_info (void);
 static void delete_alias_info (struct alias_info *);
-static void compute_points_to_and_addr_escape (struct alias_info *);
 static void compute_flow_sensitive_aliasing (struct alias_info *);
 static void setup_pointers_and_addressables (struct alias_info *);
-static bool collect_points_to_info_r (tree, tree, void *);
-static bool is_escape_site (tree, struct alias_info *);
-static void add_pointed_to_var (struct alias_info *, tree, tree);
 static void create_global_var (void);
-static void collect_points_to_info_for (struct alias_info *, tree);
 static void maybe_create_global_var (struct alias_info *ai);
 static void group_aliases (struct alias_info *);
 static void set_pt_anything (tree ptr);
-static void set_pt_malloc (tree ptr);
 
 /* Global declarations.  */
 
@@ -315,7 +257,7 @@ compute_may_aliases (void)
      address of V escapes the current function, making V call-clobbered
      (i.e., whether &V is stored in a global variable or if its passed as a
      function call argument).  */
-  compute_points_to_and_addr_escape (ai);
+  compute_points_to_sets (ai);
 
   /* Collect all pointers and addressable variables, compute alias sets,
      create memory tags for pointers and promote variables whose address is
@@ -506,7 +448,6 @@ init_alias_info (void)
   ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
   sbitmap_zero (ai->ssa_names_visited);
   VARRAY_TREE_INIT (ai->processed_ptrs, 50, "processed_ptrs");
-  ai->addresses_needed = BITMAP_ALLOC (&alias_obstack);
   ai->written_vars = BITMAP_ALLOC (&alias_obstack);
   ai->dereferenced_ptrs_store = BITMAP_ALLOC (&alias_obstack);
   ai->dereferenced_ptrs_load = BITMAP_ALLOC (&alias_obstack);
@@ -564,7 +505,6 @@ init_alias_info (void)
                 superset of its former points-to set, then a new
                 tag will need to be created in create_name_tags.  */
              pi->pt_anything = 0;
-             pi->pt_malloc = 0;
              pi->pt_null = 0;
              pi->value_escapes_p = 0;
              pi->is_dereferenced = 0;
@@ -592,7 +532,6 @@ delete_alias_info (struct alias_info *ai)
 
   sbitmap_free (ai->ssa_names_visited);
   ai->processed_ptrs = NULL;
-  BITMAP_FREE (ai->addresses_needed);
 
   for (i = 0; i < ai->num_addressable_vars; i++)
     free (ai->addressable_vars[i]);
@@ -613,171 +552,9 @@ delete_alias_info (struct alias_info *ai)
   BITMAP_FREE (ai->dereferenced_ptrs_store);
   BITMAP_FREE (ai->dereferenced_ptrs_load);
   bitmap_obstack_release (&alias_obstack);
-
   free (ai);
-}
 
-
-/* Walk use-def chains for pointer PTR to determine what variables is PTR
-   pointing to.  */
-
-static void
-collect_points_to_info_for (struct alias_info *ai, tree ptr)
-{
-  gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
-
-  if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (ptr)))
-    {
-      SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (ptr));
-      walk_use_def_chains (ptr, collect_points_to_info_r, ai, true);
-      VARRAY_PUSH_TREE (ai->processed_ptrs, ptr);
-    }
-}
-
-/* Traverse use-def links for all the pointers in the program to collect
-   address escape and points-to information.
-   
-   This is loosely based on the same idea described in R. Hasti and S.
-   Horwitz, ``Using static single assignment form to improve
-   flow-insensitive pointer analysis,'' in SIGPLAN Conference on
-   Programming Language Design and Implementation, pp. 97-105, 1998.  */
-
-static void
-compute_points_to_and_addr_escape (struct alias_info *ai)
-{
-  basic_block bb;
-  unsigned i;
-  tree op;
-  ssa_op_iter iter;
-
-  timevar_push (TV_TREE_PTA);
-
-  FOR_EACH_BB (bb)
-    {
-      block_stmt_iterator si;
-
-      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
-       {
-         bitmap addr_taken;
-         tree stmt = bsi_stmt (si);
-         bool stmt_escapes_p = is_escape_site (stmt, ai);
-         bitmap_iterator bi;
-
-         /* Mark all the variables whose address are taken by the
-            statement.  Note that this will miss all the addresses taken
-            in PHI nodes (those are discovered while following the use-def
-            chains).  */
-         addr_taken = addresses_taken (stmt);
-         if (addr_taken)
-           EXECUTE_IF_SET_IN_BITMAP (addr_taken, 0, i, bi) 
-             {
-               tree var = referenced_var (i);
-               bitmap_set_bit (ai->addresses_needed, DECL_UID (var));
-               if (stmt_escapes_p)
-                 mark_call_clobbered (var);
-             }
-
-         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
-           {
-             tree var = SSA_NAME_VAR (op);
-             var_ann_t v_ann = var_ann (var);
-             struct ptr_info_def *pi;
-             bool is_store;
-             unsigned num_uses, num_derefs;
-
-             /* If the operand's variable may be aliased, keep track
-                of how many times we've referenced it.  This is used
-                for alias grouping in compute_flow_sensitive_aliasing.
-                Note that we don't need to grow AI->NUM_REFERENCES
-                because we are processing regular variables, not
-                memory tags (the array's initial size is set to
-                NUM_REFERENCED_VARS).  */
-             if (may_be_aliased (var))
-               NUM_REFERENCES_INC (v_ann);
-
-             if (!POINTER_TYPE_P (TREE_TYPE (op)))
-               continue;
-
-             collect_points_to_info_for (ai, op);
-
-             pi = SSA_NAME_PTR_INFO (op);
-             count_uses_and_derefs (op, stmt, &num_uses, &num_derefs,
-                                    &is_store);
-
-             if (num_derefs > 0)
-               {
-                 /* Mark OP as dereferenced.  In a subsequent pass,
-                    dereferenced pointers that point to a set of
-                    variables will be assigned a name tag to alias
-                    all the variables OP points to.  */
-                 pi->is_dereferenced = 1;
-
-                 /* Keep track of how many time we've dereferenced each
-                    pointer.  */
-                 NUM_REFERENCES_INC (v_ann);
-
-                 /* If this is a store operation, mark OP as being
-                    dereferenced to store, otherwise mark it as being
-                    dereferenced to load.  */
-                 if (is_store)
-                   bitmap_set_bit (ai->dereferenced_ptrs_store, 
-                                   DECL_UID (var));
-                 else
-                   bitmap_set_bit (ai->dereferenced_ptrs_load, 
-                                   DECL_UID (var));
-               }
-
-             if (stmt_escapes_p && num_derefs < num_uses)
-               {
-                 /* If STMT is an escape point and STMT contains at
-                    least one direct use of OP, then the value of OP
-                    escapes and so the pointed-to variables need to
-                    be marked call-clobbered.  */
-                 pi->value_escapes_p = 1;
-
-                 /* If the statement makes a function call, assume
-                    that pointer OP will be dereferenced in a store
-                    operation inside the called function.  */
-                 if (get_call_expr_in (stmt))
-                   {
-                     bitmap_set_bit (ai->dereferenced_ptrs_store, 
-                                     DECL_UID (var));
-                     pi->is_dereferenced = 1;
-                   }
-               }
-           }
-
-         /* Update reference counter for definitions to any
-            potentially aliased variable.  This is used in the alias
-            grouping heuristics.  */
-         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
-           {
-             tree var = SSA_NAME_VAR (op);
-             var_ann_t ann = var_ann (var);
-             bitmap_set_bit (ai->written_vars, DECL_UID (var));
-             if (may_be_aliased (var))
-               NUM_REFERENCES_INC (ann);
-
-             if (POINTER_TYPE_P (TREE_TYPE (op)))
-               collect_points_to_info_for (ai, op);
-           }
-
-         /* Mark variables in V_MAY_DEF operands as being written to.  */
-         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_DEFS)
-           {
-             tree var = DECL_P (op) ? op : SSA_NAME_VAR (op);
-             bitmap_set_bit (ai->written_vars, DECL_UID (var));
-           }
-           
-         /* After promoting variables and computing aliasing we will
-            need to re-scan most statements.  FIXME: Try to minimize the
-            number of statements re-scanned.  It's not really necessary to
-            re-scan *all* statements.  */
-         mark_stmt_modified (stmt);
-       }
-    }
-
-  timevar_pop (TV_TREE_PTA);
+  delete_points_to_sets ();
 }
 
 
@@ -863,16 +640,10 @@ create_name_tags (void)
          if (old_name_tag && old_name_tag != pi->name_mem_tag)
            mark_sym_for_renaming (old_name_tag);
        }
-      else if (pi->pt_malloc)
-       {
-         /* Otherwise, create a unique name tag for this pointer.  */
-         pi->name_mem_tag = get_nmt_for (ptr);
-       }
       else
        {
-         /* Only pointers that may point to malloc or other variables
-            may receive a name tag.  If the pointer does not point to
-            a known spot, we should use type tags.  */
+         /* If the pointer does not point to a known spot, we should
+            use type tags.  */
          set_pt_anything (ptr);
          continue;
        }
@@ -902,11 +673,8 @@ compute_flow_sensitive_aliasing (struct alias_info *ai)
   for (i = 0; i < VARRAY_ACTIVE_SIZE (ai->processed_ptrs); i++)
     {
       tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
-      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
-      if (pi->pt_anything || pi->pt_vars == NULL)
-       {
-         find_what_p_points_to (ptr);
-       }
+      if (!find_what_p_points_to (ptr))
+       set_pt_anything (ptr);
     }
 
   create_name_tags ();
@@ -931,9 +699,7 @@ compute_flow_sensitive_aliasing (struct alias_info *ai)
 
          if (pi->pt_vars)
            EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi)
-             {
-               mark_call_clobbered (referenced_var (j));
-             }
+             mark_call_clobbered (referenced_var (j));
        }
 
       /* Set up aliasing information for PTR's name memory tag (if it has
@@ -1009,9 +775,9 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
             So we first check the call_clobbered status of the
             tag and variable before querying the bitmap.  */
          tag_stored_p = is_call_clobbered (tag)
-           || bitmap_bit_p (ai->written_vars, DECL_UID (tag));
+                        || bitmap_bit_p (ai->written_vars, DECL_UID (tag));
          var_stored_p = is_call_clobbered (var)
-           || bitmap_bit_p (ai->written_vars, DECL_UID (var));
+                        || bitmap_bit_p (ai->written_vars, DECL_UID (var));
          if (!tag_stored_p && !var_stored_p)
            continue;
 
@@ -1126,7 +892,7 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
     }
   
   if (dump_file)
-    fprintf (dump_file, "%s: Total number of aliased vops: %ld\n",
+    fprintf (dump_file, "\n%s: Total number of aliased vops: %ld\n",
             get_name (current_function_decl),
             ai->total_alias_vops);
 
@@ -1458,9 +1224,9 @@ setup_pointers_and_addressables (struct alias_info *ai)
          of ADDR_EXPR constants into INDIRECT_REF expressions and the
          removal of dead pointer assignments done by the early scalar
          cleanup passes.  */
-      if (TREE_ADDRESSABLE (var) && v_ann->mem_tag_kind != STRUCT_FIELD)
+      if (TREE_ADDRESSABLE (var))
        {
-         if (!bitmap_bit_p (ai->addresses_needed, DECL_UID (var))
+         if (!bitmap_bit_p (addressable_vars, DECL_UID (var))
              && TREE_CODE (var) != RESULT_DECL
              && !is_global_var (var))
            {
@@ -1470,6 +1236,9 @@ setup_pointers_and_addressables (struct alias_info *ai)
                 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)))
                {
@@ -1477,8 +1246,7 @@ setup_pointers_and_addressables (struct alias_info *ai)
 
                  for (sv = svars; sv; sv = sv->next)
                    {         
-                     if (bitmap_bit_p (ai->addresses_needed, 
-                                       DECL_UID (sv->var)))
+                     if (bitmap_bit_p (addressable_vars, DECL_UID (sv->var)))
                        okay_to_mark = false;
                      mark_sym_for_renaming (sv->var);
                    }
@@ -1490,22 +1258,6 @@ setup_pointers_and_addressables (struct alias_info *ai)
              if (okay_to_mark)
                mark_non_addressable (var);
            }
-         else
-           {
-             /* Add the variable to the set of addressables.  Mostly
-                used when scanning operands for ASM_EXPRs that
-                clobber memory.  In those cases, we need to clobber
-                all call-clobbered variables and all addressables.  */
-             bitmap_set_bit (addressable_vars, DECL_UID (var));
-             if (var_can_have_subvars (var)
-                 && (svars = get_subvars_for_var (var)))
-               {
-                 subvar_t sv;
-                 for (sv = svars; sv; sv = sv->next)
-                   bitmap_set_bit (addressable_vars, DECL_UID (sv->var));
-               }
-
-           }
        }
 
       /* Global variables and addressable locals may be aliased.  Create an
@@ -1562,10 +1314,9 @@ setup_pointers_and_addressables (struct alias_info *ai)
                 references of TAG.  Since TAG can be associated with
                 several pointers, add the dereferences of VAR to the
                 TAG.  */
-
              NUM_REFERENCES_SET (t_ann, 
-                                 NUM_REFERENCES (t_ann) + 
-                                 NUM_REFERENCES (v_ann));
+                                 NUM_REFERENCES (t_ann)
+                                 NUM_REFERENCES (v_ann));
            }
          else
            {
@@ -1783,8 +1534,16 @@ add_may_alias (tree var, tree alias)
   var_ann_t v_ann = get_var_ann (var);
   var_ann_t a_ann = get_var_ann (alias);
 
+  /* Don't allow self-referential aliases.  */
   gcc_assert (var != alias);
 
+  /* ALIAS must be addressable if it's being added to an alias set.  */
+#if 1
+  TREE_ADDRESSABLE (alias) = 1;
+#else
+  gcc_assert (may_be_aliased (alias));
+#endif
+
   if (v_ann->may_aliases == NULL)
     VARRAY_TREE_INIT (v_ann->may_aliases, 2, "aliases");
 
@@ -1836,7 +1595,7 @@ set_pt_anything (tree ptr)
   struct ptr_info_def *pi = get_ptr_info (ptr);
 
   pi->pt_anything = 1;
-  pi->pt_malloc = 0;
+  pi->pt_vars = NULL;
 
   /* The pointer used to have a name tag, but we now found it pointing
      to an arbitrary location.  The name tag needs to be renamed and
@@ -1849,341 +1608,6 @@ set_pt_anything (tree ptr)
 }
 
 
-/* Mark pointer PTR as pointing to a malloc'd memory area.  */
-
-static void
-set_pt_malloc (tree ptr)
-{
-  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
-
-  /* If the pointer has already been found to point to arbitrary
-     memory locations, it is unsafe to mark it as pointing to malloc.  */
-  if (pi->pt_anything)
-    return;
-
-  pi->pt_malloc = 1;
-}
-
-
-/* Given two different pointers DEST and ORIG.  Merge the points-to
-   information in ORIG into DEST.  AI contains all the alias
-   information collected up to this point.  */
-
-static void
-merge_pointed_to_info (struct alias_info *ai, tree dest, tree orig)
-{
-  struct ptr_info_def *dest_pi, *orig_pi;
-
-  gcc_assert (dest != orig);
-
-  /* Make sure we have points-to information for ORIG.  */
-  collect_points_to_info_for (ai, orig);
-
-  dest_pi = get_ptr_info (dest);
-  orig_pi = SSA_NAME_PTR_INFO (orig);
-
-  if (orig_pi)
-    {
-      gcc_assert (orig_pi != dest_pi);
-
-      /* Notice that we never merge PT_MALLOC.  This attribute is only
-        true if the pointer is the result of a malloc() call.
-        Otherwise, we can end up in this situation:
-
-        P_i = malloc ();
-        ...
-        P_j = P_i + X;
-
-        P_j would be marked as PT_MALLOC, however we currently do not
-        handle cases of more than one pointer pointing to the same
-        malloc'd area.
-
-        FIXME: If the merging comes from an expression that preserves
-        the PT_MALLOC attribute (copy assignment, address
-        arithmetic), we ought to merge PT_MALLOC, but then both
-        pointers would end up getting different name tags because
-        create_name_tags is not smart enough to determine that the
-        two come from the same malloc call.  Copy propagation before
-        aliasing should cure this.  */
-      dest_pi->pt_malloc = 0;
-      if (orig_pi->pt_malloc || orig_pi->pt_anything)
-       set_pt_anything (dest);
-
-      dest_pi->pt_null |= orig_pi->pt_null;
-
-      if (!dest_pi->pt_anything
-         && orig_pi->pt_vars
-         && !bitmap_empty_p (orig_pi->pt_vars))
-       {
-         if (dest_pi->pt_vars == NULL)
-           {
-             dest_pi->pt_vars = BITMAP_GGC_ALLOC ();
-             bitmap_copy (dest_pi->pt_vars, orig_pi->pt_vars);
-           }
-         else
-           bitmap_ior_into (dest_pi->pt_vars, orig_pi->pt_vars);
-       }
-    }
-  else
-    set_pt_anything (dest);
-}
-
-
-/* Add EXPR to the list of expressions pointed-to by PTR.  */
-
-static void
-add_pointed_to_expr (struct alias_info *ai, tree ptr, tree expr)
-{
-  if (TREE_CODE (expr) == WITH_SIZE_EXPR)
-    expr = TREE_OPERAND (expr, 0);
-
-  get_ptr_info (ptr);
-
-  if (TREE_CODE (expr) == CALL_EXPR
-      && (call_expr_flags (expr) & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
-    {
-      /* If EXPR is a malloc-like call, then the area pointed to PTR
-        is guaranteed to not alias with anything else.  */
-      set_pt_malloc (ptr);
-    }
-  else if (TREE_CODE (expr) == ADDR_EXPR)
-    {
-      /* Found P_i = ADDR_EXPR  */
-      add_pointed_to_var (ai, ptr, expr);
-    }
-  else if (TREE_CODE (expr) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (expr)))
-    {
-      /* Found P_i = Q_j.  */
-      merge_pointed_to_info (ai, ptr, expr);
-    }
-  else if (TREE_CODE (expr) == PLUS_EXPR || TREE_CODE (expr) == MINUS_EXPR)
-    {
-      /* Found P_i = PLUS_EXPR or P_i = MINUS_EXPR  */
-      tree op0 = TREE_OPERAND (expr, 0);
-      tree op1 = TREE_OPERAND (expr, 1);
-
-      /* Both operands may be of pointer type.  FIXME: Shouldn't
-        we just expect PTR + OFFSET always?  */
-      if (POINTER_TYPE_P (TREE_TYPE (op0))
-         && TREE_CODE (op0) != INTEGER_CST)
-       {
-         if (TREE_CODE (op0) == SSA_NAME)
-           merge_pointed_to_info (ai, ptr, op0);
-         else if (TREE_CODE (op0) == ADDR_EXPR)
-           add_pointed_to_var (ai, ptr, op0);
-         else
-           set_pt_anything (ptr);
-       }
-
-      if (POINTER_TYPE_P (TREE_TYPE (op1))
-         && TREE_CODE (op1) != INTEGER_CST)
-       {
-         if (TREE_CODE (op1) == SSA_NAME)
-           merge_pointed_to_info (ai, ptr, op1);
-         else if (TREE_CODE (op1) == ADDR_EXPR)
-           add_pointed_to_var (ai, ptr, op1);
-         else
-           set_pt_anything (ptr);
-       }
-
-      /* Neither operand is a pointer?  VAR can be pointing anywhere.
-        FIXME: Shouldn't we asserting here?  If we get here, we found
-        PTR = INT_CST + INT_CST, which should not be a valid pointer
-        expression.  */
-      if (!(POINTER_TYPE_P (TREE_TYPE (op0))
-           && TREE_CODE (op0) != INTEGER_CST)
-         && !(POINTER_TYPE_P (TREE_TYPE (op1))
-              && TREE_CODE (op1) != INTEGER_CST))
-       set_pt_anything (ptr);
-    }
-  else if (integer_zerop (expr))
-    {
-      /* EXPR is the NULL pointer.  Mark PTR as pointing to NULL.  */
-      SSA_NAME_PTR_INFO (ptr)->pt_null = 1;
-    }
-  else
-    {
-      /* If we can't recognize the expression, assume that PTR may
-        point anywhere.  */
-      set_pt_anything (ptr);
-    }
-}
-
-
-/* If VALUE is of the form &DECL, add DECL to the set of variables
-   pointed-to by PTR.  Otherwise, add VALUE as a pointed-to expression by
-   PTR.  AI points to the collected alias information.  */
-
-static void
-add_pointed_to_var (struct alias_info *ai, tree ptr, tree value)
-{
-  struct ptr_info_def *pi = get_ptr_info (ptr);
-  tree pt_var = NULL_TREE;
-  HOST_WIDE_INT offset, size;
-  tree addrop;
-  size_t uid;
-  tree ref;
-  subvar_t svars;
-
-  gcc_assert (TREE_CODE (value) == ADDR_EXPR);
-
-  addrop = TREE_OPERAND (value, 0);
-  if (REFERENCE_CLASS_P (addrop))
-    pt_var = get_base_address (addrop);
-  else 
-    pt_var = addrop;
-
-  /* If this is a component_ref, see if we can get a smaller number of
-     variables to take the address of.  */
-  if (TREE_CODE (addrop) == COMPONENT_REF
-      && (ref = okay_component_ref_for_subvars (addrop, &offset ,&size)))
-    {    
-      subvar_t sv;
-      svars = get_subvars_for_var (ref);
-
-      uid = DECL_UID (pt_var);
-      
-      if (pi->pt_vars == NULL)
-       pi->pt_vars = BITMAP_GGC_ALLOC ();
-       /* If the variable is a global, mark the pointer as pointing to
-        global memory (which will make its tag a global variable).  */
-      if (is_global_var (pt_var))
-       pi->pt_global_mem = 1;     
-
-      for (sv = svars; sv; sv = sv->next)
-       {
-         if (overlap_subvar (offset, size, sv, NULL))
-           {
-             bitmap_set_bit (pi->pt_vars, DECL_UID (sv->var));
-             bitmap_set_bit (ai->addresses_needed, DECL_UID (sv->var));
-           }
-       }
-    }
-  else if (pt_var && SSA_VAR_P (pt_var))
-    {
-    
-      uid = DECL_UID (pt_var);
-      
-      if (pi->pt_vars == NULL)
-       pi->pt_vars = BITMAP_GGC_ALLOC ();
-
-      /* If this is an aggregate, we may have subvariables for it that need
-        to be pointed to.  */
-      if (var_can_have_subvars (pt_var)
-         && (svars = get_subvars_for_var (pt_var)))
-       {
-         subvar_t sv;
-         for (sv = svars; sv; sv = sv->next)
-           {
-             uid = DECL_UID (sv->var);
-             bitmap_set_bit (ai->addresses_needed, uid);             
-             bitmap_set_bit (pi->pt_vars, uid);
-           }
-       }
-      else     
-       {
-         bitmap_set_bit (ai->addresses_needed, uid);
-         bitmap_set_bit (pi->pt_vars, uid);      
-       }
-
-      /* If the variable is a global, mark the pointer as pointing to
-        global memory (which will make its tag a global variable).  */
-      if (is_global_var (pt_var))
-       pi->pt_global_mem = 1;
-    }
-}
-
-
-/* Callback for walk_use_def_chains to gather points-to information from the
-   SSA web.
-   
-   VAR is an SSA variable or a GIMPLE expression.
-   
-   STMT is the statement that generates the SSA variable or, if STMT is a
-      PHI_NODE, VAR is one of the PHI arguments.
-
-   DATA is a pointer to a structure of type ALIAS_INFO.  */
-
-static bool
-collect_points_to_info_r (tree var, tree stmt, void *data)
-{
-  struct alias_info *ai = (struct alias_info *) data;
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "Visiting use-def links for ");
-      print_generic_expr (dump_file, var, dump_flags);
-      fprintf (dump_file, "\n");
-    }
-
-  switch (TREE_CODE (stmt))
-    {
-    case RETURN_EXPR:
-      gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR);
-      stmt = TREE_OPERAND (stmt, 0);
-      /* FALLTHRU  */
-
-    case MODIFY_EXPR:
-      {
-       tree rhs = TREE_OPERAND (stmt, 1);
-       STRIP_NOPS (rhs);
-       add_pointed_to_expr (ai, var, rhs);
-       break;
-      }
-
-    case ASM_EXPR:
-      /* Pointers defined by __asm__ statements can point anywhere.  */
-      set_pt_anything (var);
-      break;
-
-    case NOP_EXPR:
-      if (IS_EMPTY_STMT (stmt))
-       {
-         tree decl = SSA_NAME_VAR (var);
-         
-         if (TREE_CODE (decl) == PARM_DECL)
-           add_pointed_to_expr (ai, var, decl);
-         else if (DECL_INITIAL (decl))
-           add_pointed_to_expr (ai, var, DECL_INITIAL (decl));
-         else
-           add_pointed_to_expr (ai, var, decl);
-       }
-      break;
-
-    case PHI_NODE:
-      {
-        /* It STMT is a PHI node, then VAR is one of its arguments.  The
-          variable that we are analyzing is the LHS of the PHI node.  */
-       tree lhs = PHI_RESULT (stmt);
-
-       switch (TREE_CODE (var))
-         {
-         case ADDR_EXPR:
-           add_pointed_to_var (ai, lhs, var);
-           break;
-           
-         case SSA_NAME:
-           /* Avoid unnecessary merges.  */
-           if (lhs != var)
-             merge_pointed_to_info (ai, lhs, var);
-           break;
-           
-         default:
-           gcc_assert (is_gimple_min_invariant (var));
-           add_pointed_to_expr (ai, lhs, var);
-           break;
-         }
-       break;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-  
-  return false;
-}
-
-
 /* Return true if STMT is an "escape" site from the current function.  Escape
    sites those statements which might expose the address of a variable
    outside the current function.  STMT is an escape site iff:
@@ -2195,7 +1619,7 @@ collect_points_to_info_r (tree var, tree stmt, void *data)
 
    AI points to the alias information collected so far.  */
 
-static bool
+bool
 is_escape_site (tree stmt, struct alias_info *ai)
 {
   tree call = get_call_expr_in (stmt);
@@ -2271,9 +1695,7 @@ create_memory_tag (tree type, bool is_type_tag)
      determine whether they should be considered globals.  */
   DECL_CONTEXT (tag) = current_function_decl;
 
-  /* Memory tags are by definition addressable.  This also prevents
-     is_gimple_ref frome confusing memory tags with optimizable
-     variables.  */
+  /* Memory tags are by definition addressable.  */
   TREE_ADDRESSABLE (tag) = 1;
 
   ann = get_var_ann (tag);
@@ -2304,7 +1726,6 @@ get_nmt_for (tree ptr)
   /* If PTR is a PARM_DECL, it points to a global variable or malloc,
      then its name tag should be considered a global variable.  */
   if (TREE_CODE (SSA_NAME_VAR (ptr)) == PARM_DECL
-      || pi->pt_malloc
       || pi->pt_global_mem)
     mark_call_clobbered (tag);
 
@@ -2560,9 +1981,6 @@ dump_points_to_info_for (FILE *file, tree ptr)
       if (pi->pt_anything)
        fprintf (file, ", points-to anything");
 
-      if (pi->pt_malloc)
-       fprintf (file, ", points-to malloc");
-
       if (pi->pt_null)
        fprintf (file, ", points-to NULL");
 
@@ -2978,6 +2396,33 @@ get_or_create_used_part_for (size_t uid)
 }
 
 
+/* Create and return a structure sub-variable for field 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");
+
+  /* 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);
+  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);
+
+  return subvar;
+}
+
+
 /* Given an aggregate VAR, create the subvariables that represent its
    fields.  */
 
@@ -3067,7 +2512,6 @@ create_overlap_variables_for (tree var)
        {
          subvar_t sv;
          HOST_WIDE_INT fosize;
-         var_ann_t ann;
          tree currfotype;
 
          fosize = TREE_INT_CST_LOW (DECL_SIZE (fo->field));
@@ -3088,7 +2532,8 @@ create_overlap_variables_for (tree var)
          sv->offset = fo->offset;
          sv->size = fosize;
          sv->next = *subvars;
-         sv->var = create_tmp_var_raw (TREE_TYPE (fo->field), "SFT");
+         sv->var = create_sft (var, fo->field);
+
          if (dump_file)
            {
              fprintf (dump_file, "structure field tag %s created for var %s",
@@ -3100,25 +2545,6 @@ create_overlap_variables_for (tree var)
              fprintf (dump_file, "\n");
            }
          
-         /* We need to copy the various flags from var to sv->var, so that
-            they are is_global_var iff the original variable was.  */
-
-         DECL_EXTERNAL (sv->var) = DECL_EXTERNAL (var);
-         TREE_PUBLIC  (sv->var) = TREE_PUBLIC (var);
-         TREE_STATIC (sv->var) = TREE_STATIC (var);
-         TREE_READONLY (sv->var) = TREE_READONLY (var);
-
-         /* Like other memory tags, these need to be marked addressable to
-            keep is_gimple_reg from thinking they are real.  */
-         TREE_ADDRESSABLE (sv->var) = 1;
-
-         DECL_CONTEXT (sv->var) = DECL_CONTEXT (var);
-
-         ann = get_var_ann (sv->var);
-         ann->mem_tag_kind = STRUCT_FIELD; 
-         ann->type_mem_tag = NULL;     
-         add_referenced_tmp_var (sv->var);
-         
          lastfotype = currfotype;
          lastfooffset = fo->offset;
          lastfosize = fosize;
index 7111960..28b19d9 100644 (file)
@@ -188,7 +188,9 @@ merge_alias_info (tree orig, tree new)
 #endif
 
   /* Synchronize the type tags.  If both pointers had a tag and they
-     are different, then something has gone wrong.  */
+     are different, then something has gone wrong.  Type tags can
+     always be merged because they are flow insensitive, all the SSA
+     names of the same base DECL share the same type tag.  */
   if (new_ann->type_mem_tag == NULL_TREE)
     new_ann->type_mem_tag = orig_ann->type_mem_tag;
   else if (orig_ann->type_mem_tag == NULL_TREE)
@@ -196,32 +198,41 @@ merge_alias_info (tree orig, tree new)
   else
     gcc_assert (new_ann->type_mem_tag == orig_ann->type_mem_tag);
 
-  /* Synchronize the name tags.  If NEW did not have a name tag, get
-     it from ORIG.  This happens when NEW is a compiler generated
-     temporary which still hasn't had its points-to information filled
-     in.  */
-  if (SSA_NAME_PTR_INFO (orig))
+  /* Check that flow-sensitive information is compatible.  Notice that
+     we may not merge flow-sensitive information here.  This function
+     is called when propagating equivalences dictated by the IL, like
+     a copy operation P_i = Q_j, and from equivalences dictated by
+     control-flow, like if (P_i == Q_j).
+     
+     In the former case, P_i and Q_j are equivalent in every block
+     dominated by the assignment, so their flow-sensitive information
+     is always the same.  However, in the latter case, the pointers
+     P_i and Q_j are only equivalent in one of the sub-graphs out of
+     the predicate, so their flow-sensitive information is not the
+     same in every block dominated by the predicate.
+
+     Since we cannot distinguish one case from another in this
+     function, we can only make sure that if P_i and Q_j have
+     flow-sensitive information, they should be compatible.  */
+  if (SSA_NAME_PTR_INFO (orig) && SSA_NAME_PTR_INFO (new))
     {
       struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig);
       struct ptr_info_def *new_ptr_info = SSA_NAME_PTR_INFO (new);
 
-      if (new_ptr_info == NULL)
-       duplicate_ssa_name_ptr_info (new, orig_ptr_info);
-      else if (orig_ptr_info->name_mem_tag
-              && new_ptr_info->name_mem_tag
-              && orig_ptr_info->pt_vars
-              && new_ptr_info->pt_vars)
-       {
-         /* Note that pointer NEW may actually have a different set
-            of pointed-to variables.  However, since NEW is being
-            copy-propagated into ORIG, it must always be true that
-            the pointed-to set for pointer NEW is the same, or a
-            subset, of the pointed-to set for pointer ORIG.  If this
-            isn't the case, we shouldn't have been able to do the
-            propagation of NEW into ORIG.  */
-         gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars,
-               orig_ptr_info->pt_vars));
-       }
+      /* Note that pointer NEW and ORIG may actually have different
+        pointed-to variables (e.g., PR 18291 represented in
+        testsuite/gcc.c-torture/compile/pr18291.c).  However, since
+        NEW is being copy-propagated into ORIG, it must always be
+        true that the pointed-to set for pointer NEW is the same, or
+        a subset, of the pointed-to set for pointer ORIG.  If this
+        isn't the case, we shouldn't have been able to do the
+        propagation of NEW into ORIG.  */
+      if (orig_ptr_info->name_mem_tag
+         && new_ptr_info->name_mem_tag
+         && orig_ptr_info->pt_vars
+         && new_ptr_info->pt_vars)
+       gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars,
+                                       orig_ptr_info->pt_vars));
     }
 }   
 
index f090024..34c0992 100644 (file)
@@ -32,7 +32,6 @@ Boston, MA 02110-1301, USA.  */
 #include "ggc.h"
 #include "timevar.h"
 #include "toplev.h"
-
 #include "langhooks.h"
 
 /* This file contains the code required to manage the operands cache of the 
@@ -148,7 +147,6 @@ static bool ops_active = false;
 static GTY (()) struct ssa_operand_memory_d *operand_memory = NULL;
 static unsigned operand_memory_index;
 
-static void note_addressable (tree, stmt_ann_t);
 static void get_expr_operands (tree, tree *, int);
 static void get_asm_expr_operands (tree);
 static void get_indirect_ref_operands (tree, tree, int);
@@ -1310,7 +1308,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
     case IMAGPART_EXPR:
       {
        tree ref;
-       HOST_WIDE_INT offset, size;
+       unsigned HOST_WIDE_INT offset, size;
        /* This component ref 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
@@ -1515,8 +1513,8 @@ get_asm_expr_operands (tree stmt)
       if (!allows_reg && allows_mem)
        {
          tree t = get_base_address (TREE_VALUE (link));
-         if (t && DECL_P (t))
-           note_addressable (t, s_ann);
+         if (t && DECL_P (t) && s_ann)
+           add_to_addressable_set (t, &s_ann->addresses_taken);
        }
 
       get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def);
@@ -1534,8 +1532,8 @@ get_asm_expr_operands (tree stmt)
       if (!allows_reg && allows_mem)
        {
          tree t = get_base_address (TREE_VALUE (link));
-         if (t && DECL_P (t))
-           note_addressable (t, s_ann);
+         if (t && DECL_P (t) && s_ann)
+           add_to_addressable_set (t, &s_ann->addresses_taken);
        }
 
       get_expr_operands (stmt, &TREE_VALUE (link), 0);
@@ -1688,7 +1686,10 @@ get_tmr_operands (tree stmt, tree expr, int flags)
   flags &= ~opf_kill_def;
 
   if (TMR_SYMBOL (expr))
-    note_addressable (TMR_SYMBOL (expr), stmt_ann (stmt));
+    {
+      stmt_ann_t ann = stmt_ann (stmt);
+      add_to_addressable_set (TMR_SYMBOL (expr), &ann->addresses_taken);
+    }
 
   if (tag)
     add_stmt_operand (&tag, stmt_ann (stmt), flags);
@@ -1757,9 +1758,9 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
 
   /* If the operand is an ADDR_EXPR, add its operand to the list of
      variables that have had their address taken in this statement.  */
-  if (TREE_CODE (var) == ADDR_EXPR)
+  if (TREE_CODE (var) == ADDR_EXPR && s_ann)
     {
-      note_addressable (TREE_OPERAND (var, 0), s_ann);
+      add_to_addressable_set (TREE_OPERAND (var, 0), &s_ann->addresses_taken);
       return;
     }
 
@@ -1861,35 +1862,17 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
 
          if (flags & opf_is_def)
            {
-             bool added_may_defs_p = false;
-
              /* If the variable is also an alias tag, add a virtual
                 operand for it, otherwise we will miss representing
                 references to the members of the variable's alias set.
                 This fixes the bug in gcc.c-torture/execute/20020503-1.c.  */
              if (v_ann->is_alias_tag)
-               {
-                 added_may_defs_p = true;
-                 append_v_may_def (var);
-               }
+               append_v_may_def (var);
 
              for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
-               {
-                 /* While VAR may be modifiable, some of its aliases
-                    may not be.  If that's the case, we don't really
-                    need to add them a V_MAY_DEF for them.  */
-                 tree alias = VARRAY_TREE (aliases, i);
-
-                 if (unmodifiable_var_p (alias))
-                   append_vuse (alias);
-                 else
-                   {
-                     append_v_may_def (alias);
-                     added_may_defs_p = true;
-                   }
-               }
+               append_v_may_def (VARRAY_TREE (aliases, i));
 
-             if (s_ann && added_may_defs_p)
+             if (s_ann)
                s_ann->makes_aliased_stores = 1;
            }
          else
@@ -1910,40 +1893,51 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
 }
 
   
-/* Record that VAR had its address taken in the statement with annotations
-   S_ANN.  */
+/* Add the base address of REF to the set *ADDRESSES_TAKEN.  If
+   *ADDRESSES_TAKEN is NULL, a new set is created.  REF may be
+   a single variable whose address has been taken or any other valid
+   GIMPLE memory reference (structure reference, array, etc).  If the
+   base address of REF is a decl that has sub-variables, also add all
+   of its sub-variables.  */
 
-static void
-note_addressable (tree var, stmt_ann_t s_ann)
+void
+add_to_addressable_set (tree ref, bitmap *addresses_taken)
 {
+  tree var;
   subvar_t svars;
 
-  if (!s_ann)
-    return;
-  
+  gcc_assert (addresses_taken);
+
   /* Note that it is *NOT OKAY* to use the target of a COMPONENT_REF
-     as the only thing we take the address of.
-     See PR 21407 and the ensuing mailing list discussion.  */
-  
-  var = get_base_address (var);
+     as the only thing we take the address of.  If VAR is a structure,
+     taking the address of a field means that the whole structure may
+     be referenced using pointer arithmetic.  See PR 21407 and the
+     ensuing mailing list discussion.  */
+  var = get_base_address (ref);
   if (var && SSA_VAR_P (var))
     {
-      if (s_ann->addresses_taken == NULL)
-       s_ann->addresses_taken = BITMAP_GGC_ALLOC ();      
+      if (*addresses_taken == NULL)
+       *addresses_taken = BITMAP_GGC_ALLOC ();      
       
-
       if (var_can_have_subvars (var)
          && (svars = get_subvars_for_var (var)))
        {
          subvar_t sv;
          for (sv = svars; sv; sv = sv->next)
-           bitmap_set_bit (s_ann->addresses_taken, DECL_UID (sv->var));
+           {
+             bitmap_set_bit (*addresses_taken, DECL_UID (sv->var));
+             TREE_ADDRESSABLE (sv->var) = 1;
+           }
        }
       else
-       bitmap_set_bit (s_ann->addresses_taken, DECL_UID (var));
+       {
+         bitmap_set_bit (*addresses_taken, DECL_UID (var));
+         TREE_ADDRESSABLE (var) = 1;
+       }
     }
 }
 
+
 /* Add clobbering definitions for .GLOBAL_VAR or for each of the call
    clobbered variables in the function.  */
 
index 99233fc..c1ec365 100644 (file)
@@ -170,6 +170,8 @@ extern bool ssa_ro_call_cache_valid;
 
 extern bool ssa_operands_active (void);
 
+extern void add_to_addressable_set (tree, bitmap *);
+
 enum ssa_op_iter_type {
   ssa_op_iter_none = 0,
   ssa_op_iter_tree,
index efa2238..7ec5270 100644 (file)
@@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #include "ggc.h"
 #include "obstack.h"
 #include "bitmap.h"
-#include "tree-ssa-structalias.h"
 #include "flags.h"
 #include "rtl.h"
 #include "tm_p.h"
@@ -49,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #include "timevar.h"
 #include "alloc-pool.h"
 #include "splay-tree.h"
+#include "tree-ssa-structalias.h"
 
 /* The idea behind this analyzer is to generate set constraints from the
    program, then solve the resulting constraints in order to generate the
@@ -223,6 +223,9 @@ struct variable_info
   /* True for variables that have unions somewhere in them.  */
   unsigned int has_union:1;
 
+  /* True if this is a heap variable.  */
+  unsigned int is_heap_var:1;
+
   /* Points-to set for this variable.  */
   bitmap solution;
 
@@ -270,6 +273,12 @@ static varinfo_t var_integer;
 static tree integer_tree;
 static unsigned int integer_id;
 
+/* Variable that represents arbitrary offsets into an object.  Used to
+   represent pointer arithmetic, which may not legally escape the
+   bounds of an object.  */
+static varinfo_t var_anyoffset;
+static tree anyoffset_tree;
+static unsigned int anyoffset_id;
 
 /* Return a new variable info structure consisting for a variable
    named NAME, and using constraint graph node NODE.  */
@@ -286,6 +295,7 @@ new_var_info (tree t, unsigned int id, const char *name, unsigned int node)
   ret->address_taken = false;
   ret->indirect_target = false;
   ret->is_artificial_var = false;
+  ret->is_heap_var = false;
   ret->is_unknown_size_var = false;
   ret->solution = BITMAP_ALLOC (&ptabitmap_obstack);
   bitmap_clear (ret->solution);
@@ -941,8 +951,11 @@ build_constraint_graph (void)
   constraint_t c;
 
   graph = ggc_alloc (sizeof (struct constraint_graph));
-  graph->succs = ggc_alloc_cleared (VEC_length (varinfo_t, varmap) * sizeof (*graph->succs));
-  graph->preds = ggc_alloc_cleared (VEC_length (varinfo_t, varmap) * sizeof (*graph->preds));
+  graph->succs = ggc_alloc_cleared (VEC_length (varinfo_t, varmap)
+                                    * sizeof (*graph->succs));
+  graph->preds = ggc_alloc_cleared (VEC_length (varinfo_t, varmap)
+                                    * sizeof (*graph->preds));
+
   for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
     {
       struct constraint_expr lhs = c->lhs;
@@ -983,6 +996,8 @@ build_constraint_graph (void)
        }
     }
 }
+
+
 /* Changed variables on the last iteration.  */
 static unsigned int changed_count;
 static sbitmap changed;
@@ -2137,11 +2152,18 @@ get_constraint_for (tree t)
               &ANYTHING added.  */
            if (call_expr_flags (t) & (ECF_MALLOC | ECF_MAY_BE_ALLOCA))
              {
-               tree heapvar = create_tmp_var_raw (ptr_type_node, "HEAP");
+               varinfo_t vi;
+               tree heapvar;
+               
+               heapvar = create_tmp_var_raw (ptr_type_node, "HEAP");
+               DECL_EXTERNAL (heapvar) = 1;
+               add_referenced_tmp_var (heapvar);
                temp.var = create_variable_info_for (heapvar,
                                                     alias_get_name (heapvar));
                
-               get_varinfo (temp.var)->is_artificial_var = 1;
+               vi = get_varinfo (temp.var);
+               vi->is_artificial_var = 1;
+               vi->is_heap_var = 1;
                temp.type = ADDRESSOF;
                temp.offset = 0;
                return temp;
@@ -2191,9 +2213,11 @@ get_constraint_for (tree t)
              
              /* Cast from non-pointer to pointers are bad news for us.
                 Anything else, we see through */
-             if (!(POINTER_TYPE_P (TREE_TYPE (t))  &&
-                   ! POINTER_TYPE_P (TREE_TYPE (op))))
+             if (!(POINTER_TYPE_P (TREE_TYPE (t))
+                   && ! POINTER_TYPE_P (TREE_TYPE (op))))
                return get_constraint_for (op);
+
+             /* FALLTHRU  */
            }
          default:
            {
@@ -2467,81 +2491,300 @@ ref_contains_indirect_ref (tree ref)
 }
 
 
-/*  Tree walker that is the heart of the aliasing infrastructure.
-    TP is a pointer to the current tree.
-    WALK_SUBTREES specifies whether to continue traversing subtrees or
-    not.
-    Returns NULL_TREE when we should stop.
-    
-    This function is the main part of the constraint builder. It
-    walks the trees, calling the appropriate building functions
-    to process various statements.  */
+/* Update related alias information kept in AI.  This is used when
+   building name tags, alias sets and deciding grouping heuristics.
+   STMT is the statement to process.  This function also updates
+   ADDRESSABLE_VARS.  */
+
+static void
+update_alias_info (tree stmt, struct alias_info *ai)
+{
+  bitmap addr_taken;
+  use_operand_p use_p;
+  def_operand_p def_p;
+  ssa_op_iter iter;
+  bool stmt_escapes_p = is_escape_site (stmt, ai);
+
+  /* Mark all the variables whose address are taken by the statement.  */
+  addr_taken = addresses_taken (stmt);
+  if (addr_taken)
+    {
+      bitmap_ior_into (addressable_vars, addr_taken);
+
+      /* If STMT is an escape point, all the addresses taken by it are
+        call-clobbered.  */
+      if (stmt_escapes_p)
+       {
+         bitmap_iterator bi;
+         unsigned i;
+
+         EXECUTE_IF_SET_IN_BITMAP (addr_taken, 0, i, bi)
+           mark_call_clobbered (referenced_var (i));
+       }
+    }
+
+  /* Process each operand use.  If an operand may be aliased, keep
+     track of how many times it's being used.  For pointers, determine
+     whether they are dereferenced by the statement, or whether their
+     value escapes, etc.  */
+  FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
+    {
+      tree op, var;
+      var_ann_t v_ann;
+      struct ptr_info_def *pi;
+      bool is_store;
+      unsigned num_uses, num_derefs;
+
+      op = USE_FROM_PTR (use_p);
+
+      /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
+        to the set of addressable variables.  */
+      if (TREE_CODE (op) == ADDR_EXPR)
+       {
+         gcc_assert (TREE_CODE (stmt) == PHI_NODE);
+
+         /* PHI nodes don't have annotations for pinning the set
+            of addresses taken, so we collect them here.
+
+            FIXME, should we allow PHI nodes to have annotations
+            so that they can be treated like regular statements?
+            Currently, they are treated as second-class
+            statements.  */
+         add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
+         continue;
+       }
+
+      /* Ignore constants.  */
+      if (TREE_CODE (op) != SSA_NAME)
+       continue;
+
+      var = SSA_NAME_VAR (op);
+      v_ann = var_ann (var);
+
+      /* If the operand's variable may be aliased, keep track of how
+        many times we've referenced it.  This is used for alias
+        grouping in compute_flow_insensitive_aliasing.  */
+      if (may_be_aliased (var))
+       NUM_REFERENCES_INC (v_ann);
+
+      /* We are only interested in pointers.  */
+      if (!POINTER_TYPE_P (TREE_TYPE (op)))
+       continue;
+
+      pi = get_ptr_info (op);
+
+      /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
+      if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
+       {
+         SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
+         VARRAY_PUSH_TREE (ai->processed_ptrs, op);
+       }
+
+      /* If STMT is a PHI node, then it will not have pointer
+        dereferences and it will not be an escape point.  */
+      if (TREE_CODE (stmt) == PHI_NODE)
+       continue;
+
+      /* Determine whether OP is a dereferenced pointer, and if STMT
+        is an escape point, whether OP escapes.  */
+      count_uses_and_derefs (op, stmt, &num_uses, &num_derefs, &is_store);
+
+      if (num_derefs > 0)
+       {
+         /* Mark OP as dereferenced.  In a subsequent pass,
+            dereferenced pointers that point to a set of
+            variables will be assigned a name tag to alias
+            all the variables OP points to.  */
+         pi->is_dereferenced = 1;
+
+         /* Keep track of how many time we've dereferenced each
+            pointer.  */
+         NUM_REFERENCES_INC (v_ann);
+
+         /* If this is a store operation, mark OP as being
+            dereferenced to store, otherwise mark it as being
+            dereferenced to load.  */
+         if (is_store)
+           bitmap_set_bit (ai->dereferenced_ptrs_store, DECL_UID (var));
+         else
+           bitmap_set_bit (ai->dereferenced_ptrs_load, DECL_UID (var));
+       }
+
+      if (stmt_escapes_p && num_derefs < num_uses)
+       {
+         /* If STMT is an escape point and STMT contains at
+            least one direct use of OP, then the value of OP
+            escapes and so the pointed-to variables need to
+            be marked call-clobbered.  */
+         pi->value_escapes_p = 1;
+
+         /* If the statement makes a function call, assume
+            that pointer OP will be dereferenced in a store
+            operation inside the called function.  */
+         if (get_call_expr_in (stmt))
+           {
+             bitmap_set_bit (ai->dereferenced_ptrs_store, DECL_UID (var));
+             pi->is_dereferenced = 1;
+           }
+       }
+    }
+
+  /* Update reference counter for definitions to any potentially
+     aliased variable.  This is used in the alias grouping heuristics.  */
+  FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, iter, SSA_OP_ALL_DEFS)
+    {
+      tree op = DEF_FROM_PTR (def_p);
+      tree var = SSA_NAME_VAR (op);
+      var_ann_t ann = var_ann (var);
+      bitmap_set_bit (ai->written_vars, DECL_UID (var));
+      if (may_be_aliased (var))
+       NUM_REFERENCES_INC (ann);
+    }
+}
+
+
+/* Handle pointer arithmetic EXPR when creating aliasing constraints.
+   Expressions of the type PTR + CST can be handled in two ways:
+
+   1- If the constraint for PTR is ADDRESSOF for a non-structure
+      variable, then we can use it directly because adding or
+      subtracting a constant may not alter the original ADDRESSOF
+      constraing (i.e., pointer arithmetic may not legally go outside
+      an object's boundaries).
+
+   2- If the constraint for PTR is ADDRESSOF for a structure variable,
+      then if CST is a compile-time constant that can be used as an
+      offset, we can determine which sub-variable will be pointed-to
+      by the expression.
+
+   Return true if the expression is handled.  For any other kind of
+   expression, return false so that each operand can be added as a
+   separate constraint by the caller.  */
+
+static bool
+handle_ptr_arith (struct constraint_expr lhs, tree expr)
+{
+  tree op0, op1;
+  struct constraint_expr base, offset;
+
+  if (TREE_CODE (expr) != PLUS_EXPR)
+    return false;
+
+  op0 = TREE_OPERAND (expr, 0);
+  op1 = TREE_OPERAND (expr, 1);
+
+  base = get_constraint_for (op0);
+
+  offset.var = anyoffset_id;
+  offset.type = ADDRESSOF;
+  offset.offset = 0;
+
+  process_constraint (new_constraint (lhs, base));
+  process_constraint (new_constraint (lhs, offset));
+
+  return true;
+}
+
+
+/* Walk statement T setting up aliasing constraints according to the
+   references found in T.  This function is the main part of the
+   constraint builder.  AI points to auxiliary alias information used
+   when building alias sets and computing alias grouping heuristics.  */
 
 static void
-find_func_aliases (tree t)
+find_func_aliases (tree t, struct alias_info *ai)
 {
   struct constraint_expr lhs, rhs;
-  switch (TREE_CODE (t))
-    {      
-    case PHI_NODE:
-      {
-       int i;
 
-       /* Only care about pointers and structures containing
-          pointers.  */
-       if (POINTER_TYPE_P (TREE_TYPE (PHI_RESULT (t)))
-           || AGGREGATE_TYPE_P (TREE_TYPE (PHI_RESULT (t))))
-         {
-           lhs = get_constraint_for (PHI_RESULT (t));
-           for (i = 0; i < PHI_NUM_ARGS (t); i++)
-             {
-               rhs = get_constraint_for (PHI_ARG_DEF (t, i));
-               process_constraint (new_constraint (lhs, rhs));
-             }
-         }
-      }
-      break;
+  /* Update various related attributes like escaped addresses, pointer
+     dereferences for loads and stores.  This is used when creating
+     name tags and alias sets.  */
+  update_alias_info (t, ai);
 
-    case MODIFY_EXPR:
-      {
-       tree lhsop = TREE_OPERAND (t, 0);
-       tree rhsop = TREE_OPERAND (t, 1);
-       int i;  
+  /* Now build constraints expressions.  */
+  if (TREE_CODE (t) == PHI_NODE)
+    {
+      /* Only care about pointers and structures containing
+        pointers.  */
+      if (POINTER_TYPE_P (TREE_TYPE (PHI_RESULT (t)))
+         || AGGREGATE_TYPE_P (TREE_TYPE (PHI_RESULT (t))))
+       {
+         int i;
 
-       if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop)) 
-           && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
-         {
-           do_structure_copy (lhsop, rhsop);
-         }
-       else
-         {
-           /* Only care about operations with pointers, structures
-              containing pointers, dereferences, and call
-              expressions.  */
-           if (POINTER_TYPE_P (TREE_TYPE (lhsop))
-               || AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
-               || ref_contains_indirect_ref (lhsop)
-               || TREE_CODE (rhsop) == CALL_EXPR)
-             {
-               lhs = get_constraint_for (lhsop);
-               switch (TREE_CODE_CLASS (TREE_CODE (rhsop)))
-                 {
-                   /* RHS that consist of unary operations,
-                      exceptional types, or bare decls/constants, get
-                      handled directly by get_constraint_for.  */ 
+         lhs = get_constraint_for (PHI_RESULT (t));
+         for (i = 0; i < PHI_NUM_ARGS (t); i++)
+           {
+             rhs = get_constraint_for (PHI_ARG_DEF (t, i));
+             process_constraint (new_constraint (lhs, rhs));
+           }
+       }
+    }
+  else if (TREE_CODE (t) == MODIFY_EXPR)
+    {
+      tree lhsop = TREE_OPERAND (t, 0);
+      tree rhsop = TREE_OPERAND (t, 1);
+      int i;   
+
+      if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop)) 
+         && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
+       {
+         do_structure_copy (lhsop, rhsop);
+       }
+      else
+       {
+         /* Only care about operations with pointers, structures
+            containing pointers, dereferences, and call expressions.  */
+         if (POINTER_TYPE_P (TREE_TYPE (lhsop))
+             || AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
+             || ref_contains_indirect_ref (lhsop)
+             || TREE_CODE (rhsop) == CALL_EXPR)
+           {
+             lhs = get_constraint_for (lhsop);
+             switch (TREE_CODE_CLASS (TREE_CODE (rhsop)))
+               {
+                 /* RHS that consist of unary operations,
+                    exceptional types, or bare decls/constants, get
+                    handled directly by get_constraint_for.  */ 
                  case tcc_reference:
                  case tcc_declaration:
                  case tcc_constant:
                  case tcc_exceptional:
                  case tcc_expression:
                  case tcc_unary:
-                   {
-                     rhs = get_constraint_for (rhsop);
-                     process_constraint (new_constraint (lhs, rhs));
-                   }
+                     {
+                       rhs = get_constraint_for (rhsop);
+                       process_constraint (new_constraint (lhs, rhs));
+
+                       /* When taking the address of an aggregate
+                          type, from the LHS we can access any field
+                          of the RHS.  */
+                       if (rhs.type == ADDRESSOF
+                           && rhs.var > anything_id
+                           && AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (rhsop))))
+                         {
+                           rhs.var = anyoffset_id;
+                           rhs.type = ADDRESSOF;
+                           rhs.offset = 0;
+                           process_constraint (new_constraint (lhs, rhs));
+                         }
+                     }
                    break;
 
-                   /* Otherwise, walk each operand.  */
+                 case tcc_binary:
+                     {
+                       /* For pointer arithmetic of the form
+                          PTR + CST, we can simply use PTR's
+                          constraint because pointer arithmetic is
+                          not allowed to go out of bounds.  */
+                       if (handle_ptr_arith (lhs, rhsop))
+                         break;
+                     }
+                   /* FALLTHRU  */
+
+                 /* Otherwise, walk each operand.  Notice that we
+                    can't use the operand interface because we need
+                    to process expressions other than simple operands
+                    (e.g. INDIRECT_REF, ADDR_EXPR, CALL_EXPR).  */
                  default:
                    for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (rhsop)); i++)
                      {
@@ -2549,15 +2792,16 @@ find_func_aliases (tree t)
                        rhs = get_constraint_for (op);
                        process_constraint (new_constraint (lhs, rhs));
                      }
-                 }      
-             }
-         }
-      }
-      break;
-
-    default:
-      break;
+               }      
+           }
+       }
     }
+
+  /* After promoting variables and computing aliasing we will
+     need to re-scan most statements.  FIXME: Try to minimize the
+     number of statements re-scanned.  It's not really necessary to
+     re-scan *all* statements.  */
+  mark_stmt_modified (t);
 }
 
 
@@ -2718,12 +2962,12 @@ create_variable_info_for (tree decl, const char *name)
   tree decltype = TREE_TYPE (decl);
   bool notokay = false;
   bool hasunion;
-  subvar_t svars;
   bool is_global = DECL_P (decl) ? is_global_var (decl) : false;
   VEC (fieldoff_s,heap) *fieldstack = NULL;
   
 
-  hasunion = TREE_CODE (decltype) == UNION_TYPE || TREE_CODE (decltype) == QUAL_UNION_TYPE;
+  hasunion = TREE_CODE (decltype) == UNION_TYPE
+             || TREE_CODE (decltype) == QUAL_UNION_TYPE;
   if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
     {
       push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion);
@@ -2733,62 +2977,6 @@ create_variable_info_for (tree decl, const char *name)
          notokay = true;
        }        
     }
-
-  /* If this variable already has subvars, just create the variables for the
-     subvars and we are done.
-     NOTE: This assumes things haven't generated uses of previously
-     unused structure fields.  */
-  if (use_field_sensitive 
-      && !notokay 
-      && var_can_have_subvars (decl) 
-      && var_ann (decl)      
-      && (svars = get_subvars_for_var (decl)))
-    {
-      subvar_t sv;
-      varinfo_t base = NULL;
-      unsigned int firstindex = index;
-
-      for (sv = svars; sv; sv = sv->next)
-       {
-         /* For debugging purposes, this will print the names of the
-            fields as "<var>.<offset>.<size>"
-            This is only for debugging purposes.  */
-#define PRINT_LONG_NAMES
-#ifdef PRINT_LONG_NAMES
-         char *tempname;
-         const char *newname;
-
-         asprintf (&tempname,
-                   "%s." HOST_WIDE_INT_PRINT_DEC "." HOST_WIDE_INT_PRINT_DEC,
-                   alias_get_name (decl), sv->offset, sv->size);
-         newname = ggc_strdup (tempname);
-         free (tempname);
-         vi = new_var_info (sv->var, index, newname, index);
-#else
-         vi = new_var_info (sv->var, index, alias_get_name (sv->var), index);
-#endif
-         vi->decl = sv->var;
-         vi->fullsize = TREE_INT_CST_LOW (TYPE_SIZE (decltype));
-         vi->size = sv->size;
-         vi->offset = sv->offset;
-         if (!base)
-           {
-             base = vi;
-             insert_id_for_tree (decl, index);
-           }
-         else
-           {
-             insert_into_field_list (base, vi);
-           }
-         insert_id_for_tree (sv->var, index);  
-         VEC_safe_push (varinfo_t, gc, varmap, vi);
-         if (is_global)
-           make_constraint_to_anything (vi);
-         index++;
-         
-       }
-      return firstindex;
-    }
   
 
   /* If the variable doesn't have subvars, we may end up needing to
@@ -2935,7 +3123,6 @@ intra_create_variable_infos (void)
       lhs.type = SCALAR;
       lhs.var  = create_variable_info_for (t, alias_get_name (t));
       
-      get_varinfo (lhs.var)->is_artificial_var = true;
       rhs.var = anything_id;
       rhs.type = ADDRESSOF;
       rhs.offset = 0;
@@ -2958,30 +3145,67 @@ set_uids_in_ptset (bitmap into, bitmap from)
 {
   unsigned int i;
   bitmap_iterator bi;
+  bool found_anyoffset = false;
+  subvar_t sv;
 
   EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
     {
       varinfo_t vi = get_varinfo (i);
+
+      /* If we find ANYOFFSET in the solution and the solution
+        includes SFTs for some structure, then all the SFTs in that
+        structure will need to be added to the alias set.  */
+      if (vi->id == anyoffset_id)
+       {
+         found_anyoffset = true;
+         continue;
+       }
+
+      /* 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;
       
-      /* Variables containing unions may need to be converted to their 
-        SFT's, because SFT's can have unions and we cannot.  */
       if (vi->has_union && get_subvars_for_var (vi->decl) != NULL)
        {
-         subvar_t svars = get_subvars_for_var (vi->decl);
-         subvar_t sv;
-         for (sv = svars; sv; sv = sv->next)
+         /* Variables containing unions may need to be converted to
+            their SFT's, because SFT's can have unions and we cannot.  */
+         for (sv = get_subvars_for_var (vi->decl); sv; sv = sv->next)
            bitmap_set_bit (into, DECL_UID (sv->var));
        }
-      /* We may end up with labels in the points-to set because people
-        take their address, and they are _DECL's.  */
       else if (TREE_CODE (vi->decl) == VAR_DECL 
-         || TREE_CODE (vi->decl) == PARM_DECL)
-       bitmap_set_bit (into, DECL_UID (vi->decl));
-
-         
+              || TREE_CODE (vi->decl) == PARM_DECL)
+       {
+         if (found_anyoffset
+             && var_can_have_subvars (vi->decl)
+             && get_subvars_for_var (vi->decl))
+           {
+             /* If ANYOFFSET is in the solution set and VI->DECL is
+                an aggregate variable with sub-variables, then any of
+                the SFTs inside VI->DECL may have been accessed.  Add
+                all the sub-vars for VI->DECL.  */
+             for (sv = get_subvars_for_var (vi->decl); sv; sv = sv->next)
+               bitmap_set_bit (into, DECL_UID (sv->var));
+           }
+         else if (var_can_have_subvars (vi->decl)
+                  && get_subvars_for_var (vi->decl))
+           {
+             /* If VI->DECL is an aggregate for which we created
+                SFTs, add the SFT corresponding to VI->OFFSET.  */
+             tree sft = get_subvar_at (vi->decl, vi->offset);
+             bitmap_set_bit (into, DECL_UID (sft));
+           }
+         else
+           {
+             /* Otherwise, just add VI->DECL to the alias set.  */
+             bitmap_set_bit (into, DECL_UID (vi->decl));
+           }
+       }
     }
 }
-static int have_alias_info = false;
+
+
+static bool have_alias_info = false;
 
 /* Given a pointer variable P, fill in its points-to set, or return
    false if we can't.  */
@@ -2990,8 +3214,10 @@ bool
 find_what_p_points_to (tree p)
 {
   unsigned int id = 0;
+
   if (!have_alias_info)
     return false;
+
   if (lookup_id_for_tree (p, &id))
     {
       varinfo_t vi = get_varinfo (id);
@@ -2999,14 +3225,15 @@ find_what_p_points_to (tree p)
       if (vi->is_artificial_var)
        return false;
 
-      /* See if this is a field or a structure */
+      /* See if this is a field or a structure */
       if (vi->size != vi->fullsize)
        {
+         /* 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;
-         /* Nothing currently asks about structure fields directly, but when
-            they do, we need code here to hand back the points-to set.  */
        } 
       else
        {
@@ -3018,21 +3245,45 @@ find_what_p_points_to (tree p)
             variable.  */
          vi = get_varinfo (vi->node);
          
-         /* Make sure there aren't any artificial vars in the points to set.
-             XXX: Note that we need to translate our heap variables to
-             something.  */
+         /* Translate artificial variables into SSA_NAME_PTR_INFO
+            attributes.  */
          EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
            {
-             if (get_varinfo (i)->is_artificial_var)
-               return false;
+             varinfo_t vi = get_varinfo (i);
+
+             if (vi->is_artificial_var)
+               {
+                 /* FIXME.  READONLY should be handled better so that
+                    flow insensitive aliasing can disregard writeable
+                    aliases.  */
+                 if (vi->id == nothing_id)
+                   pi->pt_null = 1;
+                 else if (vi->id == anything_id)
+                   pi->pt_anything = 1;
+                 else if (vi->id == readonly_id)
+                   pi->pt_anything = 1;
+                 else if (vi->id == integer_id)
+                   pi->pt_anything = 1;
+                 else if (vi->is_heap_var)
+                   pi->pt_global_mem = 1;
+               }
            }
-         pi->pt_anything = false;
+
+         if (pi->pt_anything)
+           return false;
+
          if (!pi->pt_vars)
            pi->pt_vars = BITMAP_GGC_ALLOC ();
+
          set_uids_in_ptset (pi->pt_vars, vi->solution);
+
+         if (bitmap_empty_p (pi->pt_vars))
+           pi->pt_vars = NULL;
+
          return true;
        }
     }
+
   return false;
 }
 
@@ -3053,7 +3304,7 @@ dump_sa_points_to_info (FILE *outfile)
 {
   unsigned int i;
 
-  fprintf (outfile, "\nPoints-to information\n\n");
+  fprintf (outfile, "\nPoints-to sets\n\n");
 
   if (dump_flags & TDF_STATS)
     {
@@ -3124,6 +3375,7 @@ init_base_vars (void)
   rhs.var = anything_id;
   rhs.offset = 0;
   var_anything->address_taken = true;
+
   /* This specifically does not use process_constraint because
      process_constraint ignores all anything = anything constraints, since all
      but this one are redundant.  */
@@ -3177,17 +3429,44 @@ init_base_vars (void)
   rhs.var = anything_id;
   rhs.offset = 0;
   process_constraint (new_constraint (lhs, rhs));
+
+  /* Create the ANYOFFSET variable, used to represent an arbitrary offset
+     inside an object.  This is similar to ANYTHING, but less drastic.
+     It means that the pointer can point anywhere inside an object,
+     but not outside of it.  */
+  anyoffset_tree = create_tmp_var_raw (void_type_node, "ANYOFFSET");
+  anyoffset_id = 4;
+  var_anyoffset = new_var_info (anyoffset_tree, anyoffset_id, "ANYOFFSET",
+                                anyoffset_id); 
+  insert_id_for_tree (anyoffset_tree, anyoffset_id);
+  var_anyoffset->is_artificial_var = 1;
+  var_anyoffset->size = ~0;
+  var_anyoffset->offset = 0;
+  var_anyoffset->next = NULL;
+  var_anyoffset->fullsize = ~0;
+  VEC_safe_push (varinfo_t, gc, varmap, var_anyoffset);
+
+  /* ANYOFFSET points to ANYOFFSET.  */
+  lhs.type = SCALAR;
+  lhs.var = anyoffset_id;
+  lhs.offset = 0;
+  rhs.type = ADDRESSOF;
+  rhs.var = anyoffset_id;
+  rhs.offset = 0;
+  process_constraint (new_constraint (lhs, rhs));
 }  
 
 
 /* Create points-to sets for the current function.  See the comments
    at the start of the file for an algorithmic overview.  */
 
-static void
-create_alias_vars (void)
+void
+compute_points_to_sets (struct alias_info *ai)
 {
   basic_block bb;
-  
+
+  timevar_push (TV_TREE_PTA);
+
   init_alias_vars ();
 
   constraint_pool = create_alloc_pool ("Constraint pool", 
@@ -3201,7 +3480,7 @@ create_alias_vars (void)
   varmap = VEC_alloc (varinfo_t, gc, 8);
   id_for_tree = htab_create (10, tree_id_hash, tree_id_eq, free);
   memset (&stats, 0, sizeof (stats));
-  
+
   init_base_vars ();
 
   intra_create_variable_infos ();
@@ -3214,28 +3493,29 @@ create_alias_vars (void)
 
       for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
        if (is_gimple_reg (PHI_RESULT (phi)))
-         find_func_aliases (phi);
+         find_func_aliases (phi, ai);
 
       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-       find_func_aliases (bsi_stmt (bsi));
+       find_func_aliases (bsi_stmt (bsi), ai);
     }
 
   build_constraint_graph ();
 
   if (dump_file)
     {
-      fprintf (dump_file, "Constraints:\n");
+      fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n");
       dump_constraints (dump_file);
     }
 
   if (dump_file)
-    fprintf (dump_file, "Collapsing static cycles and doing variable substitution:\n");
+    fprintf (dump_file, "\nCollapsing static cycles and doing variable "
+                       "substitution:\n");
 
   find_and_collapse_graph_cycles (graph, false);
   perform_var_substitution (graph);
 
   if (dump_file)
-    fprintf (dump_file, "Solving graph:\n");
+    fprintf (dump_file, "\nSolving graph:\n");
 
   solve_graph (graph);
 
@@ -3243,30 +3523,15 @@ create_alias_vars (void)
     dump_sa_points_to_info (dump_file);
   
   have_alias_info = true;
+
+  timevar_pop (TV_TREE_PTA);
 }
 
-struct tree_opt_pass pass_build_pta = 
-{
-  "pta",                               /* name */
-  NULL,                                        /* gate */
-  create_alias_vars,                   /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_TREE_PTA,                         /* tv_id */
-  PROP_cfg,                            /* properties_required */
-  PROP_pta,                            /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
-  0                                    /* letter */
-};
 
 /* Delete created points-to sets.  */
 
-static void
-delete_alias_vars (void)
+void
+delete_points_to_sets (void)
 {
   htab_delete (id_for_tree);
   free_alloc_pool (variable_info_pool);
@@ -3275,20 +3540,3 @@ delete_alias_vars (void)
   bitmap_obstack_release (&ptabitmap_obstack);
   have_alias_info = false;
 }
-
-struct tree_opt_pass pass_del_pta = 
-{
-  NULL,                                 /* name */
-  NULL,                                        /* gate */
-  delete_alias_vars,                   /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_TREE_PTA,                         /* tv_id */
-  PROP_pta,                            /* properties_required */
-  0,                                   /* properties_provided */
-  PROP_pta,                            /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
-  0                                    /* letter */
-};
index a6241e5..ddabd6d 100644 (file)
@@ -25,6 +25,66 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 struct constraint;
 typedef struct constraint *constraint_t;
 
+/* Alias information used by compute_may_aliases and its helpers.  */
+struct alias_info
+{
+  /* SSA names visited while collecting points-to information.  If bit I
+     is set, it means that SSA variable with version I has already been
+     visited.  */
+  sbitmap ssa_names_visited;
+
+  /* Array of SSA_NAME pointers processed by the points-to collector.  */
+  varray_type processed_ptrs;
+
+  /* ADDRESSABLE_VARS contains all the global variables and locals that
+     have had their address taken.  */
+  struct alias_map_d **addressable_vars;
+  size_t num_addressable_vars;
+
+  /* POINTERS contains all the _DECL pointers with unique memory tags
+     that have been referenced in the program.  */
+  struct alias_map_d **pointers;
+  size_t num_pointers;
+
+  /* Number of function calls found in the program.  */
+  size_t num_calls_found;
+
+  /* Number of const/pure function calls found in the program.  */
+  size_t num_pure_const_calls_found;
+
+  /* Array of counters to keep track of how many times each pointer has
+     been dereferenced in the program.  This is used by the alias grouping
+     heuristic in compute_flow_insensitive_aliasing.  */
+  varray_type num_references;
+
+  /* Total number of virtual operands that will be needed to represent
+     all the aliases of all the pointers found in the program.  */
+  long total_alias_vops;
+
+  /* Variables that have been written to.  */
+  bitmap written_vars;
+
+  /* Pointers that have been used in an indirect store operation.  */
+  bitmap dereferenced_ptrs_store;
+
+  /* Pointers that have been used in an indirect load operation.  */
+  bitmap dereferenced_ptrs_load;
+};
+
+/* Keep track of how many times each pointer has been dereferenced in
+   the program using the aux variable.  This is used by the alias
+   grouping heuristic in compute_flow_insensitive_aliasing.  */
+#define NUM_REFERENCES(ANN) ((size_t)((ANN)->common.aux))
+#define NUM_REFERENCES_CLEAR(ANN) ((ANN)->common.aux) = 0
+#define NUM_REFERENCES_INC(ANN) (ANN)->common.aux = (void*) (((size_t)((ANN)->common.aux)) + 1)
+#define NUM_REFERENCES_SET(ANN, VAL) (ANN)->common.aux = (void*) ((void *)(VAL))
+
+/* In tree-ssa-alias.c.  */
+bool is_escape_site (tree, struct alias_info *);
+
+/* In tree-ssa-structalias.c.  */
+extern void compute_points_to_sets (struct alias_info *);
+extern void delete_points_to_sets (void);
 extern void dump_constraint (FILE *, constraint_t);
 extern void dump_constraints (FILE *);
 extern void debug_constraint (constraint_t);
index c88030d..ef892b5 100644 (file)
@@ -467,10 +467,9 @@ verify_flow_sensitive_alias_info (void)
        }
 
       if (pi->name_mem_tag
-         && !pi->pt_malloc
          && (pi->pt_vars == NULL || bitmap_empty_p (pi->pt_vars)))
        {
-         error ("pointers with a memory tag, should have points-to sets or point to malloc");
+         error ("pointers with a memory tag, should have points-to sets");
          goto err;
        }