1 // Test sequences that can use RISBG with a zeroed first operand.
2 // The tests here assume that RISBLG isn't available.
3 
4 /* Tests ported from the Llvm testsuite. */
5 
6 /* { dg-do compile { target s390x-*-* } } */
7 /* { dg-options "-O3 -march=z10 -mzarch -fno-asynchronous-unwind-tables" } */
8 
9 #define i64 signed long long
10 #define ui64 unsigned long long
11 #define i32 signed int
12 #define ui32 unsigned int
13 #define i8 signed char
14 #define ui8 unsigned char
15 
16 // Test an extraction of bit 0 from a right-shifted value.
f1(i32 v_foo)17 i32 f1 (i32 v_foo)
18 {
19   /* { dg-final { scan-assembler "f1:\n\trisbg\t%r2,%r2,64-1,128\\\+63,53\\\+1" } } */
20   i32 v_shr = ((ui32)v_foo) >> 10;
21   i32 v_and = v_shr & 1;
22   return v_and;
23 }
24 
25 // ...and again with i64.
f2(i64 v_foo)26 i64 f2 (i64 v_foo)
27 {
28   /* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r2,64-1,128\\\+63,53\\\+1" { target { lp64 } } } } */
29   /* { dg-final { scan-assembler "f2:\n\trisbg\t%r3,%r3,64-1,128\\\+63,53\\\+1\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
30   i64 v_shr = ((ui64)v_foo) >> 10;
31   i64 v_and = v_shr & 1;
32   return v_and;
33 }
34 
35 // Test an extraction of other bits from a right-shifted value.
f3(i32 v_foo)36 i32 f3 (i32 v_foo)
37 {
38   /* { dg-final { scan-assembler "f3:\n\trisbg\t%r2,%r2,60,128\\\+61,64-22" } } */
39   i32 v_shr = ((ui32)v_foo) >> 22;
40   i32 v_and = v_shr & 12;
41   return v_and;
42 }
43 
44 // ...and again with i64.
f4(i64 v_foo)45 i64 f4 (i64 v_foo)
46 {
47   /* { dg-final { scan-assembler "f4:\n\trisbg\t%r2,%r2,60,128\\\+61,64-22" { target { lp64 } } } } */
48   /* { dg-final { scan-assembler "f4:\n\trisbg\t%r3,%r3,60,128\\\+61,64-22\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
49   i64 v_shr = ((ui64)v_foo) >> 22;
50   i64 v_and = v_shr & 12;
51   return v_and;
52 }
53 
54 // Test an extraction of most bits from a right-shifted value.
55 // The range should be reduced to exclude the zeroed high bits.
f5(i32 v_foo)56 i32 f5 (i32 v_foo)
57 {
58   /* { dg-final { scan-assembler "f5:\n\trisbg\t%r2,%r2,34,128\\\+60,64-2" } } */
59   i32 v_shr = ((ui32)v_foo) >> 2;
60   i32 v_and = v_shr & -8;
61   return v_and;
62 }
63 
64 // ...and again with i64.
f6(i64 v_foo)65 i64 f6 (i64 v_foo)
66 {
67   /* { dg-final { scan-assembler "f6:\n\trisbg\t%r2,%r2,2,128\\\+60,64-2" { target { lp64 } } } } */
68   /* { dg-final { scan-assembler "f6:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r2,%r3,2,128\\\+60,64-2" { target { ! lp64 } } } } */
69   i64 v_shr = ((ui64)v_foo) >> 2;
70   i64 v_and = v_shr & -8;
71   return v_and;
72 }
73 
74 // Try the next value up (mask ....1111001).  This needs a separate shift
75 // and mask.
f7(i32 v_foo)76 i32 f7 (i32 v_foo)
77 {
78   /* Should be
79      { dg-final { scan-assembler "f7:\n\tsrl\t%r2,2\n\tnill\t%r2,65529" { xfail { lp64 } } } }
80      but because a zeroextend is merged into the pattern it is actually
81      { dg-final { scan-assembler "f7:\n\tsrl\t%r2,2\n\tlgfi\t%r1,1073741817\n\tngr\t%r2,%r1" { target { lp64 } } } }
82      { dg-final { scan-assembler "f7:\n\tsrl\t%r2,2\n\tnill\t%r2,65529" { target { ! lp64 } } } } */
83   i32 v_shr = ((ui32)v_foo) >> 2;
84   i32 v_and = v_shr & -7;
85   return v_and;
86 }
87 
88 // ...and again with i64.
f8(i64 v_foo)89 i64 f8 (i64 v_foo)
90 {
91   /* { dg-final { scan-assembler "f8:\n\tsrlg\t%r2,%r2,2\n\tnill\t%r2,65529" { target { lp64 } } } } */
92   /* { dg-final { scan-assembler "f8:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsrlg\t%r2,%r3,2\n\tnill\t%r2,65529" { target { ! lp64 } } } } */
93   i64 v_shr = ((ui64)v_foo) >> 2;
94   i64 v_and = v_shr & -7;
95   return v_and;
96 }
97 
98 // Test an extraction of bits from a left-shifted value.  The range should
99 // be reduced to exclude the zeroed low bits.
f9(i32 v_foo)100 i32 f9 (i32 v_foo)
101 {
102   /* { dg-final { scan-assembler "f9:\n\trisbg\t%r2,%r2,56,128\\\+61,2" } } */
103   i32 v_shr = v_foo << 2;
104   i32 v_and = v_shr & 255;
105   return v_and;
106 }
107 
108 // ...and again with i64.
f10(i64 v_foo)109 i64 f10 (i64 v_foo)
110 {
111   /* { dg-final { scan-assembler "f10:\n\trisbg\t%r2,%r2,56,128\\\+61,2" { target { lp64 } } } } */
112   /* { dg-final { scan-assembler "f10:\n\trisbg\t%r3,%r3,56,128\\\+61,2\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
113   i64 v_shr = v_foo << 2;
114   i64 v_and = v_shr & 255;
115   return v_and;
116 }
117 
118 // Try a wrap-around mask (mask ....111100001111).  This needs a separate shift
119 // and mask.
f11(i32 v_foo)120 i32 f11 (i32 v_foo)
121 {
122   /* { dg-final { scan-assembler "f11:\n\tsll\t%r2,2\n\tnill\t%r2,65295" } } */
123   i32 v_shr = v_foo << 2;
124   i32 v_and = v_shr & -241;
125   return v_and;
126 }
127 
128 // ...and again with i64.
f12(i64 v_foo)129 i64 f12 (i64 v_foo)
130 {
131   /* { dg-final { scan-assembler "f12:\n\tsllg\t%r2,%r2,2\n\tnill\t%r2,65295" { target { lp64 } } } } */
132   /* { dg-final { scan-assembler "f12:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsllg\t%r2,%r3,2\n\tnill\t%r2,65295" { target { ! lp64 } } } } */
133   i64 v_shr = v_foo << 2;
134   i64 v_and = v_shr & -241;
135   return v_and;
136 }
137 
138 // Test an extraction from a rotated value, no mask wraparound.
139 // This is equivalent to the lshr case, because the bits from the
140 // shl are not used.
f13(i32 v_foo)141 i32 f13 (i32 v_foo)
142 {
143   /* { dg-final { scan-assembler "f13:\n\trisbg\t%r2,%r2,56,128\\\+60,32\\\+14" { target { lp64 } } } } */
144   /* { dg-final { scan-assembler "f13:\n\trll\t%r2,%r2,14\n\tnilf\t%r2,248" { target { ! lp64 } } } } */
145   i32 v_parta = v_foo << 14;
146   i32 v_partb = ((ui32)v_foo) >> 18;
147   i32 v_rotl = v_parta | v_partb;
148   i32 v_and = v_rotl & 248;
149   return v_and;
150 }
151 
152 // ...and again with i64.
f14(i64 v_foo)153 i64 f14 (i64 v_foo)
154 {
155   /* { dg-final { scan-assembler "f14:\n\trisbg\t%r2,%r2,56,128\\\+60,14" { target { lp64 } } } } */
156   /* { dg-final { scan-assembler "f14:\n\trisbg\t%r3,%r2,56,128\\\+60,46\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
157   i64 v_parta = v_foo << 14;
158   i64 v_partb = ((ui64)v_foo) >> 50;
159   i64 v_rotl = v_parta | v_partb;
160   i64 v_and = v_rotl & 248;
161   return v_and;
162 }
163 
164 // Try a case in which only the bits from the shl are used.
f15(i32 v_foo)165 i32 f15 (i32 v_foo)
166 {
167   /* { dg-final { scan-assembler "f15:\n\trisbg\t%r2,%r2,47,128\\\+49,14" { target { lp64 } } } } */
168   /* { dg-final { scan-assembler "f15:\n\trll\t%r2,%r2,14\n\tnilf\t%r2,114688" { target { ! lp64 } } } } */
169   i32 v_parta = v_foo << 14;
170   i32 v_partb = ((ui32)v_foo) >> 18;
171   i32 v_rotl = v_parta | v_partb;
172   i32 v_and = v_rotl & 114688;
173   return v_and;
174 }
175 
176 // ...and again with i64.
f16(i64 v_foo)177 i64 f16 (i64 v_foo)
178 {
179   /* { dg-final { scan-assembler "f16:\n\trisbg\t%r2,%r2,47,128\\\+49,14" { target { lp64 } } } } */
180   /* { dg-final { scan-assembler "f16:\n\trisbg\t%r3,%r3,47,128\\\+49,14\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
181   i64 v_parta = v_foo << 14;
182   i64 v_partb = ((ui64)v_foo) >> 50;
183   i64 v_rotl = v_parta | v_partb;
184   i64 v_and = v_rotl & 114688;
185   return v_and;
186 }
187 
188 // Test a 32-bit rotate in which both parts of the OR are needed.
189 // This needs a separate shift and mask.
f17(i32 v_foo)190 i32 f17 (i32 v_foo)
191 {
192   /* Should be
193      { dg-final { scan-assembler "f17:\n\trll\t%r2,%r2,4\n\tnilf\t%r2,126" { xfail { lp64 } } } }
194      but because a zeroextend is merged into the pattern it is actually
195      { dg-final { scan-assembler "f17:\n\trll\t%r2,%r2,4\n\trisbg\t%r2,%r2,57,128\\\+62,0" { target { lp64 } } } }
196      { dg-final { scan-assembler "f17:\n\trll\t%r2,%r2,4\n\tnilf\t%r2,126" { target { ! lp64 } } } } */
197   i32 v_parta = v_foo << 4;
198   i32 v_partb = ((ui32)v_foo) >> 28;
199   i32 v_rotl = v_parta | v_partb;
200   i32 v_and = v_rotl & 126;
201   return v_and;
202 }
203 
204 // ...and for i64, where RISBG should do the rotate too.
f18(i64 v_foo)205 i64 f18 (i64 v_foo)
206 {
207   /* { dg-final { scan-assembler "f18:\n\trisbg\t%r2,%r2,57,128\\\+62,4" { target { lp64 } } } } */
208   /* { dg-final { scan-assembler "f18:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\trisbg\t%r3,%r3,57,128\\\+62,4" { target { ! lp64 } } } } */
209   i64 v_parta = v_foo << 4;
210   i64 v_partb = ((ui64)v_foo) >> 60;
211   i64 v_rotl = v_parta | v_partb;
212   i64 v_and = v_rotl & 126;
213   return v_and;
214 }
215 
216 // Test an arithmetic shift right in which some of the sign bits are kept.
217 // This needs a separate shift and mask on 31 bit.
f19(i32 v_foo)218 i32 f19 (i32 v_foo)
219 {
220   /* { dg-final { scan-assembler "f19:\n\trisbg\t%r2,%r2,59,128\\+62,64-28" { target { lp64 } } } } */
221   /* { dg-final { scan-assembler "f19:\n\tsra\t%r2,28\n\tnilf\t%r2,30" { target { ! lp64 } } } } */
222   i32 v_shr = v_foo >> 28;
223   i32 v_and = v_shr & 30;
224   return v_and;
225 }
226 
227 // ...and again with i64.  In this case RISBG is the best way of doing the AND.
f20(i64 v_foo)228 i64 f20 (i64 v_foo)
229 {
230   /* { dg-final { scan-assembler "f20:\n\tsrag\t%r2,%r2,60\n\trisbg\t%r2,%r2,59,128\\\+62,0" { target { lp64 } } } } */
231   /* { dg-final { scan-assembler "f20:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,60\n\tnilf\t%r3,30" { target { ! lp64 } } } } */
232   i64 v_shr = v_foo >> 60;
233   i64 v_and = v_shr & 30;
234   return v_and;
235 }
236 
237 // Now try an arithmetic right shift in which the sign bits aren't needed.
238 // Note: Unlike Llvm, Gcc replaces the ashrt with a lshrt in any case, using
239 // a risbg pattern without ashrt.
f21(i32 v_foo)240 i32 f21 (i32 v_foo)
241 {
242   /* { dg-final { scan-assembler "f21:\n\trisbg\t%r2,%r2,60,128\\\+62,64-28" } } */
243   i32 v_shr = v_foo >> 28;
244   i32 v_and = v_shr & 14;
245   return v_and;
246 }
247 
248 // ...and again with i64.
f22(i64 v_foo)249 i64 f22 (i64 v_foo)
250 {
251   /* { dg-final { scan-assembler "f22:\n\trisbg\t%r2,%r2,60,128\\\+62,64-60" { target { lp64 } } } } */
252   /* { dg-final { scan-assembler "f22:\n\trisbg\t%r3,%r2,60,128\\\+62,64-28\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
253   i64 v_shr = v_foo >> 60;
254   i64 v_and = v_shr & 14;
255   return v_and;
256 }
257 
258 // Check that we use RISBG for shifted values even if the AND is a
259 // natural zero extension.
f23(i64 v_foo)260 i64 f23 (i64 v_foo)
261 {
262   /* { dg-final { scan-assembler "f23:\n\trisbg\t%r2,%r2,64-8,128\\\+63,54\\\+8" { target { lp64 } } } } */
263   /* { dg-final { scan-assembler "f23:\n\trisbg\t%r3,%r3,64-8,128\\\+63,54\\\+8\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
264   i64 v_shr = ((ui64)v_foo) >> 2;
265   i64 v_and = v_shr & 255;
266   return v_and;
267 }
268 
269 // Test a case where the AND comes before a rotate.  This needs a separate
270 // mask and rotate.
f24(i32 v_foo)271 i32 f24 (i32 v_foo)
272 {
273   /* { dg-final { scan-assembler "f24:\n\tnilf\t%r2,254\n\trll\t%r2,%r2,29\n" } } */
274   i32 v_and = v_foo & 254;
275   i32 v_parta = ((ui32)v_and) >> 3;
276   i32 v_partb = v_and << 29;
277   i32 v_rotl = v_parta | v_partb;
278   return v_rotl;
279 }
280 
281 // ...and again with i64, where a single RISBG is enough.
f25(i64 v_foo)282 i64 f25 (i64 v_foo)
283 {
284   /* { dg-final { scan-assembler "f25:\n\trisbg\t%r2,%r2,57,128\\\+59,3" { target { lp64 } } } } */
285   /* { dg-final { scan-assembler "f25:\n\trisbg\t%r3,%r3,57,128\\\+59,3\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
286   i64 v_and = v_foo & 14;
287   i64 v_parta = v_and << 3;
288   i64 v_partb = ((ui64)v_and) >> 61;
289   i64 v_rotl = v_parta | v_partb;
290   return v_rotl;
291 }
292 
293 // Test a wrap-around case in which the AND comes before a rotate.
294 // This again needs a separate mask and rotate.
f26(i32 v_foo)295 i32 f26 (i32 v_foo)
296 {
297   /* { dg-final { scan-assembler "f26:\n\tnill\t%r2,65487\n\trll\t%r2,%r2,5" } } */
298   i32 v_and = v_foo & -49;
299   i32 v_parta = v_and << 5;
300   i32 v_partb = ((ui32)v_and) >> 27;
301   i32 v_rotl = v_parta | v_partb;
302   return v_rotl;
303 }
304 
305 // ...and again with i64, where a single RISBG is OK.
f27(i64 v_foo)306 i64 f27 (i64 v_foo)
307 {
308   /* { dg-final { scan-assembler "f27:\n\trisbg\t%r2,%r2,55,128\\\+52,5" { target { lp64 } } } } */
309   /* { dg-final { scan-assembler "f27:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r2,%r3,55,128\\\+52,5" { target { ! lp64 } } } } */
310   i64 v_and = v_foo & -49;
311   i64 v_parta = v_and << 5;
312   i64 v_partb = ((ui64)v_and) >> 59;
313   i64 v_rotl = v_parta | v_partb;
314   return v_rotl;
315 }
316 
317 // Test a case where the AND comes before a shift left.
f28(i32 v_foo)318 i32 f28 (i32 v_foo)
319 {
320   /* { dg-final { scan-assembler "f28:\n\trisbg\t%r2,%r2,32,128\\\+45,17" } } */
321   i32 v_and = v_foo & 32766;
322   i32 v_shl = v_and << 17;
323   return v_shl;
324 }
325 
326 // ...and again with i64.
f29(i64 v_foo)327 i64 f29 (i64 v_foo)
328 {
329   /* { dg-final { scan-assembler "f29:\n\trisbg\t%r2,%r2,0,128\\\+13,49" { target { lp64 } } } } */
330   /* { dg-final { scan-assembler "f29:\n\trisbg\t%r\[23\],%r3,0,128\\\+13,49\n\tlr\t%r\[23\],%r\[32\]\n\tsrlg\t%r2,%r2" { target { ! lp64 } } } } */
331   i64 v_and = v_foo & 32766;
332   i64 v_shl = v_and << 49;
333   return v_shl;
334 }
335 
336 // Test the next shift up from f28, in which the mask should get shortened.
f30(i32 v_foo)337 i32 f30 (i32 v_foo)
338 {
339   /* { dg-final { scan-assembler "f30:\n\trisbg\t%r2,%r2,32,128\\\+44,18" } } */
340   i32 v_and = v_foo & 32766;
341   i32 v_shl = v_and << 18;
342   return v_shl;
343 }
344 
345 // ...and again with i64.
f31(i64 v_foo)346 i64 f31 (i64 v_foo)
347 {
348   /* { dg-final { scan-assembler "f31:\n\trisbg\t%r2,%r2,0,128\\\+12,50" { target { lp64 } } } } */
349   /* { dg-final { scan-assembler "f31:\n\trisbg\t%r\[23\],%r3,0,128\\\+12,50\n\tlr\t%r\[23\],%r\[32\]\n\tsrlg\t%r2,%r2" { target { ! lp64 } } } } */
350   i64 v_and = v_foo & 32766;
351   i64 v_shl = v_and << 50;
352   return v_shl;
353 }
354 
355 // Test a wrap-around case in which the shift left comes after the AND.
356 // We can't use RISBG for the shift in that case.
f32(i32 v_foo)357 i32 f32 (i32 v_foo)
358 {
359   /* { dg-final { scan-assembler "f32:\n\tsll\t%r2,10\n\tnill\t%r2,58368" } } */
360   i32 v_and = v_foo & -7;
361   i32 v_shl = v_and << 10;
362   return v_shl;
363 }
364 
365 // ...and again with i64.
f33(i64 v_foo)366 i64 f33 (i64 v_foo)
367 {
368   /* { dg-final { scan-assembler "f33:\n\tsllg\t%r2,%r2,10\n\tnill\t%r2,58368" { target { lp64 } } } } */
369   /* { dg-final { scan-assembler "f33:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsllg\t%r2,%r3,10\n\tnill\t%r2,58368" { target { ! lp64 } } } } */
370   i64 v_and = v_foo & -7;
371   i64 v_shl = v_and << 10;
372   return v_shl;
373 }
374 
375 // Test a case where the AND comes before a shift right.
f34(i32 v_foo)376 i32 f34 (i32 v_foo)
377 {
378   /* { dg-final { scan-assembler "f34:\n\trisbg\t%r2,%r2,64-7,128\\\+63,48\\\+7" } } */
379   i32 v_and = v_foo & 65535;
380   i32 v_shl = ((ui32)v_and) >> 9;
381   return v_shl;
382 }
383 
384 // ...and again with i64.
f35(i64 v_foo)385 i64 f35 (i64 v_foo)
386 {
387   /* { dg-final { scan-assembler "f35:\n\trisbg\t%r2,%r2,64-7,128\\\+63,48\\\+7" { target { lp64 } } } } */
388   /* { dg-final { scan-assembler "f35:\n\trisbg\t%r3,%r3,64-7,128\\\+63,48\\\+7\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
389   i64 v_and = v_foo & 65535;
390   i64 v_shl = ((ui64)v_and) >> 9;
391   return v_shl;
392 }
393 
394 // Test a wrap-around case where the AND comes before a shift right.
395 // We can't use RISBG for the shift in that case.
f36(i32 v_foo)396 i32 f36 (i32 v_foo)
397 {
398   /* { dg-final { scan-assembler "f36:\n\tsrl\t%r2,1\n\tlgfi\t%r1,2147483635\n\tngr\t%r2,%r1" { target { lp64 } } } } */
399   /* { dg-final { scan-assembler "f36:\n\tsrl\t%r2,1\n\tnilf\t%r2,2147483635" { target { ! lp64 } } } } */
400   i32 v_and = v_foo & -25;
401   i32 v_shl = ((ui32)v_and) >> 1;
402   return v_shl;
403 }
404 
405 // ...and again with i64.
f37(i64 v_foo)406 i64 f37 (i64 v_foo)
407 {
408   /* { dg-final { scan-assembler "f37:\n\(\t.*\n\)*\tsrlg\t%r2,%r2,1\n\tng\t%r2," { target { lp64 } } } } */
409   /* { dg-final { scan-assembler "f37:\n\(\t.*\n\)*\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsrlg\t%r2,%r3,1\n\tng\t%r2," { target { ! lp64 } } } } */
410   i64 v_and = v_foo & -25;
411   i64 v_shl = ((ui64)v_and) >> 1;
412   return v_shl;
413 }
414 
415 // Test a combination involving a large ASHR and a shift left.  We can't
416 // use RISBG there.
f38(i64 v_foo)417 i64 f38 (i64 v_foo)
418 {
419   /* { dg-final { scan-assembler "f38:\n\tsrag\t%r2,%r2,32\n\tsllg\t%r2,%r2,5" { target { lp64 } } } } */
420   /* { dg-final { scan-assembler "f38:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsrag\t%r2,%r3,32\n\tsllg\t%r2,%r2,5" { target { ! lp64 } } } } */
421   i64 v_ashr = v_foo >> 32;
422   i64 v_shl = v_ashr << 5;
423   return v_shl;
424 }
425 
426 // Try a similar thing in which no shifted sign bits are kept.
f39(i64 v_foo,i64 * v_dest)427 i64 f39 (i64 v_foo, i64 *v_dest)
428 {
429   /* { dg-final { scan-assembler "f39:\n\tsrag\t%r2,%r2,35\n\(\t.*\n\)*\trisbg\t%r2,%r2,33,128\\\+61,2" { target { lp64 } } } } */
430   /* { dg-final { scan-assembler "f39:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,35\n\(\t.*\n\)*\trisbg\t%r3,%r3,33,128\\\+61,2" { target { ! lp64 } } } } */
431   i64 v_ashr = v_foo >> 35;
432   *v_dest = v_ashr;
433   i64 v_shl = v_ashr << 2;
434   i64 v_and = v_shl & 2147483647;
435   return v_and;
436 }
437 
438 // ...and again with the next highest shift value, where one sign bit is kept.
f40(i64 v_foo,i64 * v_dest)439 i64 f40 (i64 v_foo, i64 *v_dest)
440 {
441   /* { dg-final { scan-assembler "f40:\n\tsrag\t%r2,%r2,36\n\(\t.*\n\)*\trisbg\t%r2,%r2,33,128\\\+61,2" { target { lp64 } } } } */
442   /* { dg-final { scan-assembler "f40:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,36\n\(\t.*\n\)*\trisbg\t%r3,%r3,33,128\\\+61,2" { target { ! lp64 } } } } */
443   i64 v_ashr = v_foo >> 36;
444   *v_dest = v_ashr;
445   i64 v_shl = v_ashr << 2;
446   i64 v_and = v_shl & 2147483647;
447   return v_and;
448 }
449 
450 // Check a case where the result is zero-extended.
f41(i32 v_a)451 i64 f41 (i32 v_a)
452 {
453   /* { dg-final { scan-assembler "f41:\n\trisbg\t%r2,%r2,64-28,128\\\+63,34\\\+28" { target { lp64 } } } } */
454   /* { dg-final { scan-assembler "f41:\n\trisbg\t%r3,%r2,64-28,128\\\+63,34\\\+28\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
455   i32 v_shl = v_a << 2;
456   i32 v_shr = ((ui32)v_shl) >> 4;
457   i64 v_ext = (ui64)v_shr;
458   return v_ext;
459 }
460 
461 // In this case the sign extension is converted to a pair of 32-bit shifts,
462 // which is then extended to 64 bits.  We previously used the wrong bit size
463 // when testing whether the shifted-in bits of the shift right were significant.
464 typedef struct { ui64 pad : 63; ui8 a : 1; } t42;
f42(t42 v_x)465 i64 f42 (t42 v_x)
466 {
467   /* { dg-final { scan-assembler "f42:\n\tsllg\t%r2,%r2,63\n\tsrag\t%r2,%r2,63\n\tllgcr\t%r2,%r2" { target { lp64 } } } } */
468   /* { dg-final { scan-assembler "f42:\n\tsllg\t%r3,%r3,63\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,63\n\tllcr\t%r3,%r3" { target { ! lp64 } } } } */
469   ui8 a = v_x.a << 7;
470   i8 ext = ((i8)a) >> 7;
471   i64 ext2 = (ui64)(ui8)ext;
472   return ext2;
473 }
474 
475 // Check that we get the case where a 64-bit shift is used by a 32-bit and.
f43(i64 v_x)476 i32 f43 (i64 v_x)
477 {
478   /* { dg-final { scan-assembler "f43:\n\trisbg\t%r2,%r2,32,128\\+61,32\\+20\n\tlgfr\t%r2,%r2" { target { lp64 } } } } */
479   /* { dg-final { scan-assembler "f43:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r2,%r3,32,128\\\+61,64-12" { target { ! lp64 } } } } */
480   i64 v_shr3 = ((ui64)v_x) >> 12;
481   i32 v_shr3_tr = (ui32)v_shr3;
482   i32 v_conv = v_shr3_tr & -4;
483   return v_conv;
484 }
485 
486 // Check that we don't get the case where the 32-bit and mask is not contiguous
f44(i64 v_x)487 i32 f44 (i64 v_x)
488 {
489   /* { dg-final { scan-assembler "f44:\n\tsrlg\t%r2,%r2,12" { target { lp64 } } } } */
490   /* { dg-final { scan-assembler "f44:\n\tsrlg\t%r2,%r3,12\n\tnilf\t%r2,10" { target { ! lp64 } } } } */
491   i64 v_shr4 = ((ui64)v_x) >> 12;
492   i32 v_conv = (ui32)v_shr4;
493   i32 v_and = v_conv & 10;
494   return v_and;
495 }
496