From: Martin Uecker <uecker@tugraz.at>
To: Richard Biener <rguenther@suse.de>, gcc-patches@gcc.gnu.org
Cc: Jakub Jelinek <jakub@redhat.com>
Subject: Re: [PATCH] middle-end/114931 - type_hash_canon and structual equality types
Date: Fri, 03 May 2024 17:32:12 +0200 [thread overview]
Message-ID: <3616afcc455c1f80e2bb8a80a408994a67062d85.camel@tugraz.at> (raw)
In-Reply-To: <20240503121400.C8A4313991@imap1.dmz-prg2.suse.org>
Am Freitag, dem 03.05.2024 um 14:13 +0200 schrieb Richard Biener:
> TYPE_STRUCTURAL_EQUALITY_P is part of our type system so we have
> to make sure to include that into the type unification done via
> type_hash_canon. This requires the flag to be set before querying
> the hash which is the biggest part of the patch.
I assume this does not affect structs / unions because they
do not make this mechanism of type unification (each tagged type
is a unique type), but only derived types that end up having
TYPE_STRUCTURAL_EQUALITY_P because they are constructed from
incomplete structs / unions before TYPE_CANONICAL is set.
I do not yet understand why this change is needed. Type
identity should not be affected by setting TYPE_CANONICAL, so
why do we need to keep such types separate? I understand that we
created some inconsistencies, but I do not see why this change
is needed to fix it. But I also haven't understood how we ended
up with a TYPE_CANONICAL having TYPE_STRUCTURAL_EQUALITY_P in
PR 114931 ...
Martin
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu for all languages.
>
> As said in the PR this merely makes sure to keep individual types
> consistent with themselves. We still will have a set of types
> with TYPE_STRUCTURAL_EQUALITY_P and a set without that might be
> otherwise identical. That could be only avoided with changes in
> the frontend.
>
> OK for trunk?
>
> Thanks,
> Richard.
>
> PR middle-end/114931
> gcc/
> * tree.cc (type_hash_canon_hash): Hash TYPE_STRUCTURAL_EQUALITY_P.
> (type_cache_hasher::equal): Compare TYPE_STRUCTURAL_EQUALITY_P.
> (build_array_type_1): Set TYPE_STRUCTURAL_EQUALITY_P before
> probing with type_hash_canon.
> (build_function_type): Likewise.
> (build_method_type_directly): Likewise.
> (build_offset_type): Likewise.
> (build_complex_type): Likewise.
> * attribs.cc (build_type_attribute_qual_variant): Likewise.
>
> gcc/c-family/
> * c-common.cc (complete_array_type): Set TYPE_STRUCTURAL_EQUALITY_P
> before probing with type_hash_canon.
>
> gcc/testsuite/
> * gcc.dg/pr114931.c: New testcase.
> ---
> gcc/attribs.cc | 20 +++++-----
> gcc/c-family/c-common.cc | 11 ++++--
> gcc/testsuite/gcc.dg/pr114931.c | 10 +++++
> gcc/tree.cc | 65 +++++++++++++++++++++++----------
> 4 files changed, 74 insertions(+), 32 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/pr114931.c
>
> diff --git a/gcc/attribs.cc b/gcc/attribs.cc
> index 12ffc5f170a..3ab0b0fd87a 100644
> --- a/gcc/attribs.cc
> +++ b/gcc/attribs.cc
> @@ -1336,6 +1336,16 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
> tree dtype = ntype = build_distinct_type_copy (ttype);
>
> TYPE_ATTRIBUTES (ntype) = attribute;
> + /* If the target-dependent attributes make NTYPE different from
> + its canonical type, we will need to use structural equality
> + checks for this type.
> +
> + We shouldn't get here for stripping attributes from a type;
> + the no-attribute type might not need structural comparison. But
> + we can if was discarded from type_hash_table. */
> + if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
> + || !comp_type_attributes (ntype, ttype))
> + SET_TYPE_STRUCTURAL_EQUALITY (ntype);
>
> hashval_t hash = type_hash_canon_hash (ntype);
> ntype = type_hash_canon (hash, ntype);
> @@ -1343,16 +1353,6 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
> if (ntype != dtype)
> /* This variant was already in the hash table, don't mess with
> TYPE_CANONICAL. */;
> - else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
> - || !comp_type_attributes (ntype, ttype))
> - /* If the target-dependent attributes make NTYPE different from
> - its canonical type, we will need to use structural equality
> - checks for this type.
> -
> - We shouldn't get here for stripping attributes from a type;
> - the no-attribute type might not need structural comparison. But
> - we can if was discarded from type_hash_table. */
> - SET_TYPE_STRUCTURAL_EQUALITY (ntype);
> else if (TYPE_CANONICAL (ntype) == ntype)
> TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
>
> diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
> index 01e3d247fc2..032dcb4b41d 100644
> --- a/gcc/c-family/c-common.cc
> +++ b/gcc/c-family/c-common.cc
> @@ -7115,6 +7115,13 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
> TYPE_TYPELESS_STORAGE (main_type) = TYPE_TYPELESS_STORAGE (type);
> layout_type (main_type);
>
> + /* Set TYPE_STRUCTURAL_EQUALITY_P early. */
> + if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
> + || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
> + SET_TYPE_STRUCTURAL_EQUALITY (main_type);
> + else
> + TYPE_CANONICAL (main_type) = main_type;
> +
> /* Make sure we have the canonical MAIN_TYPE. */
> hashval_t hashcode = type_hash_canon_hash (main_type);
> main_type = type_hash_canon (hashcode, main_type);
> @@ -7122,7 +7129,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
> /* Fix the canonical type. */
> if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
> || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
> - SET_TYPE_STRUCTURAL_EQUALITY (main_type);
> + gcc_assert (TYPE_STRUCTURAL_EQUALITY_P (main_type));
> else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
> || (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
> != TYPE_DOMAIN (main_type)))
> @@ -7130,8 +7137,6 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
> = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
> TYPE_CANONICAL (TYPE_DOMAIN (main_type)),
> TYPE_TYPELESS_STORAGE (main_type));
> - else
> - TYPE_CANONICAL (main_type) = main_type;
>
> if (quals == 0)
> type = main_type;
> diff --git a/gcc/testsuite/gcc.dg/pr114931.c b/gcc/testsuite/gcc.dg/pr114931.c
> new file mode 100644
> index 00000000000..d690ed70e52
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr114931.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=c23" } */
> +
> +struct Tcl_Obj;
> +void(Tcl_FreeInternalRepProc)(struct Tcl_Obj *);
> +typedef struct Tcl_Obj {
> +} Tcl_Obj;
> +struct {
> + void (*tclFreeObj)(Tcl_Obj *);
> +} Tcl_InitStubs;
> diff --git a/gcc/tree.cc b/gcc/tree.cc
> index 780662549fe..6564b002dc1 100644
> --- a/gcc/tree.cc
> +++ b/gcc/tree.cc
> @@ -6012,6 +6012,8 @@ type_hash_canon_hash (tree type)
>
> hstate.add_int (TREE_CODE (type));
>
> + hstate.add_flag (TYPE_STRUCTURAL_EQUALITY_P (type));
> +
> if (TREE_TYPE (type))
> hstate.add_object (TYPE_HASH (TREE_TYPE (type)));
>
> @@ -6109,6 +6111,10 @@ type_cache_hasher::equal (type_hash *a, type_hash *b)
> || TYPE_MODE (a->type) != TYPE_MODE (b->type)))
> return false;
>
> + if (TYPE_STRUCTURAL_EQUALITY_P (a->type)
> + != TYPE_STRUCTURAL_EQUALITY_P (b->type))
> + return false;
> +
> switch (TREE_CODE (a->type))
> {
> case VOID_TYPE:
> @@ -7347,6 +7353,14 @@ build_array_type_1 (tree elt_type, tree index_type, bool typeless_storage,
> TYPE_DOMAIN (t) = index_type;
> TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type);
> TYPE_TYPELESS_STORAGE (t) = typeless_storage;
> +
> + /* Set TYPE_STRUCTURAL_EQUALITY_P. */
> + if (set_canonical
> + && (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
> + || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type))
> + || in_lto_p))
> + SET_TYPE_STRUCTURAL_EQUALITY (t);
> +
> layout_type (t);
>
> if (shared)
> @@ -7363,7 +7377,7 @@ build_array_type_1 (tree elt_type, tree index_type, bool typeless_storage,
> if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
> || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type))
> || in_lto_p)
> - SET_TYPE_STRUCTURAL_EQUALITY (t);
> + gcc_unreachable ();
> else if (TYPE_CANONICAL (elt_type) != elt_type
> || (index_type && TYPE_CANONICAL (index_type) != index_type))
> TYPE_CANONICAL (t)
> @@ -7510,21 +7524,25 @@ build_function_type (tree value_type, tree arg_types,
> TYPE_NO_NAMED_ARGS_STDARG_P (t) = 1;
> }
>
> - /* If we already have such a type, use the old one. */
> - hashval_t hash = type_hash_canon_hash (t);
> - tree probe_type = t;
> - t = type_hash_canon (hash, t);
> - if (t != probe_type)
> - return t;
> -
> /* Set up the canonical type. */
> any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type);
> any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type;
> canon_argtypes = maybe_canonicalize_argtypes (arg_types,
> &any_structural_p,
> &any_noncanonical_p);
> + /* Set TYPE_STRUCTURAL_EQUALITY_P early. */
> if (any_structural_p)
> SET_TYPE_STRUCTURAL_EQUALITY (t);
> +
> + /* If we already have such a type, use the old one. */
> + hashval_t hash = type_hash_canon_hash (t);
> + tree probe_type = t;
> + t = type_hash_canon (hash, t);
> + if (t != probe_type)
> + return t;
> +
> + if (any_structural_p)
> + gcc_assert (TYPE_STRUCTURAL_EQUALITY_P (t));
> else if (any_noncanonical_p)
> TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type),
> canon_argtypes);
> @@ -7667,13 +7685,6 @@ build_method_type_directly (tree basetype,
> argtypes = tree_cons (NULL_TREE, ptype, argtypes);
> TYPE_ARG_TYPES (t) = argtypes;
>
> - /* If we already have such a type, use the old one. */
> - hashval_t hash = type_hash_canon_hash (t);
> - tree probe_type = t;
> - t = type_hash_canon (hash, t);
> - if (t != probe_type)
> - return t;
> -
> /* Set up the canonical type. */
> any_structural_p
> = (TYPE_STRUCTURAL_EQUALITY_P (basetype)
> @@ -7684,8 +7695,20 @@ build_method_type_directly (tree basetype,
> canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes),
> &any_structural_p,
> &any_noncanonical_p);
> +
> + /* Set TYPE_STRUCTURAL_EQUALITY_P early. */
> if (any_structural_p)
> SET_TYPE_STRUCTURAL_EQUALITY (t);
> +
> + /* If we already have such a type, use the old one. */
> + hashval_t hash = type_hash_canon_hash (t);
> + tree probe_type = t;
> + t = type_hash_canon (hash, t);
> + if (t != probe_type)
> + return t;
> +
> + if (any_structural_p)
> + gcc_assert (TYPE_STRUCTURAL_EQUALITY_P (t));
> else if (any_noncanonical_p)
> TYPE_CANONICAL (t)
> = build_method_type_directly (TYPE_CANONICAL (basetype),
> @@ -7726,6 +7749,9 @@ build_offset_type (tree basetype, tree type)
>
> TYPE_OFFSET_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
> TREE_TYPE (t) = type;
> + if (TYPE_STRUCTURAL_EQUALITY_P (basetype)
> + || TYPE_STRUCTURAL_EQUALITY_P (type))
> + SET_TYPE_STRUCTURAL_EQUALITY (t);
>
> /* If we already have such a type, use the old one. */
> hashval_t hash = type_hash_canon_hash (t);
> @@ -7741,7 +7767,7 @@ build_offset_type (tree basetype, tree type)
> {
> if (TYPE_STRUCTURAL_EQUALITY_P (basetype)
> || TYPE_STRUCTURAL_EQUALITY_P (type))
> - SET_TYPE_STRUCTURAL_EQUALITY (t);
> + gcc_unreachable ();
> else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype
> || TYPE_CANONICAL (type) != type)
> TYPE_CANONICAL (t)
> @@ -7770,6 +7796,8 @@ build_complex_type (tree component_type, bool named)
> tree probe = make_node (COMPLEX_TYPE);
>
> TREE_TYPE (probe) = TYPE_MAIN_VARIANT (component_type);
> + if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (probe)))
> + SET_TYPE_STRUCTURAL_EQUALITY (probe);
>
> /* If we already have such a type, use the old one. */
> hashval_t hash = type_hash_canon_hash (probe);
> @@ -7781,11 +7809,10 @@ build_complex_type (tree component_type, bool named)
> out the type. We need to check the canonicalization and
> maybe set the name. */
> gcc_checking_assert (COMPLETE_TYPE_P (t)
> - && !TYPE_NAME (t)
> - && TYPE_CANONICAL (t) == t);
> + && !TYPE_NAME (t));
>
> if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t)))
> - SET_TYPE_STRUCTURAL_EQUALITY (t);
> + ;
> else if (TYPE_CANONICAL (TREE_TYPE (t)) != TREE_TYPE (t))
> TYPE_CANONICAL (t)
> = build_complex_type (TYPE_CANONICAL (TREE_TYPE (t)), named);
next prev parent reply other threads:[~2024-05-03 15:32 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-03 12:13 Richard Biener
2024-05-03 15:32 ` Martin Uecker [this message]
2024-05-03 16:23 ` Richard Biener
2024-05-03 17:44 ` Martin Uecker
2024-05-03 17:30 ` Jakub Jelinek
2024-05-03 18:04 ` Martin Uecker
2024-05-03 18:18 ` Jakub Jelinek
2024-05-03 18:37 ` Martin Uecker
2024-05-03 18:48 ` Richard Biener
2024-05-03 19:11 ` Martin Uecker
2024-05-03 19:16 ` Jakub Jelinek
2024-05-04 6:38 ` Martin Uecker
2024-05-06 7:00 ` Richard Biener
2024-05-06 7:27 ` Martin Uecker
2024-05-06 9:07 ` Richard Biener
2024-05-06 11:20 ` Martin Uecker
2024-05-07 11:05 ` Richard Biener
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3616afcc455c1f80e2bb8a80a408994a67062d85.camel@tugraz.at \
--to=uecker@tugraz.at \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=rguenther@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).