// testcase-981648-vsoptimizer-bug.cpp // // Testcase 1 - Optimizer generates a movups statement where, according to Andrey Semashev, it should generate a movdqu // // Compile and link this with x64 platform // #TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit // Release | x64 | c:\users\kir.izt\documents\visual studio 2013\Projects\testcase - 981648 - vsoptimizer - bug\ | // cl.command.1.tlog is // /c /Zi /nologo /W3 /WX- /sdl /O2 /Oi /D WIN32 /D NDEBUG /D _CONSOLE /D _LIB /D _UNICODE /D UNICODE /Gm- /EHsc /MT /GS /Gy /Zc:wchar_t /Zc:forScope /Fo"X64\RELEASE\\" /Fd"X64\RELEASE\VC120.PDB" /Gd /TP TESTCASE-981648-VSOPTIMIZER-BUG.CPP #pragma region copied_from_boost_uuid_x86 #include #include #include #include using std::uint8_t; namespace std { typedef ::size_t size_t; typedef ::ptrdiff_t ptrdiff_t; } #define BOOST_NOEXCEPT /*noexcept*/ #define BOOST_FORCEINLINE __forceinline #define BOOST_CONSTEXPR /*constexpr*/ // MSVC does not always have immintrin.h (at least, not up to MSVC 10), so include the appropriate header for each instruction set #if defined(BOOST_UUID_USE_SSE41) #include #elif defined(BOOST_UUID_USE_SSE3) #include #else #include #endif namespace boost { namespace uuids { namespace detail { BOOST_FORCEINLINE __m128i load_unaligned_si128(const uint8_t* p) BOOST_NOEXCEPT { #if defined(BOOST_UUID_USE_SSE3) return _mm_lddqu_si128(reinterpret_cast(p)); #else return _mm_loadu_si128(reinterpret_cast(p)); #endif } } // namespace detail } } namespace boost { namespace uuids { struct uuid { public: // or should it be array uint8_t data[16]; }; bool operator== (uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT; bool operator< (uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT; inline bool operator== (uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT { register __m128i mm_left = uuids::detail::load_unaligned_si128(lhs.data); register __m128i mm_right = uuids::detail::load_unaligned_si128(rhs.data); register __m128i mm_cmp = _mm_cmpeq_epi32(mm_left, mm_right); #if defined(BOOST_UUID_USE_SSE41) return _mm_test_all_ones(mm_cmp); #else return _mm_movemask_epi8(mm_cmp) == 0xFFFF; #endif } inline bool operator!=(uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT { return !(lhs == rhs); } }} using boost::uuids::uuid; #pragma endregion copied_from_boost_uuid_x86 class headerProperty { public: virtual ~headerProperty() {} }; class my_obj:public headerProperty { public: char tmp[8]; uuid m_uuid; const uuid &get_marker_id() const { return m_uuid; } uuid get_id() const { return m_uuid; } }; static my_obj g_my_obj; void mp_grid_update_marker_parameters(headerProperty* header_prop, my_obj ¤t_marker) { headerProperty *old_header_prop = NULL; while (old_header_prop == NULL) { my_obj *p = dynamic_cast(header_prop); if (p != NULL && (current_marker.get_id() != p->get_marker_id())) { wprintf(L"works okay, if it reaches this printf: %lx\n", (long)p); old_header_prop = header_prop; } } } int main(int argc, wchar_t* argv[]) { my_obj *p = &g_my_obj; uuid one, two; one.data[0] = 1; two.data[0] = 0; //***************************************** // This != statement generates two movdqu statements if (one != two) { wprintf(L"works okay, if it reaches this printf.\n"); } // else causes a GP my_obj a, b; //***************************************** // The != statement in this inlined function generates a movups and a movdqu statement mp_grid_update_marker_parameters(p, a); return 0; }