> Am 10.09.2025 um 09:27 schrieb Jakub Jelinek <ja...@redhat.com>:
> 
> Hi!
> 
> I thought this wouldn't be necessary because RAW_DATA_CST can only appear
> inside of (array) CONSTRUCTORs within DECL_INITIAL of TREE_STATIC vars,
> so there shouldn't be a need to expand it.  Except that we have an
> optimization when reading ARRAY_REF from such a CONSTRUCTOR which will
> try to expand the constructor if it either can be stored by pieces
> (I think that is just fine) or if it is mostly zeros (which is at least
> 75% of the initializer zeros).  Now the second case is I think in some
> cases desirable (say 256MB initializer and just 20 elements out of that
> non-zero, so clear everything and store 20 elements must be fastest and
> short), but could be really bad as well (say 40GB initializer with
> 10GB non-zero in it, especially if it doesn't result in the original
> variable being optimized away).  Maybe it would help if expand_constructor
> and store_constructor* etc. had some optional argument with addresses into
> the original VAR_DECL so that it could be copying larger amounts of data
> like larger RAW_DATA_CSTs from there instead of pushing those into new
> .rodata again.  And another problem is that we apparently expand the
> initializes twice, expand_constructor in store_constructor can expand
> the stores one and if expand_constructor returns non-NULL, we then
> expand_expr the CONSTRUCTOR again. to the same location.
> 
> This patch doesn't address either of those issues, just adds RAW_DATA_CST
> support to store_constructor for now.  For the can_store_by_pieces
> cases it stores those by pieces using a new callback very similar to
> string_cst_read_str, for the rest (unfortunately) forces it into a memory
> and copies from there.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/15
> branch?

Ok

Richard 

> 2025-09-10  Jakub Jelinek  <ja...@redhat.com>
> 
>    PR middle-end/121831
>    * expr.cc (raw_data_cst_read_str): New function.
>    (store_constructor) <case ARRAY_TYPE>: Handle RAW_DATA_CST.
> 
>    * g++.dg/lto/pr121831_0.C: New test.
>    * g++.dg/lto/pr121831_1.C: New test.
> 
> --- gcc/expr.cc.jj    2025-08-05 12:57:06.719031397 +0200
> +++ gcc/expr.cc    2025-09-09 08:52:39.246507748 +0200
> @@ -6533,6 +6533,31 @@ string_cst_read_str (void *data, void *,
>   return c_readstr (TREE_STRING_POINTER (str) + offset, mode, false);
> }
> 
> +/* Helper function for store_expr storing of RAW_DATA_CST.  */
> +
> +static rtx
> +raw_data_cst_read_str (void *data, void *, HOST_WIDE_INT offset,
> +               fixed_size_mode mode)
> +{
> +  tree cst = (tree) data;
> +
> +  gcc_assert (offset >= 0);
> +  if (offset >= RAW_DATA_LENGTH (cst))
> +    return const0_rtx;
> +
> +  if ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
> +      > (unsigned HOST_WIDE_INT) RAW_DATA_LENGTH (cst))
> +    {
> +      char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
> +      size_t l = RAW_DATA_LENGTH (cst) - offset;
> +      memcpy (p, RAW_DATA_POINTER (cst) + offset, l);
> +      memset (p + l, '\0', GET_MODE_SIZE (mode) - l);
> +      return c_readstr (p, mode, false);
> +    }
> +
> +  return c_readstr (RAW_DATA_POINTER (cst) + offset, mode, false);
> +}
> +
> /* Generate code for computing expression EXP,
>    and storing the value into TARGET.
> 
> @@ -7630,7 +7655,7 @@ store_constructor (tree exp, rtx target,
>     case ARRAY_TYPE:
>       {
>    tree value, index;
> -    unsigned HOST_WIDE_INT i;
> +    unsigned HOST_WIDE_INT i, j = 0;
>    bool need_to_clear;
>    tree domain;
>    tree elttype = TREE_TYPE (type);
> @@ -7692,6 +7717,8 @@ store_constructor (tree exp, rtx target,
>            this_node_count = (tree_to_uhwi (hi_index)
>                       - tree_to_uhwi (lo_index) + 1);
>          }
> +        else if (TREE_CODE (value) == RAW_DATA_CST)
> +          this_node_count = RAW_DATA_LENGTH (value);
>        else
>          this_node_count = 1;
> 
> @@ -7734,7 +7761,11 @@ store_constructor (tree exp, rtx target,
>        rtx xtarget = target;
> 
>        if (cleared && initializer_zerop (value))
> -          continue;
> +          {
> +        if (TREE_CODE (value) == RAW_DATA_CST)
> +          j += RAW_DATA_LENGTH (value) - 1;
> +        continue;
> +          }
> 
>        mode = TYPE_MODE (elttype);
>        if (mode != BLKmode)
> @@ -7750,6 +7781,8 @@ store_constructor (tree exp, rtx target,
>        unsigned HOST_WIDE_INT lo, hi, count;
>        tree offset;
> 
> +        gcc_assert (TREE_CODE (value) != RAW_DATA_CST);
> +
>        /* If the range is constant and "small", unroll the loop.  */
>        if (const_bounds_p
>            && tree_fits_uhwi_p (lo_index)
> @@ -7846,13 +7879,14 @@ store_constructor (tree exp, rtx target,
>          {
>        tree offset;
> 
> +        gcc_assert (TREE_CODE (value) != RAW_DATA_CST);
>        if (index)
>          offset = fold_build2 (MINUS_EXPR,
>                    TREE_TYPE (index),
>                    index,
>                    TYPE_MIN_VALUE (domain));
>        else
> -          offset = size_int (i);
> +          offset = size_int (i + j);
> 
>        offset = size_binop (MULT_EXPR,
>                     fold_convert (sizetype, offset),
> @@ -7869,7 +7903,7 @@ store_constructor (tree exp, rtx target,
>          bitpos = ((tree_to_uhwi (index) - minelt)
>                * tree_to_uhwi (TYPE_SIZE (elttype)));
>        else
> -          bitpos = (i * tree_to_uhwi (TYPE_SIZE (elttype)));
> +          bitpos = ((i + j) * tree_to_uhwi (TYPE_SIZE (elttype)));
> 
>        if (MEM_P (target) && !MEM_KEEP_ALIAS_SET_P (target)
>            && TREE_CODE (type) == ARRAY_TYPE
> @@ -7878,10 +7912,50 @@ store_constructor (tree exp, rtx target,
>            target = copy_rtx (target);
>            MEM_KEEP_ALIAS_SET_P (target) = 1;
>          }
> -        store_constructor_field (target, bitsize, bitpos, 0,
> -                     bitregion_end, mode, value,
> -                     cleared, get_alias_set (elttype),
> -                     reverse);
> +        if (TREE_CODE (value) != RAW_DATA_CST)
> +          store_constructor_field (target, bitsize, bitpos, 0,
> +                       bitregion_end, mode, value,
> +                       cleared, get_alias_set (elttype),
> +                       reverse);
> +        else
> +          {
> +            j += RAW_DATA_LENGTH (value) - 1;
> +            gcc_assert (known_eq (bitsize, BITS_PER_UNIT));
> +            rtx to_rtx = adjust_address (target, mode,
> +                         bitpos / BITS_PER_UNIT);
> +
> +            if (to_rtx == target)
> +              to_rtx = copy_rtx (to_rtx);
> +
> +            if (!MEM_KEEP_ALIAS_SET_P (to_rtx)
> +            && MEM_ALIAS_SET (to_rtx) != 0)
> +              set_mem_alias_set (to_rtx, get_alias_set (elttype));
> +
> +            if (can_store_by_pieces (RAW_DATA_LENGTH (value),
> +                         raw_data_cst_read_str,
> +                         (void *) value,
> +                         MEM_ALIGN (target), false))
> +              {
> +            store_by_pieces (target, RAW_DATA_LENGTH (value),
> +                     raw_data_cst_read_str, (void *) value,
> +                     MEM_ALIGN (target), false,
> +                     RETURN_BEGIN);
> +            continue;
> +              }
> +
> +            elttype
> +              = build_array_type_nelts (TREE_TYPE (value),
> +                        RAW_DATA_LENGTH (value));
> +            tree ctor = build_constructor_single (elttype, NULL_TREE,
> +                              value);
> +            ctor = tree_output_constant_def (ctor);
> +            mode = TYPE_MODE (type);
> +            store_constructor_field (target,
> +                         bitsize * RAW_DATA_LENGTH (value),
> +                         bitpos, 0, bitregion_end, mode,
> +                         ctor, cleared,
> +                         get_alias_set (elttype), reverse);
> +          }
>          }
>      }
>    break;
> --- gcc/testsuite/g++.dg/lto/pr121831_0.C.jj    2025-09-09 09:16:55.204603044 
> +0200
> +++ gcc/testsuite/g++.dg/lto/pr121831_0.C    2025-09-09 08:40:48.196226782 
> +0200
> @@ -0,0 +1,17 @@
> +/* PR middle-end/121831 */
> +/* { dg-lto-do run } */
> +/* { dg-lto-options { { -O2 -flto } } } */
> +
> +struct S { unsigned char s[256]; };
> +S a;
> +extern const S b[1];
> +struct T { unsigned char t[2048]; };
> +T c;
> +extern const T d[1];
> +
> +__attribute__((noipa)) void
> +foo ()
> +{
> +  a = b[0];
> +  c = d[0];
> +}
> --- gcc/testsuite/g++.dg/lto/pr121831_1.C.jj    2025-09-09 09:16:58.582556614 
> +0200
> +++ gcc/testsuite/g++.dg/lto/pr121831_1.C    2025-09-09 08:48:27.849935692 
> +0200
> @@ -0,0 +1,64 @@
> +struct S { unsigned char s[256]; };
> +extern S a;
> +struct T { unsigned char t[2048]; };
> +extern T c;
> +extern const T d[1];
> +extern void foo ();
> +
> +extern const S b[1] {
> +  { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
> +    33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
> +    49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
> +    65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
> +    81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
> +    97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
> 112,
> +    113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 
> 127, 128,
> +    129, 0 }
> +};
> +extern const T d[1] {
> +  { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
> +    33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
> +    49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
> +    65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
> +    81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
> +    97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
> 112,
> +    113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 
> 127, 128,
> +    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
> +    33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
> +    49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
> +    65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
> +    81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
> +    97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
> 112,
> +    113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 
> 127, 128,
> +    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
> +    33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
> +    49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
> +    65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
> +    81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
> +    97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
> 112,
> +    113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 
> 127, 128,
> +    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
> +    33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
> +    49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
> +    65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
> +    81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
> +    97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
> 112,
> +    113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 
> 127, 128 }
> +};
> +
> +int
> +main ()
> +{
> +  foo ();
> +  for (int i = 0; i < 256; ++i)
> +    if (a.s[i] != (i < 129 ? i + 1 : 0))
> +      __builtin_abort ();
> +  for (int i = 0; i < 2048; ++i)
> +    if (c.t[i] != (i < 512 ? (i & 127) + 1 : 0))
> +      __builtin_abort ();
> +}
> 
>    Jakub
> 

Reply via email to