Am Freitag, dem 03.05.2024 um 20:18 +0200 schrieb Jakub Jelinek:
> On Fri, May 03, 2024 at 08:04:18PM +0200, Martin Uecker wrote:
> > A change that is not optimal but would avoid a lot of trouble is to
> > only use the tag of the struct for computing a TYPE_CANONICAL, which
> > could then be set already for incomplete types and never needs to
> > change again. We would not differentiate between different struct
> > types with the same tag for aliasing analysis, but in most cases
> > I would expect different structs to have a different tag.
> 
> Having incompatible types have the same TYPE_CANONICAL would lead to wrong
> code IMHO, while for aliasing purposes that might be conservative (though
> not sure, the alias set computation is based on what types the element have
> etc., so if the alias set is computed for say struct S { int s; }; and
> then the same alias set used for struct S { long long a; double b; union {
> short c; float d; } c; };, I think nothing good will come out of that),

The C type systems requires us to form equivalence classes though.
For example

int (*r)[1];
int (*q)[];
int (*p)[3];

need to be in the same equivalence class even though r and p are 
not compatible, while at the same time r and q and q and p
are compatible.


> but middle-end also uses TYPE_CANONICAL to see if types are the same,
> say e.g. useless_type_conversion_p says that conversions from one
> RECORD_TYPE to a different RECORD_TYPE are useless if they have the
> same TYPE_CANONICAL.
>   /* For aggregates we rely on TYPE_CANONICAL exclusively and require
>      explicit conversions for types involving to be structurally
>      compared types.  */
>   else if (AGGREGATE_TYPE_P (inner_type)
>            && TREE_CODE (inner_type) == TREE_CODE (outer_type))
>     return TYPE_CANONICAL (inner_type)
>            && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type);
> So, if you have struct S { int s; } and struct S { short a, b; }; and
> VIEW_CONVERT_EXPR between them, that VIEW_CONVERT_EXPR will be removed
> as useless, etc.

Maybe we could limit for purposes of computing TYPE_CANONICAL of derived
types, e.g. TYPE_CANONICAL of structs stays the same with the transition
from TYPE_STRUCT_EQUALITY to TYPE_CANONICAL but all the derived types
remain stable.

Martin

> 
> BTW, the idea of lazily updating TYPE_CANONICAL is basically what I've
> described as the option to update all the derived types where it would
> pretty much do that for all TYPE_STRUCTURAL_EQUALITY_P types in the
> hash table (see if they are derived from the type in question and recompute
> the TYPE_CANONICAL after recomputing all the TYPE_CANONICAL of its base
> types), except perhaps even more costly (if the trigger would be some
> build_array_type/build_function_type/... function is called and found
> a cached TYPE_STRUCTURAL_EQUALITY_P type).  Note also that
> TYPE_STRUCTURAL_EQUALITY_P isn't the case just for the C23 types which
> are marked that way when incomplete and later completed, but by various
> other cases for types which will be permanently like that, so doing
> expensive checks each time some build*_type* is called that refers
> to those would be expensive.
> 
>       Jakub
> 

Reply via email to