| 1 | // testcase-981648-vsoptimizer-bug.cpp
|
|---|
| 2 | //
|
|---|
| 3 | // Testcase 1 - Optimizer generates a movups statement where, according to Andrey Semashev, it should generate a movdqu
|
|---|
| 4 | //
|
|---|
| 5 | // Compile and link this with x64 platform
|
|---|
| 6 | // #TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit
|
|---|
| 7 | // Release | x64 | c:\users\kir.izt\documents\visual studio 2013\Projects\testcase - 981648 - vsoptimizer - bug\ |
|
|---|
| 8 | // cl.command.1.tlog is
|
|---|
| 9 | // /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
|
|---|
| 10 |
|
|---|
| 11 | #pragma region copied_from_boost_uuid_x86
|
|---|
| 12 | #include <stddef.h>
|
|---|
| 13 | #include <cstdint>
|
|---|
| 14 | #include <crtdefs.h>
|
|---|
| 15 | #include <stdio.h>
|
|---|
| 16 |
|
|---|
| 17 | using std::uint8_t;
|
|---|
| 18 |
|
|---|
| 19 | namespace std {
|
|---|
| 20 | typedef ::size_t size_t;
|
|---|
| 21 | typedef ::ptrdiff_t ptrdiff_t;
|
|---|
| 22 | }
|
|---|
| 23 |
|
|---|
| 24 | #define BOOST_NOEXCEPT /*noexcept*/
|
|---|
| 25 | #define BOOST_FORCEINLINE __forceinline
|
|---|
| 26 | #define BOOST_CONSTEXPR /*constexpr*/
|
|---|
| 27 |
|
|---|
| 28 | // MSVC does not always have immintrin.h (at least, not up to MSVC 10), so include the appropriate header for each instruction set
|
|---|
| 29 | #if defined(BOOST_UUID_USE_SSE41)
|
|---|
| 30 | #include <smmintrin.h>
|
|---|
| 31 | #elif defined(BOOST_UUID_USE_SSE3)
|
|---|
| 32 | #include <pmmintrin.h>
|
|---|
| 33 | #else
|
|---|
| 34 | #include <emmintrin.h>
|
|---|
| 35 | #endif
|
|---|
| 36 |
|
|---|
| 37 | namespace boost {
|
|---|
| 38 | namespace uuids {
|
|---|
| 39 | namespace detail {
|
|---|
| 40 |
|
|---|
| 41 | BOOST_FORCEINLINE __m128i load_unaligned_si128(const uint8_t* p) BOOST_NOEXCEPT
|
|---|
| 42 | {
|
|---|
| 43 | #if defined(BOOST_UUID_USE_SSE3)
|
|---|
| 44 | return _mm_lddqu_si128(reinterpret_cast<const __m128i*>(p));
|
|---|
| 45 | #else
|
|---|
| 46 | return _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
|
|---|
| 47 | #endif
|
|---|
| 48 | }
|
|---|
| 49 |
|
|---|
| 50 | } // namespace detail
|
|---|
| 51 | }
|
|---|
| 52 | }
|
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 55 | namespace boost {
|
|---|
| 56 | namespace uuids {
|
|---|
| 57 |
|
|---|
| 58 | struct uuid
|
|---|
| 59 | {
|
|---|
| 60 | public:
|
|---|
| 61 | // or should it be array<uint8_t, 16>
|
|---|
| 62 | uint8_t data[16];
|
|---|
| 63 | };
|
|---|
| 64 |
|
|---|
| 65 | bool operator== (uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT;
|
|---|
| 66 | bool operator< (uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT;
|
|---|
| 67 |
|
|---|
| 68 |
|
|---|
| 69 | inline bool operator== (uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT
|
|---|
| 70 | {
|
|---|
| 71 | register __m128i mm_left = uuids::detail::load_unaligned_si128(lhs.data);
|
|---|
| 72 | register __m128i mm_right = uuids::detail::load_unaligned_si128(rhs.data);
|
|---|
| 73 |
|
|---|
| 74 | register __m128i mm_cmp = _mm_cmpeq_epi32(mm_left, mm_right);
|
|---|
| 75 | #if defined(BOOST_UUID_USE_SSE41)
|
|---|
| 76 | return _mm_test_all_ones(mm_cmp);
|
|---|
| 77 | #else
|
|---|
| 78 | return _mm_movemask_epi8(mm_cmp) == 0xFFFF;
|
|---|
| 79 | #endif
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|
| 82 | inline bool operator!=(uuid const& lhs, uuid const& rhs) BOOST_NOEXCEPT
|
|---|
| 83 | {
|
|---|
| 84 | return !(lhs == rhs);
|
|---|
| 85 | }
|
|---|
| 86 | }}
|
|---|
| 87 |
|
|---|
| 88 | using boost::uuids::uuid;
|
|---|
| 89 | #pragma endregion copied_from_boost_uuid_x86
|
|---|
| 90 |
|
|---|
| 91 | class headerProperty
|
|---|
| 92 | {
|
|---|
| 93 | public:
|
|---|
| 94 | virtual ~headerProperty() {}
|
|---|
| 95 | };
|
|---|
| 96 |
|
|---|
| 97 | class my_obj:public headerProperty
|
|---|
| 98 | {
|
|---|
| 99 | public:
|
|---|
| 100 | char tmp[8];
|
|---|
| 101 | uuid m_uuid;
|
|---|
| 102 | const uuid &get_marker_id() const { return m_uuid; }
|
|---|
| 103 | uuid get_id() const { return m_uuid; }
|
|---|
| 104 | };
|
|---|
| 105 |
|
|---|
| 106 | static my_obj g_my_obj;
|
|---|
| 107 |
|
|---|
| 108 | void mp_grid_update_marker_parameters(headerProperty* header_prop, my_obj ¤t_marker)
|
|---|
| 109 | {
|
|---|
| 110 | headerProperty *old_header_prop = NULL;
|
|---|
| 111 | while (old_header_prop == NULL) {
|
|---|
| 112 | my_obj *p = dynamic_cast<my_obj*>(header_prop);
|
|---|
| 113 | if (p != NULL && (current_marker.get_id() != p->get_marker_id())) {
|
|---|
| 114 | wprintf(L"works okay, if it reaches this printf: %lx\n", (long)p);
|
|---|
| 115 | old_header_prop = header_prop;
|
|---|
| 116 | }
|
|---|
| 117 | }
|
|---|
| 118 | }
|
|---|
| 119 |
|
|---|
| 120 | int main(int argc, wchar_t* argv[])
|
|---|
| 121 | {
|
|---|
| 122 | my_obj *p = &g_my_obj;
|
|---|
| 123 | uuid one, two;
|
|---|
| 124 | one.data[0] = 1; two.data[0] = 0;
|
|---|
| 125 |
|
|---|
| 126 | //*****************************************
|
|---|
| 127 | // This != statement generates two movdqu statements
|
|---|
| 128 | if (one != two) {
|
|---|
| 129 | wprintf(L"works okay, if it reaches this printf.\n");
|
|---|
| 130 | } // else causes a GP
|
|---|
| 131 | my_obj a, b;
|
|---|
| 132 |
|
|---|
| 133 | //*****************************************
|
|---|
| 134 | // The != statement in this inlined function generates a movups and a movdqu statement
|
|---|
| 135 | mp_grid_update_marker_parameters(p, a);
|
|---|
| 136 |
|
|---|
| 137 | return 0;
|
|---|
| 138 | }
|
|---|
| 139 |
|
|---|