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