[Bug c++/86763] New: Wrong code comparing member of copy of a 237 byte object with nontrivial default constructor on x86-64 arch
curlypaul924 at gmail dot com
gcc-bugzilla@gcc.gnu.org
Tue Jul 31 19:54:00 GMT 2018
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'
More information about the Gcc-bugs
mailing list