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

            Bug ID: 87791
           Summary: Unnecessary zero-initialization of constexpr unions in
                    arrays
           Product: gcc
           Version: 8.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: widlundtobias at gmail dot com
  Target Milestone: ---

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

Given a type that uses a constexpr-enabled union to store either a value, or an
empty dummy struct as followed.


>struct Container
>{
>    struct Dummy{};
>    union Storage
>    {   
>        constexpr Storage(): dummy(Dummy())
>        {   
>
>        }   
>        Dummy dummy;
>        int value;
>    };  
>
>    Storage storage;
>};

This code is a legal way to initialise the union with nothing, meaning that
it's legal for the compiler to leave the data uninitialised, even in constexpr
contexts.

However, if the above Container type is used like so:

>using Arr = std::array<Container, 4000>;
>
>Arr makeA()
>{
>    Arr a;
>    return a;
>}

Then the compiled code fills the array with zeroes, using memset.

Excerpt from compiled code:

>_Z5makeAv:
>.LFB1099:
>    .cfi_startproc
>    subq    $8, %rsp
>    .cfi_def_cfa_offset 16
>    movl    $16000, %edx
>    xorl    %esi, %esi
>    call    memset@PLT   <----unnecessary runtime overhead
>    addq    $8, %rsp
>    .cfi_def_cfa_offset 8
>    ret 
>    .cfi_endproc
>.LFE1099:
>    .size   _Z5makeAv, .-_Z5makeAv
>    .section    .text.startup,"ax",@progbits
>    .p2align 4,,15
>    .globl  main
>    .type   main, @function

This is unnecessary and problematic as it incurs runtime overhead when using
the union-based storage as a way to store items that can possibly be
uninitialised, as a constexpr-friendly alternative to placement-new.

Happens even with -O3 and only happens if the `constexpr` keyword is present.

Preprocessed code attached.

Godbolt CE link for illustrative purpose: https://godbolt.org/z/FPnEy3




Output of gcc -v -save-temps -O3 main.cpp:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib
--libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info
--with-bugurl=https://bugs.archlinux.org/
--enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared
--enable-threads=posix --enable-libmpx --with-system-zlib --with-isl
--enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu
--disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object
--enable-linker-build-id --enable-lto --enable-plugin
--enable-install-libiberty --with-linker-hash-style=gnu
--enable-gnu-indirect-function --enable-multilib --disable-werror
--enable-checking=release --enable-default-pie --enable-default-ssp
--enable-cet=auto
Thread model: posix
gcc version 8.2.1 20180831 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-O3' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/cc1plus -E -quiet -v -D_GNU_SOURCE
main.cpp -mtune=generic -march=x86-64 -O3 -fpch-preprocess -o main.ii
ignoring nonexistent directory
"/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1

/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/x86_64-pc-linux-gnu
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/backward
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/include
 /usr/local/include
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/include-fixed
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-O3' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/cc1plus -fpreprocessed main.ii -quiet
-dumpbase main.cpp -mtune=generic -march=x86-64 -auxbase main -O3 -version -o
main.s
GNU C++14 (GCC) version 8.2.1 20180831 (x86_64-pc-linux-gnu)
        compiled by GNU C version 8.2.1 20180831, GMP version 6.1.2, MPFR
version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++14 (GCC) version 8.2.1 20180831 (x86_64-pc-linux-gnu)
        compiled by GNU C version 8.2.1 20180831, GMP version 6.1.2, MPFR
version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: a03a3250bc7a24a525a6f08bf70a1ad6
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-O3' '-mtune=generic' '-march=x86-64'
 as -v --64 -o main.o main.s
GNU assembler version 2.31.1 (x86_64-pc-linux-gnu) using BFD version (GNU
Binutils) 2.31.1
COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-O3' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/collect2 -plugin
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/liblto_plugin.so
-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/lto-wrapper
-plugin-opt=-fresolution=main.res -plugin-opt=-pass-through=-lgcc
-plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id
--eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker
/lib64/ld-linux-x86-64.so.2 -pie
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib/Scrt1.o
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/crtbeginS.o
-L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1
-L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib -L/lib/../lib
-L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../.. main.o
-lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s
--no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/crtendS.o
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib/crtn.o
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-O3' '-mtune=generic' '-march=x86-64'

Reply via email to