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