Index: src/x64/lithium-codegen-x64.cc |
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
index 2d6e4cba33c6ebf86ea0877451657cc7325fcdd5..bb3ab770b358fa76d93690882f5ebbe4e072b76e 100644 |
--- a/src/x64/lithium-codegen-x64.cc |
+++ b/src/x64/lithium-codegen-x64.cc |
@@ -1263,10 +1263,26 @@ void LCodeGen::DoDivI(LDivI* instr) { |
} |
if (test_value != 0) { |
- // Deoptimize if remainder is not 0. |
- __ testl(dividend, Immediate(test_value)); |
- DeoptimizeIf(not_zero, instr->environment()); |
- __ sarl(dividend, Immediate(power)); |
+ if (instr->hydrogen()->CheckFlag( |
+ HInstruction::kAllUsesTruncatingToInt32)) { |
+ Label done, negative; |
+ __ cmpl(dividend, Immediate(0)); |
+ __ j(less, &negative, Label::kNear); |
+ __ sarl(dividend, Immediate(power)); |
+ __ jmp(&done, Label::kNear); |
+ |
+ __ bind(&negative); |
+ __ negl(dividend); |
+ __ sarl(dividend, Immediate(power)); |
+ if (divisor > 0) __ negl(dividend); |
+ __ bind(&done); |
+ return; // Don't fall through to "__ neg" below. |
+ } else { |
+ // Deoptimize if remainder is not 0. |
+ __ testl(dividend, Immediate(test_value)); |
+ DeoptimizeIf(not_zero, instr->environment()); |
+ __ sarl(dividend, Immediate(power)); |
+ } |
} |
if (divisor < 0) __ negl(dividend); |
@@ -1313,11 +1329,7 @@ void LCodeGen::DoDivI(LDivI* instr) { |
__ cdq(); |
__ idivl(right_reg); |
- if (!instr->is_flooring()) { |
- // Deoptimize if remainder is not 0. |
- __ testl(rdx, rdx); |
- DeoptimizeIf(not_zero, instr->environment()); |
- } else { |
+ if (instr->is_flooring()) { |
Label done; |
__ testl(rdx, rdx); |
__ j(zero, &done, Label::kNear); |
@@ -1325,6 +1337,11 @@ void LCodeGen::DoDivI(LDivI* instr) { |
__ sarl(rdx, Immediate(31)); |
__ addl(rax, rdx); |
__ bind(&done); |
+ } else if (!instr->hydrogen()->CheckFlag( |
+ HInstruction::kAllUsesTruncatingToInt32)) { |
+ // Deoptimize if remainder is not 0. |
+ __ testl(rdx, rdx); |
+ DeoptimizeIf(not_zero, instr->environment()); |
} |
} |