Hello, El mié., 21 nov. 2018 a las 15:46, Thomas De Schampheleire (<patrickdepinguin@xxxxxxxxx>) escribió: > > Hello, > > I have a problem with a program that links with sqlite3 and executes > an SQL statement. The program is executed under Qemu, with an 32-bit > x86 emulated machine, and Qemu is running on a 64-bit x86 host. > > Originally, the program worked fine, when it was compiled with a > toolchain composed out of gcc 4.9.2, glibc 2.21, binutils 2.24. > > Now I am rebuilding the system with a toolchain composed out of gcc > 7.3, glibc 2.27, binutils 2.30. In this case, the program receives a > SIGFPE (Arithmetic Error) in Sqlite code. Analysis of the coredump > reveals that the error occurs on an 'fldl' instruction (Floating-point > Load Long) and that the exact cause of the error is an underflow. > > The problem does not appear when Qemu is started without KVM support. > In this case, floating point handling is covered by Qemu itself. The > problem does occur when passing '-enable-kvm' which causes the host > machine to execute most instructions. > > However, it is unclear to me why gcc is emitting an 'fldl' instruction > here (which wasn't present with the old toolchain) and why it is > causing an underflow. The part of the code being executed is not > handling a floating-point value. > There is a print of a real a bit further down, which is conditional on > a flag indicating that the union indeed holds a real value. Could this > 'fldl' instruction be part of that code, moved upwards? In that case, > who is at fault here? Because the loading of the real should only > happen when we know that it is indeed a real, and not an integer. It seems I was right here: gcc optimization caused the floating-point load to move upwards, before the checking if the union value is actually of floating-point type. This optimization can cause a floating-point exception. If I add a compiler barrier between the checking of the flag and the reading of the value, then the problem is gone. No floating-point exception occurs (because the value is actually of type int). Modified code is: if( fg & MEM_Int ){ sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); }else{ assert( fg & MEM_Real ); asm volatile("" ::: "memory"); sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); } My question now becomes: is gcc allowed to optimize here (without the barrier)? Is gcc allowed to pre-load the floating point value pMem->u.r if it does not know yet that the value in the union is a floating-point value, knowing that a load of an invalid (integer) value could cause floating-point exceptions like underflow? Thanks, Thomas