我有以下功能:
void MainLayer::onMouseScroll(cocos2d::EventMouse* event)
{
const float scrollAmount = event->getScrollY();
const float newMapScale = scrollAmount < 0.f ? std::min(_mapScale * k_deltaMapScaleMag, k_maxMapScale) : std::max(_mapScale * k_deltaMapScaleMin, k_minMapScale);
const float invNewMapScale = 1.f / newMapScale;
const Vec2 anchorScreenSpace = event->getLocationInView();
_mapScale = newMapScale;
_invMapScale = invNewMapScale;
updateMapTransform();
}
Microsoft VS 2015编译器生成以下程序集:
push ebp
mov ebp, esp
push -1
push __ehhandler$?onMouseScroll@MainLayer@@AAEXPAVEventMouse@cocos2d@@@Z
mov eax, DWORD PTR fs:0
push eax
sub esp, 20 ; 00000014H
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
mov DWORD PTR __$ArrayPad$[ebp], eax
push esi
push eax
lea eax, DWORD PTR __$EHRec$[ebp]
mov DWORD PTR fs:0, eax
mov esi, ecx
mov ecx, DWORD PTR _event$[ebp]
; File c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm
; 3649 : return (_DEBUG_LT(_Right, _Left) ? _Right : _Left);
lea edx, DWORD PTR $T1[ebp]
; File e:\projects\aliceandbob\classes\mainlayer.cpp
; 121 : const float newMapScale = scrollAmount < 0.f ? std::min(_mapScale * k_deltaMapScaleMag, k_maxMapScale) : std::max(_mapScale * k_deltaMapScaleMin, k_minMapScale);
movss xmm1, DWORD PTR __real@3f800000
xorps xmm0, xmm0
comiss xmm0, DWORD PTR [ecx+56]
movss xmm0, DWORD PTR [esi+712]
jbe SHORT $LN3@onMouseScr
mulss xmm0, DWORD PTR __real@3f99999a
; File c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm
; 3649 : return (_DEBUG_LT(_Right, _Left) ? _Right : _Left);
mov eax, OFFSET ?k_maxMapScale@?A0x69cbde3b@@3MB
comiss xmm0, DWORD PTR __real@41200000
; File e:\projects\aliceandbob\classes\mainlayer.cpp
; 121 : const float newMapScale = scrollAmount < 0.f ? std::min(_mapScale * k_deltaMapScaleMag, k_maxMapScale) : std::max(_mapScale * k_deltaMapScaleMin, k_minMapScale);
jmp SHORT $LN18@onMouseScr
$LN3@onMouseScr:
mulss xmm0, DWORD PTR __real@3f4ccccd
; File c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm
; 3612 : return (_DEBUG_LT(_Left, _Right) ? _Right : _Left);
mov eax, OFFSET ?k_minMapScale@?A0x69cbde3b@@3MB
comiss xmm1, xmm0
$LN18@onMouseScr:
cmovbe eax, edx
movss xmm0, DWORD PTR [eax]
; File e:\projects\aliceandbob\classes\mainlayer.cpp
; 124 : const Vec2 anchorScreenSpace = event->getLocationInView();
lea eax, DWORD PTR _anchorScreenSpace$[ebp]
divss xmm1, xmm0
push eax
movss DWORD PTR tv161[ebp], xmm0
movss DWORD PTR _invNewMapScale$1$[ebp], xmm1
call DWORD PTR __imp_?getLocationInView@EventMouse@cocos2d@@QBE?AVVec2@2@XZ
; 125 : _mapScale = newMapScale;
movss xmm0, DWORD PTR tv161[ebp]
; 126 : _invMapScale = invNewMapScale;
; 127 :
; 128 : updateMapTransform();
mov ecx, esi
mov DWORD PTR __$EHRec$[ebp+8], 0
movss DWORD PTR [esi+712], xmm0
movss xmm0, DWORD PTR _invNewMapScale$1$[ebp]
movss DWORD PTR [esi+716], xmm0
call ?updateMapTransform@MainLayer@@AAEXXZ ; MainLayer::updateMapTransform
; 129 : }
mov ecx, DWORD PTR __$EHRec$[ebp]
mov DWORD PTR fs:0, ecx
pop ecx
pop esi
mov ecx, DWORD PTR __$ArrayPad$[ebp]
xor ecx, ebp
call @__security_check_cookie@4
mov esp, ebp
pop ebp
ret 4
问题是编译器生成的代码不会将表达式的结果存储到newMapScale变量中。如您所见,它也不会在此处插入minss和maxss指令(对于std :: max()和std :: min())。如果我拒绝计算机使用SSE指令 - 它按预期工作。我试图在测试项目上重现这个问题并且失败了 - 几乎完全相同的代码有minss和maxss指令,并将表达式的结果存储到newMapScale变量中。我是否有某种未定义的行为,或者它只是一个编译器错误?
我使用VS 2015 Update 3,VS 2015 - Windows XP(v140_xp)SDK。
UPD:我只留下了有助于重现问题的源代码。从该代码中删除任何行修复了编译器行为。请注意以下几行:
movss xmm1, DWORD PTR __real@3f800000
xorps xmm0, xmm0
comiss xmm0, DWORD PTR [ecx+56]
movss xmm0, DWORD PTR [esi+712]
jbe SHORT $LN3@onMouseScr
mulss xmm0, DWORD PTR __real@3f99999a
; File c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm
; 3649 : return (_DEBUG_LT(_Right, _Left) ? _Right : _Left);
mov eax, OFFSET ?k_maxMapScale@?A0x69cbde3b@@3MB
comiss xmm0, DWORD PTR __real@41200000
; File e:\projects\aliceandbob\classes\mainlayer.cpp
; 121 : const float newMapScale = scrollAmount < 0.f ? std::min(_mapScale * k_deltaMapScaleMag, k_maxMapScale) : std::max(_mapScale * k_deltaMapScaleMin, k_minMapScale);
jmp SHORT $LN18@onMouseScr
$LN3@onMouseScr:
mulss xmm0, DWORD PTR __real@3f4ccccd
; File c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm
; 3612 : return (_DEBUG_LT(_Left, _Right) ? _Right : _Left);
mov eax, OFFSET ?k_minMapScale@?A0x69cbde3b@@3MB
comiss xmm1, xmm0
$LN18@onMouseScr:
cmovbe eax, edx
movss xmm0, DWORD PTR [eax]
; File e:\projects\aliceandbob\classes\mainlayer.cpp
; 124 : const Vec2 anchorScreenSpace = event->getLocationInView();
lea eax, DWORD PTR _anchorScreenSpace$[ebp]
divss xmm1, xmm0
push eax
正如Andrey Turkin所说,xmm0虽然包含计算结果但会被丢弃。将单位化内存加载到xmm0中。