https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120702

            Bug ID: 120702
           Summary: Extraneous string constant at -Os
           Product: gcc
           Version: 13.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: amacleod at redhat dot com
  Target Milestone: ---
            Target: arm-none-eabi

Created attachment 61660
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61660&action=edit
Testcase demonstrating the problem

When compiled with -Os (or any optimization level) the attached testcase
produces 2 copies of the string constant.  This is a small sample of a much
larger problem when we are suppose to be compiling to preserve size.

The text from the email thread summarizes the issue:

>>> After the gimple lowering, the verify routine remains the same, but
>>> the benchmark () routine  is transformed from a memcpy and becomes:
>>>
>>>
>>>     ;; Function benchmark (benchmark, funcdef_no=1, decl_uid=4718,
>>>     cgraph_uid=4, symbol_order=3)
>>>
>>>     int benchmark ()
>>>     {
>>>       int D.4726;
>>>
>>>       MEM <unsigned char[10]> [(char * {ref-all})&test] = MEM
>>>     <unsigned char[10]> [(char * {ref-all})&orig];
>>>       D.4726 = 0;
>>>       goto <D.4727>;
>>>       <D.4727>:
>>>       return D.4726;
>>>     }
>>>
>>>
>>> It appears that forwprop is then transforming the statement to
>>>   <bb 2> :
>>>   MEM <unsigned char[10]> [(char * {ref-all})&test] = "J2OZF50FYL";
>>>   return 0;
>>>
>>> And in the final output, there are now 2 copies of the original
>>> character data:
>>>
>>> orig:
>>>         .ascii  "J2OZF50FYL"
>>>         .space  2
>>> .LC0:
>>>         .ascii  "J2OZF50FYL"
>>>         .bss
>>>
>>>
>>> and I presume that new string is a copy of the orig text that
>>> forwprop has created for some reason.
>>>
>>> Whats going on, and is there a way to disable this?  Either at the
>>> lowering stage or in forwprop?   At -Os, they are not thrilled that a
>>> bunch more redundant text is being generated in the object file.
>>> This is a reduced testcase to demonstrate a much larger problem.
>>>
>> The hope is the static var can be elided and the read might be just a
>> small part.  In this case heuristics are misfiring I guess.  You’d
>> have to track down where exactly in folding we are replacing the RHS
>> of an aggregate copy.  I can’t recall off my head.
>>
>> Richard
>
> heres my traceback where the "magic" happens
>
> #0  fold_ctor_reference (type=0x7fffe9f3be70, ctor=0x7fffe9f2cc00,
> poly_offset=..., poly_size=..., from_decl=0x7fffe9c6f980, suboff=0x0) at
> /gcc/master/gcc/gcc/gimple-fold.cc:9955
> #1  0x0000000001200074 in fold_const_aggregate_ref_1 (t=0x7fffe9f46de8,
> valueize=0x0) at /gcc/master/gcc/gcc/gimple-fold.cc:10134
> #2  0x0000000001200918 in fold_const_aggregate_ref (t=0x7fffe9f46de8) at
> /gcc/master/gcc/gcc/gimple-fold.cc:10213
> #3  0x00000000011db1aa in maybe_fold_reference (expr=0x7fffe9f46de8) at
> /gcc/master/gcc/gcc/gimple-fold.cc:325
> #4  0x00000000011db8bf in fold_gimple_assign (si=0x7fffffffd410) at
> /gcc/master/gcc/gcc/gimple-fold.cc:473
> #5  0x00000000011f20d5 in fold_stmt_1 (gsi=0x7fffffffd410,
> inplace=false, valueize=0x18d3b10 <fwprop_ssa_val(tree)>,
> dce_worklist=0x7fffffffd4c0) at /gcc/master/gcc/gcc/gimple-fold.cc:6648
>
> ctor  is a STRING_CST tree and has  the string in it  : "J2OZF50FYL"
>
> The fold routine gets to  :
>
>    /* We found the field with exact match.  */
>    if (type
>        && useless_type_conversion_p (type, TREE_TYPE (ctor))
>        && known_eq (poly_offset, 0U))
>      return canonicalize_constructor_val (unshare_expr (ctor), from_decl);
>
> I would hazard a guess that it is the "unshare_expr (ctor)"  that is
> causing the duplication of the string?  I presume we have a good reason
> for doing this?   Perhaps that is a bad thing at -Os? I don't relally
> remember all the unsharing details 🙂

unshare_expr doesn't unshare a STRING_CST.  But here I think it's
fold_stmt_1 that shouldn't replace the RHS with a STRING_CST.
We should really have the constant pool represented and have a
CONST_DECL for each STRING_CST, but we don't.  There might
be cases where a STRING_CST is cheaper (for example when
it's power-of-two size and less than word_mode as the copy can
then be a store from an immediate), but in general a STRING_CST
will end up as a new constant pool entry as you've seen.

Reply via email to