This improves hashing and comparing both regular and canonical type merging.
Bootstrapped and tested on x86_64-unknonw-linux-gnu and SPEC2k6 tested, applied to trunk. Richard. 2011-05-12 Richard Guenther <rguent...@suse.de> * gimple.c (gtc_visit): Compare TREE_ADDRESSABLE, handle NULLPTR_TYPE similar to VOID_TYPE. Defer type-leader lookup until after simple checks. (gimple_types_compatible_p): Likewise. (iterative_hash_gimple_type): Always hash pointer targets and function return and argument types. (iterative_hash_canonical_type): Do not hash TYPE_QUALS, hash TYPE_ALIGN. Do not hash TYPE_MIN/MAX_VALUE. (gimple_canonical_types_compatible_p): Compare TREE_ADDRESSABLE, handle NULLPTR_TYPE similar to VOID_TYPE. Handle non-aggregates completely in the simple compare section. (gimple_register_canonical_type): Query the cache again after registering. Index: gcc/gimple.c =================================================================== *** gcc/gimple.c (revision 173702) --- gcc/gimple.c (working copy) *************** gtc_visit (tree t1, tree t2, *** 3489,3503 **** if (t1 == NULL_TREE || t2 == NULL_TREE) return false; - /* If the types have been previously registered and found equal - they still are. */ - leader1 = gimple_lookup_type_leader (t1); - leader2 = gimple_lookup_type_leader (t2); - if (leader1 == t2 - || t1 == leader2 - || (leader1 && leader1 == leader2)) - 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; --- 3489,3494 ---- *************** gtc_visit (tree t1, tree t2, *** 3506,3528 **** 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; --- 3497,3526 ---- if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) return false; ! if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)) ! return false; ! ! /* Void types and nullptr types are always the same. */ ! if (TREE_CODE (t1) == VOID_TYPE ! || TREE_CODE (t1) == NULLPTR_TYPE) return true; + /* 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; + /* 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 ! || POINTER_TYPE_P (t1)) { ! /* Can't be the same type if they have different sign or precision. */ ! if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2) || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) return false; *************** gtc_visit (tree t1, tree t2, *** 3536,3551 **** || 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 --- 3534,3550 ---- || FIXED_POINT_TYPE_P (t1)) return true; ! /* For other types fall thru to more complex checks. */ } ! /* If the types have been previously registered and found equal ! they still are. */ ! leader1 = gimple_lookup_type_leader (t1); ! leader2 = gimple_lookup_type_leader (t2); ! if (leader1 == t2 ! || t1 == leader2 ! || (leader1 && leader1 == leader2)) ! return true; /* 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 *************** gimple_types_compatible_p_1 (tree t1, tr *** 3739,3748 **** goto different_types; } - case NULLPTR_TYPE: - /* There is only one decltype(nullptr). */ - goto same_types; - case INTEGER_TYPE: case BOOLEAN_TYPE: { --- 3738,3743 ---- *************** gimple_types_compatible_p (tree t1, tree *** 3906,3920 **** if (t1 == NULL_TREE || t2 == NULL_TREE) return false; - /* If the types have been previously registered and found equal - they still are. */ - leader1 = gimple_lookup_type_leader (t1); - leader2 = gimple_lookup_type_leader (t2); - if (leader1 == t2 - || t1 == leader2 - || (leader1 && leader1 == leader2)) - 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; --- 3901,3906 ---- *************** gimple_types_compatible_p (tree t1, tree *** 3923,3945 **** 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; --- 3909,3938 ---- if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) return false; ! if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)) ! return false; ! ! /* Void types and nullptr types are always the same. */ ! if (TREE_CODE (t1) == VOID_TYPE ! || TREE_CODE (t1) == NULLPTR_TYPE) return true; + /* 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; + /* 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 ! || POINTER_TYPE_P (t1)) { ! /* Can't be the same type if they have different sign or precision. */ ! if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2) || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) return false; *************** gimple_types_compatible_p (tree t1, tree *** 3953,3968 **** || 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 --- 3946,3962 ---- || FIXED_POINT_TYPE_P (t1)) return true; ! /* For other types fall thru to more complex checks. */ } ! /* If the types have been previously registered and found equal ! they still are. */ ! leader1 = gimple_lookup_type_leader (t1); ! leader2 = gimple_lookup_type_leader (t2); ! if (leader1 == t2 ! || t1 == leader2 ! || (leader1 && leader1 == leader2)) ! return true; /* 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 *************** iterative_hash_gimple_type (tree type, h *** 4116,4135 **** } /* For pointer and reference types, fold in information about the type ! pointed to but do not recurse into possibly incomplete types to ! avoid hash differences for complete vs. incomplete types. */ if (POINTER_TYPE_P (type)) ! { ! if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))) ! { ! v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (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); ! } /* For integer types hash the types min/max values and the string flag. */ if (TREE_CODE (type) == INTEGER_TYPE) --- 4110,4119 ---- } /* For pointer and reference types, fold in information about the type ! pointed to. */ if (POINTER_TYPE_P (type)) ! v = visit (TREE_TYPE (type), state, v, ! sccstack, sccstate, sccstate_obstack); /* For integer types hash the types min/max values and the string flag. */ if (TREE_CODE (type) == INTEGER_TYPE) *************** iterative_hash_gimple_type (tree type, h *** 4170,4198 **** v = visit (TYPE_METHOD_BASETYPE (type), state, v, sccstack, sccstate, sccstate_obstack); ! /* For result types allow mismatch in completeness. */ ! if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))) ! { ! v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (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); ! for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p)) { ! /* For argument types allow mismatch in completeness. */ ! if (RECORD_OR_UNION_TYPE_P (TREE_VALUE (p))) ! { ! v = iterative_hash_hashval_t (TREE_CODE (TREE_VALUE (p)), v); ! v = iterative_hash_name ! (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_VALUE (p))), v); ! } ! else ! v = visit (TREE_VALUE (p), state, v, ! sccstack, sccstate, sccstate_obstack); na++; } --- 4154,4166 ---- v = visit (TYPE_METHOD_BASETYPE (type), state, v, sccstack, sccstate, sccstate_obstack); ! /* Check result and argument types. */ ! v = visit (TREE_TYPE (type), state, v, ! sccstack, sccstate, sccstate_obstack); for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p)) { ! v = visit (TREE_VALUE (p), state, v, ! sccstack, sccstate, sccstate_obstack); na++; } *************** iterative_hash_canonical_type (tree type *** 4311,4329 **** only existing types having the same features as the new type will be checked. */ v = iterative_hash_hashval_t (TREE_CODE (type), 0); - v = iterative_hash_hashval_t (TYPE_QUALS (type), v); v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v); ! ! /* Do not hash the types size as this will cause differences in ! hash values for the complete vs. the incomplete type variant. */ /* Incorporate common features of numerical types. */ if (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type) ! || FIXED_POINT_TYPE_P (type)) { v = iterative_hash_hashval_t (TYPE_PRECISION (type), v); - v = iterative_hash_hashval_t (TYPE_MODE (type), v); v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v); } --- 4279,4298 ---- only existing types having the same features as the new type will be checked. */ v = iterative_hash_hashval_t (TREE_CODE (type), 0); v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v); ! v = iterative_hash_hashval_t (TYPE_ALIGN (type), v); ! v = iterative_hash_hashval_t (TYPE_MODE (type), v); /* Incorporate common features of numerical types. */ if (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type) ! || FIXED_POINT_TYPE_P (type) ! || TREE_CODE (type) == VECTOR_TYPE ! || TREE_CODE (type) == COMPLEX_TYPE ! || TREE_CODE (type) == OFFSET_TYPE ! || POINTER_TYPE_P (type)) { v = iterative_hash_hashval_t (TYPE_PRECISION (type), v); v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v); } *************** iterative_hash_canonical_type (tree type *** 4332,4350 **** if (POINTER_TYPE_P (type)) { v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v); v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v); } /* For integer types hash the types min/max values and the string flag. */ if (TREE_CODE (type) == INTEGER_TYPE) { - /* OMP lowering can introduce error_mark_node in place of - random local decls in types. */ - if (TYPE_MIN_VALUE (type) != error_mark_node) - v = iterative_hash_expr (TYPE_MIN_VALUE (type), v); - if (TYPE_MAX_VALUE (type) != error_mark_node) - 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. */ --- 4301,4316 ---- if (POINTER_TYPE_P (type)) { v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v); + v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v); + v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v); v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v); } /* For integer types hash the types min/max values and the string flag. */ if (TREE_CODE (type) == INTEGER_TYPE) { v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v); + v = iterative_hash_hashval_t (TYPE_IS_SIZETYPE (type), v); } /* For array types hash their domain and the string flag. */ *************** gimple_canonical_types_compatible_p (tre *** 4599,4625 **** 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; --- 4565,4596 ---- if (TREE_CODE (t1) != TREE_CODE (t2)) return false; ! if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)) return false; ! /* Qualifiers do not matter for canonical type comparison purposes. */ ! ! /* Void types and nullptr types are always the same. */ ! if (TREE_CODE (t1) == VOID_TYPE ! || TREE_CODE (t1) == NULLPTR_TYPE) return true; ! /* 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; ! ! /* Non-aggregate types can be handled cheaply. */ 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 ! || POINTER_TYPE_P (t1)) { ! /* Can't be the same type if they have different sign or precision. */ ! if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2) || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) return false; *************** gimple_canonical_types_compatible_p (tre *** 4628,4647 **** || 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 --- 4599,4633 ---- || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))) return false; ! /* 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 and match what ! useless_type_conversion_p would do. */ ! if (POINTER_TYPE_P (t1)) ! { ! /* 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)) ! return false; ! ! if (TYPE_ADDR_SPACE (TREE_TYPE (t1)) ! != TYPE_ADDR_SPACE (TREE_TYPE (t2))) ! return false; ! if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2)) ! return false; ! if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2))) ! return false; ! } ! ! /* Tail-recurse to components. */ ! if (TREE_CODE (t1) == VECTOR_TYPE ! || TREE_CODE (t1) == COMPLEX_TYPE) ! return gimple_canonical_types_compatible_p (TREE_TYPE (t1), ! TREE_TYPE (t2)); ! ! return true; } /* If the hash values of t1 and t2 are different the types can't *************** gimple_canonical_types_compatible_p (tre *** 4669,4680 **** /* 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. */ --- 4655,4660 ---- *************** gimple_canonical_types_compatible_p (tre *** 4767,4880 **** 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: --- 4747,4752 ---- *************** gimple_register_canonical_type (tree t) *** 4949,4954 **** --- 4821,4829 ---- to be the canonical type it will be the one we merge to as well. */ t = gimple_register_type (t); + if (TYPE_CANONICAL (t)) + return TYPE_CANONICAL (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. */