Optimization problem

Our application crashes during execution a floating point instruction. It seems to be an incorrect optimization.
When the method 'CLPController::StopPlaying' is called from the 'CLPController::SetLogTime', a floating point value is remaining on the top of the FPU stack:
00AC4575 call CLPController::StopPlaying (0AC3090h)
00AC457A fstp qword ptr [esi+24h]
'CLPController::StopPlaying' indirectly calls the ::MoveWindowW function which sometimes empties the FPU stack. It causes a crash at a next FPU instruction (in the another place) because the 'invalid instruction' flag is set.
Both methods are noninline and are defined in the same .cpp file.
In this place the problem can be solved by adding any __asm instruction which suppresses optimisation, but we can't be sure we've fixed this problem anywhere.
Sergey Ryazanov,
Transas, VTS Department
--
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
/O2 /G7 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LOG_IMPL" /D "_AFXEXT" /D "_HASLANGDLL_" /D "ENABLE_ASSURE" /D "ENABLE_TRACE" /D "USE_WINSOCK2" /D "_WINDLL" /D "_AFXDLL" /D "_UNICODE" /Gm /EHsc /MD /Zp1 /GR /Yu"GUI\StdGUI.h" /Fp".\..\..\VCOBJ\Release Unicode\Log\Log.pch" /Fo".\..\..\VCOBJ\Release Unicode\Log\\" /Fd".\..\..\VCOBJ\Release Unicode\Log\vc70.pdb" /W4 /nologo /c /Zi

// FULL_TIME - double
c:\work\current\vts\src\log\logplay\lpservice.cpp --
void CLPController::SetLogTime(FULL_TIME time) {
00AC4500 push esi
00AC4501 mov esi,ecx
_assure( Player != NULL );
00AC4503 cmp dword ptr [esi+4],0
00AC4507 push edi
00AC4508 mov edi,dword ptr [__impassure_fail (0ACDBF8h)]
00AC450E jne CLPController::SetLogTime+29h (0AC4529h)
00AC4510 push 8Dh
00AC4515 push offset string L"\\Work\\Current\\vts\\Sr"... (0AD88B8h)
00AC451A push offset string L"" (0ACDEDCh)
00AC451F push offset string L"Player != 0" (0AD827Ch)
00AC4524 call edi
00AC4526 add esp,10h
GUARD_IF_NOT ( MinTime <= time && time <= MaxTime )
00AC4529 fld qword ptr [esp+0Ch]
00AC452D fcom qword ptr [esi+1Ch]
00AC4530 fnstsw ax
00AC4532 test ah,1
00AC4535 jne CLPController::SetLogTime+41h (0AC4541h)
00AC4537 fcom qword ptr [esi+2Ch]
00AC453A fnstsw ax
00AC453C test ah,41h
00AC453F jnp CLPController::SetLogTime+5Fh (0AC455Fh)
00AC4541 push 8Fh
00AC4546 fstp st(0)
00AC4548 push offset string L"\\Work\\Current\\vts\\Sr"... (0AD88B8h)
00AC454D push offset string L"" (0ACDEDCh)
00AC4552 push offset string L"MinTime <= time && t"... (0AD8D68h)
00AC4557 call edi
{
time = MinTime;
00AC4559 fld qword ptr [esi+1Ch]
00AC455C add esp,10h
}
if (IsTimeEqual(LogTime, time)) return;
00AC455F fld qword ptr [esi+24h]
00AC4562 fsub st,st(1)
00AC4564 fabs
00AC4566 fcomp qword ptr [__real@4059000000000000 (0AD4788h)]
00AC456C fnstsw ax
00AC456E test ah,5
00AC4571 jnp CLPController::SetLogTime+90h (0AC4590h)
StopPlaying();
00AC4573 mov ecx,esi
00AC4575 call CLPController::StopPlaying (0AC3090h)
// __asm { fwait } // this code solves the problem
LogTime = time;
00AC457A fstp qword ptr [esi+24h]
OnTimeChanged();
00AC457D mov eax,dword ptr [esi]
00AC457F mov ecx,esi
00AC4581 call dword ptr [eax+20h]
NeedleDown();
00AC4584 mov ecx,esi
00AC4586 call CLPController::NeedleDown (0AC4000h)
00AC458B pop edi
00AC458C pop esi
}
00AC458D ret 8
00AC4590 pop edi
NeedleDown();
00AC4591 fstp st(0)
00AC4593 pop esi
}
00AC4594 ret 8

c:\work\current\vts\src\log\logplay\lpservice.cpp --
void CLPController::StopPlaying()
{
00AC3090 push esi
00AC3091 mov esi,ecx
_assure( Player != NULL );
00AC3093 cmp dword ptr [esi+4],0
00AC3097 push edi
00AC3098 mov edi,dword ptr [__impassure_fail (0ACDBF8h)]
00AC309E jne CLPController::StopPlaying+45h (0AC30D5h)
00AC30A0 push 0D2h
00AC30A5 push offset string L"\\Work\\Current\\vts\\Sr"... (0AD88B8h)
00AC30AA push offset string L"" (0ACDEDCh)
00AC30AF push offset string L"Player != 0" (0AD827Ch)
00AC30B4 call edi
00AC30B6 add esp,10h
if ( IsPlaying () )
00AC30B9 cmp dword ptr [esi+4],0
00AC30BD jne CLPController::StopPlaying+45h (0AC30D5h)
00AC30BF push 6Ch
00AC30C1 push offset string L"\\Work\\Current\\vts\\Sr"... (0AD88B8h)
00AC30C6 push offset string L"" (0ACDEDCh)
00AC30CB push offset string L"Player != 0" (0AD827Ch)
00AC30D0 call edi
00AC30D2 add esp,10h
00AC30D5 mov eax,dword ptr [esi+4]
00AC30D8 cmp byte ptr [eax+219h],0
00AC30DF pop edi
00AC30E0 je CLPController::StopPlaying+5Ah (0AC30EAh)
{
Player -> Stop ();
00AC30E2 mov ecx,eax
00AC30E4 mov edx,dword ptr [ecx]
00AC30E6 pop esi
00AC30E7 jmp dword ptr [edx+30h]
00AC30EA pop esi
}
}
00AC30EB ret

[5205 byte] By [SeRya] at [2007-12-16]
# 1
From the asm, it looks like an optmization issue but I can't say for sure unless there are more info on how exactly StopPlaying calls MoveWindowW and of course the asm generated for MoveWindowW.

Any ways, could you make sure that the debug build doesn't reproduce the problem?

If that is the case, then please report a bug at
http://lab.msdn.microsoft.com with all the extra needed info.

Also, I have noticed you are not using VS2005 where a whole new floating point model is introduced giving the developer more control over the FP optmizations.
Here is a nice link discussing such model: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/floapoint.asp

Thanks for raising the issue!

Ayman Shoukry
VC++ Team

AymanShoukry at 2007-9-9 > top of Msdn Tech,Visual C++,Visual C++ General...
# 2
Method StopPlaying calls virtual method Stop ('Player -> Stop ();'). The method 'Stop' calls 'MoveWindow' indirectly (through 5-10 another mwthods).
I think an asm code of MoveWidnowW is unessential because it is permissible behaviour (by the way, it's been reproduced under Win2000 and WinXP). It is enough that the 'Stop' method is virtual.
I'm sure that this problem isn't reproduced in the debug configuration. Moreover, local suppressing of optimization (by __asm {fwait} instruction) is enough.
I'll report at this site, but I don't know what extra information I can provide. I haven't managed to reproduce the same problem outside our application.
Sergey Ryazanov,
Transas, VTS Department
SeRya at 2007-9-9 > top of Msdn Tech,Visual C++,Visual C++ General...
# 3

Sounds Good!

Please go ahead and report the bug and the responsible folks will have a look. After the bug is reported, keep checking the site for workarounds or additional feedback on the bug.

Thanks for raising the issue Sergey!

Thanks,
Ayman Shoukry
VC++ Team

AymanShoukry at 2007-9-9 > top of Msdn Tech,Visual C++,Visual C++ General...
# 4
This site ( http://lab.msdn.microsoft.com) accepts only VC++ 2005 issues, but the problem has been found in VC++ 2003.
SeRya at 2007-9-9 > top of Msdn Tech,Visual C++,Visual C++ General...
# 5
You can cotact microsoft to report such a bug by using the info at:
http://support.microsoft.com/gp/contactbug

In addition, it would still be great if report the bug on lab.msdn.microsoft.com so that the reponsible folks would investigate if it can still be reproduced using VS 2005. Mention in your report that it reproduces in VS 2003 as well. After folks look at it, they would probably update the bug entry with workarounds if possible.

Thanks,
Ayman Shoukry
VC++ Team.

AymanShoukry at 2007-9-9 > top of Msdn Tech,Visual C++,Visual C++ General...