https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86763
Bug ID: 86763 Summary: Wrong code comparing member of copy of a 237 byte object with nontrivial default constructor on x86-64 arch Product: gcc Version: 8.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: curlypaul924 at gmail dot com Target Milestone: --- Created attachment 44475 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44475&action=edit .ii file generated from t4.cpp The following program produces an incorrect result on GCC 8.1 and 8.2. It succeeds on 7.2. AFAICT, the problem is that the comparison happens before the object has been copied. The compiler could compare using the temporary stored in rdx, but it instead compares using the value at [rsp+8], which isn't yet written to. This happens when using -march=x86-64, but does not happen on -march=core2 or newer. In these cases, memcpy is used to do the copy, and the comparison happens after the call to memcpy. Moreover, GCC misses an opportunity to optimize away the copy altogether. Clang 6.0.0 does optimize away the copy. The misplaced comparison happens at -O2 or higher; at -O1, the comparison is done after the copy. #include <cstdint> #include <cassert> #include <time.h> struct ID { uint64_t value; }; uint64_t value(ID id) { return id.value; } uint64_t gen { 1000 }; struct Msg { uint64_t time; ID id; }; struct V { V() { } V(Msg const & msg) : msg(msg) { } Msg & get() { return msg; } Msg msg; char pad[237 - sizeof(Msg)]; }; struct T : V { using V::V; }; Msg init_msg() { Msg msg; timespec t; clock_gettime(CLOCK_REALTIME, &t); msg.time = t.tv_sec + t.tv_nsec; msg.id.value = ++gen; return msg; } int main() { T t; t = init_msg(); assert(value(t.get().id) == 1001); } $ g++-8.1 -std=c++14 -O2 -Wall -Werror -march=x86-64 -save-temps -v t4.cpp Using built-in specs. COLLECT_GCC=/usr/local/bin/g++-8.1 COLLECT_LTO_WRAPPER=/opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/lto-wrapper Target: x86_64-linux-gnu Configured with: /home/pbrannan/git/theme_infra/packaging/gcc-8.1.0/configure --prefix=/opt/gcc/8.1 --enable-languages=c,c++ --with-pkgversion='Thesys GCC 8.1.0 for Ubuntu 16.04' --enable-shared --enable-gnu-unique-object --enable-threads=posix --enable-checking=release --disable-vtable-verify --enable-lto --with-ab i=m64 --enable-multiarch --disable-multilib --with-build-config=bootstrap-lto --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 8.1.0 (Thesys GCC 8.1.0 for Ubuntu 16.04) COLLECT_GCC_OPTIONS='-std=c++14' '-O2' '-Wall' '-Werror' '-march=x86-64' '-save-temps' '-v' '-shared-libgcc' /opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/cc1plus -E -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE t4.cpp -march=x86-64 -std=c++14 -Wall -Werror -O2 -fpch-preprocess -o t4.ii ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../../../include/c++/8.1.0 /opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../../../include/c++/8.1.0/x86_64-linux-gnu /opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../../../include/c++/8.1.0/backward /opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/include /usr/local/include /opt/gcc/8.1/include /opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. COLLECT_GCC_OPTIONS='-std=c++14' '-O2' '-Wall' '-Werror' '-march=x86-64' '-save-temps' '-v' '-shared-libgcc' /opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/cc1plus -fpreprocessed t4.ii -quiet -dumpbase t4.cpp -march=x86-64 -auxbase t4 -O2 -Wall -Werror -std=c++14 -version -o t4.s GNU C++14 (Thesys GCC 8.1.0 for Ubuntu 16.04) version 8.1.0 (x86_64-linux-gnu) compiled by GNU C version 8.1.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.16.1-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C++14 (Thesys GCC 8.1.0 for Ubuntu 16.04) version 8.1.0 (x86_64-linux-gnu) compiled by GNU C version 8.1.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.16.1-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 6724e7d270573c4346dc08c31ad9ce91 COLLECT_GCC_OPTIONS='-std=c++14' '-O2' '-Wall' '-Werror' '-march=x86-64' '-save-temps' '-v' '-shared-libgcc' as -v --64 -o t4.o t4.s GNU assembler version 2.26.1 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.26.1 COMPILER_PATH=/opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/:/opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/:/opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/:/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/:/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/:/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../../../lib64/:/lib/x86_64-linux-gnu/:/lib/../lib64/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib64/:/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-std=c++14' '-O2' '-Wall' '-Werror' '-march=x86-64' '-save-temps' '-v' '-shared-libgcc' /opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/collect2 -plugin /opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/liblto_plugin.so -plugin-opt=/opt/gcc/8.1/libexec/gcc/x86_64-linux-gnu/8.1.0/lto-wrapper -plugin-opt=-fresolution=t4.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pas s-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/crtbegin.o -L/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1 .0 -L/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/../../.. t4.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /opt/gcc/8.1/lib/gcc/x86_64-linux-gnu/8.1.0/crtend.o /usr /lib/x86_64-linux-gnu/crtn.o COLLECT_GCC_OPTIONS='-std=c++14' '-O2' '-Wall' '-Werror' '-march=x86-64' '-save-temps' '-v' '-shared-libgcc'