While investigating another issue, I came across a case where a simple
assignment gives rise to the creation of two CONSTRUCTORS in a row when a
padding type is involved. I think we can get away with only one.
Tested on x86_64-suse-linux, applied on the mainline.
2017-09-09 Eric Botcazou <ebotca...@adacore.com>
* gcc-interface/utils.c (convert): When converting to a padding type,
reuse an existing CONSTRUCTOR if it has got the right size.
--
Eric Botcazou
Index: gcc-interface/utils.c
===================================================================
--- gcc-interface/utils.c (revision 251906)
+++ gcc-interface/utils.c (working copy)
@@ -4219,8 +4219,6 @@ convert (tree type, tree expr)
constructor to build the record, unless a variable size is involved. */
else if (code == RECORD_TYPE && TYPE_PADDING_P (type))
{
- vec<constructor_elt, va_gc> *v;
-
/* If we previously converted from another type and our type is
of variable size, remove the conversion to avoid the need for
variable-sized temporaries. Likewise for a conversion between
@@ -4272,9 +4270,21 @@ convert (tree type, tree expr)
expr),
false);
+ tree t = convert (TREE_TYPE (TYPE_FIELDS (type)), expr);
+
+ /* If converting to the inner type has already created a CONSTRUCTOR with
+ the right size, then reuse it instead of creating another one. This
+ can happen for the padding type built to overalign local variables. */
+ if (TREE_CODE (t) == VIEW_CONVERT_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 0)) == CONSTRUCTOR
+ && TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (t, 0))))
+ && tree_int_cst_equal (TYPE_SIZE (type),
+ TYPE_SIZE (TREE_TYPE (TREE_OPERAND (t, 0)))))
+ return build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (t, 0));
+
+ vec<constructor_elt, va_gc> *v;
vec_alloc (v, 1);
- CONSTRUCTOR_APPEND_ELT (v, TYPE_FIELDS (type),
- convert (TREE_TYPE (TYPE_FIELDS (type)), expr));
+ CONSTRUCTOR_APPEND_ELT (v, TYPE_FIELDS (type), t);
return gnat_build_constructor (type, v);
}