1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * Functional tests for SIMD vectorization.
19  */
20 public class SimdChar {
21 
22   static char[] a;
23 
24   //
25   // Arithmetic operations.
26   //
27 
28   /// CHECK-START: void SimdChar.add(int) loop_optimization (before)
29   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
30   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
31   //
32   /// CHECK-START-{ARM,ARM64}: void SimdChar.add(int) loop_optimization (after)
33   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
34   /// CHECK-DAG: VecAdd   loop:<<Loop>>      outer_loop:none
35   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
add(int x)36   static void add(int x) {
37     for (int i = 0; i < 128; i++)
38       a[i] += x;
39   }
40 
41   /// CHECK-START: void SimdChar.sub(int) loop_optimization (before)
42   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
43   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
44   //
45   /// CHECK-START-{ARM,ARM64}: void SimdChar.sub(int) loop_optimization (after)
46   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
47   /// CHECK-DAG: VecSub   loop:<<Loop>>      outer_loop:none
48   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
sub(int x)49   static void sub(int x) {
50     for (int i = 0; i < 128; i++)
51       a[i] -= x;
52   }
53 
54   /// CHECK-START: void SimdChar.mul(int) loop_optimization (before)
55   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
56   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
57   //
58   /// CHECK-START-{ARM,ARM64}: void SimdChar.mul(int) loop_optimization (after)
59   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
60   /// CHECK-DAG: VecMul   loop:<<Loop>>      outer_loop:none
61   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
mul(int x)62   static void mul(int x) {
63     for (int i = 0; i < 128; i++)
64       a[i] *= x;
65   }
66 
67   /// CHECK-START: void SimdChar.div(int) loop_optimization (before)
68   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
69   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
70   //
71   /// CHECK-START: void SimdChar.div(int) loop_optimization (after)
72   /// CHECK-NOT: VecDiv
73   //
74   //  Not supported on any architecture.
75   //
div(int x)76   static void div(int x) {
77     for (int i = 0; i < 128; i++)
78       a[i] /= x;
79   }
80 
81   /// CHECK-START: void SimdChar.neg() loop_optimization (before)
82   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
83   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
84   //
85   /// CHECK-START-{ARM,ARM64}: void SimdChar.neg() loop_optimization (after)
86   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
87   /// CHECK-DAG: VecNeg   loop:<<Loop>>      outer_loop:none
88   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
neg()89   static void neg() {
90     for (int i = 0; i < 128; i++)
91       a[i] = (char) -a[i];
92   }
93 
94   /// CHECK-START: void SimdChar.not() loop_optimization (before)
95   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
96   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
97   //
98   /// CHECK-START-{ARM,ARM64}: void SimdChar.not() loop_optimization (after)
99   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
100   /// CHECK-DAG: VecNot   loop:<<Loop>>      outer_loop:none
101   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
not()102   static void not() {
103     for (int i = 0; i < 128; i++)
104       a[i] = (char) ~a[i];
105   }
106 
107   /// CHECK-START: void SimdChar.shl4() loop_optimization (before)
108   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
109   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
110   //
111   /// CHECK-START-{ARM,ARM64}: void SimdChar.shl4() loop_optimization (after)
112   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
113   /// CHECK-DAG: VecShl   loop:<<Loop>>      outer_loop:none
114   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
shl4()115   static void shl4() {
116     for (int i = 0; i < 128; i++)
117       a[i] <<= 4;
118   }
119 
120   /// CHECK-START: void SimdChar.sar2() loop_optimization (before)
121   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
122   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
123   //
124   // TODO: would need signess flip.
125   /// CHECK-START: void SimdChar.sar2() loop_optimization (after)
126   /// CHECK-NOT: VecShr
sar2()127   static void sar2() {
128     for (int i = 0; i < 128; i++)
129       a[i] >>= 2;
130   }
131 
132   /// CHECK-START: void SimdChar.shr2() loop_optimization (before)
133   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
134   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
135   //
136   /// CHECK-START-{ARM,ARM64}: void SimdChar.shr2() loop_optimization (after)
137   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
138   /// CHECK-DAG: VecUShr  loop:<<Loop>>      outer_loop:none
139   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
shr2()140   static void shr2() {
141     for (int i = 0; i < 128; i++)
142       a[i] >>>= 2;
143   }
144 
145   //
146   // Shift sanity.
147   //
148 
sar31()149   static void sar31() {
150     for (int i = 0; i < 128; i++)
151       a[i] >>= 31;
152   }
153 
shr31()154   static void shr31() {
155     for (int i = 0; i < 128; i++)
156       a[i] >>>= 31;
157   }
158 
shr32()159   static void shr32() {
160     for (int i = 0; i < 128; i++)
161       a[i] >>>= 32;  // 0, since & 31
162   }
163 
shr33()164   static void shr33() {
165     for (int i = 0; i < 128; i++)
166       a[i] >>>= 33;  // 1, since & 31
167   }
168 
169   //
170   // Loop bounds.
171   //
172 
bounds()173   static void bounds() {
174     for (int i = 1; i < 127; i++)
175       a[i] += 11;
176   }
177 
178   //
179   // Test Driver.
180   //
181 
main()182   public static void main() {
183     // Set up.
184     a = new char[128];
185     for (int i = 0; i < 128; i++) {
186       a[i] = (char) i;
187     }
188     // Arithmetic operations.
189     add(2);
190     for (int i = 0; i < 128; i++) {
191       expectEquals(i + 2, a[i], "add");
192     }
193     sub(2);
194     for (int i = 0; i < 128; i++) {
195       expectEquals(i, a[i], "sub");
196     }
197     mul(2);
198     for (int i = 0; i < 128; i++) {
199       expectEquals(i + i, a[i], "mul");
200     }
201     div(2);
202     for (int i = 0; i < 128; i++) {
203       expectEquals(i, a[i], "div");
204     }
205     neg();
206     for (int i = 0; i < 128; i++) {
207       expectEquals((char)-i, a[i], "neg");
208     }
209     // Loop bounds.
210     bounds();
211     expectEquals(0, a[0], "bounds0");
212     for (int i = 1; i < 127; i++) {
213       expectEquals((char)(11 - i), a[i], "bounds");
214     }
215     expectEquals((char)-127, a[127], "bounds127");
216     // Shifts.
217     for (int i = 0; i < 128; i++) {
218       a[i] = (char) 0xffff;
219     }
220     shl4();
221     for (int i = 0; i < 128; i++) {
222       expectEquals((char) 0xfff0, a[i], "shl4");
223     }
224     sar2();
225     for (int i = 0; i < 128; i++) {
226       expectEquals((char) 0x3ffc, a[i], "sar2");
227     }
228     shr2();
229     for (int i = 0; i < 128; i++) {
230       expectEquals((char) 0x0fff, a[i], "shr2");
231       a[i] = (char) 0xffff;  // reset
232     }
233     sar31();
234     for (int i = 0; i < 128; i++) {
235       expectEquals(0, a[i], "sar31");
236       a[i] = (char) 0xffff;  // reset
237     }
238     shr31();
239     for (int i = 0; i < 128; i++) {
240       expectEquals(0, a[i], "shr31");
241       a[i] = (char) 0x1200;  // reset
242     }
243     shr32();
244     for (int i = 0; i < 128; i++) {
245       expectEquals((char) 0x1200, a[i], "shr32");
246     }
247     shr33();
248     for (int i = 0; i < 128; i++) {
249       expectEquals((char) 0x0900, a[i], "shr33");
250       a[i] = (char) 0xf1f0;  // reset
251     }
252     not();
253     for (int i = 0; i < 128; i++) {
254       expectEquals((char) 0x0e0f, a[i], "not");
255     }
256     // Done.
257     System.out.println("SimdChar passed");
258   }
259 
expectEquals(int expected, int result, String action)260   private static void expectEquals(int expected, int result, String action) {
261     if (expected != result) {
262       throw new Error("Expected: " + expected + ", found: " + result + " for " + action);
263     }
264   }
265 }
266