| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| public class Main { |
| |
| public static void assertIntEquals(int expected, int result) { |
| if (expected != result) { |
| throw new Error("Expected: " + expected + ", found: " + result); |
| } |
| } |
| |
| public static void assertLongEquals(long expected, long result) { |
| if (expected != result) { |
| throw new Error("Expected: " + expected + ", found: " + result); |
| } |
| } |
| |
| /** |
| * Test basic merging of `MUL+ADD` into `MULADD`. |
| */ |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: Return [<<Add>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Add |
| /// CHECK: Return [<<MulAdd>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Add |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulAdd(int, int, int) disassembly (after) |
| /// CHECK: madd w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}} |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (before) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: Return [<<Add>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (after) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Add |
| /// CHECK: Return [<<MulAdd>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) instruction_simplifier_arm (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Add |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulAdd(int, int, int) disassembly (after) |
| /// CHECK: mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}} |
| |
| public static int $opt$noinline$mulAdd(int acc, int left, int right) { |
| return acc + left * right; |
| } |
| |
| /** |
| * Test basic merging of `MUL+SUB` into `MULSUB`. |
| */ |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] |
| /// CHECK: Return [<<Sub>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<MulSub:j\d+>> MultiplyAccumulate [<<Acc>>,<<Left>>,<<Right>>] kind:Sub |
| /// CHECK: Return [<<MulSub>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Sub |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulSub(long, long, long) disassembly (after) |
| /// CHECK: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}} |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm (before) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] |
| /// CHECK: Return [<<Sub>>] |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$mulSub(long, long, long) instruction_simplifier_arm (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| |
| public static long $opt$noinline$mulSub(long acc, long left, long right) { |
| return acc - left * right; |
| } |
| |
| /** |
| * Test that we do not create a multiply-accumulate instruction when there |
| * are other uses of the multiplication that cannot merge it. |
| */ |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] |
| /// CHECK: Return [<<Or>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] |
| /// CHECK: Return [<<Or>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (before) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] |
| /// CHECK: Return [<<Or>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (after) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:i\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Or:i\d+>> Or [<<Mul>>,<<Add>>] |
| /// CHECK: Return [<<Or>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$multipleUses1(int, int, int) instruction_simplifier_arm (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| |
| public static int $opt$noinline$multipleUses1(int acc, int left, int right) { |
| int temp = left * right; |
| return temp | (acc + temp); |
| } |
| |
| /** |
| * Test that we do not create a multiply-accumulate instruction even when all |
| * uses of the multiplication can merge it. |
| */ |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] |
| /// CHECK: Return [<<Res>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] |
| /// CHECK: Return [<<Res>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (before) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] |
| /// CHECK: Return [<<Res>>] |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (after) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Add:j\d+>> Add [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Sub:j\d+>> Sub [<<Acc>>,<<Mul>>] |
| /// CHECK: <<Res:j\d+>> Add [<<Add>>,<<Sub>>] |
| /// CHECK: Return [<<Res>>] |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$multipleUses2(long, long, long) instruction_simplifier_arm (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| |
| |
| public static long $opt$noinline$multipleUses2(long acc, long left, long right) { |
| long temp = left * right; |
| return (acc + temp) + (acc - temp); |
| } |
| |
| |
| /** |
| * Test the interpretation of `a * (b + 1)` as `a + (a * b)`. |
| */ |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Var:i\d+>> ParameterValue |
| /// CHECK: <<Const1:i\d+>> IntConstant 1 |
| /// CHECK: <<Add:i\d+>> Add [<<Var>>,<<Const1>>] |
| /// CHECK: <<Mul:i\d+>> Mul [<<Acc>>,<<Add>>] |
| /// CHECK: Return [<<Mul>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Var:i\d+>> ParameterValue |
| /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Add |
| /// CHECK: Return [<<MulAdd>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Add |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulPlusOne(int, int) disassembly (after) |
| /// CHECK: madd w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}} |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (before) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Var:i\d+>> ParameterValue |
| /// CHECK: <<Const1:i\d+>> IntConstant 1 |
| /// CHECK: <<Add:i\d+>> Add [<<Var>>,<<Const1>>] |
| /// CHECK: <<Mul:i\d+>> Mul [<<Acc>>,<<Add>>] |
| /// CHECK: Return [<<Mul>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (after) |
| /// CHECK: <<Acc:i\d+>> ParameterValue |
| /// CHECK: <<Var:i\d+>> ParameterValue |
| /// CHECK: <<MulAdd:i\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Add |
| /// CHECK: Return [<<MulAdd>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) instruction_simplifier_arm (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Add |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulPlusOne(int, int) disassembly (after) |
| /// CHECK: mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}} |
| |
| public static int $opt$noinline$mulPlusOne(int acc, int var) { |
| return acc * (var + 1); |
| } |
| |
| |
| /** |
| * Test the interpretation of `a * (1 - b)` as `a - (a * b)`. |
| */ |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Var:j\d+>> ParameterValue |
| /// CHECK: <<Const1:j\d+>> LongConstant 1 |
| /// CHECK: <<Sub:j\d+>> Sub [<<Const1>>,<<Var>>] |
| /// CHECK: <<Mul:j\d+>> Mul [<<Acc>>,<<Sub>>] |
| /// CHECK: Return [<<Mul>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Var:j\d+>> ParameterValue |
| /// CHECK: <<MulSub:j\d+>> MultiplyAccumulate [<<Acc>>,<<Acc>>,<<Var>>] kind:Sub |
| /// CHECK: Return [<<MulSub>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Sub |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulMinusOne(long, long) disassembly (after) |
| /// CHECK: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}} |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm (before) |
| /// CHECK: <<Acc:j\d+>> ParameterValue |
| /// CHECK: <<Var:j\d+>> ParameterValue |
| /// CHECK: <<Const1:j\d+>> LongConstant 1 |
| /// CHECK: <<Sub:j\d+>> Sub [<<Const1>>,<<Var>>] |
| /// CHECK: <<Mul:j\d+>> Mul [<<Acc>>,<<Sub>>] |
| /// CHECK: Return [<<Mul>>] |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| public static long $opt$noinline$mulMinusOne(long acc, long var) { |
| return acc * (1 - var); |
| } |
| |
| /** |
| * Test basic merging of `MUL+NEG` into `MULNEG`. |
| */ |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>] |
| /// CHECK: Return [<<Neg>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Const0:i\d+>> IntConstant 0 |
| /// CHECK: <<MulNeg:i\d+>> MultiplyAccumulate [<<Const0>>,<<Left>>,<<Right>>] kind:Sub |
| /// CHECK: Return [<<MulNeg>>] |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Neg |
| |
| /// CHECK-START-ARM64: int Main.$opt$noinline$mulNeg(int, int) disassembly (after) |
| /// CHECK: mneg w{{\d+}}, w{{\d+}}, w{{\d+}} |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (before) |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>] |
| /// CHECK: Return [<<Neg>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (after) |
| /// CHECK: <<Left:i\d+>> ParameterValue |
| /// CHECK: <<Right:i\d+>> ParameterValue |
| /// CHECK: <<Mul:i\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Neg:i\d+>> Neg [<<Mul>>] |
| /// CHECK: Return [<<Neg>>] |
| |
| /// CHECK-START-ARM: int Main.$opt$noinline$mulNeg(int, int) instruction_simplifier_arm (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| |
| public static int $opt$noinline$mulNeg(int left, int right) { |
| return - (left * right); |
| } |
| |
| /** |
| * Test basic merging of `MUL+NEG` into `MULNEG`. |
| */ |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (before) |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>] |
| /// CHECK: Return [<<Neg>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (after) |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Const0:j\d+>> LongConstant 0 |
| /// CHECK: <<MulNeg:j\d+>> MultiplyAccumulate [<<Const0>>,<<Left>>,<<Right>>] kind:Sub |
| /// CHECK: Return [<<MulNeg>>] |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm64 (after) |
| /// CHECK-NOT: Mul |
| /// CHECK-NOT: Neg |
| |
| /// CHECK-START-ARM64: long Main.$opt$noinline$mulNeg(long, long) disassembly (after) |
| /// CHECK: mneg x{{\d+}}, x{{\d+}}, x{{\d+}} |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (before) |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>] |
| /// CHECK: Return [<<Neg>>] |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (after) |
| /// CHECK: <<Left:j\d+>> ParameterValue |
| /// CHECK: <<Right:j\d+>> ParameterValue |
| /// CHECK: <<Mul:j\d+>> Mul [<<Left>>,<<Right>>] |
| /// CHECK: <<Neg:j\d+>> Neg [<<Mul>>] |
| /// CHECK: Return [<<Neg>>] |
| |
| /// CHECK-START-ARM: long Main.$opt$noinline$mulNeg(long, long) instruction_simplifier_arm (after) |
| /// CHECK-NOT: MultiplyAccumulate |
| |
| public static long $opt$noinline$mulNeg(long left, long right) { |
| return - (left * right); |
| } |
| |
| /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier$after_loop_opt (before) |
| /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none |
| /// CHECK-DAG: VecAdd loop:<<Loop>> outer_loop:none |
| |
| /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier$after_loop_opt (after) |
| /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| /// CHECK-DAG: VecMultiplyAccumulate kind:Add loop:<<Loop>> outer_loop:none |
| |
| /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier$after_loop_opt (after) |
| /// CHECK-NOT: VecMul |
| /// CHECK-NOT: VecAdd |
| |
| public static void SimdMulAdd(int[] array1, int[] array2) { |
| for (int j = 0; j < 100; j++) { |
| array2[j] += 12345 * array1[j]; |
| } |
| } |
| |
| public static void SimdMulAddLong(long[] array1, long[] array2) { |
| for (int j = 0; j < 100; j++) { |
| array2[j] += 12345 * array1[j]; |
| } |
| } |
| |
| /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier$after_loop_opt (before) |
| /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none |
| /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none |
| |
| /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier$after_loop_opt (after) |
| /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| /// CHECK-DAG: VecMultiplyAccumulate kind:Sub loop:<<Loop>> outer_loop:none |
| |
| /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier$after_loop_opt (after) |
| /// CHECK-NOT: VecMul |
| /// CHECK-NOT: VecSub |
| |
| public static void SimdMulSub(int[] array1, int[] array2) { |
| for (int j = 0; j < 100; j++) { |
| array2[j] -= 12345 * array1[j]; |
| } |
| } |
| |
| public static void SimdMulSubLong(long[] array1, long[] array2) { |
| for (int j = 0; j < 100; j++) { |
| array2[j] -= 12345 * array1[j]; |
| } |
| } |
| |
| /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier$after_loop_opt (before) |
| /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none |
| /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none |
| |
| /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier$after_loop_opt (after) |
| /// CHECK-NOT: VecMultiplyAccumulate |
| |
| public static void SimdMulMultipleUses(int[] array1, int[] array2) { |
| for (int j = 0; j < 100; j++) { |
| int temp = 12345 * array1[j]; |
| array2[j] -= temp; |
| array1[j] = temp; |
| } |
| } |
| |
| public static void SimdMulMultipleUsesLong(long[] array1, long[] array2) { |
| for (int j = 0; j < 100; j++) { |
| long temp = 12345 * array1[j]; |
| array2[j] -= temp; |
| array1[j] = temp; |
| } |
| } |
| |
| public static final int ARRAY_SIZE = 1000; |
| |
| public static void initArray(int[] array) { |
| for (int i = 0; i < ARRAY_SIZE; i++) { |
| array[i] = i; |
| } |
| } |
| |
| public static void initArrayLong(long[] array) { |
| for (int i = 0; i < ARRAY_SIZE; i++) { |
| array[i] = i; |
| } |
| } |
| |
| public static int calcArraySum(int[] array) { |
| int sum = 0; |
| for (int i = 0; i < ARRAY_SIZE; i++) { |
| sum += array[i]; |
| } |
| return sum; |
| } |
| |
| public static long calcArraySumLong(long[] array) { |
| long sum = 0; |
| for (int i = 0; i < ARRAY_SIZE; i++) { |
| sum += array[i]; |
| } |
| return sum; |
| } |
| |
| public static void testSimdMultiplyAccumulate() { |
| int[] array1 = new int[ARRAY_SIZE]; |
| int[] array2 = new int[ARRAY_SIZE]; |
| long[] array3 = new long[ARRAY_SIZE]; |
| long[] array4 = new long[ARRAY_SIZE]; |
| |
| initArray(array1); |
| initArray(array2); |
| SimdMulSub(array1, array2); |
| assertIntEquals(-60608250, calcArraySum(array2)); |
| |
| initArrayLong(array3); |
| initArrayLong(array4); |
| SimdMulSubLong(array3, array4); |
| assertLongEquals(-60608250, calcArraySumLong(array4)); |
| |
| initArray(array1); |
| initArray(array2); |
| SimdMulAdd(array1, array2); |
| assertIntEquals(61607250, calcArraySum(array2)); |
| |
| initArrayLong(array3); |
| initArrayLong(array4); |
| SimdMulAddLong(array3, array4); |
| assertLongEquals(61607250, calcArraySumLong(array4)); |
| } |
| |
| public static void main(String[] args) { |
| assertIntEquals(7, $opt$noinline$mulAdd(1, 2, 3)); |
| assertLongEquals(-26, $opt$noinline$mulSub(4, 5, 6)); |
| assertIntEquals(79, $opt$noinline$multipleUses1(7, 8, 9)); |
| assertLongEquals(20, $opt$noinline$multipleUses2(10, 11, 12)); |
| assertIntEquals(195, $opt$noinline$mulPlusOne(13, 14)); |
| assertLongEquals(-225, $opt$noinline$mulMinusOne(15, 16)); |
| assertIntEquals(-306, $opt$noinline$mulNeg(17, 18)); |
| assertLongEquals(-380, $opt$noinline$mulNeg(19, 20)); |
| |
| testSimdMultiplyAccumulate(); |
| } |
| } |