OSDN Git Service

Fix aliasing bug that also caused memory usage problems.
[pf3gnuchains/gcc-fork.git] / gcc / tree-vn.c
index de4c361..061a7ac 100644 (file)
@@ -42,7 +42,16 @@ static htab_t value_table;
    pairs, and the expression is the key.  */
 typedef struct val_expr_pair_d
 {
-  tree v, e;
+  /* Value handle.  */
+  tree v;
+
+  /* Associated expression.  */
+  tree e;
+
+  /* Virtual uses in E.  */
+  vuse_optype vuses;
+
+  /* E's hash value.  */
   hashval_t hashcode;
 } *val_expr_pair_t;
 
@@ -63,13 +72,37 @@ make_value_handle (tree type)
 }
 
 
-/* Given an expression or statement P, compute a hash value number using the
-   code of the expression and its real operands.  */
+/* Given an expression EXPR, compute a hash value number using the
+   code of the expression, its real operands and virtual operands (if
+   any).
+   
+   VAL can be used to iterate by passing previous value numbers (it is
+   used by iterative_hash_expr).
+
+   VUSES is the set of virtual use operands associated with EXPR.  It
+   may be NULL if EXPR has no virtual operands.  */
 
 hashval_t
-vn_compute (tree expr, hashval_t val)
+vn_compute (tree expr, hashval_t val, vuse_optype vuses)
 {
+  size_t i;
+
+#if defined ENABLE_CHECKING
+  /* EXPR must not be a statement.  We are only interested in value
+     numbering expressions on the RHS of assignments.  */
+  if (expr == NULL_TREE
+      || (expr->common.ann
+         && expr->common.ann->common.type == STMT_ANN))
+    abort ();
+#endif
+
   val = iterative_hash_expr (expr, val);
+
+  /* If the expression has virtual uses, incorporate them into the
+     hash value computed for EXPR.  */
+  for (i = 0; i < NUM_VUSES (vuses); i++)
+    val = iterative_hash_expr (VUSE_OP (vuses, i), val);
+
   return val;
 }
 
@@ -90,7 +123,7 @@ expressions_equal_p (tree e1, tree e2)
 
   if (TREE_CODE (e1) == TREE_CODE (e2) 
       && (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
-      && operand_equal_p (e1, e2, 0))
+      && operand_equal_p (e1, e2, OEP_PURE_SAME))
     return true;
 
   return false;
@@ -118,11 +151,20 @@ val_expr_pair_expr_eq (const void *p1, const void *p2)
 {
   const val_expr_pair_t ve1 = (val_expr_pair_t) p1;
   const val_expr_pair_t ve2 = (val_expr_pair_t) p2;
+  size_t i;
 
-  if (expressions_equal_p (ve1->e, ve2->e))
-    return true;
+  if (! expressions_equal_p (ve1->e, ve2->e))
+    return false;
+
+  if (NUM_VUSES (ve1->vuses) != NUM_VUSES (ve2->vuses))
+    return false;
   
-  return false;
+  for (i = 0; i < NUM_VUSES (ve1->vuses); i++)
+    if (! expressions_equal_p (VUSE_OP (ve1->vuses, i),
+                              VUSE_OP (ve2->vuses, i)))
+      return false;
+  
+  return true;
 }
 
 
@@ -135,7 +177,7 @@ set_value_handle (tree e, tree v)
     SSA_NAME_VALUE (e) = v;
   else if (EXPR_P (e) || DECL_P (e))
     get_tree_ann (e)->common.value_handle = v;
-  else if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
+  else if (is_gimple_min_invariant (e))
     /* Do nothing.  Constants are their own value handles.  */
     ;
   else
@@ -143,41 +185,51 @@ set_value_handle (tree e, tree v)
 }
 
 
-/* Insert E into VALUE_TABLE with value V, and add expression E to the
-   value set for value V.  */
+/* Insert EXPR into VALUE_TABLE with value VAL, and add expression
+   EXPR to the value set for value VAL.  VUSES represent the virtual
+   use operands associated with EXPR (if any).  They are used when
+   computing the hash value for EXPR.  */
 
 void
-vn_add (tree e, tree v)
+vn_add (tree expr, tree val, vuse_optype vuses)
 {
   void **slot;
-  val_expr_pair_t new_pair = xmalloc (sizeof (struct val_expr_pair_d));
-  new_pair->e = e;
-  new_pair->v = v;
-  new_pair->hashcode = vn_compute (e, 0);
+  val_expr_pair_t new_pair;
+  
+  new_pair = xmalloc (sizeof (struct val_expr_pair_d));
+  new_pair->e = expr;
+  new_pair->v = val;
+  new_pair->vuses = vuses;
+  new_pair->hashcode = vn_compute (expr, 0, vuses);
   slot = htab_find_slot_with_hash (value_table, new_pair, new_pair->hashcode,
                                   INSERT);
   if (*slot)
     free (*slot);
   *slot = (void *) new_pair;
-  set_value_handle (e, v);
 
-  add_to_value (v, e);
+  set_value_handle (expr, val);
+  add_to_value (val, expr);
 }
 
 
-/* Search in VALUE_TABLE for an existing instance of expression E, and
-   return its value, or NULL if none has been set.  */
+/* Search in VALUE_TABLE for an existing instance of expression EXPR,
+   and return its value, or NULL if none has been set.  VUSES
+   represent the virtual use operands associated with EXPR (if any).
+   They are used when computing the hash value for EXPR.  */
 
 tree
-vn_lookup (tree e)
+vn_lookup (tree expr, vuse_optype vuses)
 {
   void **slot;
-  struct val_expr_pair_d vep = {NULL, NULL, 0};
+  struct val_expr_pair_d vep = {NULL, NULL, NULL, 0};
 
-  if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
-    return e;
-  vep.e = e;
-  vep.hashcode = vn_compute (e, 0); 
+  /* Constants are their own value.  */
+  if (is_gimple_min_invariant (expr))
+    return expr;
+
+  vep.e = expr;
+  vep.vuses = vuses;
+  vep.hashcode = vn_compute (expr, 0, vuses); 
   slot = htab_find_slot_with_hash (value_table, &vep, vep.hashcode, NO_INSERT);
   if (!slot)
     return NULL_TREE;
@@ -186,52 +238,54 @@ vn_lookup (tree e)
 }
 
 
-/* Like vn_lookup, but creates a new value for expression E if E doesn't
-   already have a value.  Return the existing/created value for E.  */
+/* Like vn_lookup, but creates a new value for expression EXPR, if
+   EXPR doesn't already have a value.  Return the existing/created
+   value for EXPR.  VUSES represent the virtual use operands
+   associated with EXPR (if any).  They are used when computing the
+   hash value for EXPR.  */
 
 tree
-vn_lookup_or_add (tree e)
+vn_lookup_or_add (tree expr, vuse_optype vuses)
 {
-  tree x = vn_lookup (e);
-  if (x == NULL_TREE)
+  tree v = vn_lookup (expr, vuses);
+  if (v == NULL_TREE)
     {
-      tree v = make_value_handle (TREE_TYPE (e));
+      v = make_value_handle (TREE_TYPE (expr));
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        {     
          fprintf (dump_file, "Created value ");
          print_generic_expr (dump_file, v, dump_flags);
          fprintf (dump_file, " for ");
-         print_generic_expr (dump_file, e, dump_flags);
+         print_generic_expr (dump_file, expr, dump_flags);
          fprintf (dump_file, "\n");
        }
 
-      vn_add (e, v);
-      x = v;
+      vn_add (expr, v, vuses);
     }
 
-  set_value_handle (e, x);
+  set_value_handle (expr, v);
 
-  return x;
+  return v;
 }
 
 
 /* Get the value handle of EXPR.  This is the only correct way to get
    the value handle for a "thing".  If EXPR does not have a value
-   handle associated, it generates and returns a new one.  */
+   handle associated, it returns NULL_TREE.  */
 
 tree
 get_value_handle (tree expr)
 {
   if (TREE_CODE (expr) == SSA_NAME)
     return SSA_NAME_VALUE (expr);
-  else if (TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
-    return expr;
   else if (EXPR_P (expr) || DECL_P (expr))
     {
       tree_ann_t ann = tree_ann (expr);
       return ((ann) ? ann->common.value_handle : NULL_TREE);
     }
+  else if (is_gimple_min_invariant (expr))
+    return expr;
 
   abort ();
 }