[Bug c++/64490] New: incorrect -O2 and -O3 optimization of the slightly different template functions

ask at skidin dot org gcc-bugzilla@gcc.gnu.org
Sun Jan 4 19:33:00 GMT 2015


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

            Bug ID: 64490
           Summary: incorrect -O2 and -O3 optimization of the slightly
                    different template functions
           Product: gcc
           Version: 4.9.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ask at skidin dot org

Created attachment 34373
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=34373&action=edit
source code and small build scripts

Source code:
--------------
#include <iostream>
#include <stdint.h>

template <class T> void buggy_code_x64(T &dest) {            // THIS CODE IS
EXECUTED CORRECTLY ONLY IN O0 OR O1 OPTIMIZATION MODES
    dest=0x08;                            // L1
    for (size_t k=0; k<7; k++) dest=(dest*16);            // L2
    // Here dest=0x80000000, this number cannot be represented by a signed
32-bit integer value.
    if (dest<0) std::cout << "Negative number, dest=" << dest;
    else std::cout << "Non-negative number, dest=" << dest;
}


template <class T> void correct_code_x64(T &dest) {            // THIS CODE IS
ALWAYS EXECUTED CORRECTLY.
    dest=0x0800;                            // L1
    for (size_t k=0; k<5; k++) dest=(dest*16);            // L2
    // Here dest=0x80000000, this number cannot be represented by a signed
32-bit integer value.
    if (dest<0) std::cout << "Negative number, dest=" << dest;
    else std::cout << "Non-negative number, dest=" << dest;
}

int main() {
int32_t val1;
    std::cout << "int32 test:" << std::endl;
    buggy_code_x64<int32_t>(val1);
    std::cout << std::endl;
int32_t val2;
    std::cout << "int32 test:" << std::endl;
    correct_code_x64<int32_t>(val1);
    std::cout << std::endl;
}
--------------
Build keys:
g++ -m64 -O0 -L"/usr/lib64" -pedantic -Werror -x c++ -o"bug-o0.exe" "bug.cpp"
g++ -m64 -O1 -L"/usr/lib64" -pedantic -Werror -x c++ -o"bug-o1.exe" "bug.cpp"
g++ -m64 -O2 -L"/usr/lib64" -pedantic -Werror -x c++ -o"bug-o2.exe" "bug.cpp"
g++ -m64 -O3 -L"/usr/lib64" -pedantic -Werror -x c++ -o"bug-o3.exe" "bug.cpp"


--------------
Behaviour when using -O0 and -O1 optimization: as expected, no error occured.

Behaviour when using -O2, -O3 optimization levels on intel x64 architecture:
    buggy_code_x64<int32_t>(val1) prints incorrect statement "Non-negative
number, dest=-2147483648".

Expected behaviour:
    buggy_code_x64<int32_t>(val1) must print "Negative number,
dest=-2147483648".
--------------
G++ Versions:
1) 4.8.3 (OPENSUSE)
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info
--mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64
--enable-languages=c,c++,objc,fortran,obj-c++,java,ada
--enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.8
--enable-ssp --disable-libssp --disable-plugin
--with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux'
--disable-libgcj --disable-libmudflap --with-slibdir=/lib64 --with-system-zlib
--enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch
--enable-version-specific-runtime-libs --enable-linker-build-id
--enable-linux-futex --program-suffix=-4.8 --without-system-libunwind
--with-arch-32=i586 --with-tune=generic --build=x86_64-suse-linux
--host=x86_64-suse-linux
Thread model: posix
gcc version 4.8.3 20140627 [gcc-4_8-branch revision 212064] (SUSE Linux) 

2) 4.9.2 (FEDORA)
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla
--enable-bootstrap --enable-shared --enable-threads=posix
--enable-checking=release --enable-multilib --with-system-zlib
--enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object
--enable-linker-build-id --with-linker-hash-style=gnu
--enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin
--enable-initfini-array --disable-libgcj
--with-isl=/builddir/build/BUILD/gcc-4.9.2-20141101/obj-x86_64-redhat-linux/isl-install
--with-cloog=/builddir/build/BUILD/gcc-4.9.2-20141101/obj-x86_64-redhat-linux/cloog-install
--enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686
--build=x86_64-redhat-linux
Thread model: posix
gcc version 4.9.2 20141101 (Red Hat 4.9.2-1) (GCC)



Additional information:
1. When replacing lines L1 and L2 by the following lines the error disappears:
    dest=0x800;                // L1
    for (k=0; k<5; k++) dest=(dest*16);    // L2

The following variations of lines L1 and L2 are also error-free:
    dest=0x80000;                // L1
    for (k=0; k<3; k++) dest=(dest*16);    // L2

    dest=0x8000000;                // L1
    for (k=0; k<1; k++) dest=(dest*16);    // L2


As it can be easily seen, the differences between these lines and those given
in the source file should not affect the results. However they do.


2. The representation of function "buggy_code_x64" as a template function does
matter, since the error appears only if the function is a template.

3. The function function "buggy_code_x64" was not found in the disassembly
listing for -O2 and -O3 cases.
Obviously, the compiler has predicted (incorrectly) the result that the
function would return and did not include the function body to the binary
executable.


Of course, there is an integer overflow in the code and theoretically its
behaviour could depend on the hardware it is executed on.
However, the compiler should at least produce the same results for the same
command line argument and for the equivalent parts of the code.

P.S.: The similar error also exists for x86 architecture code
(buggy_code<int64_t>, where dest=0x8000000000000000).



More information about the Gcc-bugs mailing list