1 // Test sequences that can use RISBG with a normal first operand.
2 
3 /* Tests ported from the Llvm testsuite. */
4 
5 /* { dg-do compile { target s390x-*-* } } */
6 /* { dg-options "-O3 -march=z10 -mzarch -fno-asynchronous-unwind-tables" }  */
7 
8 #define i64 signed long long
9 #define ui64 unsigned long long
10 #define i32 signed int
11 #define ui32 unsigned int
12 
13 // Test a case with two ANDs.
f1(i32 v_a,i32 v_b)14 i32 f1 (i32 v_a, i32 v_b)
15 {
16   /* { dg-final { scan-assembler "f1:\n\trisbg\t%r2,%r3,60,62,0" } } */
17   i32 v_anda = v_a & -15;
18   i32 v_andb = v_b & 14;
19   i32 v_or = v_anda | v_andb;
20   return v_or;
21 }
22 
23 // ...and again with i64.
f2(i64 v_a,i64 v_b)24 i64 f2 (i64 v_a, i64 v_b)
25 {
26   /* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r3,60,62,0" { target { lp64 } } } } */
27   /* { dg-final { scan-assembler "f2:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\(\t.*\n\)*\trisbg\t%r\[23\],%r5,60,62,0" { target { ! lp64 } } } } */
28   i64 v_anda = v_a & -15;
29   i64 v_andb = v_b & 14;
30   i64 v_or = v_anda | v_andb;
31   return v_or;
32 }
33 
34 // Test a case with two ANDs and a shift.
f3(i32 v_a,i32 v_b)35 i32 f3 (i32 v_a, i32 v_b)
36 {
37   /* { dg-final { scan-assembler "f3:\n\trisbg\t%r2,%r3,64-4,63,\\(64-32\\)\\+4\\+20\n\tlgfr\t%r2,%r2" } } */
38   i32 v_anda = v_a & -16;
39   i32 v_shr = ((ui32)v_b) >> 8;
40   i32 v_andb = v_shr & 15;
41   i32 v_or = v_anda | v_andb;
42   return v_or;
43 }
44 
45 // ...and again with i64.
f4(i64 v_a,i64 v_b)46 i64 f4 (i64 v_a, i64 v_b)
47 {
48   /* { dg-final { scan-assembler "f4:\n\trisbg\t%r2,%r3,64-4,63,\\(64-64\\)\\+4\\+52" { target { lp64 } } } } */
49   /* { dg-final { scan-assembler "f4:\n\(\t.*\n\)*\trisbg\t%r5,%r5,64-4,128\\+63,\\(64-64\\)\\+52\\+4" { target { ! lp64 } } } } */
50   i64 v_anda = v_a & -16;
51   i64 v_shr = ((ui64)v_b) >> 8;
52   i64 v_andb = v_shr & 15;
53   i64 v_or = v_anda | v_andb;
54   return v_or;
55 }
56 
57 // Test a case with a single AND and a left shift.
f5(i32 v_a,i32 v_b)58 i32 f5 (i32 v_a, i32 v_b)
59 {
60   /* { dg-final { scan-assembler "f5:\n\trisbg\t%r2,%r3,32,64-10-1,10" } } */
61   i32 v_anda = v_a & 1023;
62   i32 v_shlb = v_b << 10;
63   i32 v_or = v_anda | v_shlb;
64   return v_or;
65 }
66 
67 // ...and again with i64.
f6(i64 v_a,i64 v_b)68 i64 f6 (i64 v_a, i64 v_b)
69 {
70   /* { dg-final { scan-assembler "f6:\n\trisbg\t%r2,%r3,0,64-10-1,10" { target { lp64 } } } } */
71   /* { dg-final { scan-assembler "f6:\n\trisbg\t%r5,%r4,0,0\\\+32-1,64-0-32\n\(\t.*\n\)*\trisbg\t%r\[23\],%r5,0,64-10-1,10" { target { ! lp64 } } } } */
72   i64 v_anda = v_a & 1023;
73   i64 v_shlb = v_b << 10;
74   i64 v_or = v_anda | v_shlb;
75   return v_or;
76 }
77 
78 // Test a case with a single AND and a right shift.
f7(i32 v_a,i32 v_b)79 i32 f7 (i32 v_a, i32 v_b)
80 {
81   /* { dg-final { scan-assembler "f7:\n\trisbg\t%r2,%r3,32\\\+8,63,64-8" } } */
82   i32 v_anda = v_a & -16777216;
83   i32 v_shrb = ((ui32)v_b) >> 8;
84   i32 v_or = v_anda | v_shrb;
85   return v_or;
86 }
87 
88 // ...and again with i64.
f8(i64 v_a,i64 v_b)89 i64 f8 (i64 v_a, i64 v_b)
90 {
91   /* { dg-final { scan-assembler "f8:\n\trisbg\t%r2,%r3,8,63,64-8" { target { lp64 } } } } */
92   /* With -m31 risbg is not really useful here, so do not test for it.  */
93   i64 v_anda = v_a & -72057594037927936;
94   i64 v_shrb = ((ui64)v_b) >> 8;
95   i64 v_or = v_anda | v_shrb;
96   return v_or;
97 }
98 
99 // Check that we can get the case where a 64-bit shift feeds a 32-bit or of
100 // ands with complement masks.
f9(i64 v_x,i32 v_y)101 i32 f9 (i64 v_x, i32 v_y)
102 {
103   /* { dg-final { scan-assembler "f9:\n\trisbg\t%r3,%r2,48,63,64-48" { target { lp64 } }} } */
104   /* { dg-final { scan-assembler "f9:\n\trisbg\t%r4,%r2,32\\+16,63,64-16" { target { ! lp64 } }} } */
105   i64 v_shr6 = ((ui64)v_x) >> 48;
106   i32 v_conv = (ui32)v_shr6;
107   i32 v_and1 = v_y & -65536;
108   i32 v_or = v_conv | v_and1;
109   return v_or;
110 }
111 
112 // Check that we don't get the case where a 64-bit shift feeds a 32-bit or of
113 // ands with incompatible masks.
f10(i64 v_x,i32 v_y)114 i32 f10 (i64 v_x, i32 v_y)
115 {
116   /* { dg-final { scan-assembler "f10:\n\tsrlg\t%r2,%r2,48\n\trosbg\t%r2,%r3,32,39,0" { target { lp64 } } } } */
117   /* { dg-final { scan-assembler "f10:\n\tnilf\t%r4,4278190080\n\trosbg\t%r4,%r2,48,63,48" { target { ! lp64 } } } } */
118   i64 v_shr6 = ((ui64)v_x) >> 48;
119   i32 v_conv = (ui32)v_shr6;
120   i32 v_and1 = v_y & -16777216;
121   i32 v_or = v_conv | v_and1;
122   return v_or;
123 }
124