1 /* { dg-additional-options "-Wno-shift-overflow" } */
2 /* { dg-require-effective-target vect_shift } */
3 /* { dg-require-effective-target vect_int } */
4 /* Check the standard integer types for left and right shifts to see if the
5    compiler replaced a scalar instruction with a vector instruction whether the
6    correct value is generated.  */
7 
8 #ifdef TRACE
9 #endif
10 
11 #include <stdarg.h>
12 #include "tree-vect.h"
13 
14 #ifndef ALIGN
15 #define ALIGN __attribute__((__aligned__(__BIGGEST_ALIGNMENT__)))
16 #endif
17 
18 #ifndef NOINLINE
19 #define NOINLINE __attribute__((__noinline__))
20 #endif
21 
22 #ifdef TRACE
23 #define TRACE_FUNC(PREFIX, NAME) printf (#PREFIX #NAME "\n")
24 #define TRACE_DONE()  printf ("done!\n")
25 #define TRACE_ABORT(I,E,G)						\
26 do {									\
27   printf ("Element %d, expected 0x%lx, got 0x%lx\n",			\
28 	  I, (long)(E), (long)(G));					\
29   abort ();								\
30 } while (0)
31 
32 #else
33 #define TRACE_FUNC(PREFIX, A)
34 #define TRACE_DONE()
35 #define TRACE_ABORT(I,E,G) abort ()
36 #endif
37 
38 #define NAME(A,B) A ## B
39 
40 #define VECT_TESTS(PREFIX, TYPE, N)					\
41  /* Restrict the optimizer from optimizing the setup loops.  */		\
42 volatile TYPE NAME (PREFIX, zero) = 0;					\
43 									\
44 TYPE NAME (PREFIX, a)[N] ALIGN;						\
45 TYPE NAME (PREFIX, b)[N] ALIGN;						\
46 TYPE NAME (PREFIX, c)[N] ALIGN;						\
47 TYPE NAME (PREFIX, d)[N] ALIGN;						\
48 									\
49 static void NOINLINE							\
50 NAME (PREFIX, lshift_2) (void)						\
51 {									\
52   int i;								\
53 									\
54   TRACE_FUNC (PREFIX, lshift_2);					\
55   for (i = 0; i < N; i++)						\
56     NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] << 2;			\
57 }									\
58 									\
59 static void NOINLINE							\
60 NAME (PREFIX, lshift_var) (int shift)					\
61 {									\
62   int i;								\
63 									\
64   TRACE_FUNC (PREFIX, lshift_var);					\
65   for (i = 0; i < N; i++)						\
66     NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] << shift;			\
67 }									\
68 									\
69 static void NOINLINE							\
70 NAME (PREFIX, lshift_vect) (void)					\
71 {									\
72   int i;								\
73 									\
74   TRACE_FUNC (PREFIX, lshift_vect);					\
75   for (i = 0; i < N; i++)						\
76     NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] << NAME (PREFIX, c)[i];	\
77 }									\
78 									\
79 static void NOINLINE							\
80 NAME (PREFIX, rshift_2) (void)						\
81 {									\
82   int i;								\
83 									\
84   TRACE_FUNC (PREFIX, rshift_2);					\
85   for (i = 0; i < N; i++)						\
86     NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] >> 2;			\
87 }									\
88 									\
89 static void NOINLINE							\
90 NAME (PREFIX, rshift_var) (int shift)					\
91 {									\
92   int i;								\
93 									\
94   TRACE_FUNC (PREFIX, rshift_var);					\
95   for (i = 0; i < N; i++)						\
96     NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] >> shift;			\
97 }									\
98 									\
99 static void NOINLINE							\
100 NAME (PREFIX, rshift_vect) (void)					\
101 {									\
102   int i;								\
103 									\
104   TRACE_FUNC (PREFIX, rshift_vect);					\
105   for (i = 0; i < N; i++)						\
106     NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] >> NAME (PREFIX, c)[i];	\
107 }									\
108 									\
109 static void NOINLINE							\
110 NAME (PREFIX, check) (void)						\
111 {									\
112   int i;								\
113 									\
114   TRACE_FUNC (PREFIX, check);						\
115   for (i = 0; i < N; i++)						\
116     if (NAME (PREFIX, a)[i] != NAME (PREFIX, d)[i])			\
117       TRACE_ABORT (i, NAME (PREFIX, d)[i], NAME (PREFIX, a)[i]);	\
118 }									\
119 									\
120 static void NOINLINE							\
121 NAME (PREFIX, tests) (void)						\
122 {									\
123   int i;								\
124 									\
125   TRACE_FUNC (PREFIX, tests);						\
126   for (i = 0; i < N; i++)						\
127     {									\
128       NAME (PREFIX, b)[i] = (i + NAME (PREFIX, zero));			\
129       NAME (PREFIX, c)[i] = 2;						\
130       NAME (PREFIX, d)[i] = (i + NAME (PREFIX, zero)) << 2;		\
131     }									\
132 									\
133   NAME (PREFIX, lshift_2) ();						\
134   NAME (PREFIX, check) ();						\
135 									\
136   NAME (PREFIX, lshift_var) (2);					\
137   NAME (PREFIX, check) ();						\
138 									\
139   NAME (PREFIX, lshift_vect) ();					\
140   NAME (PREFIX, check) ();						\
141 									\
142   for (i = 0; i < N; i++)						\
143     {									\
144       NAME (PREFIX, b)[i] = ((i + NAME (PREFIX, zero)) << 4)		\
145 	| (((TYPE)0x80) << ((sizeof (TYPE) * 8) - 8));			\
146       NAME (PREFIX, c)[i] = 2;						\
147       NAME (PREFIX, d)[i] = (TYPE)((NAME (PREFIX, b)[i]			\
148 				    + NAME (PREFIX, zero)) >> 2);	\
149     }									\
150 									\
151   NAME (PREFIX, rshift_2) ();						\
152   NAME (PREFIX, check) ();						\
153 									\
154   NAME (PREFIX, rshift_var) (2);					\
155   NAME (PREFIX, check) ();						\
156 									\
157   NAME (PREFIX, rshift_vect) ();					\
158   NAME (PREFIX, check) ();						\
159 }
160 
161 VECT_TESTS(uc_, unsigned char,  16)
162 VECT_TESTS(us_, unsigned short, 32)
163 VECT_TESTS(ui_, unsigned int,   32)
164 VECT_TESTS(ul_, unsigned long,  32)
165 
166 VECT_TESTS(sc_, signed char,    16)
167 VECT_TESTS(ss_, short,          32)
168 VECT_TESTS(si_, int,            32)
169 VECT_TESTS(sl_, long,           32)
170 
main()171 int main ()
172 {
173   int i;
174 
175   check_vect ();
176 
177   uc_tests ();
178   us_tests ();
179   ui_tests ();
180   ul_tests ();
181 
182   sc_tests ();
183   ss_tests ();
184   si_tests ();
185   sl_tests ();
186 
187   TRACE_DONE ();
188   return 0;
189 }
190 
191