This splits the TYPE_CANONICAL merging machinery from the regular
merging machinery.  It just gets too confusing to share code-paths
as both cases require opposing conservatism (merge everything for
TYPE_CANONICAL, merge nothing for regular merging).

Bootstrapped and tested on x86_64-unknown-linux-gnu, SPEC2k6 LTO tested.

Next on the list is to do the same for hashing and then remove
those discriminators that do not make much sense for TYPE_CANONICAL
merging.

Richard.

2011-05-10  Richard Guenther  <rguent...@suse.de>

        * gimple.c (gimple_canonical_types_compatible_p): Split out
        from gimple_types_compatible_p and friends.  Do not recurse
        to pointed-to types.
        (gimple_canonical_type_eq): Use it.

Index: trunk/gcc/gimple.c
===================================================================
*** trunk.orig/gcc/gimple.c     2011-05-10 11:55:52.000000000 +0200
--- trunk/gcc/gimple.c  2011-05-10 12:19:56.000000000 +0200
*************** gimple_register_type (tree t)
*** 4479,4484 ****
--- 4479,4840 ----
  }
  
  
+ /* The TYPE_CANONICAL merging machinery.  It should closely resemble
+    the middle-end types_compatible_p function.  It needs to avoid
+    claiming types are different for types that should be treated
+    the same with respect to TBAA.  Canonical types are also used
+    for IL consistency checks via the useless_type_conversion_p
+    predicate which does not handle all type kinds itself but falls
+    back to pointer-comparison of TYPE_CANONICAL for aggregates
+    for example.  */
+ 
+ /* Return true iff T1 and T2 are structurally identical for what
+    TBAA is concerned.  */
+ 
+ static bool
+ gimple_canonical_types_compatible_p (tree t1, tree t2)
+ {
+   type_pair_t p = NULL;
+ 
+   /* Before starting to set up the SCC machinery handle simple cases.  */
+ 
+   /* Check first for the obvious case of pointer identity.  */
+   if (t1 == t2)
+     return true;
+ 
+   /* Check that we have two types to compare.  */
+   if (t1 == NULL_TREE || t2 == NULL_TREE)
+     return false;
+ 
+   /* If the types have been previously registered and found equal
+      they still are.  */
+   if (TYPE_CANONICAL (t1)
+       && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
+     return true;
+ 
+   /* Can't be the same type if the types don't have the same code.  */
+   if (TREE_CODE (t1) != TREE_CODE (t2))
+     return false;
+ 
+   /* Can't be the same type if they have different CV qualifiers.  */
+   if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
+     return false;
+ 
+   /* Void types are always the same.  */
+   if (TREE_CODE (t1) == VOID_TYPE)
+     return true;
+ 
+   /* 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 false;
+ 
+       if (TREE_CODE (t1) == INTEGER_TYPE
+         && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
+             || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
+       return false;
+ 
+       /* 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 true;
+ 
+       /* For integral types fall thru to more complex checks.  */
+     }
+ 
+   else if (AGGREGATE_TYPE_P (t1) || POINTER_TYPE_P (t1))
+     {
+       /* Can't be the same type if they have different alignment or mode.  */
+       if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
+         || TYPE_MODE (t1) != TYPE_MODE (t2))
+       return false;
+     }
+ 
+   /* 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
+      small, only tracking comparisons for hash collisions.  */
+   if (gimple_canonical_type_hash (t1) != gimple_canonical_type_hash (t2))
+     return false;
+ 
+   /* 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, &gtc_ob);
+   if (p->same_p[GTC_DIAG] == 0 || p->same_p[GTC_DIAG] == 1)
+     {
+       /* We have already decided whether T1 and T2 are the
+        same, return the cached result.  */
+       return p->same_p[GTC_DIAG] == 1;
+     }
+ 
+   gcc_assert (p->same_p[GTC_DIAG] == -2);
+ 
+   /* If their attributes are not the same they can't be the same type.  */
+   if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
+     goto different_types;
+ 
+   /* Do type-specific comparisons.  */
+   switch (TREE_CODE (t1))
+     {
+     case VECTOR_TYPE:
+     case COMPLEX_TYPE:
+       if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE 
(t2)))
+       goto different_types;
+       goto same_types;
+ 
+     case ARRAY_TYPE:
+       /* Array types are the same if the element types are the same and
+        the number of elements are the same.  */
+       if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE 
(t2))
+         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
+         || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
+       goto different_types;
+       else
+       {
+         tree i1 = TYPE_DOMAIN (t1);
+         tree i2 = TYPE_DOMAIN (t2);
+ 
+         /* For an incomplete external array, the type domain can be
+            NULL_TREE.  Check this condition also.  */
+         if (i1 == NULL_TREE && i2 == NULL_TREE)
+           goto same_types;
+         else if (i1 == NULL_TREE || i2 == NULL_TREE)
+           goto different_types;
+         /* If for a complete array type the possibly gimplified sizes
+            are different the types are different.  */
+         else if (((TYPE_SIZE (i1) != NULL) ^ (TYPE_SIZE (i2) != NULL))
+                  || (TYPE_SIZE (i1)
+                      && TYPE_SIZE (i2)
+                      && !operand_equal_p (TYPE_SIZE (i1), TYPE_SIZE (i2), 0)))
+           goto different_types;
+         else
+           {
+             tree min1 = TYPE_MIN_VALUE (i1);
+             tree min2 = TYPE_MIN_VALUE (i2);
+             tree max1 = TYPE_MAX_VALUE (i1);
+             tree max2 = TYPE_MAX_VALUE (i2);
+ 
+             /* The minimum/maximum values have to be the same.  */
+             if ((min1 == min2
+                  || (min1 && min2
+                      && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
+                           && TREE_CODE (min2) == PLACEHOLDER_EXPR)
+                          || operand_equal_p (min1, min2, 0))))
+                 && (max1 == max2
+                     || (max1 && max2
+                         && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
+                              && TREE_CODE (max2) == PLACEHOLDER_EXPR)
+                             || operand_equal_p (max1, max2, 0)))))
+               goto same_types;
+             else
+               goto different_types;
+           }
+       }
+ 
+     case METHOD_TYPE:
+       /* Method types should belong to the same class.  */
+       if (!gimple_canonical_types_compatible_p
+            (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2)))
+       goto different_types;
+ 
+       /* Fallthru  */
+ 
+     case FUNCTION_TYPE:
+       /* Function types are the same if the return type and arguments types
+        are the same.  */
+       if (!gimple_compatible_complete_and_incomplete_subtype_p
+            (TREE_TYPE (t1), TREE_TYPE (t2))
+         && !gimple_canonical_types_compatible_p
+               (TREE_TYPE (t1), TREE_TYPE (t2)))
+       goto different_types;
+ 
+       if (!comp_type_attributes (t1, t2))
+       goto different_types;
+ 
+       if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
+       goto same_types;
+       else
+       {
+         tree parms1, parms2;
+ 
+         for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
+              parms1 && parms2;
+              parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
+           {
+             if (!gimple_compatible_complete_and_incomplete_subtype_p
+                        (TREE_VALUE (parms1), TREE_VALUE (parms2))
+                 && !gimple_canonical_types_compatible_p
+                       (TREE_VALUE (parms1), TREE_VALUE (parms2)))
+               goto different_types;
+           }
+ 
+         if (parms1 || parms2)
+           goto different_types;
+ 
+         goto same_types;
+       }
+ 
+     case OFFSET_TYPE:
+       {
+       if (!gimple_canonical_types_compatible_p
+              (TREE_TYPE (t1), TREE_TYPE (t2))
+           || !gimple_canonical_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 (TYPE_ADDR_SPACE (TREE_TYPE (t1))
+           != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
+         goto different_types;
+ 
+       if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
+         goto different_types;
+ 
+       /* For canonical type comparisons we do not want to build SCCs
+          so we cannot compare pointed-to types.  But we can, for now,
+          require the same pointed-to type kind.  */
+       if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
+         goto different_types;
+ 
+       goto same_types;
+       }
+ 
+     case NULLPTR_TYPE:
+       /* There is only one decltype(nullptr).  */
+       goto same_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;
+ 
+       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);
+ 
+           if (TREE_CODE (c1) == CONST_DECL)
+             c1 = DECL_INITIAL (c1);
+ 
+           if (TREE_CODE (c2) == CONST_DECL)
+             c2 = DECL_INITIAL (c2);
+ 
+           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;
+ 
+       goto same_types;
+       }
+ 
+     case RECORD_TYPE:
+     case UNION_TYPE:
+     case QUAL_UNION_TYPE:
+       {
+       tree f1, f2;
+ 
+       /* 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_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
+               || !gimple_compare_field_offset (f1, f2)
+               || !gimple_canonical_types_compatible_p
+                     (TREE_TYPE (f1), TREE_TYPE (f2)))
+             goto different_types;
+         }
+ 
+       /* If one aggregate has more fields than the other, they
+          are not the same.  */
+       if (f1 || f2)
+         goto different_types;
+ 
+       goto same_types;
+       }
+ 
+     default:
+       gcc_unreachable ();
+     }
+ 
+   /* Common exit path for types that are not compatible.  */
+ different_types:
+   p->same_p[GTC_DIAG] = 0;
+   return false;
+ 
+   /* Common exit path for types that are compatible.  */
+ same_types:
+   p->same_p[GTC_DIAG] = 1;
+   return true;
+ }
+ 
+ 
  /* Returns nonzero if P1 and P2 are equal.  */
  
  static int
*************** gimple_canonical_type_eq (const void *p1
*** 4486,4493 ****
  {
    const_tree t1 = (const_tree) p1;
    const_tree t2 = (const_tree) p2;
!   return gimple_types_compatible_p (CONST_CAST_TREE (t1),
!                                   CONST_CAST_TREE (t2), GTC_DIAG);
  }
  
  /* Register type T in the global type table gimple_types.
--- 4842,4849 ----
  {
    const_tree t1 = (const_tree) p1;
    const_tree t2 = (const_tree) p2;
!   return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
!                                             CONST_CAST_TREE (t2));
  }
  
  /* Register type T in the global type table gimple_types.

Reply via email to