• 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  * 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: int Main.reductionInt(int[]) loop_optimization (after)
66   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 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-START-ARM64: int Main.reductionInt(int[]) loop_optimization (after)
76   /// CHECK-IF:     hasIsaFeature("sve")
77   //
78   ///     CHECK-DAG: <<TrueC:i\d+>>     IntConstant 1                            loop:none
79   ///     CHECK-DAG: <<Set:d\d+>>       VecSetScalars [{{i\d+}},{{j\d+}}]        loop:none
80   ///     CHECK-DAG: <<Phi:d\d+>>       Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop:B\d+>> outer_loop:none
81   ///     CHECK-DAG: <<LoopP:j\d+>>     VecPredWhile                             loop:<<Loop>>      outer_loop:none
82   ///     CHECK-DAG: <<Load:d\d+>>      VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>]  loop:<<Loop>>      outer_loop:none
83   ///     CHECK-DAG:                    VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]      loop:<<Loop>>      outer_loop:none
84   ///     CHECK-DAG:                    Add [<<I>>,{{i\d+}}]                     loop:<<Loop>>      outer_loop:none
85   ///     CHECK-DAG: <<PostLoopP:j\d+>> VecPredSetAll [<<TrueC>>]                loop:none
86   ///     CHECK-DAG: <<Red:d\d+>>       VecReduce [<<Phi>>,<<PostLoopP>>]        loop:none
87   ///     CHECK-DAG: <<Extr:i\d+>>      VecExtractScalar [<<Red>>,<<PostLoopP>>] loop:none
88   //
89   /// CHECK-ELSE:
90   //
91   ///     CHECK-DAG: <<Cons:i\d+>>      IntConstant 4                            loop:none
92   ///     CHECK-DAG: <<Set:d\d+>>       VecSetScalars [{{i\d+}}]                 loop:none
93   ///     CHECK-DAG: <<Phi:d\d+>>       Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop:B\d+>> outer_loop:none
94   ///     CHECK-DAG: <<Load:d\d+>>      VecLoad [{{l\d+}},<<I:i\d+>>]            loop:<<Loop>>      outer_loop:none
95   ///     CHECK-DAG:                    VecAdd [<<Phi>>,<<Load>>]                loop:<<Loop>>      outer_loop:none
96   ///     CHECK-DAG:                    Add [<<I>>,<<Cons>>]                     loop:<<Loop>>      outer_loop:none
97   ///     CHECK-DAG: <<Red:d\d+>>       VecReduce [<<Phi>>]                      loop:none
98   ///     CHECK-DAG: <<Extr:i\d+>>      VecExtractScalar [<<Red>>]               loop:none
99   //
100   /// CHECK-FI:
101   //
102   //  Check that full 128-bit Q-Register are saved across SuspendCheck slow path.
103   /// CHECK-START-ARM64: int Main.reductionInt(int[]) disassembly (after)
104   /// CHECK:                            SuspendCheckSlowPathARM64
105   /// CHECK-IF:     hasIsaFeature("sve")
106   //
107   ///     CHECK:                                str z<<RegNo:\d+>>,
108   ///     CHECK:                                ldr z<<RegNo>>,
109   //
110   /// CHECK-ELSE:
111   //
112   ///     CHECK:                                stur q<<RegNo:\d+>>, [sp, #<<Offset:\d+>>]
113   ///     CHECK:                                ldur q<<RegNo>>, [sp, #<<Offset>>]
114   //
115   /// CHECK-FI:
reductionInt(int[] x)116   private static int reductionInt(int[] x) {
117     int sum = 0;
118     for (int i = 0; i < x.length; i++) {
119       sum += x[i];
120     }
121     return sum;
122   }
123 
124   /// CHECK-START: int Main.reductionIntChain() loop_optimization (before)
125   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
126   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
127   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons1>>,{{i\d+}}]      loop:<<Loop1:B\d+>> outer_loop:none
128   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1>>      outer_loop:none
129   /// CHECK-DAG: <<Get1:i\d+>>   ArrayGet [{{l\d+}},<<Phi2>>]  loop:<<Loop1>>      outer_loop:none
130   /// CHECK-DAG:                 Add [<<Phi1>>,<<Get1>>]       loop:<<Loop1>>      outer_loop:none
131   /// CHECK-DAG:                 Add [<<Phi2>>,<<Cons1>>]      loop:<<Loop1>>      outer_loop:none
132   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop2:B\d+>> outer_loop:none
133   /// CHECK-DAG: <<Phi4:i\d+>>   Phi [<<Phi1>>,{{i\d+}}]       loop:<<Loop2>>      outer_loop:none
134   /// CHECK-DAG: <<Get2:i\d+>>   ArrayGet [{{l\d+}},<<Phi3>>]  loop:<<Loop2>>      outer_loop:none
135   /// CHECK-DAG:                 Add [<<Phi4>>,<<Get2>>]       loop:<<Loop2>>      outer_loop:none
136   /// CHECK-DAG:                 Add [<<Phi3>>,<<Cons1>>]      loop:<<Loop2>>      outer_loop:none
137   /// CHECK-DAG:                 Return [<<Phi4>>]             loop:none
138   //
139   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
140   //
141   /// CHECK-START-ARM: int Main.reductionIntChain() loop_optimization (after)
142   /// CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
143   /// CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
144   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>] loop:<<Loop1>>      outer_loop:none
145   /// CHECK-DAG:                 VecAdd [<<Phi1>>,<<Load1>>]    loop:<<Loop1>>      outer_loop:none
146   /// CHECK-DAG:                 Add [<<I1>>,{{i\d+}}]          loop:<<Loop1>>      outer_loop:none
147   /// CHECK-DAG: <<Red1:d\d+>>   VecReduce [<<Phi1>>]           loop:none
148   /// CHECK-DAG: <<Extr1:i\d+>>  VecExtractScalar [<<Red1>>]    loop:none
149   /// CHECK-DAG: <<Set2:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
150   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set2>>,{{d\d+}}]        loop:<<Loop2:B\d+>> outer_loop:none
151   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<I2:i\d+>>] loop:<<Loop2>>      outer_loop:none
152   /// CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load2>>]    loop:<<Loop2>>      outer_loop:none
153   /// CHECK-DAG:                 Add [<<I2>>,{{i\d+}}]          loop:<<Loop2>>      outer_loop:none
154   /// CHECK-DAG: <<Red2:d\d+>>   VecReduce [<<Phi2>>]           loop:none
155   /// CHECK-DAG: <<Extr2:i\d+>>  VecExtractScalar [<<Red2>>]    loop:none
156   //
157   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
158   //
159   /// CHECK-START-ARM64: int Main.reductionIntChain() loop_optimization (after)
160   /// CHECK-IF:     hasIsaFeature("sve")
161   //
162   ///     CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}},{{j\d+}}]         loop:none
163   ///     CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]                   loop:<<Loop1:B\d+>> outer_loop:none
164   ///     CHECK-DAG: <<Loop1P:j\d+>> VecPredWhile                              loop:<<Loop1>>      outer_loop:none
165   ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>,<<Loop1P>>] loop:<<Loop1>>      outer_loop:none
166   ///     CHECK-DAG:                 VecAdd [<<Phi1>>,<<Load1>>,<<Loop1P>>]    loop:<<Loop1>>      outer_loop:none
167   ///     CHECK-DAG:                 Add [<<I1>>,{{i\d+}}]                     loop:<<Loop1>>      outer_loop:none
168   ///     CHECK-DAG: <<Red1:d\d+>>   VecReduce [<<Phi1>>,{{j\d+}}]             loop:none
169   ///     CHECK-DAG: <<Extr1:i\d+>>  VecExtractScalar [<<Red1>>,{{j\d+}}]      loop:none
170   ///     CHECK-DAG: <<Set2:d\d+>>   VecSetScalars [{{i\d+}},{{j\d+}}]         loop:none
171   ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set2>>,{{d\d+}}]                   loop:<<Loop2:B\d+>> outer_loop:none
172   ///     CHECK-DAG: <<Loop2P:j\d+>> VecPredWhile                              loop:<<Loop2>>      outer_loop:none
173   ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<I2:i\d+>>,<<Loop2P>>] loop:<<Loop2>>      outer_loop:none
174   ///     CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load2>>,<<Loop2P>>]    loop:<<Loop2>>      outer_loop:none
175   ///     CHECK-DAG:                 Add [<<I2>>,{{i\d+}}]                     loop:<<Loop2>>      outer_loop:none
176   ///     CHECK-DAG: <<Red2:d\d+>>   VecReduce [<<Phi2>>,{{j\d+}}]             loop:none
177   ///     CHECK-DAG: <<Extr2:i\d+>>  VecExtractScalar [<<Red2>>,{{j\d+}}]      loop:none
178   //
179   /// CHECK-ELSE:
180   //
181   ///     CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
182   ///     CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
183   ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>] loop:<<Loop1>>      outer_loop:none
184   ///     CHECK-DAG:                 VecAdd [<<Phi1>>,<<Load1>>]    loop:<<Loop1>>      outer_loop:none
185   ///     CHECK-DAG:                 Add [<<I1>>,{{i\d+}}]          loop:<<Loop1>>      outer_loop:none
186   ///     CHECK-DAG: <<Red1:d\d+>>   VecReduce [<<Phi1>>]           loop:none
187   ///     CHECK-DAG: <<Extr1:i\d+>>  VecExtractScalar [<<Red1>>]    loop:none
188   ///     CHECK-DAG: <<Set2:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
189   ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set2>>,{{d\d+}}]        loop:<<Loop2:B\d+>> outer_loop:none
190   ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<I2:i\d+>>] loop:<<Loop2>>      outer_loop:none
191   ///     CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load2>>]    loop:<<Loop2>>      outer_loop:none
192   ///     CHECK-DAG:                 Add [<<I2>>,{{i\d+}}]          loop:<<Loop2>>      outer_loop:none
193   ///     CHECK-DAG: <<Red2:d\d+>>   VecReduce [<<Phi2>>]           loop:none
194   ///     CHECK-DAG: <<Extr2:i\d+>>  VecExtractScalar [<<Red2>>]    loop:none
195   //
196   /// CHECK-FI:
197   //
198   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
199   //
200   // NOTE: pattern is robust with respect to vector loop unrolling and peeling.
reductionIntChain()201   private static int reductionIntChain() {
202     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
203     int r = 1;
204     for (int i = 0; i < 16; i++) {
205       r += x[i];
206     }
207     for (int i = 0; i < 16; i++) {
208       r += x[i];
209     }
210     return r;
211   }
212 
213   /// CHECK-START: int Main.reductionIntToLoop(int[]) loop_optimization (before)
214   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
215   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
216   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1:B\d+>> outer_loop:none
217   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1>>      outer_loop:none
218   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop1>>      outer_loop:none
219   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop1>>      outer_loop:none
220   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop1>>      outer_loop:none
221   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Phi2>>,{{i\d+}}]       loop:<<Loop2:B\d+>> outer_loop:none
222   /// CHECK-DAG: <<Phi4:i\d+>>   Phi [<<Phi2>>,{{i\d+}}]       loop:<<Loop2>>      outer_loop:none
223   //
224   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
225   //
226   /// CHECK-START-ARM: int Main.reductionIntToLoop(int[]) loop_optimization (after)
227   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 loop:none
228   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
229   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
230   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop1>>      outer_loop:none
231   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop1>>      outer_loop:none
232   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop1>>      outer_loop:none
233   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
234   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
235   //
236   /// CHECK-START-ARM64: int Main.reductionIntToLoop(int[]) loop_optimization (after)
237   /// CHECK-IF:     hasIsaFeature("sve")
238   //
239   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}},{{j\d+}}]        loop:none
240   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop1:B\d+>> outer_loop:none
241   ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                             loop:<<Loop1>>
242   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>]  loop:<<Loop1>>      outer_loop:none
243   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]      loop:<<Loop1>>      outer_loop:none
244   ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                     loop:<<Loop1>>      outer_loop:none
245   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]             loop:none
246   ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]      loop:none
247   //
248   /// CHECK-ELSE:
249   //
250   ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                 loop:none
251   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
252   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
253   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop1>>      outer_loop:none
254   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop1>>      outer_loop:none
255   ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop1>>      outer_loop:none
256   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
257   ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
258   //
259   /// CHECK-FI:
reductionIntToLoop(int[] x)260   private static int reductionIntToLoop(int[] x) {
261     int r = 0;
262     for (int i = 0; i < 8; i++) {
263       r += x[i];
264     }
265     for (int i = r; i < 16; i++) {
266       r += i;
267     }
268     return r;
269   }
270 
271   /// CHECK-START: long Main.reductionLong(long[]) loop_optimization (before)
272   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
273   /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
274   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
275   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
276   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
277   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
278   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
279   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
280   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
281   //
282   /// CHECK-START-ARM64: long Main.reductionLong(long[]) loop_optimization (after)
283   /// CHECK-IF:     hasIsaFeature("sve")
284   //
285   ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant                              loop:none
286   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}},{{j\d+}}]        loop:none
287   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop:B\d+>> outer_loop:none
288   ///     CHECK-DAG: <<Loop1P:j\d+>> VecPredWhile                             loop:<<Loop>>      outer_loop:none
289   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<Loop1P>>] loop:<<Loop>>      outer_loop:none
290   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<Loop1P>>]     loop:<<Loop>>      outer_loop:none
291   ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                     loop:<<Loop>>      outer_loop:none
292   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]             loop:none
293   ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]      loop:none
294   //
295   /// CHECK-ELSE:
296   //
297   ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
298   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
299   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
300   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
301   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
302   ///     CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
303   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
304   ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
305   //
306   /// CHECK-FI:
reductionLong(long[] x)307   private static long reductionLong(long[] x) {
308     long sum = 0;
309     for (int i = 0; i < x.length; i++) {
310       sum += x[i];
311     }
312     return sum;
313   }
314 
reductionByteM1(byte[] x)315   private static byte reductionByteM1(byte[] x) {
316     byte sum = -1;
317     for (int i = 0; i < x.length; i++) {
318       sum += x[i];
319     }
320     return sum;
321   }
322 
reductionShortM1(short[] x)323   private static short reductionShortM1(short[] x) {
324     short sum = -1;
325     for (int i = 0; i < x.length; i++) {
326       sum += x[i];
327     }
328     return sum;
329   }
330 
reductionCharM1(char[] x)331   private static char reductionCharM1(char[] x) {
332     char sum = 0xffff;
333     for (int i = 0; i < x.length; i++) {
334       sum += x[i];
335     }
336     return sum;
337   }
338 
339   /// CHECK-START: int Main.reductionIntM1(int[]) loop_optimization (before)
340   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
341   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
342   /// CHECK-DAG: <<ConsM1:i\d+>> IntConstant -1                loop:none
343   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
344   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM1>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
345   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
346   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
347   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
348   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
349   //
350   /// CHECK-START-ARM: int Main.reductionIntM1(int[]) loop_optimization (after)
351   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 loop:none
352   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
353   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
354   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
355   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
356   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
357   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
358   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
359   //
360   /// CHECK-START-ARM64: int Main.reductionIntM1(int[]) loop_optimization (after)
361   /// CHECK-IF:     hasIsaFeature("sve")
362   //
363   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}},{{j\d+}}]       loop:none
364   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
365   ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
366   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
367   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
368   ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
369   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
370   ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
371   //
372   /// CHECK-ELSE:
373   //
374   ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                 loop:none
375   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
376   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
377   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
378   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
379   ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
380   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
381   ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
382   //
383   /// CHECK-FI:
reductionIntM1(int[] x)384   private static int reductionIntM1(int[] x) {
385     int sum = -1;
386     for (int i = 0; i < x.length; i++) {
387       sum += x[i];
388     }
389     return sum;
390   }
391 
392   /// CHECK-START: long Main.reductionLongM1(long[]) loop_optimization (before)
393   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
394   /// CHECK-DAG: <<LongM1:j\d+>> LongConstant -1               loop:none
395   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
396   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
397   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<LongM1>>,{{j\d+}}]     loop:<<Loop>>      outer_loop:none
398   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
399   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
400   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
401   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
402   //
403   /// CHECK-START-ARM64: long Main.reductionLongM1(long[]) loop_optimization (after)
404   /// CHECK-IF:     hasIsaFeature("sve")
405   //
406   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}},{{j\d+}}]       loop:none
407   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
408   ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
409   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
410   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
411   ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
412   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
413   ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
414   //
415   /// CHECK-ELSE:
416   //
417   ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
418   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
419   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
420   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
421   ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
422   ///     CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
423   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
424   ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
425   //
426   /// CHECK-FI:
reductionLongM1(long[] x)427   private static long reductionLongM1(long[] x) {
428     long sum = -1L;
429     for (int i = 0; i < x.length; i++) {
430       sum += x[i];
431     }
432     return sum;
433   }
434 
reductionMinusByte(byte[] x)435   private static byte reductionMinusByte(byte[] x) {
436     byte sum = 0;
437     for (int i = 0; i < x.length; i++) {
438       sum -= x[i];
439     }
440     return sum;
441   }
442 
reductionMinusShort(short[] x)443   private static short reductionMinusShort(short[] x) {
444     short sum = 0;
445     for (int i = 0; i < x.length; i++) {
446       sum -= x[i];
447     }
448     return sum;
449   }
450 
reductionMinusChar(char[] x)451   private static char reductionMinusChar(char[] x) {
452     char sum = 0;
453     for (int i = 0; i < x.length; i++) {
454       sum -= x[i];
455     }
456     return sum;
457   }
458 
459   /// CHECK-START: int Main.reductionMinusInt(int[]) loop_optimization (before)
460   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
461   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
462   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
463   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
464   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
465   /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
466   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
467   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
468   //
469   /// CHECK-START-ARM: int Main.reductionMinusInt(int[]) loop_optimization (after)
470   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 loop:none
471   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
472   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
473   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
474   /// CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
475   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
476   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
477   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
478   //
479   /// CHECK-START-ARM64: int Main.reductionMinusInt(int[]) loop_optimization (after)
480   /// CHECK-IF:     hasIsaFeature("sve")
481   //
482   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}},{{j\d+}}]       loop:none
483   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
484   ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
485   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
486   ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
487   ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
488   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
489   ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
490   //
491   /// CHECK-ELSE:
492   //
493   ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                 loop:none
494   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
495   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
496   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
497   ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
498   ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
499   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
500   ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
501   //
502   /// CHECK-FI:
reductionMinusInt(int[] x)503   private static int reductionMinusInt(int[] x) {
504     int sum = 0;
505     for (int i = 0; i < x.length; i++) {
506       sum -= x[i];
507     }
508     return sum;
509   }
510 
511   /// CHECK-START: long Main.reductionMinusLong(long[]) loop_optimization (before)
512   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
513   /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
514   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
515   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
516   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
517   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
518   /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
519   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
520   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
521   //
522   /// CHECK-START-ARM64: long Main.reductionMinusLong(long[]) loop_optimization (after)
523   /// CHECK-IF:     hasIsaFeature("sve")
524   //
525   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}},{{j\d+}}]       loop:none
526   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
527   ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
528   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
529   ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
530   ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
531   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
532   ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
533   //
534   /// CHECK-ELSE:
535   //
536   ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
537   ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
538   ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
539   ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
540   ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
541   ///     CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
542   ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
543   ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
544   //
545   /// CHECK-FI:
reductionMinusLong(long[] x)546   private static long reductionMinusLong(long[] x) {
547     long sum = 0;
548     for (int i = 0; i < x.length; i++) {
549       sum -= x[i];
550     }
551     return sum;
552   }
553 
554   //
555   // A few special cases.
556   //
557 
558   // TODO: consider unrolling
559 
reductionInt10(int[] x)560   private static int reductionInt10(int[] x) {
561     int sum = 0;
562     // Amenable to complete unrolling.
563     for (int i = 10; i <= 10; i++) {
564       sum += x[i];
565     }
566     return sum;
567   }
568 
reductionMinusInt10(int[] x)569   private static int reductionMinusInt10(int[] x) {
570     int sum = 0;
571     // Amenable to complete unrolling.
572     for (int i = 10; i <= 10; i++) {
573       sum -= x[i];
574     }
575     return sum;
576   }
577 
578   //
579   // Main driver.
580   //
581 
main(String[] args)582   public static void main(String[] args) {
583     byte[] xb = new byte[N];
584     short[] xs = new short[N];
585     char[] xc = new char[N];
586     int[] xi = new int[N];
587     long[] xl = new long[N];
588     for (int i = 0, k = -17; i < N; i++, k += 3) {
589       xb[i] = (byte) k;
590       xs[i] = (short) k;
591       xc[i] = (char) k;
592       xi[i] = k;
593       xl[i] = k;
594     }
595 
596     // Arrays with all positive elements.
597     byte[] xpb = new byte[M];
598     short[] xps = new short[M];
599     char[] xpc = new char[M];
600     int[] xpi = new int[M];
601     long[] xpl = new long[M];
602     for (int i = 0, k = 3; i < M; i++, k++) {
603       xpb[i] = (byte) k;
604       xps[i] = (short) k;
605       xpc[i] = (char) k;
606       xpi[i] = k;
607       xpl[i] = k;
608     }
609 
610     // Arrays with all negative elements.
611     byte[] xnb = new byte[M];
612     short[] xns = new short[M];
613     int[] xni = new int[M];
614     long[] xnl = new long[M];
615     for (int i = 0, k = -103; i < M; i++, k++) {
616       xnb[i] = (byte) k;
617       xns[i] = (short) k;
618       xni[i] = k;
619       xnl[i] = k;
620     }
621 
622     // Test various reductions in loops.
623     int[] x0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
624     int[] x1 = { 0, 0, 0, 1, 0, 0, 0, 0 };
625     int[] x2 = { 1, 1, 1, 1, 0, 0, 0, 0 };
626     expectEquals(-74, reductionByte(xb));
627     expectEquals(-27466, reductionShort(xs));
628     expectEquals(38070, reductionChar(xc));
629     expectEquals(365750, reductionInt(xi));
630     expectEquals(273, reductionIntChain());
631     expectEquals(120, reductionIntToLoop(x0));
632     expectEquals(121, reductionIntToLoop(x1));
633     expectEquals(118, reductionIntToLoop(x2));
634     expectEquals(-1310, reductionIntToLoop(xi));
635     expectEquals(365750L, reductionLong(xl));
636     expectEquals(-75, reductionByteM1(xb));
637     expectEquals(-27467, reductionShortM1(xs));
638     expectEquals(38069, reductionCharM1(xc));
639     expectEquals(365749, reductionIntM1(xi));
640     expectEquals(365749L, reductionLongM1(xl));
641     expectEquals(74, reductionMinusByte(xb));
642     expectEquals(27466, reductionMinusShort(xs));
643     expectEquals(27466, reductionMinusChar(xc));
644     expectEquals(-365750, reductionMinusInt(xi));
645     expectEquals(365750L, reductionLong(xl));
646     expectEquals(-75, reductionByteM1(xb));
647     expectEquals(-27467, reductionShortM1(xs));
648     expectEquals(38069, reductionCharM1(xc));
649     expectEquals(365749, reductionIntM1(xi));
650     expectEquals(365749L, reductionLongM1(xl));
651     expectEquals(74, reductionMinusByte(xb));
652     expectEquals(27466, reductionMinusShort(xs));
653     expectEquals(27466, reductionMinusChar(xc));
654     expectEquals(-365750, reductionMinusInt(xi));
655     expectEquals(-365750L, reductionMinusLong(xl));
656 
657     // Test special cases.
658     expectEquals(13, reductionInt10(xi));
659     expectEquals(-13, reductionMinusInt10(xi));
660 
661     System.out.println("passed");
662   }
663 
expectEquals(int expected, int result)664   private static void expectEquals(int expected, int result) {
665     if (expected != result) {
666       throw new Error("Expected: " + expected + ", found: " + result);
667     }
668   }
669 
expectEquals(long expected, long result)670   private static void expectEquals(long expected, long result) {
671     if (expected != result) {
672       throw new Error("Expected: " + expected + ", found: " + result);
673     }
674   }
675 }
676