From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17364 invoked by alias); 26 Mar 2002 17:46:06 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 17269 invoked by uid 71); 26 Mar 2002 17:46:02 -0000 Resent-Date: 26 Mar 2002 17:46:01 -0000 Resent-Message-ID: <20020326174601.17264.qmail@sources.redhat.com> Resent-From: gcc-gnats@gcc.gnu.org (GNATS Filer) Resent-To: nobody@gcc.gnu.org Resent-Cc: gcc-prs@gcc.gnu.org, gcc-bugs@gcc.gnu.org Resent-Reply-To: gcc-gnats@gcc.gnu.org, Daniel.Villeneuve@gerad.ca Received:(qmail 14076 invoked from network); 26 Mar 2002 17:41:01 -0000 Received: from unknown (HELO crt0.crt.umontreal.ca) (132.204.100.27) by sources.redhat.com with SMTP; 26 Mar 2002 17:41:01 -0000 Received: from mckinley.crt.umontreal.ca (mckinley.crt.umontreal.ca [132.204.100.252]) by crt0.crt.umontreal.ca (8.12.2/8.12.2) with ESMTP id g2QHeJPD000943; Tue, 26 Mar 2002 12:40:19 -0500 (EST) Received: (from danielv@localhost) by mckinley.crt.umontreal.ca (8.12.0/8.12.0) id g2QHdW9O012485; Tue, 26 Mar 2002 12:39:32 -0500 (EST) Message-Id:<200203261739.g2QHdW9O012485@mckinley.crt.umontreal.ca> Date: Tue, 26 Mar 2002 09:46:00 -0000 From: Daniel Villeneuve Reply-To: Daniel.Villeneuve@gerad.ca To: gcc-gnats@gcc.gnu.org Cc: Daniel.Villeneuve@gerad.ca X-Send-Pr-Version:3.113 Subject: optimization/6065: gcc seems to reorder IEEE fpsetsticky and sqrt functions X-SW-Source: 2002-03/txt/msg00987.txt.bz2 List-Id: >Number: 6065 >Category: optimization >Synopsis: gcc seems to reorder IEEE fpsetsticky and sqrt functions >Confidential: no >Severity: serious >Priority: medium >Responsible: unassigned >State: open >Class: wrong-code >Submitter-Id: net >Arrival-Date: Tue Mar 26 09:46:01 PST 2002 >Closed-Date: >Last-Modified: >Originator: Daniel Villeneuve >Release: 3.0.3 >Organization: >Environment: System: SunOS mckinley 5.7 Generic_106541-05 sun4u sparc SUNW,Ultra-5_10 Architecture: sun4 host: sparc-sun-solaris2.7 build: sparc-sun-solaris2.7 target: sparc-sun-solaris2.7 configured with: ./configure --disable-shared --prefix=/home/sparc-sun-solaris2/gcc-3.0.3 >Description: I try to access the ``inexact'' status flag after performing a call to sqrt(), and the result is wrong for sqrt(2.0) (i.e., the inexact flags is not set) when compiling with gcc -O3. The program needs two arguments: a double whose square root is to be computed, and an initial value for the inexact flag (which can be seen to complete the floating-point value). Test that fails: t_sqrt 2 0 which outputs res = 1.41421, inexact flag = 0 instead of res = 1.41421, inexact flag = 1 >How-To-Repeat: ======================================== t_sqrt: t_sqrt.o gcc -v -save-temps -ansi -Wall -pedantic -Wshadow -Wbad-function-cast -Wsign-compare -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wpointer-arith -W -Wwrite-strings -O3 -finline-functions -funroll-loops -Wl,-s -Wl,-R/usr/openwin/lib:/usr/dt/lib:/home/ultra-sun-solaris2/gcc-3.0.3/lib -o t_sqrt t_sqrt.o -lm t_sqrt.o: t_sqrt.c gcc -v -save-temps -ansi -Wall -pedantic -Wshadow -Wbad-function-cast -Wsign-compare -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wpointer-arith -W -Wwrite-strings -O3 -finline-functions -funroll-loops -o t_sqrt.o -c t_sqrt.c ======================================== ======================================== #include #include #include #include #undef NDEBUG #include typedef struct S { double d; int i; } S; static S *psSqrt(S *ps) { #ifdef VOLATILE double volatile d; #else double d; #endif int i; d = ps->d; if( !d ) return ps; assert( d > 0 ); i = ps->i; fpsetsticky(0); d = sqrt(d); if( fpgetsticky() & FP_X_IMP ) i = 1; ps = malloc(sizeof(S)); ps->d = d; ps->i = i; return ps; } int main(int argc, char **argv) { S psArg[1], *psRes; assert(argc == 3); psArg->d = atof(argv[1]); psArg->i = atoi(argv[2]); psRes = psSqrt(psArg); printf("res = %g, inexact flag = %d\n", psRes->d, psRes->i); return 0; } ======================================== ======================================== gcc -v -save-temps -ansi -Wall -pedantic -Wshadow -Wbad-function-cast -Wsign-compare -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wpointer-arith -W -Wwrite-strings -O3 -finline-functions -funroll-loops -o t_sqrt.o -c t_sqrt.c Reading specs from /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/specs Configured with: ./configure --disable-shared --prefix=/home/sparc-sun-solaris2/gcc-3.0.3 Thread model: posix gcc version 3.0.3 /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/cpp0 -lang-c -std=c89 -v -iprefix /home/gencol/ref/gcm-3.0/bin/ultra-sun-solaris2/../lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/ -D__GNUC__=3 -D__GNUC_MINOR__=0 -D__GNUC_PATCHLEVEL__=3 -D__sparc__ -D__sun__ -D__unix__ -D__svr4__ -D__SVR4 -D__sparc -D__sun -D__unix -Asystem=unix -Asystem=svr4 -D__OPTIMIZE__ -D__STDC_HOSTED__=1 -Wall -Wshadow -Wbad-function-cast -Wsign-compare -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wpointer-arith -W -Wwrite-strings -pedantic -D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc t_sqrt.c t_sqrt.i GNU CPP version 3.0.3 (cpplib) (sparc) ignoring nonexistent directory "/home/gencol/ref/gcm-3.0/bin/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include" ignoring nonexistent directory "/home/gencol/ref/gcm-3.0/bin/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/../../../../sparc-sun-solaris2.7/include" ignoring nonexistent directory "/usr/local/include" ignoring nonexistent directory "/home/sparc-sun-solaris2/gcc-3.0.3/sparc-sun-solaris2.7/include" #include "..." search starts here: #include <...> search starts here: /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include /usr/include End of search list. /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/cc1 -fpreprocessed t_sqrt.i -quiet -dumpbase t_sqrt.c -ansi -O3 -Wall -Wshadow -Wbad-function-cast -Wsign-compare -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wpointer-arith -W -Wwrite-strings -pedantic -ansi -version -finline-functions -funroll-loops -o t_sqrt.s GNU CPP version 3.0.3 (cpplib) (sparc) GNU C version 3.0.3 (sparc-sun-solaris2.7) compiled by GNU C version 3.0.3. /usr/ccs/bin/as -V -Qy -s -o t_sqrt.o t_sqrt.s /usr/ccs/bin/as: WorkShop Compilers 5.0 98/12/21 gcc -v -save-temps -ansi -Wall -pedantic -Wshadow -Wbad-function-cast -Wsign-compare -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wpointer-arith -W -Wwrite-strings -O3 -finline-functions -funroll-loops -Wl,-s -Wl,-R/usr/openwin/lib:/usr/dt/lib:/home/ultra-sun-solaris2/gcc-3.0.3/lib -o t_sqrt t_sqrt.o -lm Reading specs from /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/specs Configured with: ./configure --disable-shared --prefix=/home/sparc-sun-solaris2/gcc-3.0.3 Thread model: posix gcc version 3.0.3 /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/collect2 -V -Y P,/usr/ccs/lib:/usr/lib -Qy -o t_sqrt /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/crt1.o /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/crti.o /usr/ccs/lib/values-Xc.o /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/crtbegin.o -L/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3 -L/usr/ccs/bin -L/usr/ccs/lib -L/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/../../.. -s -R/usr/openwin/lib:/usr/dt/lib:/home/ultra-sun-solaris2/gcc-3.0.3/lib t_sqrt.o -lm -lgcc -lc -lgcc /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/crtend.o /home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/crtn.o ld: Software Generation Utilities - Solaris/ELF (3.0) ======================================== ======================================== # 1 "t_sqrt.c" # 1 "/usr/include/ieeefp.h" 1 3 # 19 "/usr/include/ieeefp.h" 3 #pragma ident "@(#)ieeefp.h 1.15 97/11/22 SMI" # 64 "/usr/include/ieeefp.h" 3 typedef enum fpclass_t { FP_SNAN = 0, FP_QNAN = 1, FP_NINF = 2, FP_PINF = 3, FP_NDENORM = 4, FP_PDENORM = 5, FP_NZERO = 6, FP_PZERO = 7, FP_NNORM = 8, FP_PNORM = 9 } fpclass_t; extern fpclass_t fpclass(double); extern int finite(double); extern int unordered(double, double); # 113 "/usr/include/ieeefp.h" 3 typedef enum fp_rnd { FP_RN = 0, FP_RZ = 1, FP_RP = 2, FP_RM = 3 } fp_rnd; extern fp_rnd fpsetround(fp_rnd); extern fp_rnd fpgetround(void); # 191 "/usr/include/ieeefp.h" 3 extern int fpgetmask(void); extern int fpsetmask(int); extern int fpgetsticky(void); extern int fpsetsticky(int); # 209 "/usr/include/ieeefp.h" 3 extern int isnanf(float); extern int isnand(double); # 2 "t_sqrt.c" 2 # 1 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/math.h" 1 3 # 27 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/math.h" 3 #pragma ident "@(#)math.h 2.7 98/01/27" # 46 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/math.h" 3 typedef union _h_val { unsigned long _i[sizeof(double) / sizeof(unsigned long)]; double _d; } _h_val; extern const _h_val __huge_val; # 134 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/math.h" 3 extern double acos (double); extern double asin (double); extern double atan (double); extern double atan2 (double, double); extern double cos (double); extern double sin (double); extern double tan (double); extern double cosh (double); extern double sinh (double); extern double tanh (double); extern double exp (double); extern double frexp (double, int *); extern double ldexp (double, int); extern double log (double); extern double log10 (double); extern double modf (double, double *); extern double pow (double, double); extern double sqrt (double); extern double ceil (double); extern double fabs (double); extern double floor (double); extern double fmod (double, double); # 3 "t_sqrt.c" 2 # 1 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 1 3 # 14 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 # 1 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdarg.h" 1 3 # 43 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdarg.h" 3 typedef __builtin_va_list __gnuc_va_list; # 15 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 2 3 # 34 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 #pragma ident "@(#)stdio.h 1.69 98/07/13 SMI" # 1 "/usr/include/sys/feature_tests.h" 1 3 # 13 "/usr/include/sys/feature_tests.h" 3 #pragma ident "@(#)feature_tests.h 1.17 97/12/04 SMI" # 1 "/usr/include/sys/isa_defs.h" 1 3 # 9 "/usr/include/sys/isa_defs.h" 3 #pragma ident "@(#)isa_defs.h 1.15 97/11/22 SMI" # 16 "/usr/include/sys/feature_tests.h" 2 3 # 37 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 2 3 # 1 "/usr/include/sys/va_list.h" 1 3 # 9 "/usr/include/sys/va_list.h" 3 #pragma ident "@(#)va_list.h 1.11 97/11/22 SMI" # 26 "/usr/include/sys/va_list.h" 3 typedef void *__va_list; # 38 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 2 3 # 1 "/usr/include/stdio_tag.h" 1 3 # 9 "/usr/include/stdio_tag.h" 3 #pragma ident "@(#)stdio_tag.h 1.3 98/04/20 SMI" # 21 "/usr/include/stdio_tag.h" 3 typedef struct __FILE __FILE; # 39 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 2 3 # 1 "/usr/include/stdio_impl.h" 1 3 # 9 "/usr/include/stdio_impl.h" 3 #pragma ident "@(#)stdio_impl.h 1.7 98/04/17 SMI" # 1 "/usr/include/sys/isa_defs.h" 1 3 # 12 "/usr/include/stdio_impl.h" 2 3 # 22 "/usr/include/stdio_impl.h" 3 typedef int ssize_t; # 38 "/usr/include/stdio_impl.h" 3 struct __FILE { ssize_t _cnt; unsigned char *_ptr; unsigned char *_base; unsigned char _flag; unsigned char _file; unsigned __orientation:2; unsigned __filler:6; }; # 40 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 2 3 # 55 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 typedef __FILE FILE; typedef unsigned int size_t; # 103 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 typedef long fpos_t; # 203 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 extern FILE __iob[20]; # 215 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 extern unsigned char _sibuf[], _sobuf[]; # 244 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 extern unsigned char *_bufendtab[]; extern FILE *_lastbuf; # 275 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdio.h" 3 extern int remove(const char *); extern int rename(const char *, const char *); extern FILE *tmpfile(void); extern char *tmpnam(char *); extern int fclose(FILE *); extern int fflush(FILE *); extern FILE *fopen(const char *, const char *); extern FILE *freopen(const char *, const char *, FILE *); extern void setbuf(FILE *, char *); extern int setvbuf(FILE *, char *, int, size_t); extern int fprintf(FILE *, const char *, ...); extern int fscanf(FILE *, const char *, ...); extern int printf(const char *, ...); extern int scanf(const char *, ...); extern int sprintf(char *, const char *, ...); extern int sscanf(const char *, const char *, ...); extern int vfprintf(FILE *, const char *, __gnuc_va_list); extern int vprintf(const char *, __gnuc_va_list); extern int vsprintf(char *, const char *, __gnuc_va_list); extern int fgetc(FILE *); extern char *fgets(char *, int, FILE *); extern int fputc(int, FILE *); extern int fputs(const char *, FILE *); extern int getc(FILE *); extern int getchar(void); extern char *gets(char *); extern int putc(int, FILE *); extern int putchar(int); extern int puts(const char *); extern int ungetc(int, FILE *); extern size_t fread(void *, size_t, size_t, FILE *); extern size_t fwrite(const void *, size_t, size_t, FILE *); extern int fgetpos(FILE *, fpos_t *); extern int fseek(FILE *, long, int); extern int fsetpos(FILE *, const fpos_t *); extern long ftell(FILE *); extern void rewind(FILE *); extern void clearerr(FILE *); extern int feof(FILE *); extern int ferror(FILE *); extern void perror(const char *); extern int __filbuf(FILE *); extern int __flsbuf(int, FILE *); # 4 "t_sqrt.c" 2 # 1 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 1 3 # 25 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 3 #pragma ident "@(#)stdlib.h 1.44 98/01/22 SMI" # 1 "/usr/include/sys/feature_tests.h" 1 3 # 28 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 2 3 # 38 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 3 typedef struct { int quot; int rem; } div_t; typedef struct { long quot; long rem; } ldiv_t; # 77 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 3 typedef long uid_t; # 107 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 3 typedef long int wchar_t; # 148 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 3 extern unsigned char __ctype[]; extern double atof(const char *); extern int atoi(const char *); extern long int atol(const char *); extern double strtod(const char *, char **); extern long int strtol(const char *, char **, int); extern unsigned long int strtoul(const char *, char **, int); extern int rand(void); extern void srand(unsigned int); extern void *calloc(size_t, size_t); extern void free(void *); extern void *malloc(size_t); extern void *realloc(void *, size_t); extern void abort(void); extern int atexit(void (*)(void)); extern void exit(int); extern void _exithandle(void); extern char *getenv(const char *); extern int system(const char *); extern void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); extern int abs(int); extern div_t div(int, int); extern long int labs(long); extern ldiv_t ldiv(long, long); extern int mbtowc(wchar_t *, const char *, size_t); extern int mblen(const char *, size_t); extern int wctomb(char *, wchar_t); extern size_t mbstowcs(wchar_t *, const char *, size_t); extern size_t wcstombs(char *, const wchar_t *, size_t); # 219 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 3 extern int mkstemp(char *); # 5 "t_sqrt.c" 2 # 1 "/usr/include/assert.h" 1 3 # 11 "/usr/include/assert.h" 3 #pragma ident "@(#)assert.h 1.9 92/07/14 SMI" extern void __assert(const char *, const char *, int); # 8 "t_sqrt.c" 2 typedef struct S { double d; int i; } S; static S *psSqrt(S *ps) { double d; int i; d = ps->d; if( !d ) return ps; (void)((d > 0) || (__assert("d > 0", "t_sqrt.c", 26), 0)); i = ps->i; fpsetsticky(0); d = sqrt(d); if( fpgetsticky() & 0x01 ) i = 1; ps = malloc(sizeof(S)); ps->d = d; ps->i = i; return ps; } int main(int argc, char **argv) { S psArg[1], *psRes; (void)((argc == 3) || (__assert("argc == 3", "t_sqrt.c", 41), 0)); psArg->d = atof(argv[1]); psArg->i = atoi(argv[2]); psRes = psSqrt(psArg); printf("res = %g, inexact flag = %d\n", psRes->d, psRes->i); return 0; } ======================================== >Fix: Declare as volatile all ``double'' variables used in computations that might affect IEEE status flags (when we want to access those flags, of course). I am not sure this is always correct: it happened to work on my restricted test case. I am aware that C99 provides the FENV_ACCESS pragma and the fe(clear|test)except functions, but they are still not widely available. Is there a better way (compiler options, pragmas, attributes) than using `volatile' to tell gcc not to `over'-optimize the code in such specific circumstances? >Release-Note: >Audit-Trail: >Unformatted: