summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc29
-rw-r--r--test/411-checker-hdiv-hrem-pow2/src/DivTest.java12
2 files changed, 33 insertions, 8 deletions
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 14cff05f58..e7212cd479 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -3608,9 +3608,17 @@ void InstructionCodeGeneratorX86_64::DivByPowerOfTwo(HDiv* instruction) {
CpuRegister tmp = locations->GetTemp(0).AsRegister<CpuRegister>();
if (instruction->GetResultType() == DataType::Type::kInt32) {
- __ leal(tmp, Address(numerator, abs_imm - 1));
- __ testl(numerator, numerator);
- __ cmov(kGreaterEqual, tmp, numerator);
+ // When denominator is equal to 2, we can add signed bit and numerator to tmp.
+ // Below we are using addl instruction instead of cmov which give us 1 cycle benefit.
+ if (abs_imm == 2) {
+ __ leal(tmp, Address(numerator, 0));
+ __ shrl(tmp, Immediate(31));
+ __ addl(tmp, numerator);
+ } else {
+ __ leal(tmp, Address(numerator, abs_imm - 1));
+ __ testl(numerator, numerator);
+ __ cmov(kGreaterEqual, tmp, numerator);
+ }
int shift = CTZ(imm);
__ sarl(tmp, Immediate(shift));
@@ -3622,11 +3630,16 @@ void InstructionCodeGeneratorX86_64::DivByPowerOfTwo(HDiv* instruction) {
} else {
DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64);
CpuRegister rdx = locations->GetTemp(0).AsRegister<CpuRegister>();
-
- codegen_->Load64BitValue(rdx, abs_imm - 1);
- __ addq(rdx, numerator);
- __ testq(numerator, numerator);
- __ cmov(kGreaterEqual, rdx, numerator);
+ if (abs_imm == 2) {
+ __ movq(rdx, numerator);
+ __ shrq(rdx, Immediate(63));
+ __ addq(rdx, numerator);
+ } else {
+ codegen_->Load64BitValue(rdx, abs_imm - 1);
+ __ addq(rdx, numerator);
+ __ testq(numerator, numerator);
+ __ cmov(kGreaterEqual, rdx, numerator);
+ }
int shift = CTZ(imm);
__ sarq(rdx, Immediate(shift));
diff --git a/test/411-checker-hdiv-hrem-pow2/src/DivTest.java b/test/411-checker-hdiv-hrem-pow2/src/DivTest.java
index a3882e7c15..1a086ef04d 100644
--- a/test/411-checker-hdiv-hrem-pow2/src/DivTest.java
+++ b/test/411-checker-hdiv-hrem-pow2/src/DivTest.java
@@ -94,6 +94,9 @@ public class DivTest {
/// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntDivBy2(int) disassembly (after)
/// CHECK: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
/// CHECK: asr w{{\d+}}, w{{\d+}}, #1
+ /// CHECK-START-X86_64: java.lang.Integer DivTest.$noinline$IntDivBy2(int) disassembly (after)
+ /// CHECK-NOT: cmovnl/geq
+ /// CHECK: add
private static Integer $noinline$IntDivBy2(int v) {
int r = v / 2;
return r;
@@ -102,6 +105,9 @@ public class DivTest {
/// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntDivByMinus2(int) disassembly (after)
/// CHECK: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
/// CHECK: neg w{{\d+}}, w{{\d+}}, asr #1
+ /// CHECK-START-X86_64: java.lang.Integer DivTest.$noinline$IntDivByMinus2(int) disassembly (after)
+ /// CHECK-NOT: cmovnl/geq
+ /// CHECK: add
private static Integer $noinline$IntDivByMinus2(int v) {
int r = v / -2;
return r;
@@ -205,6 +211,9 @@ public class DivTest {
/// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongDivBy2(long) disassembly (after)
/// CHECK: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
/// CHECK: asr x{{\d+}}, x{{\d+}}, #1
+ /// CHECK-START-X86_64: java.lang.Long DivTest.$noinline$LongDivBy2(long) disassembly (after)
+ /// CHECK-NOT: cmovnl/geq
+ /// CHECK: addq
private static Long $noinline$LongDivBy2(long v) {
long r = v / 2;
return r;
@@ -213,6 +222,9 @@ public class DivTest {
/// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongDivByMinus2(long) disassembly (after)
/// CHECK: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
/// CHECK: neg x{{\d+}}, x{{\d+}}, asr #1
+ /// CHECK-START-X86_64: java.lang.Long DivTest.$noinline$LongDivByMinus2(long) disassembly (after)
+ /// CHECK-NOT: cmovnl/geq
+ /// CHECK: addq
private static Long $noinline$LongDivByMinus2(long v) {
long r = v / -2;
return r;