On Fri, Feb 06, 2026 at 10:52:49AM +0100, Richard Biener wrote:
> > --- gcc/alias.cc.jj 2026-02-05 15:34:14.545990112 +0100
> > +++ gcc/alias.cc    2026-02-05 15:54:32.762394480 +0100
> > @@ -948,7 +948,12 @@ get_alias_set (tree t)
> >    else
> >      {
> >        t = TYPE_CANONICAL (t);
> > -      gcc_checking_assert (!TYPE_STRUCTURAL_EQUALITY_P (t));
> > +      gcc_checking_assert (TYPE_CANONICAL (t) == t);
> > +      if (t != TYPE_MAIN_VARIANT (t))
> > +   {
> > +     t = TYPE_MAIN_VARIANT (t);
> 
> We already did
> 
>   /* Variant qualifiers don't affect the alias set, so get the main
>      variant.  */
>   t = TYPE_MAIN_VARIANT (t);
> 
> at the start.  I'd rather not do this, is this really necessary?

Unfortunately yes.
The first t = TYPE_MAIN_VARIANT (t) will look through say typedefs
or cv quals (if they would be there, for C/C++ on array types they aren't
except for the array_as_string hack).  So, given say
typedef volatile int A [2] __attribute__((may_alias));
typedef A B;
that goes from B to volatile int [2] __attribute__((may_alias)), but
doesn't go further because it is a distinct type copy.
Then t = TYPE_CANONICAL (t); goes from that
volatile int [2] __attribute__((may_alias)) to volatile int [2],
i.e. for FE canonical representation of that, and the second
t = TYPE_MAIN_VARIANT (t);
goes from volatile int [2] to int [2].

> But I'm a bit confused now.  So we have const int * being its own
> canonical type and a variant of int *.  All fine.  But the canonical
> type of  'int *' (a main variant) can now be, say 'const int *'?

I think pointers behave differently from array types, I think for
typedef const int *__attribute__((may_alias)) const T;
T a;
TYPE_MAIN_VARIANT (T) is const int *__attribute__((may_alias))
(because again, attribute variants are distinct types),
TYPE_CANONICAL (T) is const int *const (TYPE_CANONICAL wants to
preserve cv quals but ignores attributes or typedefs etc.).
TYPE_CANONICAL (TYPE_MAIN_VARIANT (T)) is const int * which is
its own TYPE_MAIN_VARIANT.

The problem is I think only with ARRAY_TYPEs.
For POINTER_TYPEs etc., const int *const has main variant of
const int * rather than int *.  For ARRAY_TYPEs in C/C++,
const int[2] has main variant int[2] rather than const int[2].

> That means that get_alias should swap TYPE_MAIN_VARIANT and
> TYPE_CANONICAL punning?  What happens whe TYPE_STRUCTURAL_EQUALITY (t)?

No, we need all 3 I'm afraid.  If you want, this third step could be
asserted only for ARRAY_TYPEs.

> Can we assert that TYPE_STRUCRTURAL_EQUALITY (TYPE_MAIN_VARIANT (t))?

TYPE_STRUCTURAL_EQUALITY_P is just NULL TYPE_CANONICAL.  Either
all similar (quals/attrs etc.) types use structural equality, or all
use canonical types.
> 
> IIRC when the middle-end re-computes TYPE_CANONICAL it does so only
> for main variants (and we only stream the TYPE_MAIN_VARIANT pointers,
> re-building variant chains at stream-in).  lto/lto-common.cc has
> 
>   /* Canonical types are same among all complete variants.  */
>   if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (t)))
>     TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_MAIN_VARIANT (t));
>   else
>     {
>       hashval_t h = hash_canonical_type (TYPE_MAIN_VARIANT (t));
>       gimple_register_canonical_type_1 (TYPE_MAIN_VARIANT (t), h);
>       TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_MAIN_VARIANT (t));
> 
> I guess with the old scheme the order of TYPE_CANONICAL/TYPE_MAIN_VARIANT
> punning doesn't matter, nor with how LTO re-computes it.  But with
> the C/C++ way it would matter unless you iterate one more time.
> 
> There is tree-ssa-alias.cc:same_type_for_tbaa which probably needs
> updating for this as well (but it's only a missed optimization there
> I guess).  Possibly similarly types_equal_for_same_type_for_tbaa_p.

Seems same_type_for_tbaa just punts on ARRAY_TYPES:
1016      /* Compare the canonical types.  */
1017      if (TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2))
1018        return 1;
1019    
1020      /* ??? Array types are not properly unified in all cases as we have
1021         spurious changes in the index types for example.  Removing this
1022         causes all sorts of problems with the Fortran frontend.  */
1023      if (TREE_CODE (type1) == ARRAY_TYPE
1024          && TREE_CODE (type2) == ARRAY_TYPE)
1025        return -1;

        Jakub

Reply via email to