On Mon, Nov 24, 2025 at 09:28:53AM +0100, Richard Biener wrote: > I think INTEGER_TYPEs should be handled the same.
Ok, here is an updated patch (so far untested) to handle INTEGER_TYPEs the same. Even for the standard INTEGER_TYPEs it will have an advantage that we just remember the TYPE_ALIAS_SET on the unsigned ones, so while the first call of get_alias_set on a particular INTEGER_TYPE will be slightly slower due to the c_common_*signed_type call, we won't call on the other side get_alias_set again and again. BTW, I don't really understand the /* t1 == t can happen for boolean nodes which are always unsigned. */ comment, boolean types are not INTEGER_TYPEs nor BITINT_TYPES, and furthermore, I think for BOOLEAN_TYPE c_common_signed_type will just return non-standard TYPE_PRECISION (boolean_type_node) signed INTEGER_TYPE. Only for !INTEGRAL_TYPE_P types it will just return TYPE_MAIN_VARIANT of the passed in type without changing it. Thus, I've changed it into gcc_checking_assert. > I wonder if the > pointer handling get_alias_set does (re-constructing "simplified" > chains) suffers from a similar issue in case such chain is GCed > before we query for the exact same alias set again ... I don't see how that can happen. The problem with the signed vs. unsigned is that it creates (or can create) new types which aren't in the GTY reachable locations yet. The pointer handling doesn't do this, it walks the referenced types from the type and picks something based on that. The only exception is prevailing_odr_type, but I think that isn't done again and again. That build a new type, use alias set from it, GC collect it, build a new type again and use alias set from it is the problem. > So I wonder whether we should keep a back-mapping of alias-set to > type as GC root? Meaning, add a pointer to the tree to > alias_set_entry? I'd like to avoid that if at all possible. 2025-11-24 Jakub Jelinek <[email protected]> PR middle-end/122624 * tree.cc (build_bitint_type): Use type_hash_canon_hash. * c-common.cc (c_common_get_alias_set): Fix up handling of BITINT_TYPE and non-standard INTEGER_TYPEs. For unsigned _BitInt(1) always return -1. For other unsigned types set TYPE_ALIAS_SET to get_alias_set of corresponding signed type and return that. For signed types check if corresponding unsigned type has TYPE_ALIAS_SET_KNOWN_P and if so copy its TYPE_ALIAS_SET and return that. --- gcc/tree.cc.jj 2025-11-24 09:02:41.856988851 +0100 +++ gcc/tree.cc 2025-11-24 09:42:18.382123139 +0100 @@ -7414,9 +7414,8 @@ build_bitint_type (unsigned HOST_WIDE_IN else fixup_signed_type (itype); - inchash::hash hstate; - inchash::add_expr (TYPE_MAX_VALUE (itype), hstate); - ret = type_hash_canon (hstate.end (), itype); + hashval_t hash = type_hash_canon_hash (itype); + ret = type_hash_canon (hash, itype); if (precision <= MAX_INT_CACHED_PREC) (*bitint_type_cache)[precision + unsignedp] = ret; --- gcc/c-family/c-common.cc.jj 2025-11-24 09:02:41.761990505 +0100 +++ gcc/c-family/c-common.cc 2025-11-24 09:50:05.732088006 +0100 @@ -3943,14 +3943,40 @@ c_common_get_alias_set (tree t) /* The C standard specifically allows aliasing between signed and unsigned variants of the same type. We treat the signed variant as canonical. */ - if ((TREE_CODE (t) == INTEGER_TYPE || TREE_CODE (t) == BITINT_TYPE) - && TYPE_UNSIGNED (t)) + if (TREE_CODE (t) == INTEGER_TYPE || TREE_CODE (t) == BITINT_TYPE) { - tree t1 = c_common_signed_type (t); - - /* t1 == t can happen for boolean nodes which are always unsigned. */ - if (t1 != t) - return get_alias_set (t1); + /* For normal INTEGER_TYPEs (except ones built by + build_nonstandard_integer_type), both signed and unsigned variants + of the type are always reachable from GTY roots, so just calling + get_alias_set on the signed type is ok. For BITINT_TYPE and + non-standard INTEGER_TYPEs, only unsigned could be used and the + corresponding signed type could be created on demand and garbage + collected as unused, so the alias set of unsigned type could keep + changing. + Avoid that by remembering the signed type alias set in + TYPE_ALIAS_SET and also when being asked about !TYPE_UNSIGNED + check if there isn't a corresponding unsigned type with + TYPE_ALIAS_SET_KNOWN_P. */ + if (TYPE_UNSIGNED (t)) + { + /* There is no signed _BitInt(1). */ + if (TREE_CODE (t) == BITINT_TYPE && TYPE_PRECISION (t) == 1) + return -1; + tree t1 = c_common_signed_type (t); + gcc_checking_assert (t != t1); + TYPE_ALIAS_SET (t) = get_alias_set (t1); + return TYPE_ALIAS_SET (t); + } + else + { + tree t1 = c_common_unsigned_type (t); + gcc_checking_assert (t != t1); + if (TYPE_ALIAS_SET_KNOWN_P (t1)) + { + TYPE_ALIAS_SET (t) = TYPE_ALIAS_SET (t1); + return TYPE_ALIAS_SET (t); + } + } } return -1; Jakub
