public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/12308] New: '387 mode switching clobbers flags
@ 2003-09-17  2:35 stuart at apple dot com
  2003-09-17  7:17 ` [Bug target/12308] " pinskia at gcc dot gnu dot org
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: stuart at apple dot com @ 2003-09-17  2:35 UTC (permalink / raw)
  To: gcc-bugs

PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12308

           Summary: '387 mode switching clobbers flags
           Product: gcc
           Version: 3.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: stuart at apple dot com
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i686-apple-darwin7.0.0b1
  GCC host triplet: i686-apple-darwin7.0.0b1
GCC target triplet: i686-apple-darwin7.0.0b1

We found this problem on Darwin/x86, but we believe it will reproduce on GNU/Linux/x86.

Pre-PNI '387s need to switch into "truncate towards zero" mode in order to convert a double into 
an integral type.  The testcase is a pathological instance where the five-instruction mode-
switching idiom lands between a compare and a subsequent conditional jump ("if (x)" in the 
testcase).  Subsequent passes notice the flags set by the compare are lost, and delete the 
compare instruction.

Here is the '387 mode-switching idiom:

        fnstcw  -6(%ebp)                                                    store '387 Control Word register
        movzwl  -6(%ebp), %eax
        orb     $12, %ah                                                      compute "truncate towards zero" mode
        movw    %ax, -8(%ebp)
        fldcw   -8(%ebp)                                                      set '387 to "truncate towards zero" mode

Theoretically, the compiler could issue the idiom once in the prologue, and the "fldcw -6(%ebp)" to 
switch modes for zero-trunc mode and "fldcw -6(%ebp)" to restore "round nearest" mode.  Instead, 
it seems to re-issue the entire idiom every time it needs to issue an fp->int conversion.

The short-term hack is to mark the mode-switching idiom (the "orb") as clobbering the flags.  (We 
have such a patch, if you like.)

The better long-term fix is to fully apply the lcm.c:optimize_mode_switching() feature.

Getting this working correctly may be difficult; mistakes will cause subtle rounding errors that may 
or may not be noticed.  I humbly suggest the fix include support for correct code without the 
optimize_mode_switching() pass; perhaps a flag "-fno-optimize-mode-switching" could cause an 
fldcw-fistp-fldcw sequence.  This should be a significant help when a mode-switching bug is 
suspected.

If your P4 supports PNI (P4 "Prescott New Instructions"), there is a new instruction ("fisttp") that 
will convert st(0) into an integral type, truncating towards zero, regardless of the current rounding 
mode set in CW.  This is clearly the preferred (modeless) solution, but it doesn't work on every P4, 
and won't work on anything older.

Here is the commandline used to compile the testcase:

   gcc -g -Wall -O2 -o test test.c -save-temps

You need -O2 or equivalent to see the problem.

Here is the testcase:

----------------------------------------------------
/* this #include is only for the abort() decl; may be omitted */
#include <stdlib.h>

static unsigned char x = 0;
static unsigned char y = 0;

float
width(void)
{
  return 0.0f;
}

int
foo(void)
{
  float w = width();
  int index;

  if (x) {
    index = y ? 2 : 1;
  } else {
    index = y ? 2 : 0;
  }

  return index + (int)w;
}

int
main (void)
{
  int x = foo() ;
  if (x)
    abort();
  return 0;
}
------------------------------------------------


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2005-03-11  9:49 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-09-17  2:35 [Bug c/12308] New: '387 mode switching clobbers flags stuart at apple dot com
2003-09-17  7:17 ` [Bug target/12308] " pinskia at gcc dot gnu dot org
2003-10-05 17:18 ` pinskia at gcc dot gnu dot org
2003-10-05 17:28 ` pinskia at gcc dot gnu dot org
2003-10-17 18:20 ` pinskia at gcc dot gnu dot org
2003-10-20 23:54 ` stuart at apple dot com
2003-12-11 20:00 ` pinskia at gcc dot gnu dot org
2004-01-19 20:31 ` pinskia at gcc dot gnu dot org
2004-01-21  7:13 ` dhazeghi at yahoo dot com
2004-01-21 20:54 ` cvs-commit at gcc dot gnu dot org
2004-01-21 20:55 ` pinskia at gcc dot gnu dot org
2004-03-15  8:34 ` matt at use dot net
2004-03-15  8:42 ` matt at use dot net
2004-03-27 16:15 ` cvs-commit at gcc dot gnu dot org
2004-04-22 17:50 ` cvs-commit at gcc dot gnu dot org
2005-03-11  9:49 ` uros at kss-loka dot si

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).