OSDN Git Service

PR c++/39413
[pf3gnuchains/gcc-fork.git] / gcc / gimple.c
index 481daf0..676e3fd 100644 (file)
@@ -46,6 +46,7 @@ static struct pointer_map_t *type_hash_cache;
 
 /* Global type comparison cache.  */
 static htab_t gtc_visited;
+static struct obstack gtc_ob;
 
 /* All the tuples have their operand vector (if present) at the very bottom
    of the structure.  Therefore, the offset required to find the
@@ -3025,8 +3026,8 @@ static hashval_t gimple_type_hash (const void *);
    infinite recursion due to self-referential types.  */
 struct type_pair_d
 {
-  tree t1;
-  tree t2;
+  unsigned int uid1;
+  unsigned int uid2;
   int same_p;
 };
 typedef struct type_pair_d *type_pair_t;
@@ -3037,8 +3038,8 @@ static hashval_t
 type_pair_hash (const void *p)
 {
   const struct type_pair_d *pair = (const struct type_pair_d *) p;
-  hashval_t val1 = iterative_hash_hashval_t (htab_hash_pointer (pair->t1), 0);
-  hashval_t val2 = iterative_hash_hashval_t (htab_hash_pointer (pair->t2), 0);
+  hashval_t val1 = pair->uid1;
+  hashval_t val2 = pair->uid2;
   return (iterative_hash_hashval_t (val2, val1)
          ^ iterative_hash_hashval_t (val1, val2));
 }
@@ -3050,34 +3051,37 @@ type_pair_eq (const void *p1, const void *p2)
 {
   const struct type_pair_d *pair1 = (const struct type_pair_d *) p1;
   const struct type_pair_d *pair2 = (const struct type_pair_d *) p2;
-  return ((pair1->t1 == pair2->t1 && pair1->t2 == pair2->t2)
-         || (pair1->t1 == pair2->t2 && pair1->t2 == pair2->t1));
+  return ((pair1->uid1 == pair2->uid1 && pair1->uid2 == pair2->uid2)
+         || (pair1->uid1 == pair2->uid2 && pair1->uid2 == pair2->uid1));
 }
 
 /* Lookup the pair of types T1 and T2 in *VISITED_P.  Insert a new
    entry if none existed.  */
 
 static type_pair_t
-lookup_type_pair (tree t1, tree t2, htab_t *visited_p)
+lookup_type_pair (tree t1, tree t2, htab_t *visited_p, struct obstack *ob_p)
 {
   struct type_pair_d pair;
   type_pair_t p;
   void **slot;
 
   if (*visited_p == NULL)
-    *visited_p = htab_create (251, type_pair_hash, type_pair_eq, free);
+    {
+      *visited_p = htab_create (251, type_pair_hash, type_pair_eq, NULL);
+      gcc_obstack_init (ob_p);
+    }
 
-  pair.t1 = t1;
-  pair.t2 = t2;
+  pair.uid1 = TYPE_UID (t1);
+  pair.uid2 = TYPE_UID (t2);
   slot = htab_find_slot (*visited_p, &pair, INSERT);
 
   if (*slot)
     p = *((type_pair_t *) slot);
   else
     {
-      p = XNEW (struct type_pair_d);
-      p->t1 = t1;
-      p->t2 = t2;
+      p = XOBNEW (ob_p, struct type_pair_d);
+      p->uid1 = TYPE_UID (t1);
+      p->uid2 = TYPE_UID (t2);
       p->same_p = -2;
       *slot = (void *) p;
     }
@@ -3086,62 +3090,38 @@ lookup_type_pair (tree t1, tree t2, htab_t *visited_p)
 }
 
 
-/* Force merging the type T2 into the type T1.  */
-
-void
-gimple_force_type_merge (tree t1, tree t2)
-{
-  void **slot;
-  type_pair_t p;
-
-  /* There's no other way than copying t2 to t1 in this case.
-     Yuck.  We'll just call this "completing" t1.  */
-  memcpy (t1, t2, tree_size (t1));
-
-  /* Adjust the hash value of T1 if it was computed already.  Otherwise
-     we would be forced to not hash fields of structs to match the
-     hash value of an incomplete struct.  */
-  if (type_hash_cache
-      && (slot = pointer_map_contains (type_hash_cache, t1)) != NULL)
-    {
-      gimple_type_hash (t2);
-      *slot = *pointer_map_contains (type_hash_cache, t2);
-    }
-
-  /* Adjust cached comparison results for T1 and T2 to make sure
-     they now compare compatible.  */
-  p = lookup_type_pair (t1, t2, &gtc_visited);
-  p->same_p = 1;
-}
-
-
-/* Return true if both types have the same name.  */
+/* Return true if T1 and T2 have the same name.  If FOR_COMPLETION_P is
+   true then if any type has no name return false, otherwise return
+   true if both types have no names.  */
 
 static bool
-compare_type_names_p (tree t1, tree t2)
+compare_type_names_p (tree t1, tree t2, bool for_completion_p)
 {
   tree name1 = TYPE_NAME (t1);
   tree name2 = TYPE_NAME (t2);
 
-  /* Consider anonymous types all unique.  */
-  if (!name1 || !name2)
+  /* Consider anonymous types all unique for completion.  */
+  if (for_completion_p
+      && (!name1 || !name2))
     return false;
 
-  if (TREE_CODE (name1) == TYPE_DECL)
+  if (name1 && TREE_CODE (name1) == TYPE_DECL)
     {
       name1 = DECL_NAME (name1);
-      if (!name1)
+      if (for_completion_p
+         && !name1)
        return false;
     }
-  gcc_assert (TREE_CODE (name1) == IDENTIFIER_NODE);
+  gcc_assert (!name1 || TREE_CODE (name1) == IDENTIFIER_NODE);
 
-  if (TREE_CODE (name2) == TYPE_DECL)
+  if (name2 && TREE_CODE (name2) == TYPE_DECL)
     {
       name2 = DECL_NAME (name2);
-      if (!name2)
+      if (for_completion_p
+         && !name2)
        return false;
     }
-  gcc_assert (TREE_CODE (name2) == IDENTIFIER_NODE);
+  gcc_assert (!name2 || TREE_CODE (name2) == IDENTIFIER_NODE);
 
   /* Identifiers can be compared with pointer equality rather
      than a string comparison.  */
@@ -3187,30 +3167,65 @@ compare_field_offset (tree f1, tree f2)
 /* Return 1 iff T1 and T2 are structurally identical.
    Otherwise, return 0.  */
 
-int
+static int
 gimple_types_compatible_p (tree t1, tree t2)
 {
   type_pair_t p = NULL;
 
   /* Check first for the obvious case of pointer identity.  */
   if (t1 == t2)
-    goto same_types;
+    return 1;
 
   /* Check that we have two types to compare.  */
   if (t1 == NULL_TREE || t2 == NULL_TREE)
-    goto different_types;
+    return 0;
 
   /* Can't be the same type if the types don't have the same code.  */
   if (TREE_CODE (t1) != TREE_CODE (t2))
-    goto different_types;
+    return 0;
+
+  /* Can't be the same type if they have different CV qualifiers.  */
+  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
+    return 0;
 
   /* Void types are always the same.  */
   if (TREE_CODE (t1) == VOID_TYPE)
-    goto same_types;
+    return 1;
 
-  /* Can't be the same type if they have different CV qualifiers.  */
-  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
-    goto different_types;
+  /* For numerical types do some simple checks before doing three
+     hashtable queries.  */
+  if (INTEGRAL_TYPE_P (t1)
+      || SCALAR_FLOAT_TYPE_P (t1)
+      || FIXED_POINT_TYPE_P (t1)
+      || TREE_CODE (t1) == VECTOR_TYPE
+      || TREE_CODE (t1) == COMPLEX_TYPE
+      || TREE_CODE (t1) == OFFSET_TYPE)
+    {
+      /* Can't be the same type if they have different alignment,
+        sign, precision or mode.  */
+      if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
+         || TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
+         || TYPE_MODE (t1) != TYPE_MODE (t2)
+         || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
+       return 0;
+
+      if (TREE_CODE (t1) == INTEGER_TYPE
+         && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
+             || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
+       return 0;
+
+      /* That's all we need to check for float and fixed-point types.  */
+      if (SCALAR_FLOAT_TYPE_P (t1)
+         || FIXED_POINT_TYPE_P (t1))
+       return 1;
+
+      /* Perform cheap tail-recursion for vector and complex types.  */
+      if (TREE_CODE (t1) == VECTOR_TYPE
+         || TREE_CODE (t1) == COMPLEX_TYPE)
+       return gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2));
+
+      /* For integral types fall thru to more complex checks.  */
+    }
 
   /* If the hash values of t1 and t2 are different the types can't
      possibly be the same.  This helps keeping the type-pair hashtable
@@ -3220,7 +3235,7 @@ gimple_types_compatible_p (tree t1, tree t2)
 
   /* If we've visited this type pair before (in the case of aggregates
      with self-referential types), and we made a decision, return it.  */
-  p = lookup_type_pair (t1, t2, &gtc_visited);
+  p = lookup_type_pair (t1, t2, &gtc_visited, &gtc_ob);
   if (p->same_p == 0 || p->same_p == 1)
     {
       /* We have already decided whether T1 and T2 are the
@@ -3243,71 +3258,6 @@ gimple_types_compatible_p (tree t1, tree t2)
   if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
     goto different_types;
 
-  /* For numerical types, the bounds must coincide.  */
-  if (INTEGRAL_TYPE_P (t1)
-      || SCALAR_FLOAT_TYPE_P (t1)
-      || FIXED_POINT_TYPE_P (t1))
-    {
-      /* Can't be the same type if they have different size, alignment,
-        sign, precision or mode.  Note that from now on, comparisons
-        between *_CST nodes must be done using tree_int_cst_equal because
-        we cannot assume that constants from T1 and T2 will be shared
-        since T1 and T2 are distinct pointers.  */
-      if (!tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
-         || !tree_int_cst_equal (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2))
-         || TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
-         || TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
-         || TYPE_MODE (t1) != TYPE_MODE (t2)
-         || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
-       goto different_types;
-
-      /* For non-enumeral types, check type bounds.  FIXME lto, we
-        cannot check bounds on enumeral types because different front
-        ends will produce different values.  In C, enumeral types are
-        integers, while in C++ each element will have its own
-        symbolic value.  We should decide how enums are to be
-        represented in GIMPLE and have each front end lower to that.  */
-      if (TREE_CODE (t1) != ENUMERAL_TYPE)
-       {
-         tree min1 = TYPE_MIN_VALUE (t1);
-         tree max1 = TYPE_MAX_VALUE (t1);
-         tree min2 = TYPE_MIN_VALUE (t2);
-         tree max2 = TYPE_MAX_VALUE (t2);
-         bool min_equal_p = false;
-         bool max_equal_p = false;
-
-         /* If either type has a minimum value, the other type must
-            have the same.  */
-         if (min1 == NULL_TREE && min2 == NULL_TREE)
-           min_equal_p = true;
-         else if (min1 && min2 && operand_equal_p (min1, min2, 0))
-           min_equal_p = true;
-
-         /* Likewise, if either type has a maximum value, the other
-            type must have the same.  */
-         if (max1 == NULL_TREE && max2 == NULL_TREE)
-           max_equal_p = true;
-         else if (max1 && max2 && operand_equal_p (max1, max2, 0))
-           max_equal_p = true;
-
-         if (!min_equal_p || !max_equal_p)
-           goto different_types;
-       }
-
-      if (TREE_CODE (t1) == INTEGER_TYPE)
-       {
-         if (TYPE_IS_SIZETYPE (t1) == TYPE_IS_SIZETYPE (t2)
-             && TYPE_STRING_FLAG (t1) == TYPE_STRING_FLAG (t2))
-           goto same_types;
-         else
-           goto different_types;
-       }
-      else if (TREE_CODE (t1) == BOOLEAN_TYPE)
-       goto same_types;
-      else if (TREE_CODE (t1) == REAL_TYPE)
-       goto same_types;
-    }
-
   /* Do type-specific comparisons.  */
   switch (TREE_CODE (t1))
     {
@@ -3315,7 +3265,8 @@ gimple_types_compatible_p (tree t1, tree t2)
       /* Array types are the same if the element types are the same and
         the number of elements are the same.  */
       if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
-         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
+         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
+         || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
        goto different_types;
       else
        {
@@ -3393,120 +3344,170 @@ gimple_types_compatible_p (tree t1, tree t2)
            }
        }
 
+    case OFFSET_TYPE:
+      {
+       if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
+           || !gimple_types_compatible_p (TYPE_OFFSET_BASETYPE (t1),
+                                          TYPE_OFFSET_BASETYPE (t2)))
+         goto different_types;
+
+       goto same_types;
+      }
+
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-       {
-         /* If the two pointers have different ref-all attributes,
-            they can't be the same type.  */
-         if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
-           goto different_types;
-
-         /* If one pointer points to an incomplete type variant of
-            the other pointed-to type they are the same.  */
-         if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
-             && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
-                 || !COMPLETE_TYPE_P (TREE_TYPE (t2)))
-             && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2)))
-           {
-             /* If t2 is complete we want to choose it instead of t1.  */
-             if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
-               gimple_force_type_merge (TREE_TYPE (t1), TREE_TYPE (t2));
-             goto same_types;
-           }
+      {
+       /* If the two pointers have different ref-all attributes,
+          they can't be the same type.  */
+       if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
+         goto different_types;
 
-         /* Otherwise, pointer and reference types are the same if the
-            pointed-to types are the same.  */
-         if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+       /* If one pointer points to an incomplete type variant of
+          the other pointed-to type they are the same.  */
+       if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
+           && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1))
+           && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
+               || !COMPLETE_TYPE_P (TREE_TYPE (t2)))
+           && compare_type_names_p (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
+                                    TYPE_MAIN_VARIANT (TREE_TYPE (t2)), true))
+         {
+           /* Replace the pointed-to incomplete type with the
+              complete one.  */
+           if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
+             TREE_TYPE (t1) = TREE_TYPE (t2);
+           else
+             TREE_TYPE (t2) = TREE_TYPE (t1);
            goto same_types;
-         
+         }
+
+       /* Otherwise, pointer and reference types are the same if the
+          pointed-to types are the same.  */
+       if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+         goto same_types;
+
+       goto different_types;
+      }
+
+    case INTEGER_TYPE:
+    case BOOLEAN_TYPE:
+      {
+       tree min1 = TYPE_MIN_VALUE (t1);
+       tree max1 = TYPE_MAX_VALUE (t1);
+       tree min2 = TYPE_MIN_VALUE (t2);
+       tree max2 = TYPE_MAX_VALUE (t2);
+       bool min_equal_p = false;
+       bool max_equal_p = false;
+
+       /* If either type has a minimum value, the other type must
+          have the same.  */
+       if (min1 == NULL_TREE && min2 == NULL_TREE)
+         min_equal_p = true;
+       else if (min1 && min2 && operand_equal_p (min1, min2, 0))
+         min_equal_p = true;
+
+       /* Likewise, if either type has a maximum value, the other
+          type must have the same.  */
+       if (max1 == NULL_TREE && max2 == NULL_TREE)
+         max_equal_p = true;
+       else if (max1 && max2 && operand_equal_p (max1, max2, 0))
+         max_equal_p = true;
+
+       if (!min_equal_p || !max_equal_p)
          goto different_types;
-       }
 
-    case ENUMERAL_TYPE:
-       {
-         /* For enumeral types, all the values must be the same.  */
-         tree v1, v2;
+       goto same_types;
+      }
 
-         if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
-           goto same_types;
+    case ENUMERAL_TYPE:
+      {
+       /* FIXME lto, we cannot check bounds on enumeral types because
+          different front ends will produce different values.
+          In C, enumeral types are integers, while in C++ each element
+          will have its own symbolic value.  We should decide how enums
+          are to be represented in GIMPLE and have each front end lower
+          to that.  */
+       tree v1, v2;
+
+       /* For enumeral types, all the values must be the same.  */
+       if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
+         goto same_types;
 
-         for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
-              v1 && v2;
-              v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
-           {
-             tree c1 = TREE_VALUE (v1);
-             tree c2 = TREE_VALUE (v2);
+       for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
+            v1 && v2;
+            v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
+         {
+           tree c1 = TREE_VALUE (v1);
+           tree c2 = TREE_VALUE (v2);
 
-             if (TREE_CODE (c1) == CONST_DECL)
-               c1 = DECL_INITIAL (c1);
+           if (TREE_CODE (c1) == CONST_DECL)
+             c1 = DECL_INITIAL (c1);
 
-             if (TREE_CODE (c2) == CONST_DECL)
-               c2 = DECL_INITIAL (c2);
+           if (TREE_CODE (c2) == CONST_DECL)
+             c2 = DECL_INITIAL (c2);
 
-             if (tree_int_cst_equal (c1, c2) != 1)
-               goto different_types;
-           }
+           if (tree_int_cst_equal (c1, c2) != 1)
+             goto different_types;
+         }
 
-         /* If one enumeration has more values than the other, they
-            are not the same.  */
-         if (v1 || v2)
-           goto different_types;
+       /* If one enumeration has more values than the other, they
+          are not the same.  */
+       if (v1 || v2)
+         goto different_types;
 
-         goto same_types;
-       }
+       goto same_types;
+      }
 
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-       {
-         /* For aggregate types, all the fields must be the same.  */
-         tree f1, f2;
+      {
+       tree f1, f2;
 
-         /* Compare every field.  */
-         for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
-              f1 && f2;
-              f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
-           {
-             /* The fields must have the same name, offset and type.  */
-             if (DECL_NAME (f1) != DECL_NAME (f2)
-                 || !compare_field_offset (f1, f2)
-                 || !gimple_types_compatible_p (TREE_TYPE (f1),
-                                           TREE_TYPE (f2)))
-               goto different_types;
-           }
+       /* If one type requires structural equality checks and the
+          other doesn't, do not merge the types.  */
+       if (TYPE_STRUCTURAL_EQUALITY_P (t1)
+           != TYPE_STRUCTURAL_EQUALITY_P (t2))
+         goto different_types;
 
-         /* If one aggregate has more fields than the other, they
-            are not the same.  */
-         if (f1 || f2)
-           goto different_types;
+       /* The struct tags shall compare equal.  */
+       if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1),
+                                  TYPE_MAIN_VARIANT (t2), false))
+         goto different_types;
 
-         goto same_types;
-       }
+       /* For aggregate types, all the fields must be the same.  */
+       for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
+            f1 && f2;
+            f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+         {
+           /* The fields must have the same name, offset and type.  */
+           if (DECL_NAME (f1) != DECL_NAME (f2)
+               || DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
+               || !compare_field_offset (f1, f2)
+               || !gimple_types_compatible_p (TREE_TYPE (f1),
+                                              TREE_TYPE (f2)))
+             goto different_types;
+         }
 
-    case VECTOR_TYPE:
-      if (TYPE_VECTOR_SUBPARTS (t1) != TYPE_VECTOR_SUBPARTS (t2))
-       goto different_types;
+       /* If one aggregate has more fields than the other, they
+          are not the same.  */
+       if (f1 || f2)
+         goto different_types;
 
-      /* Fallthru  */
-    case COMPLEX_TYPE:
-      if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
-       goto different_types;
-      goto same_types;
+       goto same_types;
+      }
 
     default:
-      goto different_types;
+      gcc_unreachable ();
     }
 
   /* Common exit path for types that are not compatible.  */
 different_types:
-  if (p)
-    p->same_p = 0;
+  p->same_p = 0;
   return 0;
 
   /* Common exit path for types that are compatible.  */
 same_types:
-  if (p)
-    p->same_p = 1;
+  p->same_p = 1;
   return 1;
 }
 
@@ -3578,12 +3579,11 @@ visit (tree t, struct sccs *state, hashval_t v,
   return v;
 }
 
-/* Hash the name of TYPE with the previous hash value V and return it.  */
+/* Hash NAME with the previous hash value V and return it.  */
 
 static hashval_t
-iterative_hash_type_name (tree type, hashval_t v)
+iterative_hash_name (tree name, hashval_t v)
 {
-  tree name = TYPE_NAME (TYPE_MAIN_VARIANT (type));
   if (!name)
     return v;
   if (TREE_CODE (name) == TYPE_DECL)
@@ -3591,21 +3591,6 @@ iterative_hash_type_name (tree type, hashval_t v)
   if (!name)
     return v;
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-  /* Do not hash names of anonymous unions.  At least the C++ FE insists
-     to have a non-NULL TYPE_NAME for them.  See cp/cp-tree.h for all
-     the glory.  */
-#ifndef NO_DOT_IN_LABEL
-  if (IDENTIFIER_POINTER (name)[0] == '.')
-    return v;
-#else
-#ifndef NO_DOLLAR_IN_LABEL
-  if (IDENTIFIER_POINTER (name)[0] == '$')
-    return v;
-#else
-  if (!strncmp (IDENTIFIER_POINTER (name), "__anon_", sizeof ("__anon_") - 1))
-    return v;
-#endif
-#endif
   return iterative_hash_object (IDENTIFIER_HASH_VALUE (name), v);
 }
 
@@ -3670,17 +3655,35 @@ iterative_hash_gimple_type (tree type, hashval_t val,
      avoid hash differences for complete vs. incomplete types.  */
   if (POINTER_TYPE_P (type))
     {
-      if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
+      if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
        {
          v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
-         v = iterative_hash_type_name (type, v);
+         v = iterative_hash_name
+             (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
        }
       else
        v = visit (TREE_TYPE (type), state, v,
                   sccstack, sccstate, sccstate_obstack);
     }
 
-  /* Recurse for aggregates with a single element.  */
+  /* For integer types hash the types min/max values and the string flag.  */
+  if (TREE_CODE (type) == INTEGER_TYPE)
+    {
+      v = iterative_hash_expr (TYPE_MIN_VALUE (type), v);
+      v = iterative_hash_expr (TYPE_MAX_VALUE (type), v);
+      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+    }
+
+  /* For array types hash their domain and the string flag.  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_DOMAIN (type))
+    {
+      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+      v = visit (TYPE_DOMAIN (type), state, v,
+                sccstack, sccstate, sccstate_obstack);
+    }
+
+  /* Recurse for aggregates with a single element type.  */
   if (TREE_CODE (type) == ARRAY_TYPE
       || TREE_CODE (type) == COMPLEX_TYPE
       || TREE_CODE (type) == VECTOR_TYPE)
@@ -3718,10 +3721,11 @@ iterative_hash_gimple_type (tree type, hashval_t val,
       unsigned nf;
       tree f;
 
-      v = iterative_hash_type_name (type, v);
+      v = iterative_hash_name (TYPE_NAME (TYPE_MAIN_VARIANT (type)), v);
 
       for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
        {
+         v = iterative_hash_name (DECL_NAME (f), v);
          v = visit (TREE_TYPE (f), state, v,
                     sccstack, sccstate, sccstate_obstack);
          nf++;
@@ -3817,6 +3821,12 @@ gimple_register_type (tree t)
 
   gcc_assert (TYPE_P (t));
 
+  /* Always register the main variant first.  This is important so we
+     pick up the non-typedef variants as canonical, otherwise we'll end
+     up taking typedef ids for structure tags during comparison.  */
+  if (TYPE_MAIN_VARIANT (t) != t)
+    gimple_register_type (TYPE_MAIN_VARIANT (t));
+
   if (gimple_types == NULL)
     gimple_types = htab_create (16381, gimple_type_hash, gimple_type_eq, 0);
 
@@ -3899,8 +3909,8 @@ print_gimple_types_stats (void)
   else
     fprintf (stderr, "GIMPLE type table is empty\n");
   if (gtc_visited)
-    fprintf (stderr, "GIMPLE type comparison table: size %ld, %ld elements, "
-            "%ld searches, %ld collisions (ratio: %f)\n",
+    fprintf (stderr, "GIMPLE type comparison table: size %ld, %ld "
+            "elements, %ld searches, %ld collisions (ratio: %f)\n",
             (long) htab_size (gtc_visited),
             (long) htab_elements (gtc_visited),
             (long) gtc_visited->searches,
@@ -3910,6 +3920,33 @@ print_gimple_types_stats (void)
     fprintf (stderr, "GIMPLE type comparison table is empty\n");
 }
 
+/* Free the gimple type hashtables used for LTO type merging.  */
+
+void
+free_gimple_type_tables (void)
+{
+  /* Last chance to print stats for the tables.  */
+  if (flag_lto_report)
+    print_gimple_types_stats ();
+
+  if (gimple_types)
+    {
+      htab_delete (gimple_types);
+      gimple_types = NULL;
+    }
+  if (type_hash_cache)
+    {
+      pointer_map_destroy (type_hash_cache);
+      type_hash_cache = NULL;
+    }
+  if (gtc_visited)
+    {
+      htab_delete (gtc_visited);
+      obstack_free (&gtc_ob, NULL);
+      gtc_visited = NULL;
+    }
+}
+
 
 /* Return a type the same as TYPE except unsigned or
    signed according to UNSIGNEDP.  */
@@ -4134,9 +4171,9 @@ gimple_get_alias_set (tree t)
     }
   else if (POINTER_TYPE_P (t))
     {
-      tree t1;
+      /* From the common C and C++ langhook implementation:
 
-      /* Unfortunately, there is no canonical form of a pointer type.
+        Unfortunately, there is no canonical form of a pointer type.
         In particular, if we have `typedef int I', then `int *', and
         `I *' are different types.  So, we have to pick a canonical
         representative.  We do this below.
@@ -4158,9 +4195,36 @@ gimple_get_alias_set (tree t)
         can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
         the pointed-to types.  This issue has been reported to the
         C++ committee.  */
-      t1 = build_type_no_quals (t);
-      if (t1 != t)
-       return get_alias_set (t1);
+
+      /* In addition to the above canonicalization issue with LTO
+         we should also canonicalize `T (*)[]' to `T *' avoiding
+        alias issues with pointer-to element types and pointer-to
+        array types.
+
+        Likewise we need to deal with the situation of incomplete
+        pointed-to types and make `*(struct X **)&a' and
+        `*(struct X {} **)&a' alias.  Otherwise we will have to
+        guarantee that all pointer-to incomplete type variants
+        will be replaced by pointer-to complete type variants if
+        they are available.
+
+        With LTO the convenient situation of using `void *' to
+        access and store any pointer type will also become
+        more apparent (and `void *' is just another pointer-to
+        incomplete type).  Assigning alias-set zero to `void *'
+        and all pointer-to incomplete types is a not appealing
+        solution.  Assigning an effective alias-set zero only
+        affecting pointers might be - by recording proper subset
+        relationships of all pointer alias-sets.
+
+        Pointer-to function types are another grey area which
+        needs caution.  Globbing them all into one alias-set
+        or the above effective zero set would work.  */
+
+      /* For now just assign the same alias-set to all pointers.
+         That's simple and avoids all the above problems.  */
+      if (t != ptr_type_node)
+       return get_alias_set (ptr_type_node);
     }
 
   return -1;