OSDN Git Service

2008-06-29 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 29 Jun 2008 15:44:00 +0000 (15:44 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 29 Jun 2008 15:44:00 +0000 (15:44 +0000)
* tree-ssa-structalias.h (compute_points_to_sets): Adjust
prototype.
(struct alias_info): Move ...
* tree-ssa-alias.c: ... here.
(update_alias_info): Declare.
(compute_may_aliases): Call it.
(update_alias_info): New function.
* tree-ssa-structalias.c (update_alias_info): Move ...
* tree-ssa-alias.c (update_alias_info_1): ... here.
* tree-ssa-structalias.c (process_constraint_1): Remove
unused from_call argument.  Rename to ...
(process_constraint): ... this.  Delete old wrapper.
(make_constraint_to): Adjust callers.
(handle_const_call): Likewise.
(handle_pure_call): Likewise.
(init_base_vars): Likewise.
(handle_lhs_call): Likewise.  Remove unnecessary constraint.
(find_func_aliases): We don't need structure copies for
complex types.
(make_constraint_from_anything): Remove.
(create_variable_info_for): For globals make constraints
from escaped, not from anything.
(compute_points_to_sets): Do not call update_alias_info.
(ipa_pta_execute): Use make_constraint_from.

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

gcc/ChangeLog
gcc/tree-ssa-alias.c
gcc/tree-ssa-structalias.c
gcc/tree-ssa-structalias.h

index 26a22db..99e5011 100644 (file)
@@ -1,3 +1,30 @@
+2008-06-29  Richard Guenther  <rguenther@suse.de>
+
+       * tree-ssa-structalias.h (compute_points_to_sets): Adjust
+       prototype.
+       (struct alias_info): Move ...
+       * tree-ssa-alias.c: ... here.
+       (update_alias_info): Declare.
+       (compute_may_aliases): Call it.
+       (update_alias_info): New function.
+       * tree-ssa-structalias.c (update_alias_info): Move ...
+       * tree-ssa-alias.c (update_alias_info_1): ... here.
+       * tree-ssa-structalias.c (process_constraint_1): Remove
+       unused from_call argument.  Rename to ...
+       (process_constraint): ... this.  Delete old wrapper.
+       (make_constraint_to): Adjust callers.
+       (handle_const_call): Likewise.
+       (handle_pure_call): Likewise.
+       (init_base_vars): Likewise.
+       (handle_lhs_call): Likewise.  Remove unnecessary constraint.
+       (find_func_aliases): We don't need structure copies for
+       complex types.
+       (make_constraint_from_anything): Remove.
+       (create_variable_info_for): For globals make constraints
+       from escaped, not from anything.
+       (compute_points_to_sets): Do not call update_alias_info.
+       (ipa_pta_execute): Use make_constraint_from.
+
 2008-06-29  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * Makefile.in (CXX_COMPAT_WARN, cxx_compat_warn): Delete.
index 9a6552b..ee0f4a7 100644 (file)
@@ -166,6 +166,40 @@ along with GCC; see the file COPYING3.  If not see
    Lastly, we delete partitions with no symbols, and clean up after
    ourselves.  */
 
+
+/* Alias information used by compute_may_aliases and its helpers.  */
+struct alias_info
+{
+  /* SSA names visited while collecting points-to information.  If bit I
+     is set, it means that SSA variable with version I has already been
+     visited.  */
+  sbitmap ssa_names_visited;
+
+  /* Array of SSA_NAME pointers processed by the points-to collector.  */
+  VEC(tree,heap) *processed_ptrs;
+
+  /* ADDRESSABLE_VARS contains all the global variables and locals that
+     have had their address taken.  */
+  struct alias_map_d **addressable_vars;
+  size_t num_addressable_vars;
+
+  /* POINTERS contains all the _DECL pointers with unique memory tags
+     that have been referenced in the program.  */
+  struct alias_map_d **pointers;
+  size_t num_pointers;
+
+  /* Variables that have been written to directly (i.e., not through a
+     pointer dereference).  */
+  struct pointer_set_t *written_vars;
+
+  /* Pointers that have been used in an indirect store operation.  */
+  struct pointer_set_t *dereferenced_ptrs_store;
+
+  /* Pointers that have been used in an indirect load operation.  */
+  struct pointer_set_t *dereferenced_ptrs_load;
+};
+
+
 /* Structure to map a variable to its alias set.  */
 struct alias_map_d
 {
@@ -205,6 +239,7 @@ static struct alias_info *init_alias_info (void);
 static void delete_alias_info (struct alias_info *);
 static void compute_flow_sensitive_aliasing (struct alias_info *);
 static void setup_pointers_and_addressables (struct alias_info *);
+static void update_alias_info (struct alias_info *);
 static void create_global_var (void);
 static void maybe_create_global_var (void);
 static void set_pt_anything (tree);
@@ -1722,7 +1757,12 @@ 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_sets (ai);
+  compute_points_to_sets ();
+
+  /* Update various related attributes like escaped addresses,
+     pointer dereferences for loads and stores.  This is used
+     when creating name tags and alias sets.  */
+  update_alias_info (ai);
 
   /* Collect all pointers and addressable variables, compute alias sets,
      create memory tags for pointers and promote variables whose address is
@@ -2438,6 +2478,270 @@ create_alias_map_for (tree var, struct alias_info *ai)
 }
 
 
+/* Update related alias information kept in AI.  This is used when
+   building name tags, alias sets and deciding grouping heuristics.
+   STMT is the statement to process.  This function also updates
+   ADDRESSABLE_VARS.  */
+
+static void
+update_alias_info_1 (tree stmt, struct alias_info *ai)
+{
+  bitmap addr_taken;
+  use_operand_p use_p;
+  ssa_op_iter iter;
+  bool stmt_dereferences_ptr_p;
+  enum escape_type stmt_escape_type = is_escape_site (stmt);
+  struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
+
+  stmt_dereferences_ptr_p = false;
+
+  if (stmt_escape_type == ESCAPE_TO_CALL
+      || stmt_escape_type == ESCAPE_TO_PURE_CONST)
+    {
+      mem_ref_stats->num_call_sites++;
+      if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
+       mem_ref_stats->num_pure_const_call_sites++;
+    }
+  else if (stmt_escape_type == ESCAPE_TO_ASM)
+    mem_ref_stats->num_asm_sites++;
+
+  /* Mark all the variables whose address are taken by the statement.  */
+  addr_taken = addresses_taken (stmt);
+  if (addr_taken)
+    bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
+
+  /* Process each operand use.  For pointers, determine whether they
+     are dereferenced by the statement, or whether their value
+     escapes, etc.  */
+  FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
+    {
+      tree op, var;
+      var_ann_t v_ann;
+      struct ptr_info_def *pi;
+      unsigned num_uses, num_loads, num_stores;
+
+      op = USE_FROM_PTR (use_p);
+
+      /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
+        to the set of addressable variables.  */
+      if (TREE_CODE (op) == ADDR_EXPR)
+       {
+         bitmap addressable_vars = gimple_addressable_vars (cfun);
+
+         gcc_assert (TREE_CODE (stmt) == PHI_NODE);
+         gcc_assert (addressable_vars);
+
+         /* PHI nodes don't have annotations for pinning the set
+            of addresses taken, so we collect them here.
+
+            FIXME, should we allow PHI nodes to have annotations
+            so that they can be treated like regular statements?
+            Currently, they are treated as second-class
+            statements.  */
+         add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
+         continue;
+       }
+
+      /* Ignore constants (they may occur in PHI node arguments).  */
+      if (TREE_CODE (op) != SSA_NAME)
+       continue;
+
+      var = SSA_NAME_VAR (op);
+      v_ann = var_ann (var);
+
+      /* The base variable of an SSA name must be a GIMPLE register, and thus
+        it cannot be aliased.  */
+      gcc_assert (!may_be_aliased (var));
+
+      /* We are only interested in pointers.  */
+      if (!POINTER_TYPE_P (TREE_TYPE (op)))
+       continue;
+
+      pi = get_ptr_info (op);
+
+      /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
+      if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
+       {
+         SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
+         VEC_safe_push (tree, heap, ai->processed_ptrs, op);
+       }
+
+      /* If STMT is a PHI node, then it will not have pointer
+        dereferences and it will not be an escape point.  */
+      if (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_loads, &num_stores);
+
+      /* For directly dereferenced pointers we can apply
+        TBAA-pruning to their points-to set.  We may not count the
+        implicit dereferences &PTR->FLD here.  */
+      if (num_loads + num_stores > 0)
+       pi->is_dereferenced = 1;
+
+      /* Handle a corner case involving address expressions of the
+        form '&PTR->FLD'.  The problem with these expressions is that
+        they do not represent a dereference of PTR.  However, if some
+        other transformation propagates them into an INDIRECT_REF
+        expression, we end up with '*(&PTR->FLD)' which is folded
+        into 'PTR->FLD'.
+
+        So, if the original code had no other dereferences of PTR,
+        the aliaser will not create memory tags for it, and when
+        &PTR->FLD gets propagated to INDIRECT_REF expressions, the
+        memory operations will receive no VDEF/VUSE operands.
+
+        One solution would be to have count_uses_and_derefs consider
+        &PTR->FLD a dereference of PTR.  But that is wrong, since it
+        is not really a dereference but an offset calculation.
+
+        What we do here is to recognize these special ADDR_EXPR
+        nodes.  Since these expressions are never GIMPLE values (they
+        are not GIMPLE invariants), they can only appear on the RHS
+        of an assignment and their base address is always an
+        INDIRECT_REF expression.  */
+      if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+         && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR
+         && !is_gimple_val (GIMPLE_STMT_OPERAND (stmt, 1)))
+       {
+         /* If the RHS if of the form &PTR->FLD and PTR == OP, then
+            this represents a potential dereference of PTR.  */
+         tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+         tree base = get_base_address (TREE_OPERAND (rhs, 0));
+         if (TREE_CODE (base) == INDIRECT_REF
+             && TREE_OPERAND (base, 0) == op)
+           num_loads++;
+       }
+
+      if (num_loads + num_stores > 0)
+       {
+         /* Mark OP as dereferenced.  In a subsequent pass,
+            dereferenced pointers that point to a set of
+            variables will be assigned a name tag to alias
+            all the variables OP points to.  */
+         pi->memory_tag_needed = 1;
+
+         /* ???  For always executed direct dereferences we can
+            apply TBAA-pruning to their escape set.  */
+
+         /* If this is a store operation, mark OP as being
+            dereferenced to store, otherwise mark it as being
+            dereferenced to load.  */
+         if (num_stores > 0)
+           pointer_set_insert (ai->dereferenced_ptrs_store, var);
+         else
+           pointer_set_insert (ai->dereferenced_ptrs_load, var);
+
+         /* Update the frequency estimate for all the dereferences of
+            pointer OP.  */
+         update_mem_sym_stats_from_stmt (op, stmt, num_loads, num_stores);
+
+         /* Indicate that STMT contains pointer dereferences.  */
+         stmt_dereferences_ptr_p = true;
+       }
+
+      if (stmt_escape_type != NO_ESCAPE && num_loads + num_stores < num_uses)
+       {
+         /* If STMT is an escape point and STMT contains at
+            least one direct use of OP, then the value of OP
+            escapes and so the pointed-to variables need to
+            be marked call-clobbered.  */
+         pi->value_escapes_p = 1;
+         pi->escape_mask |= stmt_escape_type;
+
+         /* If the statement makes a function call, assume
+            that pointer OP will be dereferenced in a store
+            operation inside the called function.  */
+         if (get_call_expr_in (stmt)
+             || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
+           {
+             pointer_set_insert (ai->dereferenced_ptrs_store, var);
+             pi->memory_tag_needed = 1;
+           }
+       }
+    }
+
+  if (TREE_CODE (stmt) == PHI_NODE)
+    return;
+
+  /* Mark stored variables in STMT as being written to and update the
+     memory reference stats for all memory symbols referenced by STMT.  */
+  if (stmt_references_memory_p (stmt))
+    {
+      unsigned i;
+      bitmap_iterator bi;
+
+      mem_ref_stats->num_mem_stmts++;
+
+      /* Notice that we only update memory reference stats for symbols
+        loaded and stored by the statement if the statement does not
+        contain pointer dereferences and it is not a call/asm site.
+        This is to avoid double accounting problems when creating
+        memory partitions.  After computing points-to information,
+        pointer dereference statistics are used to update the
+        reference stats of the pointed-to variables, so here we
+        should only update direct references to symbols.
+
+        Indirect references are not updated here for two reasons: (1)
+        The first time we compute alias information, the sets
+        LOADED/STORED are empty for pointer dereferences, (2) After
+        partitioning, LOADED/STORED may have references to
+        partitions, not the original pointed-to variables.  So, if we
+        always counted LOADED/STORED here and during partitioning, we
+        would count many symbols more than once.
+
+        This does cause some imprecision when a statement has a
+        combination of direct symbol references and pointer
+        dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
+        memory symbols in its argument list, but these cases do not
+        occur so frequently as to constitute a serious problem.  */
+      if (STORED_SYMS (stmt))
+       EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
+         {
+           tree sym = referenced_var (i);
+           pointer_set_insert (ai->written_vars, sym);
+           if (!stmt_dereferences_ptr_p
+               && stmt_escape_type != ESCAPE_TO_CALL
+               && stmt_escape_type != ESCAPE_TO_PURE_CONST
+               && stmt_escape_type != ESCAPE_TO_ASM)
+             update_mem_sym_stats_from_stmt (sym, stmt, 0, 1);
+         }
+
+      if (!stmt_dereferences_ptr_p
+         && LOADED_SYMS (stmt)
+         && stmt_escape_type != ESCAPE_TO_CALL
+         && stmt_escape_type != ESCAPE_TO_PURE_CONST
+         && stmt_escape_type != ESCAPE_TO_ASM)
+       EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi)
+         update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
+    }
+}
+
+/* Update various related attributes like escaped addresses,
+   pointer dereferences for loads and stores.  This is used
+   when creating name tags and alias sets.  */
+
+static void
+update_alias_info (struct alias_info *ai)
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator bsi;
+      tree phi;
+
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+       if (is_gimple_reg (PHI_RESULT (phi)))
+         update_alias_info_1 (phi, ai);
+
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+       update_alias_info_1 (bsi_stmt (bsi), ai);
+    }
+}
+
 /* Create memory tags for all the dereferenced pointers and build the
    ADDRESSABLE_VARS and POINTERS arrays used for building the may-alias
    sets.  Based on the address escape and points-to information collected
index 4a3896b..b2ba204 100644 (file)
@@ -2526,13 +2526,11 @@ get_constraint_exp_from_ssa_var (tree t)
   return cexpr;
 }
 
-/* Process a completed constraint T, and add it to the constraint
-   list.  FROM_CALL is true if this is a constraint coming from a
-   call, which means any DEREFs we see are "may-deref's", not
-   "must-deref"'s.  */
+/* Process constraint T, performing various simplifications and then
+   adding it to our list of overall constraints.  */
 
 static void
-process_constraint_1 (constraint_t t, bool from_call)
+process_constraint (constraint_t t)
 {
   struct constraint_expr rhs = t->rhs;
   struct constraint_expr lhs = t->lhs;
@@ -2556,7 +2554,7 @@ process_constraint_1 (constraint_t t, bool from_call)
       rhs = t->lhs;
       t->lhs = t->rhs;
       t->rhs = rhs;
-      process_constraint_1 (t, from_call);
+      process_constraint (t);
     }
   /* This can happen in our IR with things like n->a = *p */
   else if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id)
@@ -2574,8 +2572,8 @@ process_constraint_1 (constraint_t t, bool from_call)
       gcc_assert (!AGGREGATE_TYPE_P (pointedtotype)
                  || get_varinfo (rhs.var)->is_unknown_size_var);
 
-      process_constraint_1 (new_constraint (tmplhs, rhs), from_call);
-      process_constraint_1 (new_constraint (lhs, tmplhs), from_call);
+      process_constraint (new_constraint (tmplhs, rhs));
+      process_constraint (new_constraint (lhs, tmplhs));
     }
   else if (rhs.type == ADDRESSOF && lhs.type == DEREF)
     {
@@ -2585,8 +2583,8 @@ process_constraint_1 (constraint_t t, bool from_call)
       tree tmpvar = create_tmp_var_raw (pointertype, "derefaddrtmp");
       struct constraint_expr tmplhs = get_constraint_exp_from_ssa_var (tmpvar);
 
-      process_constraint_1 (new_constraint (tmplhs, rhs), from_call);
-      process_constraint_1 (new_constraint (lhs, tmplhs), from_call);
+      process_constraint (new_constraint (tmplhs, rhs));
+      process_constraint (new_constraint (lhs, tmplhs));
     }
   else
     {
@@ -2595,16 +2593,6 @@ process_constraint_1 (constraint_t t, bool from_call)
     }
 }
 
-
-/* Process constraint T, performing various simplifications and then
-   adding it to our list of overall constraints.  */
-
-static void
-process_constraint (constraint_t t)
-{
-  process_constraint_1 (t, false);
-}
-
 /* Return true if T is a variable of a type that could contain
    pointers.  */
 
@@ -3267,248 +3255,6 @@ do_structure_copy (tree lhsop, tree rhsop)
 }
 
 
-/* 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;
-  ssa_op_iter iter;
-  bool stmt_dereferences_ptr_p;
-  enum escape_type stmt_escape_type = is_escape_site (stmt);
-  struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
-
-  stmt_dereferences_ptr_p = false;
-
-  if (stmt_escape_type == ESCAPE_TO_CALL
-      || stmt_escape_type == ESCAPE_TO_PURE_CONST)
-    {
-      mem_ref_stats->num_call_sites++;
-      if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
-       mem_ref_stats->num_pure_const_call_sites++;
-    }
-  else if (stmt_escape_type == ESCAPE_TO_ASM)
-    mem_ref_stats->num_asm_sites++;
-
-  /* Mark all the variables whose address are taken by the statement.  */
-  addr_taken = addresses_taken (stmt);
-  if (addr_taken)
-    bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
-
-  /* Process each operand use.  For pointers, determine whether they
-     are dereferenced by the statement, or whether their value
-     escapes, etc.  */
-  FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
-    {
-      tree op, var;
-      var_ann_t v_ann;
-      struct ptr_info_def *pi;
-      unsigned num_uses, num_loads, num_stores;
-
-      op = USE_FROM_PTR (use_p);
-
-      /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
-        to the set of addressable variables.  */
-      if (TREE_CODE (op) == ADDR_EXPR)
-       {
-         bitmap addressable_vars = gimple_addressable_vars (cfun);
-
-         gcc_assert (TREE_CODE (stmt) == PHI_NODE);
-         gcc_assert (addressable_vars);
-
-         /* PHI nodes don't have annotations for pinning the set
-            of addresses taken, so we collect them here.
-
-            FIXME, should we allow PHI nodes to have annotations
-            so that they can be treated like regular statements?
-            Currently, they are treated as second-class
-            statements.  */
-         add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
-         continue;
-       }
-
-      /* Ignore constants (they may occur in PHI node arguments).  */
-      if (TREE_CODE (op) != SSA_NAME)
-       continue;
-
-      var = SSA_NAME_VAR (op);
-      v_ann = var_ann (var);
-
-      /* The base variable of an SSA name must be a GIMPLE register, and thus
-        it cannot be aliased.  */
-      gcc_assert (!may_be_aliased (var));
-
-      /* We are only interested in pointers.  */
-      if (!POINTER_TYPE_P (TREE_TYPE (op)))
-       continue;
-
-      pi = get_ptr_info (op);
-
-      /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
-      if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
-       {
-         SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
-         VEC_safe_push (tree, heap, ai->processed_ptrs, op);
-       }
-
-      /* If STMT is a PHI node, then it will not have pointer
-        dereferences and it will not be an escape point.  */
-      if (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_loads, &num_stores);
-
-      /* For directly dereferenced pointers we can apply
-        TBAA-pruning to their points-to set.  We may not count the
-        implicit dereferences &PTR->FLD here.  */
-      if (num_loads + num_stores > 0)
-       pi->is_dereferenced = 1;
-
-      /* Handle a corner case involving address expressions of the
-        form '&PTR->FLD'.  The problem with these expressions is that
-        they do not represent a dereference of PTR.  However, if some
-        other transformation propagates them into an INDIRECT_REF
-        expression, we end up with '*(&PTR->FLD)' which is folded
-        into 'PTR->FLD'.
-
-        So, if the original code had no other dereferences of PTR,
-        the aliaser will not create memory tags for it, and when
-        &PTR->FLD gets propagated to INDIRECT_REF expressions, the
-        memory operations will receive no VDEF/VUSE operands.
-
-        One solution would be to have count_uses_and_derefs consider
-        &PTR->FLD a dereference of PTR.  But that is wrong, since it
-        is not really a dereference but an offset calculation.
-
-        What we do here is to recognize these special ADDR_EXPR
-        nodes.  Since these expressions are never GIMPLE values (they
-        are not GIMPLE invariants), they can only appear on the RHS
-        of an assignment and their base address is always an
-        INDIRECT_REF expression.  */
-      if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-         && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR
-         && !is_gimple_val (GIMPLE_STMT_OPERAND (stmt, 1)))
-       {
-         /* If the RHS if of the form &PTR->FLD and PTR == OP, then
-            this represents a potential dereference of PTR.  */
-         tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-         tree base = get_base_address (TREE_OPERAND (rhs, 0));
-         if (TREE_CODE (base) == INDIRECT_REF
-             && TREE_OPERAND (base, 0) == op)
-           num_loads++;
-       }
-
-      if (num_loads + num_stores > 0)
-       {
-         /* Mark OP as dereferenced.  In a subsequent pass,
-            dereferenced pointers that point to a set of
-            variables will be assigned a name tag to alias
-            all the variables OP points to.  */
-         pi->memory_tag_needed = 1;
-
-         /* ???  For always executed direct dereferences we can
-            apply TBAA-pruning to their escape set.  */
-
-         /* If this is a store operation, mark OP as being
-            dereferenced to store, otherwise mark it as being
-            dereferenced to load.  */
-         if (num_stores > 0)
-           pointer_set_insert (ai->dereferenced_ptrs_store, var);
-         else
-           pointer_set_insert (ai->dereferenced_ptrs_load, var);
-
-         /* Update the frequency estimate for all the dereferences of
-            pointer OP.  */
-         update_mem_sym_stats_from_stmt (op, stmt, num_loads, num_stores);
-
-         /* Indicate that STMT contains pointer dereferences.  */
-         stmt_dereferences_ptr_p = true;
-       }
-
-      if (stmt_escape_type != NO_ESCAPE && num_loads + num_stores < num_uses)
-       {
-         /* If STMT is an escape point and STMT contains at
-            least one direct use of OP, then the value of OP
-            escapes and so the pointed-to variables need to
-            be marked call-clobbered.  */
-         pi->value_escapes_p = 1;
-         pi->escape_mask |= stmt_escape_type;
-
-         /* If the statement makes a function call, assume
-            that pointer OP will be dereferenced in a store
-            operation inside the called function.  */
-         if (get_call_expr_in (stmt)
-             || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
-           {
-             pointer_set_insert (ai->dereferenced_ptrs_store, var);
-             pi->memory_tag_needed = 1;
-           }
-       }
-    }
-
-  if (TREE_CODE (stmt) == PHI_NODE)
-    return;
-
-  /* Mark stored variables in STMT as being written to and update the
-     memory reference stats for all memory symbols referenced by STMT.  */
-  if (stmt_references_memory_p (stmt))
-    {
-      unsigned i;
-      bitmap_iterator bi;
-
-      mem_ref_stats->num_mem_stmts++;
-
-      /* Notice that we only update memory reference stats for symbols
-        loaded and stored by the statement if the statement does not
-        contain pointer dereferences and it is not a call/asm site.
-        This is to avoid double accounting problems when creating
-        memory partitions.  After computing points-to information,
-        pointer dereference statistics are used to update the
-        reference stats of the pointed-to variables, so here we
-        should only update direct references to symbols.
-
-        Indirect references are not updated here for two reasons: (1)
-        The first time we compute alias information, the sets
-        LOADED/STORED are empty for pointer dereferences, (2) After
-        partitioning, LOADED/STORED may have references to
-        partitions, not the original pointed-to variables.  So, if we
-        always counted LOADED/STORED here and during partitioning, we
-        would count many symbols more than once.
-
-        This does cause some imprecision when a statement has a
-        combination of direct symbol references and pointer
-        dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
-        memory symbols in its argument list, but these cases do not
-        occur so frequently as to constitute a serious problem.  */
-      if (STORED_SYMS (stmt))
-       EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
-         {
-           tree sym = referenced_var (i);
-           pointer_set_insert (ai->written_vars, sym);
-           if (!stmt_dereferences_ptr_p
-               && stmt_escape_type != ESCAPE_TO_CALL
-               && stmt_escape_type != ESCAPE_TO_PURE_CONST
-               && stmt_escape_type != ESCAPE_TO_ASM)
-             update_mem_sym_stats_from_stmt (sym, stmt, 0, 1);
-         }
-
-      if (!stmt_dereferences_ptr_p
-         && LOADED_SYMS (stmt)
-         && stmt_escape_type != ESCAPE_TO_CALL
-         && stmt_escape_type != ESCAPE_TO_PURE_CONST
-         && stmt_escape_type != ESCAPE_TO_ASM)
-       EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi)
-         update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
-    }
-}
-
-
 /* Handle pointer arithmetic EXPR when creating aliasing constraints.
    Expressions of the type PTR + CST can be handled in two ways:
 
@@ -3598,7 +3344,7 @@ make_constraint_to (unsigned id, tree op)
 
   get_constraint_for (op, &rhsc);
   for (j = 0; VEC_iterate (ce_s, rhsc, j, c); j++)
-    process_constraint_1 (new_constraint (includes, *c), true);
+    process_constraint (new_constraint (includes, *c));
   VEC_free (ce_s, heap, rhsc);
 }
 
@@ -3643,16 +3389,11 @@ handle_lhs_call (tree lhs)
   struct constraint_expr *lhsp;
 
   get_constraint_for (lhs, &lhsc);
-  rhsc.var = nonlocal_id;
-  rhsc.offset = 0;
-  rhsc.type = ADDRESSOF;
-  for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
-    process_constraint_1 (new_constraint (*lhsp, rhsc), true);
   rhsc.var = escaped_id;
   rhsc.offset = 0;
   rhsc.type = ADDRESSOF;
   for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
-    process_constraint_1 (new_constraint (*lhsp, rhsc), true);
+    process_constraint (new_constraint (*lhsp, rhsc));
   VEC_free (ce_s, heap, lhsc);
 }
 
@@ -3680,7 +3421,7 @@ handle_const_call (tree stmt)
       rhsc.offset = 0;
       rhsc.type = ADDRESSOF;
       for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
-       process_constraint_1 (new_constraint (*lhsp, rhsc), true);
+       process_constraint (new_constraint (*lhsp, rhsc));
       VEC_free (ce_s, heap, lhsc);
       return;
     }
@@ -3690,7 +3431,7 @@ handle_const_call (tree stmt)
   rhsc.offset = 0;
   rhsc.type = ADDRESSOF;
   for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
-    process_constraint_1 (new_constraint (*lhsp, rhsc), true);
+    process_constraint (new_constraint (*lhsp, rhsc));
 
   /* May return arguments.  */
   FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
@@ -3702,7 +3443,7 @@ handle_const_call (tree stmt)
        get_constraint_for (arg, &argc);
        for (i = 0; VEC_iterate (ce_s, argc, i, argp); i++)
          for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
-           process_constraint_1 (new_constraint (*lhsp, *argp), true);
+           process_constraint (new_constraint (*lhsp, *argp));
        VEC_free (ce_s, heap, argc);
       }
 
@@ -3748,7 +3489,7 @@ handle_pure_call (tree stmt)
          rhsc.offset = 0;
          rhsc.type = ADDRESSOF;
          for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
-           process_constraint_1 (new_constraint (*lhsp, rhsc), true);
+           process_constraint (new_constraint (*lhsp, rhsc));
          VEC_free (ce_s, heap, lhsc);
          return;
        }
@@ -3759,7 +3500,7 @@ handle_pure_call (tree stmt)
       rhsc.offset = 0;
       rhsc.type = ADDRESSOF;
       for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
-       process_constraint_1 (new_constraint (*lhsp, rhsc), true);
+       process_constraint (new_constraint (*lhsp, rhsc));
       VEC_free (ce_s, heap, lhsc);
     }
 }
@@ -3957,10 +3698,8 @@ find_func_aliases (tree origt)
       tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
       int i;
 
-      if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
-          || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
-         && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop))
-             || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE))
+      if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
+         && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
        {
          do_structure_copy (lhsop, rhsop);
        }
@@ -4340,13 +4079,6 @@ make_constraint_from (varinfo_t vi, int from)
   process_constraint (new_constraint (lhs, rhs));
 }
 
-/* Create a constraint from ANYTHING variable to VI.  */
-static void
-make_constraint_from_anything (varinfo_t vi)
-{
-  make_constraint_from (vi, anything_id);
-}
-
 /* Count the number of arguments DECL has, and set IS_VARARGS to true
    if it is a varargs function.  */
 
@@ -4552,8 +4284,9 @@ create_variable_info_for (tree decl, const char *name)
 
   insert_vi_for_tree (vi->decl, vi);
   VEC_safe_push (varinfo_t, heap, varmap, vi);
-  if (is_global && (!flag_whole_program || !in_ipa_mode))
-    make_constraint_from_anything (vi);
+  if (is_global && (!flag_whole_program || !in_ipa_mode)
+      && could_have_pointers (decl))
+    make_constraint_from (vi, escaped_id);
 
   stats.total_vars++;
   if (use_field_sensitive
@@ -4633,8 +4366,9 @@ create_variable_info_for (tree decl, const char *name)
          newvi->fullsize = vi->fullsize;
          insert_into_field_list (vi, newvi);
          VEC_safe_push (varinfo_t, heap, varmap, newvi);
-         if (is_global && (!flag_whole_program || !in_ipa_mode))
-             make_constraint_from_anything (newvi);
+         if (is_global && (!flag_whole_program || !in_ipa_mode)
+             && (!fo->decl || could_have_pointers (fo->decl)))
+           make_constraint_from (newvi, escaped_id);
 
          stats.total_vars++;
        }
@@ -5296,7 +5030,7 @@ init_base_vars (void)
   rhs.type = DEREF;
   rhs.var = escaped_id;
   rhs.offset = 0;
-  process_constraint_1 (new_constraint (lhs, rhs), true);
+  process_constraint (new_constraint (lhs, rhs));
 
   /* Create the NONLOCAL variable, used to represent the set of nonlocal
      memory.  */
@@ -5339,7 +5073,7 @@ init_base_vars (void)
   rhs.type = DEREF;
   rhs.var = callused_id;
   rhs.offset = 0;
-  process_constraint_1 (new_constraint (lhs, rhs), true);
+  process_constraint (new_constraint (lhs, rhs));
 
   /* Create the INTEGER variable, used to represent that a variable points
      to an INTEGER.  */
@@ -5372,7 +5106,7 @@ init_base_vars (void)
   rhs.type = ADDRESSOF;
   rhs.var = escaped_id;
   rhs.offset = 0;
-  process_constraint_1 (new_constraint (lhs, rhs), true);
+  process_constraint (new_constraint (lhs, rhs));
 
   /* *ESCAPED = &NONLOCAL.  This is true because we have to assume
      everything pointed to by escaped can also point to nonlocal. */
@@ -5382,7 +5116,7 @@ init_base_vars (void)
   rhs.type = ADDRESSOF;
   rhs.var = nonlocal_id;
   rhs.offset = 0;
-  process_constraint_1 (new_constraint (lhs, rhs), true);
+  process_constraint (new_constraint (lhs, rhs));
 }
 
 /* Initialize things necessary to perform PTA */
@@ -5581,7 +5315,7 @@ compute_tbaa_pruning (void)
    at the start of the file for an algorithmic overview.  */
 
 void
-compute_points_to_sets (struct alias_info *ai)
+compute_points_to_sets (void)
 {
   struct scc_info *si;
   basic_block bb;
@@ -5600,18 +5334,8 @@ compute_points_to_sets (struct alias_info *ai)
       tree phi;
 
       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-       {
-         if (is_gimple_reg (PHI_RESULT (phi)))
-           {
-             find_func_aliases (phi);
-
-             /* 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 (phi, ai);
-           }
-       }
+       if (is_gimple_reg (PHI_RESULT (phi)))
+         find_func_aliases (phi);
 
       for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
        {
@@ -5619,12 +5343,6 @@ compute_points_to_sets (struct alias_info *ai)
 
          find_func_aliases (stmt);
 
-         /* 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 (stmt, ai);
-
          /* The information in CHANGE_DYNAMIC_TYPE_EXPR nodes has now
             been captured, and we can remove them.  */
          if (TREE_CODE (stmt) == CHANGE_DYNAMIC_TYPE_EXPR)
@@ -5761,7 +5479,7 @@ ipa_pta_execute (void)
            {
              varinfo_t fi = get_varinfo (varid);
              for (; fi; fi = fi->next)
-               make_constraint_from_anything (fi);
+               make_constraint_from (fi, anything_id);
            }
        }
     }
index 737135b..7d468b4 100644 (file)
 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.  */
-  VEC(tree,heap) *processed_ptrs;
-
-  /* ADDRESSABLE_VARS contains all the global variables and locals that
-     have had their address taken.  */
-  struct alias_map_d **addressable_vars;
-  size_t num_addressable_vars;
-
-  /* POINTERS contains all the _DECL pointers with unique memory tags
-     that have been referenced in the program.  */
-  struct alias_map_d **pointers;
-  size_t num_pointers;
-
-  /* Variables that have been written to directly (i.e., not through a
-     pointer dereference).  */
-  struct pointer_set_t *written_vars;
-
-  /* Pointers that have been used in an indirect store operation.  */
-  struct pointer_set_t *dereferenced_ptrs_store;
-
-  /* Pointers that have been used in an indirect load operation.  */
-  struct pointer_set_t *dereferenced_ptrs_load;
-};
-
 /* In tree-ssa-alias.c.  */
 enum escape_type is_escape_site (tree);
 void update_mem_sym_stats_from_stmt (tree, tree, long, long);
 
 /* In tree-ssa-structalias.c.  */
-extern void compute_points_to_sets (struct alias_info *);
+extern void compute_points_to_sets (void);
 extern void delete_points_to_sets (void);
 extern void dump_constraint (FILE *, constraint_t);
 extern void dump_constraints (FILE *);