On 01/12/2018 09:03 AM, Jakub Jelinek wrote:
> Hi!
>
> In 7.x and earlier, decl_constant_value_for_optimization punted if
> the initializer has ARRAY_TYPE or BLKmode type, and the following patch
> shows that is reasonable thing to do, otherwise we might grab very large
> initializers out of constant variable initializers and if e.g. ARRAY_REF
> on it doesn't fold into a small constant, this may result in the large
> constants being duplicated, because the IL before gimplification will
> no longer refer to portions of the original constant var decl.
> E.g. look at the testcase below, with current trunk we fold the first
> function to:
> return (char)
> "01234567890123456789012345678901234567890123456789012345678901234567890123456789"[i];
> and because it is first an initializer of a variable, without
> -fmerge-all-constants we end up with 2 copies of that string.
> Haven't changed for this decl_constant_value, because it is used in the
> -Wformat code and needs to grab there the format strings (i.e.
> ARRAY_TYPE/BLKmode initializers).
> On the other side, when folding expressions in static variable initializers,
> we can try harder, because if e.g. the ARRAY_REF has index that doesn't fold
> into constant, it will be invalid anyway, so it is useful to pick there even
> CONSTRUCTORs and handle COMPONENT_REFs on them.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2018-01-12 Jakub Jelinek <ja...@redhat.com>
>
> PR c/83801
> * c-tree.h (decl_constant_value_1): Add a bool argument.
> * c-typeck.c (decl_constant_value_1): Add IN_INIT argument, allow
> returning a CONSTRUCTOR if it is true. Use error_operand_p.
> (decl_constant_value): Adjust caller.
> * c-fold.c (c_fully_fold_internal): If in_init, pass true to
> decl_constant_value_1 as IN_INIT. Otherwise, punt if
> decl_constant_value returns initializer that has BLKmode or
> array type.
> (c_fully_fold_internal) <case COMPONENT_REF>: Fold if !lval.
>
> * gcc.dg/pr83801.c: New test.
OK.
jeff