From 914f9f34594404ad91c05e9f8819e0b2187eb459 Mon Sep 17 00:00:00 2001 From: "Edward Nevill edward.nevill@linaro.org" Date: Mon, 7 Jul 2014 16:24:51 +0100 Subject: Add support for MathExact intrinsics --- src/cpu/aarch64/vm/aarch64.ad | 133 +++++++++++++++++++++ .../intrinsics/mathexact/sanity/IntrinsicBase.java | 4 +- .../com/oracle/java/testlibrary/Platform.java | 4 + 3 files changed, 139 insertions(+), 2 deletions(-) diff --git a/src/cpu/aarch64/vm/aarch64.ad b/src/cpu/aarch64/vm/aarch64.ad index 3a912e104..12367469d 100644 --- a/src/cpu/aarch64/vm/aarch64.ad +++ b/src/cpu/aarch64/vm/aarch64.ad @@ -10469,6 +10469,139 @@ instruct clearArray_reg_reg(iRegL_R11 cnt, iRegP_R10 base, Universe dummy, rFlag ins_pipe(pipe_class_memory); %} +// ============================================================================ +// Overflow Math Instructions + +instruct overflowAddI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2) +%{ + match(Set cr (OverflowAddI op1 op2)); + + format %{ "cmnw $op1, $op2\t# overflow check int" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmnw($op1$$Register, $op2$$Register); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowAddI_reg_imm(rFlagsReg cr, iRegI op1, immIAddSub op2) +%{ + match(Set cr (OverflowAddI op1 op2)); + + format %{ "cmnw $op1, $op2\t# overflow check int" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmnw($op1$$Register, $op2$$constant); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowAddL_reg_reg(rFlagsReg cr, iRegL op1, iRegL op2) +%{ + match(Set cr (OverflowAddL op1 op2)); + + format %{ "cmn $op1, $op2\t# overflow check long" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmn($op1$$Register, $op2$$Register); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowAddL_reg_imm(rFlagsReg cr, iRegL op1, immLAddSub op2) +%{ + match(Set cr (OverflowAddL op1 op2)); + + format %{ "cmn $op1, $op2\t# overflow check long" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmn($op1$$Register, $op2$$constant); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowSubI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2) +%{ + match(Set cr (OverflowSubI op1 op2)); + + format %{ "cmpw $op1, $op2\t# overflow check int" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmpw($op1$$Register, $op2$$Register); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowSubI_reg_imm(rFlagsReg cr, iRegI op1, immIAddSub op2) +%{ + match(Set cr (OverflowSubI op1 op2)); + + format %{ "cmpw $op1, $op2\t# overflow check int" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmpw($op1$$Register, $op2$$constant); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowSubL_reg_reg(rFlagsReg cr, iRegL op1, iRegL op2) +%{ + match(Set cr (OverflowSubL op1 op2)); + + format %{ "cmp $op1, $op2\t# overflow check long" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmp($op1$$Register, $op2$$Register); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowSubL_reg_imm(rFlagsReg cr, iRegL op1, immLAddSub op2) +%{ + match(Set cr (OverflowSubL op1 op2)); + + format %{ "cmp $op1, $op2\t# overflow check long" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmp($op1$$Register, $op2$$constant); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowNegI_reg(rFlagsReg cr, immI0 zero, iRegI op2) +%{ + match(Set cr (OverflowSubI zero op2)); + + format %{ "cmpw zr, $op2\t# overflow check int" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmpw(zr, $op2$$Register); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowNegL_reg(rFlagsReg cr, immI0 zero, iRegL op2) +%{ + match(Set cr (OverflowSubL zero op2)); + + format %{ "cmp zr, $op2\t# overflow check long" %} + ins_cost(INSN_COST); + ins_encode %{ + __ cmp(zr, $op2$$Register); + %} + + ins_pipe(pipe_class_default); +%} + // ============================================================================ // Compare Instructions diff --git a/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java b/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java index cecd6ce2d..337007dd7 100644 --- a/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java +++ b/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java @@ -128,7 +128,7 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest { @Override protected boolean isIntrinsicSupported() { - return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && (Platform.isX86() || Platform.isX64()); + return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && (Platform.isX86() || Platform.isX64() || Platform.isAArch64()); } @Override @@ -144,7 +144,7 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest { @Override protected boolean isIntrinsicSupported() { - return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && Platform.isX64(); + return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && (Platform.isX64() || Platform.isAArch64()); } @Override diff --git a/test/testlibrary/com/oracle/java/testlibrary/Platform.java b/test/testlibrary/com/oracle/java/testlibrary/Platform.java index fa4b36361..9bce59585 100644 --- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java +++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java @@ -113,6 +113,10 @@ public class Platform { return (isArch("amd64") || isArch("x86_64")); } + public static boolean isAArch64() { + return isArch("aarch64"); + } + private static boolean isArch(String archname) { return osArch.toLowerCase().startsWith(archname.toLowerCase()); } -- cgit v1.2.3 From ae2174287dc0eaa9e54382ec730d8bacaba7379d Mon Sep 17 00:00:00 2001 From: "Edward Nevill edward.nevill@linaro.org" Date: Mon, 7 Jul 2014 16:25:52 +0100 Subject: Add support for multiplyExact --- src/cpu/aarch64/vm/aarch64.ad | 90 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/cpu/aarch64/vm/aarch64.ad b/src/cpu/aarch64/vm/aarch64.ad index 12367469d..5031373d2 100644 --- a/src/cpu/aarch64/vm/aarch64.ad +++ b/src/cpu/aarch64/vm/aarch64.ad @@ -10602,6 +10602,96 @@ instruct overflowNegL_reg(rFlagsReg cr, immI0 zero, iRegL op2) ins_pipe(pipe_class_default); %} +instruct overflowMulI_reg(rFlagsReg cr, iRegI op1, iRegI op2) +%{ + match(Set cr (OverflowMulI op1 op2)); + + format %{ "smull rscratch1, $op1, $op2\t# overflow check int\n\t" + "cmp rscratch1, rscratch1, sxtw\n\t" + "movw rscratch1, #0x80000000\n\t" + "cselw rscratch1, rscratch1, zr, NE\n\t" + "cmpw rscratch1, #1" %} + ins_cost(5 * INSN_COST); + ins_encode %{ + __ smull(rscratch1, $op1$$Register, $op2$$Register); + __ subs(zr, rscratch1, rscratch1, ext::sxtw); // NE => overflow + __ movw(rscratch1, 0x80000000); // Develop 0 (EQ), + __ cselw(rscratch1, rscratch1, zr, Assembler::NE); // or 0x80000000 (NE) + __ cmpw(rscratch1, 1); // 0x80000000 - 1 => VS + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowMulI_reg_branch(cmpOp cmp, iRegI op1, iRegI op2, label labl, rFlagsReg cr) +%{ + match(If cmp (OverflowMulI op1 op2)); + predicate(n->in(1)->as_Bool()->_test._test == BoolTest::overflow + || n->in(1)->as_Bool()->_test._test == BoolTest::no_overflow); + effect(USE labl, KILL cr); + + format %{ "smull rscratch1, $op1, $op2\t# overflow check int\n\t" + "cmp rscratch1, rscratch1, sxtw\n\t" + "b$cmp $labl" %} + ins_cost(3 * INSN_COST); // Branch is rare so treat as INSN_COST + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + __ smull(rscratch1, $op1$$Register, $op2$$Register); + __ subs(zr, rscratch1, rscratch1, ext::sxtw); // NE => overflow + __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L); + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowMulL_reg(rFlagsReg cr, iRegL op1, iRegL op2) +%{ + match(Set cr (OverflowMulL op1 op2)); + + format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t" + "smulh rscratch2, $op1, $op2\n\t" + "cmp rscratch2, rscratch1, ASR #31\n\t" + "movw rscratch1, #0x80000000\n\t" + "cselw rscratch1, rscratch1, zr, NE\n\t" + "cmpw rscratch1, #1" %} + ins_cost(6 * INSN_COST); + ins_encode %{ + __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63 + __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127 + __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext + __ movw(rscratch1, 0x80000000); // Develop 0 (EQ), + __ cselw(rscratch1, rscratch1, zr, Assembler::NE); // or 0x80000000 (NE) + __ cmpw(rscratch1, 1); // 0x80000000 - 1 => VS + %} + + ins_pipe(pipe_class_default); +%} + +instruct overflowMulL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, rFlagsReg cr) +%{ + match(If cmp (OverflowMulL op1 op2)); + predicate(n->in(1)->as_Bool()->_test._test == BoolTest::overflow + || n->in(1)->as_Bool()->_test._test == BoolTest::no_overflow); + effect(USE labl, KILL cr); + + format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t" + "smulh rscratch2, $op1, $op2\n\t" + "cmp rscratch2, rscratch1, ASR #31\n\t" + "b$cmp $labl" %} + ins_cost(4 * INSN_COST); // Branch is rare so treat as INSN_COST + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63 + __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127 + __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext + __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L); + %} + + ins_pipe(pipe_class_default); +%} + // ============================================================================ // Compare Instructions -- cgit v1.2.3