• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 SimdLong {
21 
22   static long[] a;
23 
24   //
25   // Arithmetic operations.
26   //
27 
28   /// CHECK-START: void SimdLong.add(long) 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-ARM64: void SimdLong.add(long) 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(long x)36   static void add(long x) {
37     for (int i = 0; i < 128; i++)
38       a[i] += x;
39   }
40 
41   /// CHECK-START: void SimdLong.sub(long) 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-ARM64: void SimdLong.sub(long) 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(long x)49   static void sub(long x) {
50     for (int i = 0; i < 128; i++)
51       a[i] -= x;
52   }
53 
54   /// CHECK-START: void SimdLong.mul(long) 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   //  Not directly supported for longs.
59   //
60   /// CHECK-START-ARM64: void SimdLong.mul(long) loop_optimization (after)
61   /// CHECK-IF:     hasIsaFeature("sve")
62   //
63   ///     CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
64   ///     CHECK-DAG: VecMul   loop:<<Loop>>      outer_loop:none
65   ///     CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
66   //
67   /// CHECK-ELSE:
68   //
69   ///     CHECK-NOT: VecMul
70   //
71   /// CHECK-FI:
mul(long x)72   static void mul(long x) {
73     for (int i = 0; i < 128; i++)
74       a[i] *= x;
75   }
76 
77   /// CHECK-START: void SimdLong.div(long) loop_optimization (before)
78   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
79   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
80   //
81   /// CHECK-START: void SimdLong.div(long) loop_optimization (after)
82   /// CHECK-NOT: VecDiv
83   //
84   //  Not supported on any architecture.
85   //
div(long x)86   static void div(long x) {
87     for (int i = 0; i < 128; i++)
88       a[i] /= x;
89   }
90 
91   /// CHECK-START: void SimdLong.neg() loop_optimization (before)
92   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
93   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
94   //
95   /// CHECK-START-ARM64: void SimdLong.neg() loop_optimization (after)
96   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
97   /// CHECK-DAG: VecNeg   loop:<<Loop>>      outer_loop:none
98   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
neg()99   static void neg() {
100     for (int i = 0; i < 128; i++)
101       a[i] = -a[i];
102   }
103 
104   /// CHECK-START: void SimdLong.not() loop_optimization (before)
105   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
106   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
107   //
108   /// CHECK-START-ARM64: void SimdLong.not() loop_optimization (after)
109   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
110   /// CHECK-DAG: VecNot   loop:<<Loop>>      outer_loop:none
111   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
not()112   static void not() {
113     for (int i = 0; i < 128; i++)
114       a[i] = ~a[i];
115   }
116 
117   /// CHECK-START: void SimdLong.shl4() loop_optimization (before)
118   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
119   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
120   //
121   /// CHECK-START-ARM64: void SimdLong.shl4() loop_optimization (after)
122   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
123   /// CHECK-DAG: VecShl   loop:<<Loop>>      outer_loop:none
124   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
shl4()125   static void shl4() {
126     for (int i = 0; i < 128; i++)
127       a[i] <<= 4;
128   }
129 
130   /// CHECK-START: void SimdLong.sar2() loop_optimization (before)
131   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
132   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
133   //
134   /// CHECK-START-ARM64: void SimdLong.sar2() loop_optimization (after)
135   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
136   /// CHECK-DAG: VecShr   loop:<<Loop>>      outer_loop:none
137   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
sar2()138   static void sar2() {
139     for (int i = 0; i < 128; i++)
140       a[i] >>= 2;
141   }
142 
143   /// CHECK-START: void SimdLong.shr2() loop_optimization (before)
144   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
145   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
146   //
147   /// CHECK-START-ARM64: void SimdLong.shr2() loop_optimization (after)
148   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
149   /// CHECK-DAG: VecUShr  loop:<<Loop>>      outer_loop:none
150   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
shr2()151   static void shr2() {
152     for (int i = 0; i < 128; i++)
153       a[i] >>>= 2;
154   }
155 
156   //
157   // Shift checks.
158   //
159 
160   // Expose constants to optimizing compiler, but not to front-end.
$opt$inline$IntConstant64()161   public static int $opt$inline$IntConstant64()       { return 64; }
$opt$inline$IntConstant65()162   public static int $opt$inline$IntConstant65()       { return 65; }
$opt$inline$IntConstantMinus254()163   public static int $opt$inline$IntConstantMinus254() { return -254; }
164 
165   /// CHECK-START: void SimdLong.shr64() instruction_simplifier$after_inlining (before)
166   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 64                        loop:none
167   /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop:B\d+>> outer_loop:none
168   /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
169   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
170   //
171   /// CHECK-START: void SimdLong.shr64() instruction_simplifier$after_inlining (after)
172   /// CHECK-DAG: <<Get:j\d+>> ArrayGet                             loop:<<Loop:B\d+>> outer_loop:none
173   /// CHECK-DAG:              ArraySet [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
174   //
175   /// CHECK-START-ARM64: void SimdLong.shr64() loop_optimization (after)
176   /// CHECK-IF:     hasIsaFeature("sve")
177   //
178   ///     CHECK-DAG: <<Get:d\d+>> VecLoad                                       loop:<<Loop:B\d+>> outer_loop:none
179   ///     CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
180   //
181   /// CHECK-ELSE:
182   //
183   ///     CHECK-DAG: <<Get:d\d+>> VecLoad                              loop:<<Loop:B\d+>> outer_loop:none
184   ///     CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
185   //
186   /// CHECK-FI:
shr64()187   static void shr64() {
188     // TODO: remove a[i] = a[i] altogether?
189     for (int i = 0; i < 128; i++)
190       a[i] >>>= $opt$inline$IntConstant64();  // 0, since & 63
191   }
192 
193   /// CHECK-START: void SimdLong.shr65() instruction_simplifier$after_inlining (before)
194   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 65                        loop:none
195   /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop:B\d+>> outer_loop:none
196   /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
197   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
198   //
199   /// CHECK-START: void SimdLong.shr65() instruction_simplifier$after_inlining (after)
200   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                         loop:none
201   /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop:B\d+>> outer_loop:none
202   /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
203   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
204   //
205   /// CHECK-START-ARM64: void SimdLong.shr65() loop_optimization (after)
206   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                         loop:none
207   /// CHECK-IF:     hasIsaFeature("sve")
208   //
209   ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                                        loop:<<Loop:B\d+>> outer_loop:none
210   ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>,{{j\d+}}]            loop:<<Loop>>      outer_loop:none
211   ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
212   //
213   /// CHECK-ELSE:
214   //
215   ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
216   ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
217   ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
218   //
219   /// CHECK-FI:
shr65()220   static void shr65() {
221     for (int i = 0; i < 128; i++)
222       a[i] >>>= $opt$inline$IntConstant65();  // 1, since & 63
223   }
224 
225   /// CHECK-START: void SimdLong.shrMinus254() instruction_simplifier$after_inlining (before)
226   /// CHECK-DAG: <<Dist:i\d+>> IntConstant -254                      loop:none
227   /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop:B\d+>> outer_loop:none
228   /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
229   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
230   //
231   /// CHECK-START: void SimdLong.shrMinus254() instruction_simplifier$after_inlining (after)
232   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                         loop:none
233   /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop:B\d+>> outer_loop:none
234   /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
235   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
236   //
237   /// CHECK-START-ARM64: void SimdLong.shrMinus254() loop_optimization (after)
238   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                         loop:none
239   /// CHECK-IF:     hasIsaFeature("sve")
240   //
241   ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                                        loop:<<Loop:B\d+>> outer_loop:none
242   ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>,{{j\d+}}]            loop:<<Loop>>      outer_loop:none
243   ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
244   //
245   /// CHECK-ELSE:
246   //
247   ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
248   ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
249   ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
250   //
251   /// CHECK-FI:
shrMinus254()252   static void shrMinus254() {
253     for (int i = 0; i < 128; i++)
254       a[i] >>>= $opt$inline$IntConstantMinus254();  // 2, since & 63
255   }
256 
257   //
258   // Loop bounds.
259   //
260 
bounds()261   static void bounds() {
262     for (int i = 1; i < 127; i++)
263       a[i] += 11;
264   }
265 
266   //
267   // Test Driver.
268   //
269 
main()270   public static void main() {
271     // Set up.
272     a = new long[128];
273     for (int i = 0; i < 128; i++) {
274       a[i] = i;
275     }
276     // Arithmetic operations.
277     add(2L);
278     for (int i = 0; i < 128; i++) {
279       expectEquals(i + 2, a[i], "add");
280     }
281     sub(2L);
282     for (int i = 0; i < 128; i++) {
283       expectEquals(i, a[i], "sub");
284     }
285     mul(2L);
286     for (int i = 0; i < 128; i++) {
287       expectEquals(i + i, a[i], "mul");
288     }
289     div(2L);
290     for (int i = 0; i < 128; i++) {
291       expectEquals(i, a[i], "div");
292     }
293     neg();
294     for (int i = 0; i < 128; i++) {
295       expectEquals(-i, a[i], "neg");
296     }
297     // Loop bounds.
298     bounds();
299     expectEquals(0, a[0], "bounds0");
300     for (int i = 1; i < 127; i++) {
301       expectEquals(11 - i, a[i], "bounds");
302     }
303     expectEquals(-127, a[127], "bounds127");
304     // Shifts.
305     for (int i = 0; i < 128; i++) {
306       a[i] = 0xffffffffffffffffL;
307     }
308     shl4();
309     for (int i = 0; i < 128; i++) {
310       expectEquals(0xfffffffffffffff0L, a[i], "shl4");
311     }
312     sar2();
313     for (int i = 0; i < 128; i++) {
314       expectEquals(0xfffffffffffffffcL, a[i], "sar2");
315     }
316     shr2();
317     for (int i = 0; i < 128; i++) {
318       expectEquals(0x3fffffffffffffffL, a[i], "shr2");
319     }
320     shr64();
321     for (int i = 0; i < 128; i++) {
322       expectEquals(0x3fffffffffffffffL, a[i], "shr64");
323     }
324     shr65();
325     for (int i = 0; i < 128; i++) {
326       expectEquals(0x1fffffffffffffffL, a[i], "shr65");
327     }
328     shrMinus254();
329     for (int i = 0; i < 128; i++) {
330       expectEquals(0x07ffffffffffffffL, a[i], "shrMinus254");
331     }
332     // Bit-wise not operator.
333     not();
334     for (int i = 0; i < 128; i++) {
335       expectEquals(0xf800000000000000L, a[i], "not");
336     }
337     // Done.
338     System.out.println("SimdLong passed");
339   }
340 
expectEquals(long expected, long result, String action)341   private static void expectEquals(long expected, long result, String action) {
342     if (expected != result) {
343       throw new Error("Expected: " + expected + ", found: " + result + " for " + action);
344     }
345   }
346 }
347