On Sun, Jun 29, 2014 at 12:44 AM, Jan Hubicka <[email protected]> wrote:
> Hi,
> this patch fixes another problem where we manage to produce a variant of
> variadic array that has different TYPE_SIZE (but an equivalent expression).
> This happens because remap_type_1 blindly copies all expressions referred by
> variadic type while for variants it may just reuse ones it earlier copied when
> producing a copy of the main variant.
>
> Bootstrapped/regtested x86_64-linux, lto-bootstrapped and tested on Firefox
> build with the main variant checking patch in, comitted.
Note that we do have variant types which do _not_ share the fields list
of the main variant (see PR61456). Not sure if your patches fix that.
But if they didn't yet the following patch silently re-write those types.
Richard.
> Honza
>
> * tree-inline.c (remap_type_1): Do not duplicate fields
> that are shared in between type and its main variant.
> Index: tree-inline.c
> ===================================================================
> --- tree-inline.c (revision 212098)
> +++ tree-inline.c (working copy)
> @@ -451,6 +451,8 @@ remap_type_1 (tree type, copy_body_data
> TYPE_POINTER_TO (new_tree) = NULL;
> TYPE_REFERENCE_TO (new_tree) = NULL;
>
> + /* Copy all types that may contain references to local variables; be sure
> to
> + preserve sharing in between type and its main variant when possible. */
> switch (TREE_CODE (new_tree))
> {
> case INTEGER_TYPE:
> @@ -458,40 +460,72 @@ remap_type_1 (tree type, copy_body_data
> case FIXED_POINT_TYPE:
> case ENUMERAL_TYPE:
> case BOOLEAN_TYPE:
> - t = TYPE_MIN_VALUE (new_tree);
> - if (t && TREE_CODE (t) != INTEGER_CST)
> - walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id, NULL);
> -
> - t = TYPE_MAX_VALUE (new_tree);
> - if (t && TREE_CODE (t) != INTEGER_CST)
> - walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id, NULL);
> + if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
> + {
> + gcc_checking_assert (TYPE_MIN_VALUE (type) == TYPE_MIN_VALUE
> (TYPE_MAIN_VARIANT (type)));
> + gcc_checking_assert (TYPE_MAX_VALUE (type) == TYPE_MAX_VALUE
> (TYPE_MAIN_VARIANT (type)));
> +
> + TYPE_MIN_VALUE (new_tree) = TYPE_MIN_VALUE (TYPE_MAIN_VARIANT
> (new_tree));
> + TYPE_MAX_VALUE (new_tree) = TYPE_MAX_VALUE (TYPE_MAIN_VARIANT
> (new_tree));
> + }
> + else
> + {
> + t = TYPE_MIN_VALUE (new_tree);
> + if (t && TREE_CODE (t) != INTEGER_CST)
> + walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id,
> NULL);
> +
> + t = TYPE_MAX_VALUE (new_tree);
> + if (t && TREE_CODE (t) != INTEGER_CST)
> + walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id,
> NULL);
> + }
> return new_tree;
>
> case FUNCTION_TYPE:
> - TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
> - walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL);
> + if (TYPE_MAIN_VARIANT (new_tree) != new_tree
> + && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type)))
> + TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree));
> + else
> + TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
> + if (TYPE_MAIN_VARIANT (new_tree) != new_tree
> + && TYPE_ARG_TYPES (type) == TYPE_ARG_TYPES (TYPE_MAIN_VARIANT
> (type)))
> + TYPE_ARG_TYPES (new_tree) = TYPE_ARG_TYPES (TYPE_MAIN_VARIANT
> (new_tree));
> + else
> + walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL);
> return new_tree;
>
> case ARRAY_TYPE:
> - TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
> - TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id);
> + if (TYPE_MAIN_VARIANT (new_tree) != new_tree
> + && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type)))
> + TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree));
> +
> + if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
> + {
> + gcc_checking_assert (TYPE_DOMAIN (type) == TYPE_DOMAIN
> (TYPE_MAIN_VARIANT (type)));
> + TYPE_DOMAIN (new_tree) = TYPE_DOMAIN (TYPE_MAIN_VARIANT (new_tree));
> + }
> + else
> + TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id);
> break;
>
> case RECORD_TYPE:
> case UNION_TYPE:
> case QUAL_UNION_TYPE:
> - {
> - tree f, nf = NULL;
> -
> - for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f))
> - {
> - t = remap_decl (f, id);
> - DECL_CONTEXT (t) = new_tree;
> - DECL_CHAIN (t) = nf;
> - nf = t;
> - }
> - TYPE_FIELDS (new_tree) = nreverse (nf);
> - }
> + if (TYPE_MAIN_VARIANT (type) != type
> + && TYPE_FIELDS (type) == TYPE_FIELDS (TYPE_MAIN_VARIANT (type)))
> + TYPE_FIELDS (new_tree) = TYPE_FIELDS (TYPE_MAIN_VARIANT (new_tree));
> + else
> + {
> + tree f, nf = NULL;
> +
> + for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f))
> + {
> + t = remap_decl (f, id);
> + DECL_CONTEXT (t) = new_tree;
> + DECL_CHAIN (t) = nf;
> + nf = t;
> + }
> + TYPE_FIELDS (new_tree) = nreverse (nf);
> + }
> break;
>
> case OFFSET_TYPE:
> @@ -500,8 +534,20 @@ remap_type_1 (tree type, copy_body_data
> gcc_unreachable ();
> }
>
> - walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL);
> - walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL);
> + /* All variants of type share the same size, so use the already remaped
> data. */
> + if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
> + {
> + gcc_checking_assert (TYPE_SIZE (type) == TYPE_SIZE (TYPE_MAIN_VARIANT
> (type)));
> + gcc_checking_assert (TYPE_SIZE_UNIT (type) == TYPE_SIZE_UNIT
> (TYPE_MAIN_VARIANT (type)));
> +
> + TYPE_SIZE (new_tree) = TYPE_SIZE (TYPE_MAIN_VARIANT (new_tree));
> + TYPE_SIZE_UNIT (new_tree) = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT
> (new_tree));
> + }
> + else
> + {
> + walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL);
> + walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL);
> + }
>
> return new_tree;
> }