home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / gnu / gcc / bug / 2785 < prev    next >
Encoding:
Text File  |  1992-11-17  |  3.5 KB  |  119 lines

  1. Newsgroups: gnu.gcc.bug
  2. Path: sparky!uunet!charon.amdahl.com!pacbell.com!sgiblab!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!runx.oz.AU!bde
  3. From: bde@runx.oz.AU (Bruce Evans)
  4. Subject: 386 gcc-2.3.1: sin (x) wrong for large x
  5. Message-ID: <1992Nov17.171303.19178@runx.oz.au>
  6. Sender: gnulists@ai.mit.edu
  7. Organization: RUNX Un*x Timeshare.  Sydney, Australia.
  8. Distribution: gnu
  9. Date: Tue, 17 Nov 1992 17:13:03 GMT
  10. Approved: bug-gcc@prep.ai.mit.edu
  11. Lines: 106
  12.  
  13. gcc-2.3.1 for the 386 generates incorrect code for sin (x).  It is necessary to
  14. check the C2 bit in the FP status word to handle the case abs (x) >= 2**64.
  15. cos (x) requires the same treatment.
  16.  
  17. I think that the C2 bit should be checked even for -ffast-math.  It does not
  18. cause an exception (the arg is not changed) so the error will be discarded
  19. silently if C2 is not checked.
  20.  
  21. I don't think it is worth inlining the transcendental functions for 486's
  22. (and probably not for 386/387's).  The speedup is only 10-20% compared
  23. with an extern function and zero compared with an inline function.  There
  24. is another correctness issue.  The inline code will trap if the arg is a
  25. NaN or infinity and the exception masks say to trap.  I think the ANSI
  26. standard says that sin () should not trap.  The function implementation
  27. could easily change the exception masks to avoid the trap (or better
  28. keep track of the exception masks and change them only when necessary).
  29. This is a bit much for automatically inlined versions.
  30.  
  31. See the comments in the assembler output for more remarks.  The comment
  32. starting with a single / shows suitable correct code.  Comments starting
  33. with // are about side issues.
  34.  
  35. ---
  36. command
  37. ---
  38. gcc -v -S -O -m80387 -mfp-ret-in-387 -mieee-fp z.c
  39. ---
  40.  
  41. ---
  42. error output
  43. ---
  44. Reading specs from /usr/gnu/gcc/lib/gcc-lib/i386-minix/2.3.1/specs
  45. gcc version 2.3.1
  46.  /usr/gnu/gcc/lib/gcc-lib/i386-minix/2.3.1/cpp -lang-c -v -undef -D__GNUC__=2 -D__OPTIMIZE__ z.c /usr/tmp/cca02026.i
  47. GNU CPP version 2.3.1 (80386, BSD syntax)
  48.  /usr/gnu/gcc/lib/gcc-lib/i386-minix/2.3.1/cc1 /usr/tmp/cca02026.i -quiet -dumpbase z.c -m80387 -mfp-ret-in-387 -mieee-fp -O -version -o z.s
  49. GNU C version 2.3.1 (80386, BSD syntax) compiled by GNU C version 2.3.1.
  50.  
  51. ---
  52. input file z.c
  53. ---
  54. double sin(double x);
  55.  
  56. extern double x;
  57.  
  58. double g(void)
  59. {
  60.     return sin(x);
  61. }
  62. ---
  63.  
  64. ---
  65. commented output file
  66. ---
  67.     .file    "z.c"
  68. gcc2_compiled.:
  69. .text
  70.     .align 2        // I want .align 2,0x90 - need to use a macro
  71.                 // more like ASM_OUTPUT_ALIGN_CODE than
  72.                 // ASM_OUTPUT_ALIGN at the start of a function
  73. .globl _g
  74. _g:
  75.     pushl %ebp
  76.     movl %esp,%ebp
  77.     fldl _x
  78.     fld %st(0)        // inefficient
  79.     fsin
  80.         / Must test C2 set by fsin now since fucom will clobber it.
  81.         / Add this:
  82.         /     fnstsw %ax
  83.         /     testb $4,%ah    / 4 = C2
  84.         /     jne Lnew
  85.         / Or delete the old 5 instructions starting at fucom and
  86.         / add this:
  87.         /     fnstsw %ax
  88.         /     testl $0x4zz,%eax    / 0x400 = C2, zz = relevant exceptions
  89.         /     jne Lnew
  90.         / The second version calls the sin () function if the fsin
  91.         / set an exception bit or if an exception bit was already
  92.         / set.  This version is better unless there are a lot of
  93.         / (masked) exceptions and the sin () function is much slower.
  94.     fucom %st(0)
  95.     fnstsw %ax
  96.     andb $69,%ah
  97.     cmpb $64,%ah
  98.     je L3            // inefficient - branch usually taken
  99.         / Lnew:
  100.     fstp %st(0)
  101.     subl $8,%esp        // inefficient
  102.     fstpl (%esp)        // inefficient
  103.                 // It was not good to dup the value of x in
  104.                 // loaded into %st for fsin, since we want
  105.                 // it on the x86 and not the x87 stack for
  106.                 // the function call.
  107.     call _sin
  108.     leave
  109.     ret
  110.     .align 2,0x90
  111. L3:
  112.     fstp %st(1)
  113.     leave
  114.     ret
  115. ---
  116. -- 
  117. Bruce Evans  (bde@runx.oz.au)
  118.  
  119.