davis@ACDPYR.UCAR.EDU (Glenn P. Davis) (03/10/87)
The following code and script demonstrates a bug with the pyramid 'c' compiler, version 3.2. This code developed as an attempted workaround to a similar problem with the fortran compiler, hence the underscores and pointer argument. **** Script started on Fri Nov 7 12:41:35 1986 (acdpyr) 93 % cat foo.c float foo_(px) float *px ; { return( *px * ((float)1/128 ) ) ; } main() { float x = 256 ; printf("x , foo_(&x) : %f %f\n", x, foo_(&x)); } (acdpyr) 94 % cc foo.c (acdpyr) 95 % strings `which cc` | grep @ @(#)$Header: cc.c,v 3.2 86/04/16 14:32:40 george Exp $ (acdpyr) 96 % a.out x , foo_(&x) : 256.000000 256.000000 (acdpyr) 97 % x script done on Fri Nov 7 12:43:02 1986 ***** The result should be, of course , 2.000000 . The same assembly code is produced for return( *px * ((float) .0078125 ) ) ; That is: *** foo.s WRONG *** .data 0 .data 1 .text 0 .globl _foo_ _foo_: movw (pr0),pr0 ret ret *** end **** Based on what one gets with other values of the constant, I would rather expect something like *** foo.s, RIGHT? *** .data 0 .data 1 .text 0 .globl _foo_ _foo_: movw (pr0),pr2 movw $0x3c000000,pr3 mulf pr3,pr2 movw pr2,pr0 ret ret *** end ***** It seems this problem is an artifact specifically of the (single precision) floating point representation of 1/128. Other numbers or the double representation of this number do not cause problems. It is interesting to note that this is the 'bias' of the single precision exponent field. Would we have the same problem with a double precision representation of 1/1024 ??? This is left as an exercise to the reader. Glenn P. Davis NCAR / ACD PO Box 3000 Boulder, CO 80307 (303) 497 - 1489
mikel@decwrl.DEC.com@pyramid.UUCP (03/11/87)
In article <8703092244.AA15530@acdpyr.UCAR.EDU> davis@ACDPYR.UCAR.EDU (Glenn P. Davis) writes: [highly edited] > >The following code and script demonstrates a bug >with the pyramid 'c' compiler, version 3.2. > >This code developed as an attempted workaround to >a similar problem with the fortran compiler, >hence the underscores and pointer argument. > > return( *px * ((float)1/128 ) ) ; > >generates >_foo_: > movw (pr0),pr0 > ret > ret > >[i.e., ignores the (float)1/128] > > >It seems this problem is an artifact specifically of the >(single precision) floating point representation of 1/128. >Other numbers or the double representation of this number >do not cause problems. > >It is interesting to note that this is the 'bias' of >the single precision exponent field. > > >Glenn P. Davis >NCAR / ACD I have already responded by e-mail to Glenn to inform him that this problem has been fixed in c version 4.0.0 and in f77 version 3.3.2. He suggested that I post this information since his not knowing was the reason for his posting in the first place. So I did a little more research to find out the cause of the bug in the first place. As you probably know, Pyramid Technology computers use the IEEE floating-point formats and compilers are known to like to represent special floating-point constants as bit patterns. The code generator (for c, f77, and pascal) optimizes out multiplication by one (the plot thickens). The single-precision (float) representation of (float)1/128 is 0x3c000000 and the double-precision (double) representation of 1.0 is 0x3c000000 0x00000000. We store all numeric values in two words with unused bits zeroed. So the code generator thought it was optimizing out a multiply by one. The fix involved checking the type field more closely. -- Mike Lipsie {allegra,cmcl2,decwrl,hplabs,ut-sally,utzoo}!pyramid!mikel Pyramid Technology Corp, Mountain View, CA +1 415 965 7200 ext. 4980
mikel@gymble.umd.edu@pyramid.UUCP (03/12/87)
In article <8703092244.AA15530@acdpyr.UCAR.EDU> davis@ACDPYR.UCAR.EDU (Glenn P. Davis) writes: [highly edited] > >The following code and script demonstrates a bug >with the pyramid 'c' compiler, version 3.2. > >This code developed as an attempted workaround to >a similar problem with the fortran compiler, >hence the underscores and pointer argument. > > return( *px * ((float)1/128 ) ) ; > >generates >_foo_: > movw (pr0),pr0 > ret > ret > >[i.e., ignores the (float)1/128] > > >It seems this problem is an artifact specifically of the >(single precision) floating point representation of 1/128. >Other numbers or the double representation of this number >do not cause problems. > >It is interesting to note that this is the 'bias' of >the single precision exponent field. > > >Glenn P. Davis >NCAR / ACD I have already responded by e-mail to Glenn to inform him that this problem has been fixed in c version 4.0.0 and in f77 version 3.3.2. He suggested that I post this information since his not knowing was the reason for his posting in the first place. So I did a little more research to find out the cause of the bug in the first place. As you probably know, Pyramid Technology computers use the IEEE floating-point formats and compilers are known to like to represent special floating-point constants as bit patterns. The code generator (for c, f77, and pascal) optimizes out multiplication by one (the plot thickens). The single-precision (float) representation of (float)1/128 is 0x3c000000 and the double-precision (double) representation of 1.0 is 0x3c000000 0x00000000. We store all numeric values in two words with unused bits zeroed. So the code generator thought it was optimizing out a multiply by one. The fix involved checking the type field more closely. -- Mike Lipsie {allegra,cmcl2,decwrl,hplabs,ut-sally,utzoo}!pyramid!mikel Pyramid Technology Corp, Mountain View, CA +1 415 965 7200 ext. 4980
boyle@ANL-MCS.ARPA.UUCP (03/12/87)
This is an interesting bug for me. It appears to be a classic example of scheduling the optimization (of removing multiplication by 1.0) too late in the derivation of the object program, after multiplications by 1.0 have been converted to a form is which they are no longer easily identifiable. This seems to be a general property of optimizations--"to everything there is a season". They cannot be done too soon, because the opportunity to apply them may not exist, and they should not be done too late, because they may be much harder to detect than when done at the best time, or (as in this case), other cases that shouldn't be optimized may have been commoned with them. I would suggest doing this optimization near the source code level. Doing it at the object code level is likely to leave behind a lot to clean up--nonoptimal register allocation, etc. Consider the results for the expression (a*1.0 - b*c), for example; after the multiplication by 1.0 is removed, a register (unneed on some machine architectures) might still be used to hold a. I discuss this point briefly in a paper "Program Reusability through Program Transformation" (hey, what can I say?) in the Sept. 84 IEEE Transactions on Software Engineering. Jim Boyle