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

            Bug ID: 87502
           Summary: Poor code generation for std::string("c-style string")
           Product: gcc
           Version: 8.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: terra at gnome dot org
  Target Milestone: ---

Created attachment 44776
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44776&action=edit
Preprocessed source code

It appears that gcc is creating quite poor code when "c-style strings"
are used to construct std::string objects.  Ideally, the result ought
to be just a few move instructions for small strings.


Host: Linux x86_64 4.4.140-62-default (OpenSuSE)

Test code:
---------------------------------------------------------------
#include <string>

extern void foo (const std::string &);

void
bar ()
{
  foo ("abc");
  foo (std::string("abc"));
}
---------------------------------------------------------------



# /usr/local/products/gcc/8.2.0/bin/g++ -std=gnu++1z  -S -m32 -O3 ttt.C
# grep 'call.*construct' ttt.s 
        call   
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag.constprop.18
        call   
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag.constprop.18

Here gcc generates complete calls to the generic string construction
even though the strings are constructed from small, known strings.

"-std=gnu++1z" is important; "-m32" and "-O3" (as opposed to "-m64" and
"-O2") are not.

# /usr/local/products/gcc/8.2.0/bin/g++ -S -m32 -O3 ttt.C
# grep 'call.*construct' ttt.s
# (nada)

No calls -- good.  In this case gcc generates this fragment:

_Z3barv:
.LFB1084:
        .cfi_startproc
        .cfi_personality 0,__gxx_personality_v0
        .cfi_lsda 0,.LLSDA1084
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    $25185, %edx
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        pushl   %edi
        pushl   %esi
        .cfi_offset 7, -12
        .cfi_offset 6, -16
        leal    -48(%ebp), %esi
        pushl   %ebx
        .cfi_offset 3, -20
        leal    -40(%ebp), %ebx
        subl    $56, %esp
        movl    %ebx, -48(%ebp)
        pushl   %esi
        movw    %dx, -40(%ebp)
        movb    $99, -38(%ebp)
        movl    $3, -44(%ebp)
        movb    $0, -37(%ebp)
.LEHB6:
        .cfi_escape 0x2e,0x10
        call    _Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
[...]

This is better than a call, but not great:
1. The string is moved into position in three chunks (25185, 99, 0).
   This probably comes from inlined memcpy of 3 bytes, but the source
   is zero-terminated so rounding the memcpy size up to 4 would have
   been better.
2. It's unclear why 25185 is passed through a register.

Reply via email to