Index: src/arm/lithium-codegen-arm.cc |
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
index 25c81970193d1799243f4525d370cf753da5e114..03a905533f433568759a7297e69d0e00cd2c62ad 100644 |
--- a/src/arm/lithium-codegen-arm.cc |
+++ b/src/arm/lithium-codegen-arm.cc |
@@ -1406,8 +1406,7 @@ void LCodeGen::EmitSignedIntegerDivisionByConstant( |
void LCodeGen::DoDivI(LDivI* instr) { |
if (instr->hydrogen()->HasPowerOf2Divisor()) { |
Register dividend = ToRegister(instr->left()); |
- int32_t divisor = |
- HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
+ int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); |
int32_t test_value = 0; |
int32_t power = 0; |
@@ -1430,10 +1429,19 @@ void LCodeGen::DoDivI(LDivI* instr) { |
} |
if (test_value != 0) { |
- // Deoptimize if remainder is not 0. |
- __ tst(dividend, Operand(test_value)); |
- DeoptimizeIf(ne, instr->environment()); |
- __ mov(dividend, Operand(dividend, ASR, power)); |
+ if (instr->hydrogen()->CheckFlag( |
+ HInstruction::kAllUsesTruncatingToInt32)) { |
+ __ cmp(dividend, Operand(0)); |
+ __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); |
+ __ mov(dividend, Operand(dividend, ASR, power)); |
+ if (divisor > 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); |
+ return; // Don't fall through to "__ rsb" below. |
+ } else { |
+ // Deoptimize if remainder is not 0. |
+ __ tst(dividend, Operand(test_value)); |
+ DeoptimizeIf(ne, instr->environment()); |
+ __ mov(dividend, Operand(dividend, ASR, power)); |
+ } |
} |
if (divisor < 0) __ rsb(dividend, dividend, Operand(0)); |
@@ -1474,11 +1482,14 @@ void LCodeGen::DoDivI(LDivI* instr) { |
CpuFeatureScope scope(masm(), SUDIV); |
__ sdiv(result, left, right); |
- // Compute remainder and deopt if it's not zero. |
- const Register remainder = scratch0(); |
- __ mls(remainder, result, right, left); |
- __ cmp(remainder, Operand::Zero()); |
- DeoptimizeIf(ne, instr->environment()); |
+ if (!instr->hydrogen()->CheckFlag( |
+ HInstruction::kAllUsesTruncatingToInt32)) { |
+ // Compute remainder and deopt if it's not zero. |
+ const Register remainder = scratch0(); |
+ __ mls(remainder, result, right, left); |
+ __ cmp(remainder, Operand::Zero()); |
+ DeoptimizeIf(ne, instr->environment()); |
+ } |
} else { |
const DoubleRegister vleft = ToDoubleRegister(instr->temp()); |
const DoubleRegister vright = double_scratch0(); |
@@ -1487,14 +1498,17 @@ void LCodeGen::DoDivI(LDivI* instr) { |
__ vcvt_f64_s32(vleft, vleft.low()); |
__ vcvt_f64_s32(vright, vright.low()); |
__ vdiv(vleft, vleft, vright); // vleft now contains the result. |
- |
- // Convert back to integer32; deopt if exact conversion is not possible. |
- // Use vright as scratch register. |
__ vcvt_s32_f64(vright.low(), vleft); |
__ vmov(result, vright.low()); |
- __ vcvt_f64_s32(vright, vright.low()); |
- __ VFPCompareAndSetFlags(vleft, vright); |
- DeoptimizeIf(ne, instr->environment()); |
+ |
+ if (!instr->hydrogen()->CheckFlag( |
+ HInstruction::kAllUsesTruncatingToInt32)) { |
+ // Deopt if exact conversion to integer was not possible. |
+ // Use vright as scratch register. |
+ __ vcvt_f64_s32(vright, vright.low()); |
+ __ VFPCompareAndSetFlags(vleft, vright); |
+ DeoptimizeIf(ne, instr->environment()); |
+ } |
} |
} |