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  * Tests for simple integral reductions: same type for accumulator and data.
19  */
20 public class Main {
21 
22   static final int N = 500;
23   static final int M = 100;
24 
25   //
26   // Basic reductions in loops.
27   //
28 
29   // TODO: vectorize these (second step of b/64091002 plan)
30 
reductionByte(byte[] x)31   private static byte reductionByte(byte[] x) {
32     byte sum = 0;
33     for (int i = 0; i < x.length; i++) {
34       sum += x[i];
35     }
36     return sum;
37   }
38 
reductionShort(short[] x)39   private static short reductionShort(short[] x) {
40     short sum = 0;
41     for (int i = 0; i < x.length; i++) {
42       sum += x[i];
43     }
44     return sum;
45   }
46 
reductionChar(char[] x)47   private static char reductionChar(char[] x) {
48     char sum = 0;
49     for (int i = 0; i < x.length; i++) {
50       sum += x[i];
51     }
52     return sum;
53   }
54 
55   /// CHECK-START: int Main.reductionInt(int[]) loop_optimization (before)
56   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
57   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
58   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
59   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
60   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
61   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
62   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
63   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
64   //
65   /// CHECK-START-{ARM,ARM64}: int Main.reductionInt(int[]) loop_optimization (after)
66   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
67   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
68   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
69   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
70   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
71   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
72   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
73   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
74 
75   //  Check that full 128-bit Q-Register are saved across SuspendCheck slow path.
76   /// CHECK-START-ARM64: int Main.reductionInt(int[]) disassembly (after)
77   /// CHECK:                     SuspendCheckSlowPathARM64
78   /// CHECK:                       stur q<<RegNo:\d+>>, [sp, #<<Offset:\d+>>]
79   /// CHECK:                       ldur q<<RegNo>>, [sp, #<<Offset>>]
reductionInt(int[] x)80   private static int reductionInt(int[] x) {
81     int sum = 0;
82     for (int i = 0; i < x.length; i++) {
83       sum += x[i];
84     }
85     return sum;
86   }
87 
88   /// CHECK-START: int Main.reductionIntChain() loop_optimization (before)
89   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
90   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
91   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons1>>,{{i\d+}}]      loop:<<Loop1:B\d+>> outer_loop:none
92   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1>>      outer_loop:none
93   /// CHECK-DAG: <<Get1:i\d+>>   ArrayGet [{{l\d+}},<<Phi2>>]  loop:<<Loop1>>      outer_loop:none
94   /// CHECK-DAG:                 Add [<<Phi1>>,<<Get1>>]       loop:<<Loop1>>      outer_loop:none
95   /// CHECK-DAG:                 Add [<<Phi2>>,<<Cons1>>]      loop:<<Loop1>>      outer_loop:none
96   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop2:B\d+>> outer_loop:none
97   /// CHECK-DAG: <<Phi4:i\d+>>   Phi [<<Phi1>>,{{i\d+}}]       loop:<<Loop2>>      outer_loop:none
98   /// CHECK-DAG: <<Get2:i\d+>>   ArrayGet [{{l\d+}},<<Phi3>>]  loop:<<Loop2>>      outer_loop:none
99   /// CHECK-DAG:                 Add [<<Phi4>>,<<Get2>>]       loop:<<Loop2>>      outer_loop:none
100   /// CHECK-DAG:                 Add [<<Phi3>>,<<Cons1>>]      loop:<<Loop2>>      outer_loop:none
101   /// CHECK-DAG:                 Return [<<Phi4>>]             loop:none
102   //
103   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
104   //
105   /// CHECK-START-{ARM,ARM64}: int Main.reductionIntChain() loop_optimization (after)
106   /// CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
107   /// CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
108   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>] loop:<<Loop1>>      outer_loop:none
109   /// CHECK-DAG:                 VecAdd [<<Phi1>>,<<Load1>>]    loop:<<Loop1>>      outer_loop:none
110   /// CHECK-DAG:                 Add [<<I1>>,{{i\d+}}]          loop:<<Loop1>>      outer_loop:none
111   /// CHECK-DAG: <<Red1:d\d+>>   VecReduce [<<Phi1>>]           loop:none
112   /// CHECK-DAG: <<Extr1:i\d+>>  VecExtractScalar [<<Red1>>]    loop:none
113   /// CHECK-DAG: <<Set2:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
114   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set2>>,{{d\d+}}]        loop:<<Loop2:B\d+>> outer_loop:none
115   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<I2:i\d+>>] loop:<<Loop2>>      outer_loop:none
116   /// CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load2>>]    loop:<<Loop2>>      outer_loop:none
117   /// CHECK-DAG:                 Add [<<I2>>,{{i\d+}}]          loop:<<Loop2>>      outer_loop:none
118   /// CHECK-DAG: <<Red2:d\d+>>   VecReduce [<<Phi2>>]           loop:none
119   /// CHECK-DAG: <<Extr2:i\d+>>  VecExtractScalar [<<Red2>>]    loop:none
120   //
121   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
122   //
123   // NOTE: pattern is robust with respect to vector loop unrolling and peeling.
reductionIntChain()124   private static int reductionIntChain() {
125     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
126     int r = 1;
127     for (int i = 0; i < 16; i++) {
128       r += x[i];
129     }
130     for (int i = 0; i < 16; i++) {
131       r += x[i];
132     }
133     return r;
134   }
135 
136   /// CHECK-START: int Main.reductionIntToLoop(int[]) loop_optimization (before)
137   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
138   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
139   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1:B\d+>> outer_loop:none
140   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1>>      outer_loop:none
141   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop1>>      outer_loop:none
142   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop1>>      outer_loop:none
143   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop1>>      outer_loop:none
144   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Phi2>>,{{i\d+}}]       loop:<<Loop2:B\d+>> outer_loop:none
145   /// CHECK-DAG: <<Phi4:i\d+>>   Phi [<<Phi2>>,{{i\d+}}]       loop:<<Loop2>>      outer_loop:none
146   //
147   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
148   //
149   /// CHECK-START-{ARM,ARM64}: int Main.reductionIntToLoop(int[]) loop_optimization (after)
150   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
151   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
152   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
153   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop1>>      outer_loop:none
154   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop1>>      outer_loop:none
155   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop1>>      outer_loop:none
156   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
157   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
reductionIntToLoop(int[] x)158   private static int reductionIntToLoop(int[] x) {
159     int r = 0;
160     for (int i = 0; i < 8; i++) {
161       r += x[i];
162     }
163     for (int i = r; i < 16; i++) {
164       r += i;
165     }
166     return r;
167   }
168 
169   /// CHECK-START: long Main.reductionLong(long[]) loop_optimization (before)
170   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
171   /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
172   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
173   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
174   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
175   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
176   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
177   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
178   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
179   //
180   /// CHECK-START-ARM64: long Main.reductionLong(long[]) loop_optimization (after)
181   /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
182   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
183   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
184   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
185   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
186   /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
187   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
188   /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
reductionLong(long[] x)189   private static long reductionLong(long[] x) {
190     long sum = 0;
191     for (int i = 0; i < x.length; i++) {
192       sum += x[i];
193     }
194     return sum;
195   }
196 
reductionByteM1(byte[] x)197   private static byte reductionByteM1(byte[] x) {
198     byte sum = -1;
199     for (int i = 0; i < x.length; i++) {
200       sum += x[i];
201     }
202     return sum;
203   }
204 
reductionShortM1(short[] x)205   private static short reductionShortM1(short[] x) {
206     short sum = -1;
207     for (int i = 0; i < x.length; i++) {
208       sum += x[i];
209     }
210     return sum;
211   }
212 
reductionCharM1(char[] x)213   private static char reductionCharM1(char[] x) {
214     char sum = 0xffff;
215     for (int i = 0; i < x.length; i++) {
216       sum += x[i];
217     }
218     return sum;
219   }
220 
221   /// CHECK-START: int Main.reductionIntM1(int[]) loop_optimization (before)
222   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
223   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
224   /// CHECK-DAG: <<ConsM1:i\d+>> IntConstant -1                loop:none
225   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
226   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM1>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
227   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
228   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
229   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
230   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
231   //
232   /// CHECK-START-{ARM,ARM64}: int Main.reductionIntM1(int[]) loop_optimization (after)
233   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
234   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
235   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
236   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
237   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
238   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
239   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
240   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
reductionIntM1(int[] x)241   private static int reductionIntM1(int[] x) {
242     int sum = -1;
243     for (int i = 0; i < x.length; i++) {
244       sum += x[i];
245     }
246     return sum;
247   }
248 
249   /// CHECK-START: long Main.reductionLongM1(long[]) loop_optimization (before)
250   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
251   /// CHECK-DAG: <<LongM1:j\d+>> LongConstant -1               loop:none
252   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
253   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
254   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<LongM1>>,{{j\d+}}]     loop:<<Loop>>      outer_loop:none
255   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
256   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
257   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
258   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
259   //
260   /// CHECK-START-ARM64: long Main.reductionLongM1(long[]) loop_optimization (after)
261   /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
262   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
263   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
264   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
265   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
266   /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
267   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
268   /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
reductionLongM1(long[] x)269   private static long reductionLongM1(long[] x) {
270     long sum = -1L;
271     for (int i = 0; i < x.length; i++) {
272       sum += x[i];
273     }
274     return sum;
275   }
276 
reductionMinusByte(byte[] x)277   private static byte reductionMinusByte(byte[] x) {
278     byte sum = 0;
279     for (int i = 0; i < x.length; i++) {
280       sum -= x[i];
281     }
282     return sum;
283   }
284 
reductionMinusShort(short[] x)285   private static short reductionMinusShort(short[] x) {
286     short sum = 0;
287     for (int i = 0; i < x.length; i++) {
288       sum -= x[i];
289     }
290     return sum;
291   }
292 
reductionMinusChar(char[] x)293   private static char reductionMinusChar(char[] x) {
294     char sum = 0;
295     for (int i = 0; i < x.length; i++) {
296       sum -= x[i];
297     }
298     return sum;
299   }
300 
301   /// CHECK-START: int Main.reductionMinusInt(int[]) loop_optimization (before)
302   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
303   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
304   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
305   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
306   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
307   /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
308   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
309   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
310   //
311   /// CHECK-START-{ARM,ARM64}: int Main.reductionMinusInt(int[]) loop_optimization (after)
312   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
313   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
314   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
315   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
316   /// CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
317   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
318   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
319   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
reductionMinusInt(int[] x)320   private static int reductionMinusInt(int[] x) {
321     int sum = 0;
322     for (int i = 0; i < x.length; i++) {
323       sum -= x[i];
324     }
325     return sum;
326   }
327 
328   /// CHECK-START: long Main.reductionMinusLong(long[]) loop_optimization (before)
329   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
330   /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
331   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
332   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
333   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
334   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
335   /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
336   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
337   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
338   //
339   /// CHECK-START-ARM64: long Main.reductionMinusLong(long[]) loop_optimization (after)
340   /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
341   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
342   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
343   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
344   /// CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
345   /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
346   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
347   /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
reductionMinusLong(long[] x)348   private static long reductionMinusLong(long[] x) {
349     long sum = 0;
350     for (int i = 0; i < x.length; i++) {
351       sum -= x[i];
352     }
353     return sum;
354   }
355 
356   //
357   // A few special cases.
358   //
359 
360   // TODO: consider unrolling
361 
reductionInt10(int[] x)362   private static int reductionInt10(int[] x) {
363     int sum = 0;
364     // Amenable to complete unrolling.
365     for (int i = 10; i <= 10; i++) {
366       sum += x[i];
367     }
368     return sum;
369   }
370 
reductionMinusInt10(int[] x)371   private static int reductionMinusInt10(int[] x) {
372     int sum = 0;
373     // Amenable to complete unrolling.
374     for (int i = 10; i <= 10; i++) {
375       sum -= x[i];
376     }
377     return sum;
378   }
379 
380   //
381   // Main driver.
382   //
383 
main(String[] args)384   public static void main(String[] args) {
385     byte[] xb = new byte[N];
386     short[] xs = new short[N];
387     char[] xc = new char[N];
388     int[] xi = new int[N];
389     long[] xl = new long[N];
390     for (int i = 0, k = -17; i < N; i++, k += 3) {
391       xb[i] = (byte) k;
392       xs[i] = (short) k;
393       xc[i] = (char) k;
394       xi[i] = k;
395       xl[i] = k;
396     }
397 
398     // Arrays with all positive elements.
399     byte[] xpb = new byte[M];
400     short[] xps = new short[M];
401     char[] xpc = new char[M];
402     int[] xpi = new int[M];
403     long[] xpl = new long[M];
404     for (int i = 0, k = 3; i < M; i++, k++) {
405       xpb[i] = (byte) k;
406       xps[i] = (short) k;
407       xpc[i] = (char) k;
408       xpi[i] = k;
409       xpl[i] = k;
410     }
411 
412     // Arrays with all negative elements.
413     byte[] xnb = new byte[M];
414     short[] xns = new short[M];
415     int[] xni = new int[M];
416     long[] xnl = new long[M];
417     for (int i = 0, k = -103; i < M; i++, k++) {
418       xnb[i] = (byte) k;
419       xns[i] = (short) k;
420       xni[i] = k;
421       xnl[i] = k;
422     }
423 
424     // Test various reductions in loops.
425     int[] x0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
426     int[] x1 = { 0, 0, 0, 1, 0, 0, 0, 0 };
427     int[] x2 = { 1, 1, 1, 1, 0, 0, 0, 0 };
428     expectEquals(-74, reductionByte(xb));
429     expectEquals(-27466, reductionShort(xs));
430     expectEquals(38070, reductionChar(xc));
431     expectEquals(365750, reductionInt(xi));
432     expectEquals(273, reductionIntChain());
433     expectEquals(120, reductionIntToLoop(x0));
434     expectEquals(121, reductionIntToLoop(x1));
435     expectEquals(118, reductionIntToLoop(x2));
436     expectEquals(-1310, reductionIntToLoop(xi));
437     expectEquals(365750L, reductionLong(xl));
438     expectEquals(-75, reductionByteM1(xb));
439     expectEquals(-27467, reductionShortM1(xs));
440     expectEquals(38069, reductionCharM1(xc));
441     expectEquals(365749, reductionIntM1(xi));
442     expectEquals(365749L, reductionLongM1(xl));
443     expectEquals(74, reductionMinusByte(xb));
444     expectEquals(27466, reductionMinusShort(xs));
445     expectEquals(27466, reductionMinusChar(xc));
446     expectEquals(-365750, reductionMinusInt(xi));
447     expectEquals(365750L, reductionLong(xl));
448     expectEquals(-75, reductionByteM1(xb));
449     expectEquals(-27467, reductionShortM1(xs));
450     expectEquals(38069, reductionCharM1(xc));
451     expectEquals(365749, reductionIntM1(xi));
452     expectEquals(365749L, reductionLongM1(xl));
453     expectEquals(74, reductionMinusByte(xb));
454     expectEquals(27466, reductionMinusShort(xs));
455     expectEquals(27466, reductionMinusChar(xc));
456     expectEquals(-365750, reductionMinusInt(xi));
457     expectEquals(-365750L, reductionMinusLong(xl));
458 
459     // Test special cases.
460     expectEquals(13, reductionInt10(xi));
461     expectEquals(-13, reductionMinusInt10(xi));
462 
463     System.out.println("passed");
464   }
465 
expectEquals(int expected, int result)466   private static void expectEquals(int expected, int result) {
467     if (expected != result) {
468       throw new Error("Expected: " + expected + ", found: " + result);
469     }
470   }
471 
expectEquals(long expected, long result)472   private static void expectEquals(long expected, long result) {
473     if (expected != result) {
474       throw new Error("Expected: " + expected + ", found: " + result);
475     }
476   }
477 }
478