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 |
|
---|