BUG: Global-Register Allocation Generates Incorrect Results

Last reviewed: July 22, 1997
Article ID: Q116241
1.00 1.50 WINDOWS kbtool kbbuglist

The information in this article applies to:

  • The Microsoft C/C++ Compiler (CL.EXE) included with:

        - Microsoft Visual C++ for Windows, versions 1.0 and 1.5
    

SYMPTOMS

The use of the global-register-allocation optimization switch, /Oe, on floating-point intensive code, such as in the sample below, can generate incorrect results.

RESOLUTION

There are several methods that can be used to work around this problem:

  • Use the fast compiler option, /f.

    -or-

  • Remove the /Oe compiler option to disable global-register optimization.

    -or-

  • Disable optimization during the function using the optimize pragma:

          #pragma optimize("",off)
    

                void bad_function()
                {
                /* ... */
                }
    
                #pragma optimize("",on)
    
       -or-
    
    
  • Use the volatile descriptor with the variables of type double. This way, the variables are less likely to be optimized and the data is correctly maintained. To do this with the sample code shown in the "MORE INFORMATION" section, below, compile using the /DFIX compiler option.

    -or-

  • In the sample code below, call function junk() to resolve the floating- point error.

STATUS

Microsoft has confirmed this to be a bug with the C/C++ compiler for MS-DOS, versions 8.0 and 8.0c. We are researching the problem and will post new information here in the Microsoft Knowledge Base as it becomes available.

The problem does not occur with the 32-bit C/C++ compiler.

MORE INFORMATION

The following sample code can be used to demonstrate this problem:

Sample Code

/* Compile options needed: /Oe
*/

TEST.c

   #include <stdio.h>
   #include <math.h>

   void junk(void)
   {
   }

   void main(void)
   {
      double x, y, x1 = 623.0, x2 = 724.0, y1 = 308.0, y2 = 244.0;
      double angle1 = 325, angle2 = 265;
   #ifdef FIX
      volatile double m1 = -0.70, m2 = 11.43;
   #else
      double m1 = -0.70, m2 = 11.43;
   #endif

      m1 = tan( (double)angle1 / 180.0 * 3.1415926535 );
      m2 = tan( (double)angle2 / 180.0 * 3.1415926535 );

      if( fabs( m1 ) > 99999 )
      {
         x = x1;
         y = m2 * ( x - x2 ) + y2;
      }
      else if( fabs( m2 ) > 99999 )
      {
         x = x2;
         y = m1 * ( x - x1 ) + y1;
      }
      else
      {
      // Bad optimizations occur in this code
      // Uncomment this line to fix the problem
      // junk();
         x = ( m1 * x1 - m2 * x2 - y1 + y2 ) / ( m1 - m2 );
         y = m1 * ( x - x1 ) + y1;
      }
      printf ("x = %f, y = %f\n",x, y);
   }

Output

   x = -723.445934, y = 1250.791593

Correct Output

   x = 723.445934, y = 237.667000


Additional reference words: 1.00 1.50 8.00 8.00c
KBCategory: kbtool kbbuglist
KBSubcategory: CodeGen
Keywords : kb16bitonly


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 22, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.