[Bug c/85661] New: double comparison illegally statically reduced
manuel.serrano at inria dot fr
gcc-bugzilla@gcc.gnu.org
Sat May 5 04:54:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85661
Bug ID: 85661
Summary: double comparison illegally statically reduced
Product: gcc
Version: 7.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: manuel.serrano at inria dot fr
Target Milestone: ---
Double comparisons are sometime erroneously resolved by the compiler. Let's us
consider the following C code:
% cat bar.c
int BGl_testz00zzbugz002(double BgL_lhs1029z00_4) {
double BgL_tmpz00_1191 = BgL_lhs1029z00_4 * ((double) 0.1);
return (((double) 0.0) == BgL_tmpz00_1191);
}
The generated assembly code is:
% gcc -v -O1 -c bar.c -S
% cat bar.s
.file "bar.c"
.text
.globl BGl_testz00zzbugz002
.type BGl_testz00zzbugz002, @function
BGl_testz00zzbugz002:
.LFB0:
.cfi_startproc
call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
fldl .LC0@GOTOFF(%eax)
fmull 4(%esp)
fldz
fucomip %st(1), %st
fstp %st(0)
setnp %al
movzbl %al, %eax
movl $0, %edx
cmovne %edx, %eax
ret
.cfi_endproc
.LFE0:
.size BGl_testz00zzbugz002, .-BGl_testz00zzbugz002
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long -1717986918
.long 1069128089
.section
.text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
.globl __x86.get_pc_thunk.ax
.hidden __x86.get_pc_thunk.ax
.type __x86.get_pc_thunk.ax, @function
__x86.get_pc_thunk.ax:
.LFB1:
.cfi_startproc
movl (%esp), %eax
ret
.cfi_endproc
.LFE1:
.ident "GCC: (Debian 7.3.0-17) 7.3.0"
.section .note.GNU-stack,"",@progbits
As far I understand it, BGl_testz00zzbugz002 always returns 0, even is
called with 5e-324 (min double value) which yields the multiplication to
return 0.
Now, lets modify the function for:
#include <stdio.h>
int BGl_testz00zzbugz002(double BgL_lhs1029z00_4) {
double BgL_tmpz00_1191 = BgL_lhs1029z00_4 * ((double) 0.1);
fprintf( stderr, "FOO\n" );
return (((double) 0.0) == BgL_tmpz00_1191);
}
That is, let's just add a call to fprintf before the return statement.
The generated assembly code is now correct:
% gcc -v -O1 -c bar.c -S
% cat bar.s
.file "bar.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "FOO\n"
.text
.globl BGl_testz00zzbugz002
.type BGl_testz00zzbugz002, @function
BGl_testz00zzbugz002:
.LFB11:
.cfi_startproc
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_offset 3, -8
subl $24, %esp
.cfi_def_cfa_offset 32
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
fldl 32(%esp)
fstpl 8(%esp)
movl stderr@GOT(%ebx), %eax
pushl (%eax)
.cfi_def_cfa_offset 36
pushl $4
.cfi_def_cfa_offset 40
pushl $1
.cfi_def_cfa_offset 44
leal .LC0@GOTOFF(%ebx), %eax
pushl %eax
.cfi_def_cfa_offset 48
call fwrite@PLT
fldl .LC1@GOTOFF(%ebx)
fmull 24(%esp)
fldz
fucomip %st(1), %st
fstp %st(0)
setnp %al
movzbl %al, %eax
movl $0, %edx
cmovne %edx, %eax
addl $40, %esp
.cfi_def_cfa_offset 8
popl %ebx
.cfi_restore 3
.cfi_def_cfa_offset 4
ret
.cfi_endproc
.LFE11:
.size BGl_testz00zzbugz002, .-BGl_testz00zzbugz002
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC1:
.long -1717986918
.long 1069128089
.section
.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
.globl __x86.get_pc_thunk.bx
.hidden __x86.get_pc_thunk.bx
.type __x86.get_pc_thunk.bx, @function
__x86.get_pc_thunk.bx:
.LFB12:
.cfi_startproc
movl (%esp), %ebx
ret
.cfi_endproc
.LFE12:
.ident "GCC: (Debian 7.3.0-17) 7.3.0"
.section .note.GNU-stack,"",@progbits
Here are the other informations you ask to provide when filling a bug report.
% gcc -v -O1 -c bar.c -S -save-temps
Using built-in specs.
COLLECT_GCC=gcc
Target: i686-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 7.3.0-17'
--with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs
--enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr
--with-gcc-major-version-only --with-as=/usr/bin/i686-linux-gnu-as
--with-ld=/usr/bin/i686-linux-gnu-ld --program-suffix=-7
--program-prefix=i686-linux-gnu- --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object
--disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie
--with-system-zlib --with-target-system-zlib --enable-objc-gc=auto
--enable-targets=all --enable-multiarch --disable-werror --with-arch-32=i686
--with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic
--enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu
--target=i686-linux-gnu
Thread model: posix
gcc version 7.3.0 (Debian 7.3.0-17)
COLLECT_GCC_OPTIONS='-v' '-O1' '-c' '-S' '-save-temps' '-mtune=generic'
'-march=i686'
/usr/lib/gcc/i686-linux-gnu/7/cc1 -E -quiet -v -imultiarch i386-linux-gnu
bar.c -mtune=generic -march=i686 -O1 -fpch-preprocess -o bar.i
ignoring nonexistent directory "/usr/local/include/i386-linux-gnu"
ignoring nonexistent directory
"/usr/lib/gcc/i686-linux-gnu/7/../../../../i686-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/i686-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/i686-linux-gnu/7/include-fixed
/usr/include/i386-linux-gnu
/usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-O1' '-c' '-S' '-save-temps' '-mtune=generic'
'-march=i686'
/usr/lib/gcc/i686-linux-gnu/7/cc1 -fpreprocessed bar.i -quiet -dumpbase bar.c
-mtune=generic -march=i686 -auxbase bar -O1 -version -o bar.s
GNU C11 (Debian 7.3.0-17) version 7.3.0 (i686-linux-gnu)
compiled by GNU C version 7.3.0, 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 C11 (Debian 7.3.0-17) version 7.3.0 (i686-linux-gnu)
compiled by GNU C version 7.3.0, 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: 0871246de3664cbf1722cc29275b2ed4
COMPILER_PATH=/usr/lib/gcc/i686-linux-gnu/7/:/usr/lib/gcc/i686-linux-gnu/7/:/usr/lib/gcc/i686-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/7/:/usr/lib/gcc/i686-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/7/:/usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/7/../../../../lib/:/lib/i386-linux-gnu/:/lib/../lib/:/usr/lib/i386-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/i686-linux-gnu/7/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-O1' '-c' '-S' '-save-temps' '-mtune=generic'
'-march=i686'
% cat bar.i
# 1 "bar.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "bar.c"
int BGl_testz00zzbugz002(double BgL_lhs1029z00_4) {
double BgL_tmpz00_1191 = BgL_lhs1029z00_4 * ((double) 0.1);
return (((double) 0.0) == BgL_tmpz00_1191);
}
Finally, the GCC version I use the is only currently available under
Debian/Testing executed on a Linux x86 box.
% gcc --version
gcc (Debian 7.3.0-17) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Please, let me know if this bug report is not sufficient for you to understand
what's going on and if you need anything else.
Thanks in advance for your help.
--
Manuel
ps: You might object that running exact comparison of double is meaningless,
this bug shows up when running the ECMAScript compliance
test with my JavaScript->C compiler. The original JavaScript test is:
% cat S11.5.1_A4_T7.js
/**
* The result of a floating-point multiplication is governed by the rules of
IEEE 754 double-precision arithmetics
*
* @path ch11/11.5/11.5.1/S11.5.1_A4_T7.js
* @description If the magnitude is too small to represent, the result is then
a zero of appropriate sign
*/
//CHECK#1
if (Number.MIN_VALUE * 0.1 !== 0) {
$ERROR('#1: Number.MIN_VALUE * 0.1 === 0. Actual: ' + (Number.MIN_VALUE *
0.1));
}
//CHECK#2
if (-0.1 * Number.MIN_VALUE !== -0) {
$ERROR('#2.1: -0.1 * Number.MIN_VALUE === -0. Actual: ' + (-0.1 *
Number.MIN_VALUE));
} else {
if (1 / (-0.1 * Number.MIN_VALUE) !== Number.NEGATIVE_INFINITY) {
$ERROR('#2.2: -0.1 * Number.MIN_VALUE === -0. Actual: +0');
}
}
...
More information about the Gcc-bugs
mailing list