From owner-freebsd-bugs Sun Jul 14 18:40:25 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C05F937B400 for ; Sun, 14 Jul 2002 18:40:07 -0700 (PDT) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3F79343E31 for ; Sun, 14 Jul 2002 18:40:05 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.4/8.12.4) with ESMTP id g6F1e4JU056497 for ; Sun, 14 Jul 2002 18:40:04 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.4/8.12.4/Submit) id g6F1e4SI056496; Sun, 14 Jul 2002 18:40:04 -0700 (PDT) Date: Sun, 14 Jul 2002 18:40:04 -0700 (PDT) Message-Id: <200207150140.g6F1e4SI056496@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Dan Lukes Subject: Re: bin/40209: __dtoa broken with -O2 or -O3 optimisation Reply-To: Dan Lukes Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org The following reply was made to PR bin/40209; it has been noted by GNATS. From: Dan Lukes To: FreeBSD-gnats-submit@FreeBSD.ORG Cc: Bruce Evans Subject: Re: bin/40209: __dtoa broken with -O2 or -O3 optimisation Date: Mon, 15 Jul 2002 03:31:55 +0200 Bruce Evans wrote: > Can you do some more work to isolate the bug? I haven't had time. Well, I did the very time-expensive depth-in analysis of the code. It still seems to be bug in optimisation code of GCC. I used the copy of strtod.c source to create small test program, compiled it with gcc then disassembled by IDA (because I discovered that the gdb has sometimes incorrect assumptions about variable locations, and - we can't trust the gdb if we are searching gcc bugs) and checked it for functional equivalence with source C code. The machine code didn't what it should do. Relevant parts of C source code (with line numbers): 226: #define word0(x) ((ULong *)&x)[1] 227: #define word1(x) ((ULong *)&x)[0] --- skipped --- 1933: d2 = d; 1934: word0(d2) &= Frac_mask1; 1935: word0(d2) |= Exp_11; --- text on lines 1936-1968 isn't executable code --- 1969: denorm = 0; Related machine code (with disassembler and my comments; disassembly-flavor set to 'intel', focus your eyes for comments starting with '#### !!!?'): ; +-------------------------------------------------------------------+ ; | This file is generated by The Interactive Disassembler (IDA) | ; | Copyright (c) 2001 by DataRescue sa/nv, | ; | Licensed to: Dan Lukes, 1 user upg, 03/2002 | ; +-------------------------------------------------------------------+ ; File Name : a.out ; Format : ELF (Executable) ; Source File : 'crtstuff.c' ; Source File : 'x.c' ; Source File : 'MYstrtod.c' ; NOTE: MYstrtod.c is exact copy od strtod, ; the rename of __dtoa to MY__dtoa is the only modification model flat ; ========== [removed] =========== ; Segment type: Pure code ; Segment permissions: Read/Execute _text segment dword public 'CODE' use32 assume cs:_text, ds:_data ;org 80480B8h ; ========== [removed] =========== ; ------------- S U B R O U T I N E -------------------------------- ; Attributes: bp-based frame ; char *MY__dtoa(double d,int mode,int ndigits,int *decpt,int *sign, ; char **rve,char **resultp) public MY__dtoa MY__dtoa proc near ; CODE XREF: main+52 p ; local variables i = dword ptr -9Ch var_94 = dword ptr -94h j = dword ptr -90h s0 = dword ptr -8Ch s = dword ptr -88h S = dword ptr -84h mhi = dword ptr -80h mlo = dword ptr -7Ch b = dword ptr -78h denorm = dword ptr -74h spec_case = dword ptr -70h s5 = dword ptr -6Ch m5 = dword ptr -68h m2 = dword ptr -64h leftright = dword ptr -60h k_check = dword ptr -5Ch k0 = dword ptr -58h k = dword ptr -54h ilim1 = dword ptr -50h ilim0 = dword ptr -4Ch ilim = dword ptr -48h dig = dword ptr -44h b5 = dword ptr -40h b2 = dword ptr -3Ch L = dword ptr -38h ds_ = qword ptr -34h eps = dword ptr -2Ch d2 = qword ptr -28h be = dword ptr -20h bbits = dword ptr -1Ch local_d = qword ptr -18h var_C = byte ptr -0Ch ; subroutine parameters d = qword ptr 8 mode = dword ptr 10h ndigits = dword ptr 14h decpt = dword ptr 18h sign = dword ptr 1Ch rve = dword ptr 20h resultp = dword ptr 24h ; ========== [removed] =========== ;C:1929: if ( (i = (int)((word0(d) >> Exp_shift1) & (Exp_mask>>Exp_shift1))) ) { mov edx, dword ptr [ebp+local_d+4] mov ecx, edx shr ecx, 14h ; Exp_shift1 mov esi, ecx add esp, 10h ; Add and esi, 7FFh ; Exp_mask>>Exp_shift1 mov [ebp+b], eax jz loc_804A31C ; Jump if Zero (ZF=1) ;C:1933: d2 = d; ; #### !!!? following two instructions move only bottom half of d to d2 mov eax, dword ptr [ebp+local_d] mov dword ptr [ebp+d2], eax ;C:1934: word0(d2) &= Frac_mask1; ; #### !!!? upper half of d2 is still not copied from d, so it is used uninitialised mov eax, dword ptr [ebp+d2+4] and eax, 0FFFFFh ; Frac_mask1 mov edi, dword ptr [ebp+local_d+4] ;C:1935: word0(d2) |= Exp_11; or eax, 3FF00000h ; Exp_11 ;C:1963: i -=Bias; sub esi, 1023 ; Bias mov ebx, [ebp+bbits] ; #### !!!? there is completed the copy of upper half of d to d2 ; #### !!!? (via edi register), ; #### !!!? but it is overwritten by eax computed ; #### !!!? from uninitialized upper half of d2 mov dword ptr [ebp+d2+4], edi mov dword ptr [ebp+d2+4], eax ;C:1969: denorm = 0; mov [ebp+denorm], 0 ; ========== [removed] =========== =================================================================== The code on line 1933 is improperly compiled because the compiler ignored dependencies on lines 1934 and 1935. If you start the bad optimized code under gcc with breakpoint on line 1933 and you manually set d2 ('set d2=d') whenever the code stops, the program start to work O.K. If somebody is interested in complete disassembly of compiled __dtoa with comments containing original source C code, lets me know. The minimal testing environment can be created using following patch source: *** /dev/null Mon Jul 15 01:54:32 2002 --- Makefile Mon Jul 8 18:14:01 2002 *************** *** 0 **** --- 1,23 ---- + #OPTFLAGS=-fno-schedule-insns2 + #OPTFLAGS=-fno-strict-aliasing + CFLAGS=-g -Wall -pipe -O3 $(OPTFLAGS) + + ALL: a.out + + MYstrtod.c: /usr/src/lib/libc/stdlib/strtod.c + sed -e 's/__dtoa/MY__dtoa/g' /usr/src/lib/libc/stdlib/strtod.c > MYstrtod.c + + MYstrtod.o: MYstrtod.c Makefile + $(CC) $(CFLAGS) -I/usr/src/include -c MYstrtod.c -o MYstrtod.o + + x.o: x.c Makefile + $(CC) $(CFLAGS) -c x.c -o x.o + + a.out: x.o MYstrtod.o Makefile + $(CC) $(CFLAGS) -static x.o MYstrtod.o + + clean: + -rm x.o a.out MYstrtod.o MYstrtod.c + + run: a.out + -./a.out *** /dev/null Mon Jul 15 01:54:32 2002 --- x.c Tue Jul 9 01:00:23 2002 *************** *** 0 **** --- 1,21 ---- + #include + + #define mode 3 + #define ndigits 6 + + char *MY__dtoa(double, int, int, int *, int *, char **, char **); + + int main(argc, argv) { + int i, dsgn; + int xdecpt=1; + char *xdtoaresult, *xresult, *rve; + + for (i=11;i<14;i++) { + xdecpt=1; xdtoaresult = xresult = rve = NULL; + xresult = MY__dtoa((double)i, mode, ndigits, &xdecpt, &dsgn, &rve, &xdtoaresult); + xdtoaresult[rve - xresult]='\0'; + puts(xdtoaresult); + } + + return(0); + } Please note the only first round (i=11) give improper results as the memory place where d2 lives is already initialised from previous run (e.g. i=12 and i=13 return expected values). Disabling schedule-insns2 OR strict-aliasing during compilation create code that seems to work (but it msy contain other undiscovered bugs). ================================== During depth-in analysis of the strtod.c code I discovered it's dirty code, somewhat. It never test's if malloc has been succesfull - it just reference it without checking. Look into Balloc function and __dtoa line 2042. IMHO, good code should never abends unless programmer decide to abend it, so current beta-quality strtod.c code is acceptable in current, but it's not suitable for stable. Should I submit separate PR about it ? (I see no simple fix without rewriting large amount of code as affected functions has no concept of "internal error/resource unavaiable" reporting and/or handling). Dan Note: english isn't my native language -- Dan Lukes tel: +420 2 21914205, fax: +420 2 21914206 root of FIONet, KolejNET, webmaster of www.freebsd.cz AKA: dan@obluda.cz, dan@freebsd.cz,dan@kolej.mff.cuni.cz To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message