This is the mail archive of the gcc-prs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: optimization/6065: gcc seems to reorder IEEE fpsetsticky and sqrt functions


The following reply was made to PR optimization/6065; it has been noted by GNATS.

From: Daniel Villeneuve <Daniel.Villeneuve@gerad.ca>
To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, gcc-bugs@gcc.gnu.org,
   nobody@gcc.gnu.org, Daniel.Villeneuve@gerad.ca
Cc:  
Subject: Re: optimization/6065: gcc seems to reorder IEEE fpsetsticky and sqrt 
 functions
Date: Wed, 27 Mar 2002 12:47:38 -0500

 This is a multi-part message in MIME format.
 --------------3B0C834164807D03C8631D29
 Content-Type: text/plain; charset=us-ascii
 Content-Transfer-Encoding: 7bit
 
 Here is a trimmed down version of the bug report optimization/6065.
 The compilation command is shorter, the C code is simpler.
 
 >Submitter-Id:	net
 >Originator:	Daniel Villeneuve
 >Organization:	
 >Confidential:	no
 >Synopsis:	gcc seems to reorder IEEE fpsetsticky and sqrt functions
 >Severity:	serious
 >Priority:	medium
 >Category:	optimization
 >Class:		wrong-code
 >Release:	3.0.3
 >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:
 
 When compiling with -O2 or higher, gcc seems to move the call to
 sqrt()
 outside the bracketing function pair fpsetsticky()/fpgetsticky(),
 making
 the result of fpgetsticky incorrect.
 
 >How-To-Repeat:
 
 Compile the file t_sqrt.c into an executable named t_sqrt, then try:
   ./t_sqrt 2
 whose output ought to be
   res = 1.41421, inexact flag = 1
 but is
   res = 1.41421, inexact flag = 0
 .
 
 When compiling with -DVOLATILE, the local double variable is declared
 as
 volatile and the code works correctly, even with -O2 or -O3.
 
 >Fix:
 
 Declare as volatile all floating-point 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 and I would like a portable solution
 if possible.
 
 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?
 --
 Daniel Villeneuve
 GERAD/University of Montreal
 --------------3B0C834164807D03C8631D29
 Content-Type: text/plain; charset=us-ascii;
  name="t_sqrt.c"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="t_sqrt.c"
 
 #include <ieeefp.h>
 #include <math.h>
 #include <stdlib.h>
 #include <stdio.h>
 
 typedef struct S
 {
   double d;
   int i;
 } S;
 
 static void Sqrt(S *ps)
 {
 #ifdef VOLATILE
   double        volatile d;
 #else
   double        d;
 #endif
   int           i;
 
   d = ps->d, i = ps->i;
 
   fpsetsticky(0);
   d = sqrt(d);
   if( fpgetsticky() & FP_X_IMP ) i = 1;
 
   ps->d = d, ps->i = i;
 }
 
 int main(int argc, char **argv)
 {
   S             ps[1];
 
   ps->d = atof(argv[1]);
   ps->i = 0;
 
   Sqrt(ps);
 
   printf("res = %g, inexact flag = %d\n", ps->d, ps->i);
   return 0;
 }
 
 --------------3B0C834164807D03C8631D29
 Content-Type: text/plain; charset=us-ascii;
  name="t_sqrt.i"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="t_sqrt.i"
 
 # 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/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
 # 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
 # 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;
 # 66 "/home/sparc-sun-solaris2/gcc-3.0.3/lib/gcc-lib/sparc-sun-solaris2.7/3.0.3/include/stdlib.h" 3
 typedef unsigned int size_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 *);
 # 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/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
 # 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;
 # 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 *);
 # 5 "t_sqrt.c" 2
 
 typedef struct S
 {
   double d;
   int i;
 } S;
 
 static void Sqrt(S *ps)
 {
 
 
 
   double d;
 
   int i;
 
   d = ps->d, i = ps->i;
 
   fpsetsticky(0);
   d = sqrt(d);
   if( fpgetsticky() & 0x01 ) i = 1;
 
   ps->d = d, ps->i = i;
 }
 
 int main(int argc, char **argv)
 {
   S ps[1];
 
   ps->d = atof(argv[1]);
   ps->i = 0;
 
   Sqrt(ps);
 
   printf("res = %g, inexact flag = %d\n", ps->d, ps->i);
   return 0;
 }
 
 --------------3B0C834164807D03C8631D29
 Content-Type: text/plain; charset=us-ascii;
  name="Makefile"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="Makefile"
 
 t_sqrt: t_sqrt.c
 	gcc -v -save-temps -ansi -O2 -o t_sqrt t_sqrt.c -lm
 #	gcc -DVOLATILE -v -save-temps -ansi -O2 -o t_sqrt t_sqrt.c -lm
 clean:
 	rm -f t_sqrt t_sqrt.[ois]
 
 --------------3B0C834164807D03C8631D29
 Content-Type: text/plain; charset=us-ascii;
  name="t_sqrt.s"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="t_sqrt.s"
 
 	.file	"t_sqrt.i"
 	.section	".text"
 	.align 4
 	.type	Sqrt,#function
 	.proc	020
 Sqrt:
 	!#PROLOGUE# 0
 	save	%sp, -128, %sp
 	!#PROLOGUE# 1
 	ldd	[%i0], %o0
 	std	%o0, [%fp-24]
 	ldd	[%fp-24], %f2
 	mov	0, %o0
 	fsqrtd	%f2, %f2
 	ld	[%i0+8], %l0
 	call	fpsetsticky, 0
 	std	%f2, [%fp-32]
 	ldd	[%fp-32], %f4
 	fmovs	%f4, %f2
 	fmovs	%f5, %f3
 	fcmpd	%f4, %f2
 	nop
 	fbe	.LL2
 	ldd	[%fp-24], %o0
 	call	sqrt, 0
 	 nop
 	std	%f0, [%fp-32]
 .LL2:
 	call	fpgetsticky, 0
 	 nop
 	andcc	%o0, 1, %g0
 	bne,a	.LL3
 	mov	1, %l0
 .LL3:
 	ldd	[%fp-32], %o0
 	st	%l0, [%i0+8]
 	std	%o0, [%i0]
 	ret
 	restore
 .LLfe1:
 	.size	Sqrt,.LLfe1-Sqrt
 	.section	".rodata"
 	.align 8
 .LLC0:
 	.asciz	"res = %g, inexact flag = %d\n"
 	.section	".text"
 	.align 4
 	.global main
 	.type	main,#function
 	.proc	04
 main:
 	!#PROLOGUE# 0
 	save	%sp, -128, %sp
 	!#PROLOGUE# 1
 	ld	[%i1+4], %o0
 	call	atof, 0
 	mov	0, %i0
 	add	%fp, -32, %o0
 	std	%f0, [%fp-32]
 	call	Sqrt, 0
 	st	%g0, [%fp-24]
 	sethi	%hi(.LLC0), %o0
 	ld	[%fp-32], %o1
 	or	%o0, %lo(.LLC0), %o0
 	ld	[%fp-28], %o2
 	call	printf, 0
 	ld	[%fp-24], %o3
 	ret
 	restore
 .LLfe2:
 	.size	main,.LLfe2-main
 	.ident	"GCC: (GNU) 3.0.3"
 
 --------------3B0C834164807D03C8631D29--
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]