1 /* 2 * Copyright (C) 2015 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 public class Main { 18 19 // A dummy value to defeat inlining of these routines. 20 static boolean doThrow = false; 21 assertIntEquals(int expected, int result)22 public static void assertIntEquals(int expected, int result) { 23 if (expected != result) { 24 throw new Error("Expected: " + expected + ", found: " + result); 25 } 26 } 27 assertLongEquals(long expected, long result)28 public static void assertLongEquals(long expected, long result) { 29 if (expected != result) { 30 throw new Error("Expected: " + expected + ", found: " + result); 31 } 32 } 33 34 /** 35 * Test basic merging of `MUL+ADD` into `MULADD`. 36 */ 37 38 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (before) 39 /// CHECK: <<Acc:i\d+>> ParameterValue 40 /// CHECK: <<Left:i\d+>> ParameterValue 41 /// CHECK: <<Right:i\d+>> ParameterValue 42 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 43 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] 44 /// CHECK: Return [<<Add>>] 45 46 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (after) 47 /// CHECK: <<Acc:i\d+>> ParameterValue 48 /// CHECK: <<Left:i\d+>> ParameterValue 49 /// CHECK: <<Right:i\d+>> ParameterValue 50 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Add 51 /// CHECK: Return [<<MulAdd>>] 52 53 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (after) 54 /// CHECK-NOT: Mul 55 /// CHECK-NOT: Add 56 57 /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) disassembly (after) 58 /// CHECK: madd w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}} 59 60 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (before) 61 /// CHECK: <<Acc:i\d+>> ParameterValue 62 /// CHECK: <<Left:i\d+>> ParameterValue 63 /// CHECK: <<Right:i\d+>> ParameterValue 64 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 65 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] 66 /// CHECK: Return [<<Add>>] 67 68 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (after) 69 /// CHECK: <<Acc:i\d+>> ParameterValue 70 /// CHECK: <<Left:i\d+>> ParameterValue 71 /// CHECK: <<Right:i\d+>> ParameterValue 72 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Add 73 /// CHECK: Return [<<MulAdd>>] 74 75 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (after) 76 /// CHECK-NOT: Mul 77 /// CHECK-NOT: Add 78 79 /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) disassembly (after) 80 /// CHECK: mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}} 81 $opt$noinline$mulAdd(int acc, int left, int right)82 public static int $opt$noinline$mulAdd(int acc, int left, int right) { 83 if (doThrow) throw new Error(); 84 return acc + left * right; 85 } 86 87 /** 88 * Test basic merging of `MUL+SUB` into `MULSUB`. 89 */ 90 91 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (before) 92 /// CHECK: <<Acc:j\d+>> ParameterValue 93 /// CHECK: <<Left:j\d+>> ParameterValue 94 /// CHECK: <<Right:j\d+>> ParameterValue 95 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 96 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] 97 /// CHECK: Return [<<Sub>>] 98 99 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (after) 100 /// CHECK: <<Acc:j\d+>> ParameterValue 101 /// CHECK: <<Left:j\d+>> ParameterValue 102 /// CHECK: <<Right:j\d+>> ParameterValue 103 /// CHECK: <<MulSub:j\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Sub 104 /// CHECK: Return [<<MulSub>>] 105 106 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (after) 107 /// CHECK-NOT: Mul 108 /// CHECK-NOT: Sub 109 110 /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) disassembly (after) 111 /// CHECK: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}} 112 113 /// CHECK-START-ARM: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm (before) 114 /// CHECK: <<Acc:j\d+>> ParameterValue 115 /// CHECK: <<Left:j\d+>> ParameterValue 116 /// CHECK: <<Right:j\d+>> ParameterValue 117 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 118 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] 119 /// CHECK: Return [<<Sub>>] 120 121 /// CHECK-START-ARM: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm (after) 122 /// CHECK-NOT: MultiplyAccumulate 123 $opt$noinline$mulSub(long acc, long left, long right)124 public static long $opt$noinline$mulSub(long acc, long left, long right) { 125 if (doThrow) throw new Error(); 126 return acc - left * right; 127 } 128 129 /** 130 * Test that we do not create a multiply-accumulate instruction when there 131 * are other uses of the multiplication that cannot merge it. 132 */ 133 134 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (before) 135 /// CHECK: <<Acc:i\d+>> ParameterValue 136 /// CHECK: <<Left:i\d+>> ParameterValue 137 /// CHECK: <<Right:i\d+>> ParameterValue 138 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 139 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] 140 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] 141 /// CHECK: Return [<<Or>>] 142 143 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (after) 144 /// CHECK: <<Acc:i\d+>> ParameterValue 145 /// CHECK: <<Left:i\d+>> ParameterValue 146 /// CHECK: <<Right:i\d+>> ParameterValue 147 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 148 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] 149 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] 150 /// CHECK: Return [<<Or>>] 151 152 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (after) 153 /// CHECK-NOT: MultiplyAccumulate 154 155 /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (before) 156 /// CHECK: <<Acc:i\d+>> ParameterValue 157 /// CHECK: <<Left:i\d+>> ParameterValue 158 /// CHECK: <<Right:i\d+>> ParameterValue 159 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 160 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] 161 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] 162 /// CHECK: Return [<<Or>>] 163 164 /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (after) 165 /// CHECK: <<Acc:i\d+>> ParameterValue 166 /// CHECK: <<Left:i\d+>> ParameterValue 167 /// CHECK: <<Right:i\d+>> ParameterValue 168 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 169 /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] 170 /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] 171 /// CHECK: Return [<<Or>>] 172 173 /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (after) 174 /// CHECK-NOT: MultiplyAccumulate 175 $opt$noinline$multipleUses1(int acc, int left, int right)176 public static int $opt$noinline$multipleUses1(int acc, int left, int right) { 177 if (doThrow) throw new Error(); 178 int temp = left * right; 179 return temp | (acc + temp); 180 } 181 182 /** 183 * Test that we do not create a multiply-accumulate instruction even when all 184 * uses of the multiplication can merge it. 185 */ 186 187 /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (before) 188 /// CHECK: <<Acc:j\d+>> ParameterValue 189 /// CHECK: <<Left:j\d+>> ParameterValue 190 /// CHECK: <<Right:j\d+>> ParameterValue 191 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 192 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] 193 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] 194 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] 195 /// CHECK: Return [<<Res>>] 196 197 /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (after) 198 /// CHECK: <<Acc:j\d+>> ParameterValue 199 /// CHECK: <<Left:j\d+>> ParameterValue 200 /// CHECK: <<Right:j\d+>> ParameterValue 201 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 202 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] 203 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] 204 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] 205 /// CHECK: Return [<<Res>>] 206 207 /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (after) 208 /// CHECK-NOT: MultiplyAccumulate 209 210 /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (before) 211 /// CHECK: <<Acc:j\d+>> ParameterValue 212 /// CHECK: <<Left:j\d+>> ParameterValue 213 /// CHECK: <<Right:j\d+>> ParameterValue 214 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 215 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] 216 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] 217 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] 218 /// CHECK: Return [<<Res>>] 219 220 /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (after) 221 /// CHECK: <<Acc:j\d+>> ParameterValue 222 /// CHECK: <<Left:j\d+>> ParameterValue 223 /// CHECK: <<Right:j\d+>> ParameterValue 224 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 225 /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] 226 /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] 227 /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] 228 /// CHECK: Return [<<Res>>] 229 230 /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (after) 231 /// CHECK-NOT: MultiplyAccumulate 232 233 $opt$noinline$multipleUses2(long acc, long left, long right)234 public static long $opt$noinline$multipleUses2(long acc, long left, long right) { 235 if (doThrow) throw new Error(); 236 long temp = left * right; 237 return (acc + temp) + (acc - temp); 238 } 239 240 241 /** 242 * Test the interpretation of `a * (b + 1)` as `a + (a * b)`. 243 */ 244 245 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (before) 246 /// CHECK: <<Acc:i\d+>> ParameterValue 247 /// CHECK: <<Var:i\d+>> ParameterValue 248 /// CHECK: <<Const1:i\d+>> IntConstant 1 249 /// CHECK: <<Add:i\d+>> Add [<<Var>>,<<Const1>>] 250 /// CHECK: <<Mul:i\d+>> Mul [<<Acc>>,<<Add>>] 251 /// CHECK: Return [<<Mul>>] 252 253 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (after) 254 /// CHECK: <<Acc:i\d+>> ParameterValue 255 /// CHECK: <<Var:i\d+>> ParameterValue 256 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Add 257 /// CHECK: Return [<<MulAdd>>] 258 259 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (after) 260 /// CHECK-NOT: Mul 261 /// CHECK-NOT: Add 262 263 /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) disassembly (after) 264 /// CHECK: madd w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}} 265 266 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (before) 267 /// CHECK: <<Acc:i\d+>> ParameterValue 268 /// CHECK: <<Var:i\d+>> ParameterValue 269 /// CHECK: <<Const1:i\d+>> IntConstant 1 270 /// CHECK: <<Add:i\d+>> Add [<<Var>>,<<Const1>>] 271 /// CHECK: <<Mul:i\d+>> Mul [<<Acc>>,<<Add>>] 272 /// CHECK: Return [<<Mul>>] 273 274 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (after) 275 /// CHECK: <<Acc:i\d+>> ParameterValue 276 /// CHECK: <<Var:i\d+>> ParameterValue 277 /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Add 278 /// CHECK: Return [<<MulAdd>>] 279 280 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (after) 281 /// CHECK-NOT: Mul 282 /// CHECK-NOT: Add 283 284 /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) disassembly (after) 285 /// CHECK: mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}} 286 $opt$noinline$mulPlusOne(int acc, int var)287 public static int $opt$noinline$mulPlusOne(int acc, int var) { 288 if (doThrow) throw new Error(); 289 return acc * (var + 1); 290 } 291 292 293 /** 294 * Test the interpretation of `a * (1 - b)` as `a - (a * b)`. 295 */ 296 297 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (before) 298 /// CHECK: <<Acc:j\d+>> ParameterValue 299 /// CHECK: <<Var:j\d+>> ParameterValue 300 /// CHECK: <<Const1:j\d+>> LongConstant 1 301 /// CHECK: <<Sub:j\d+>> Sub [<<Const1>>,<<Var>>] 302 /// CHECK: <<Mul:j\d+>> Mul [<<Acc>>,<<Sub>>] 303 /// CHECK: Return [<<Mul>>] 304 305 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (after) 306 /// CHECK: <<Acc:j\d+>> ParameterValue 307 /// CHECK: <<Var:j\d+>> ParameterValue 308 /// CHECK: <<MulSub:j\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Sub 309 /// CHECK: Return [<<MulSub>>] 310 311 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (after) 312 /// CHECK-NOT: Mul 313 /// CHECK-NOT: Sub 314 315 /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) disassembly (after) 316 /// CHECK: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}} 317 318 /// CHECK-START-ARM: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm (before) 319 /// CHECK: <<Acc:j\d+>> ParameterValue 320 /// CHECK: <<Var:j\d+>> ParameterValue 321 /// CHECK: <<Const1:j\d+>> LongConstant 1 322 /// CHECK: <<Sub:j\d+>> Sub [<<Const1>>,<<Var>>] 323 /// CHECK: <<Mul:j\d+>> Mul [<<Acc>>,<<Sub>>] 324 /// CHECK: Return [<<Mul>>] 325 326 /// CHECK-START-ARM: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm (after) 327 /// CHECK-NOT: MultiplyAccumulate $opt$noinline$mulMinusOne(long acc, long var)328 public static long $opt$noinline$mulMinusOne(long acc, long var) { 329 if (doThrow) throw new Error(); 330 return acc * (1 - var); 331 } 332 333 /** 334 * Test basic merging of `MUL+NEG` into `MULNEG`. 335 */ 336 337 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (before) 338 /// CHECK: <<Left:i\d+>> ParameterValue 339 /// CHECK: <<Right:i\d+>> ParameterValue 340 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 341 /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>] 342 /// CHECK: Return [<<Neg>>] 343 344 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (after) 345 /// CHECK: <<Left:i\d+>> ParameterValue 346 /// CHECK: <<Right:i\d+>> ParameterValue 347 /// CHECK: <<Const0:i\d+>> IntConstant 0 348 /// CHECK: <<MulNeg:i\d+>> MultiplyAccumulate [<<Const0>>,<<Left>>,<<Right>>] kind:Sub 349 /// CHECK: Return [<<MulNeg>>] 350 351 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (after) 352 /// CHECK-NOT: Mul 353 /// CHECK-NOT: Neg 354 355 /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) disassembly (after) 356 /// CHECK: mneg w{{\d+}}, w{{\d+}}, w{{\d+}} 357 358 /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (before) 359 /// CHECK: <<Left:i\d+>> ParameterValue 360 /// CHECK: <<Right:i\d+>> ParameterValue 361 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 362 /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>] 363 /// CHECK: Return [<<Neg>>] 364 365 /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (after) 366 /// CHECK: <<Left:i\d+>> ParameterValue 367 /// CHECK: <<Right:i\d+>> ParameterValue 368 /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] 369 /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>] 370 /// CHECK: Return [<<Neg>>] 371 372 /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (after) 373 /// CHECK-NOT: MultiplyAccumulate 374 $opt$noinline$mulNeg(int left, int right)375 public static int $opt$noinline$mulNeg(int left, int right) { 376 if (doThrow) throw new Error(); 377 return - (left * right); 378 } 379 380 /** 381 * Test basic merging of `MUL+NEG` into `MULNEG`. 382 */ 383 384 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (before) 385 /// CHECK: <<Left:j\d+>> ParameterValue 386 /// CHECK: <<Right:j\d+>> ParameterValue 387 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 388 /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>] 389 /// CHECK: Return [<<Neg>>] 390 391 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (after) 392 /// CHECK: <<Left:j\d+>> ParameterValue 393 /// CHECK: <<Right:j\d+>> ParameterValue 394 /// CHECK: <<Const0:j\d+>> LongConstant 0 395 /// CHECK: <<MulNeg:j\d+>> MultiplyAccumulate [<<Const0>>,<<Left>>,<<Right>>] kind:Sub 396 /// CHECK: Return [<<MulNeg>>] 397 398 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (after) 399 /// CHECK-NOT: Mul 400 /// CHECK-NOT: Neg 401 402 /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) disassembly (after) 403 /// CHECK: mneg x{{\d+}}, x{{\d+}}, x{{\d+}} 404 405 /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (before) 406 /// CHECK: <<Left:j\d+>> ParameterValue 407 /// CHECK: <<Right:j\d+>> ParameterValue 408 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 409 /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>] 410 /// CHECK: Return [<<Neg>>] 411 412 /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (after) 413 /// CHECK: <<Left:j\d+>> ParameterValue 414 /// CHECK: <<Right:j\d+>> ParameterValue 415 /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] 416 /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>] 417 /// CHECK: Return [<<Neg>>] 418 419 /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (after) 420 /// CHECK-NOT: MultiplyAccumulate 421 $opt$noinline$mulNeg(long left, long right)422 public static long $opt$noinline$mulNeg(long left, long right) { 423 if (doThrow) throw new Error(); 424 return - (left * right); 425 } 426 427 /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier$after_bce (before) 428 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 429 /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none 430 /// CHECK-DAG: VecAdd loop:<<Loop>> outer_loop:none 431 432 /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier$after_bce (after) 433 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 434 /// CHECK-DAG: VecMultiplyAccumulate kind:Add loop:<<Loop>> outer_loop:none 435 436 /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier$after_bce (after) 437 /// CHECK-NOT: VecMul 438 /// CHECK-NOT: VecAdd 439 SimdMulAdd(int[] array1, int[] array2)440 public static void SimdMulAdd(int[] array1, int[] array2) { 441 for (int j = 0; j < 100; j++) { 442 array2[j] += 12345 * array1[j]; 443 } 444 } 445 SimdMulAddLong(long[] array1, long[] array2)446 public static void SimdMulAddLong(long[] array1, long[] array2) { 447 for (int j = 0; j < 100; j++) { 448 array2[j] += 12345 * array1[j]; 449 } 450 } 451 452 /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier$after_bce (before) 453 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 454 /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none 455 /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none 456 457 /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier$after_bce (after) 458 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 459 /// CHECK-DAG: VecMultiplyAccumulate kind:Sub loop:<<Loop>> outer_loop:none 460 461 /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier$after_bce (after) 462 /// CHECK-NOT: VecMul 463 /// CHECK-NOT: VecSub 464 SimdMulSub(int[] array1, int[] array2)465 public static void SimdMulSub(int[] array1, int[] array2) { 466 for (int j = 0; j < 100; j++) { 467 array2[j] -= 12345 * array1[j]; 468 } 469 } 470 SimdMulSubLong(long[] array1, long[] array2)471 public static void SimdMulSubLong(long[] array1, long[] array2) { 472 for (int j = 0; j < 100; j++) { 473 array2[j] -= 12345 * array1[j]; 474 } 475 } 476 477 /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier$after_bce (before) 478 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 479 /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none 480 /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none 481 482 /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier$after_bce (after) 483 /// CHECK-NOT: VecMultiplyAccumulate 484 SimdMulMultipleUses(int[] array1, int[] array2)485 public static void SimdMulMultipleUses(int[] array1, int[] array2) { 486 for (int j = 0; j < 100; j++) { 487 int temp = 12345 * array1[j]; 488 array2[j] -= temp; 489 array1[j] = temp; 490 } 491 } 492 SimdMulMultipleUsesLong(long[] array1, long[] array2)493 public static void SimdMulMultipleUsesLong(long[] array1, long[] array2) { 494 for (int j = 0; j < 100; j++) { 495 long temp = 12345 * array1[j]; 496 array2[j] -= temp; 497 array1[j] = temp; 498 } 499 } 500 501 public static final int ARRAY_SIZE = 1000; 502 initArray(int[] array)503 public static void initArray(int[] array) { 504 for (int i = 0; i < ARRAY_SIZE; i++) { 505 array[i] = i; 506 } 507 } 508 initArrayLong(long[] array)509 public static void initArrayLong(long[] array) { 510 for (int i = 0; i < ARRAY_SIZE; i++) { 511 array[i] = i; 512 } 513 } 514 calcArraySum(int[] array)515 public static int calcArraySum(int[] array) { 516 int sum = 0; 517 for (int i = 0; i < ARRAY_SIZE; i++) { 518 sum += array[i]; 519 } 520 return sum; 521 } 522 calcArraySumLong(long[] array)523 public static long calcArraySumLong(long[] array) { 524 long sum = 0; 525 for (int i = 0; i < ARRAY_SIZE; i++) { 526 sum += array[i]; 527 } 528 return sum; 529 } 530 testSimdMultiplyAccumulate()531 public static void testSimdMultiplyAccumulate() { 532 int[] array1 = new int[ARRAY_SIZE]; 533 int[] array2 = new int[ARRAY_SIZE]; 534 long[] array3 = new long[ARRAY_SIZE]; 535 long[] array4 = new long[ARRAY_SIZE]; 536 537 initArray(array1); 538 initArray(array2); 539 SimdMulSub(array1, array2); 540 assertIntEquals(-60608250, calcArraySum(array2)); 541 542 initArrayLong(array3); 543 initArrayLong(array4); 544 SimdMulSubLong(array3, array4); 545 assertLongEquals(-60608250, calcArraySumLong(array4)); 546 547 initArray(array1); 548 initArray(array2); 549 SimdMulAdd(array1, array2); 550 assertIntEquals(61607250, calcArraySum(array2)); 551 552 initArrayLong(array3); 553 initArrayLong(array4); 554 SimdMulAddLong(array3, array4); 555 assertLongEquals(61607250, calcArraySumLong(array4)); 556 } 557 main(String[] args)558 public static void main(String[] args) { 559 assertIntEquals(7, $opt$noinline$mulAdd(1, 2, 3)); 560 assertLongEquals(-26, $opt$noinline$mulSub(4, 5, 6)); 561 assertIntEquals(79, $opt$noinline$multipleUses1(7, 8, 9)); 562 assertLongEquals(20, $opt$noinline$multipleUses2(10, 11, 12)); 563 assertIntEquals(195, $opt$noinline$mulPlusOne(13, 14)); 564 assertLongEquals(-225, $opt$noinline$mulMinusOne(15, 16)); 565 assertIntEquals(-306, $opt$noinline$mulNeg(17, 18)); 566 assertLongEquals(-380, $opt$noinline$mulNeg(19, 20)); 567 568 testSimdMultiplyAccumulate(); 569 } 570 } 571