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'