This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix duplication of TYPE_SIZE/TYPE_SIZE_UNIT of variadic array type variants
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 29 Jun 2014 00:44:07 +0200
- Subject: Fix duplication of TYPE_SIZE/TYPE_SIZE_UNIT of variadic array type variants
- Authentication-results: sourceware.org; auth=none
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.
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;
}