Microsoft KB Archive/236349

= FIX: Bad Code Generated by Global Optimization =

Article ID: 236349

Article Last Modified on 11/18/2003

-

APPLIES TO


 * Microsoft Visual C++ 6.0 Enterprise Edition
 * Microsoft Visual C++ 6.0 Professional Edition
 * Microsoft Visual C++ 6.0 Standard Edition

-



This article was previously published under Q236349



SYMPTOMS
For builds that use global optimization (/Og), the condition of an if or while statement in which two pointers are compared and incremented, can appear to be false when in fact the condition is true. This problem occurs only under a fairly narrow set of circumstances. See the sample code in the "More Information" section for an example. Note that both the "maximize speed" (/O2) and "minimize size" (/O1) optimizations are composite optimization switches that include /Og.



CAUSE
The optimizer has incorrectly removed a CMP instruction.



RESOLUTION
Disable the global optimizations for the function, source file, or project in question. Global optimizations can be disabled on a function-by-function basis by using #pragma optimize. Global optimizations can be disabled for a source file (or project) by adding /Og- to the file's (or project's) settings. See "workaround #2" in the "More Information" section for an example of the #pragma approach.

Another workaround is to move the increment (or decrement) of the pointers outside the comparison. See "workaround #3" in the "More Information" section for an example of this approach.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

This problem was corrected in Microsoft Visual C++ .NET.



MORE INFORMATION
/****************************************************/ /* test.c - demonstrates Global Optimization Problem*/ /* cl /c /FAs /Fa /Og test.c                       */ /****************************************************/ // #define WORKAROUND3 // Uncomment this line for workaround #3.

struct MyStruct  { unsigned long m_len; unsigned char *m_lpData;  }; typedef struct MyStruct *LPMyStruct;

// #pragma optimize("g",off) // Uncomment this line for workaround #2. short MyStructComp ( struct MyStruct *Arg1,struct MyStruct *Arg2) {      unsigned long dwLen; unsigned char *str1, *str2; dwLen = Arg1->m_len; str1 = Arg1->m_lpData; str2 = Arg2->m_lpData; while (dwLen--) if (*str1 < *str2) return (-1); else if (*(str1++) > *(str2++)) return (1); else if (*str1 > *str2) {              str1++; str2++; }      return (0); } // #pragma optimize("g",on) // Uncomment this line for workaround #2.
 * 1) ifndef WORKAROUND3
 * 1) else
 * 1) endif

When the code is compiled with /Og, the MyStructComp function may return 0 (zero); the function should return 1. The code path for the "else if" condition may not be taken, even when the condition is true. To see the reason why, examine the following mixed assembly and source listing, generated by using /FAs /Fa, (hand annotated): Test.asm generated by cl /c /FAs /Fa /Og Test.c:


 * 16  :       while (dwLen--)

mov edx, edi dec edi test   edx, edx je SHORT $L234 sub esi, eax $L233:


 * 17  :            if (*str1 < *str2)

mov cl, BYTE PTR [eax] mov dl, BYTE PTR [esi+eax] cmp cl, dl   jb  SHORT $L242


 * 19  : #ifndef WORKAROUND3
 * 20  :           else if (*(str1++) > *(str2++))

inc eax       ; ja SHORT $L243 ; <== Note that this depends upon the zero flag mov ecx, edi   ; remaining from the cmp cl,dl above, dec edi        ;but the inc eax instruction just before it may test   ecx, ecx    ;have affected the zero flag... jne SHORT $L233 $L234: pop edi


 * 22  : #else
 * 23  :           else if (*str1 > *str2)
 * 24  :           {
 * 25  :               str1++;
 * 26  :               str2++;
 * 27  :           }
 * 28  : #endif
 * 29  :        return (0);

xor ax, ax   pop esi


 * 30  :  }

pop ebp ret 0 $L242: pop edi


 * 18  :                return (-1);

or ax, -1 pop esi


 * 30  :  }

pop ebp ret 0 $L243: pop edi


 * 21  :                return (1);

mov ax, 1 pop esi


 * 30  :  }

Additional query words: Og CodeGen

Keywords: kbbug kbfix kbnoupdate kbcodegen KB236349

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.