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