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