1/* PR middle-end/37809 */
2
3/* { dg-do run } */
4/* { dg-options "-O2 -mmmx" } */
5
6#include <mmintrin.h>
7
8#include "mmx-check.h"
9
10// Various tests of cases where it is incorrect to optimise vectors as if they
11// were integers of the same width.
12
13extern void abort (void);
14
15void __attribute__ ((noinline))
16Sshift()
17{
18    volatile __m64 y = (__m64) 0xffffffffll;
19    __m64 x = y & (__m64) 0xffffffffll;
20    x = _m_psradi (x, 1);
21    x &= (__m64) 0x80000000ll;
22    if (0 == (long long) x)
23        abort();
24}
25
26#define SHIFTU(F,B,S,T)                         \
27    void F()                                    \
28    {                                           \
29        volatile __m64 y = (__m64) 0ll;         \
30        __m64 x = y | (__m64) (1llu << B);      \
31        if (S > 0)                              \
32            x = _m_pslldi (x, S);               \
33        else                                    \
34            x = _m_psrldi (x, -S);              \
35        if (T > 0)                              \
36            x = _m_pslldi (x, T);               \
37        else                                    \
38            x = _m_psrldi (x, -T);              \
39        x &= (__m64) (1llu << (B + S + T));     \
40        if ((long long) x)                      \
41            abort();                            \
42    }
43
44SHIFTU (shiftU1, 31, 1, -1)
45SHIFTU (shiftU2, 32, -1, 1)
46SHIFTU (shiftU3, 31, 1, 0)
47SHIFTU (shiftU4, 32, -1, 0)
48
49void __attribute__ ((noinline))
50add_1()
51{
52    volatile long long ONE = 1;
53    long long one = ONE;
54
55    __m64 a = (__m64) one;
56    __m64 b = (__m64) -one;
57    __m64 c = a + b;
58    if (0 == (long long) c)
59        abort();
60}
61
62void __attribute__ ((noinline))
63add_2()
64{
65    volatile long long ONE = 1;
66    long long one = ONE;
67
68    __m64 a = (__m64) one;
69    __m64 b = (__m64) -one;
70    __m64 c = _m_paddd (a, b);
71    if (0 == (long long) c)
72        abort();
73}
74
75void __attribute__ ((noinline))
76mult_1()
77{
78    volatile __m64 y = (__m64) 0ll;
79    __m64 x = y | (__m64) (1ll << 32);
80    x = x * (__m64) 1ll;
81    x &= (__m64) (1ll << 32);
82    if (0 != (long long) x)
83        abort();
84}
85
86void __attribute__ ((noinline))
87mult_2()
88{
89    volatile int foo = 1;
90    unsigned long long one = foo & 1;
91
92    __m64 x = (__m64) (one << 16);
93    x *= x;
94    x &= (__m64) (1ll << 32);
95    if (0 != (long long) x)
96        abort();
97}
98
99void __attribute__ ((noinline))
100mult_3()
101{
102    volatile __m64 y = (__m64) (1ll << 32);
103    __m64 a = y;
104    __m64 b = y * (__m64) 1ll;
105    if (((long long) a) == (long long) b)
106        abort();
107}
108
109void __attribute__ ((noinline))
110div_1()
111{
112    volatile __m64 y = (__m64) 0ll;
113    __m64 x = y | (__m64) (1ull << 32);
114    x |= (__m64) 1ull;
115    x = x / x;
116    if (1ll == (long long) x)
117        abort();
118}
119
120
121void mmx_test (void)
122{
123    Sshift();
124    shiftU1();
125    shiftU2();
126    shiftU3();
127    shiftU4();
128
129    add_1();
130    add_2();
131
132    mult_1();
133    mult_2();
134    mult_3();
135
136    div_1();
137}
138