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; }