Fixed flooring division by -1 on ARM.

We should avoid ASR #0 on ARM. Simplified and improved code a bit
while we're there on all platforms. Human brains are very bad at
understanding nested structures...

BUG=v8:3259
LOG=y
R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/227553003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20544 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 20461079
......@@ -1469,19 +1469,21 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr->environment());
}
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
// Note that we could emit branch-free code, but that would need one more
// register.
if (divisor == -1) {
DeoptimizeIf(vs, instr->environment());
__ mov(result, Operand(dividend, ASR, shift));
} else {
__ mov(result, Operand(kMinInt / divisor), LeaveCC, vs);
__ mov(result, Operand(dividend, ASR, shift), LeaveCC, vc);
}
} else {
// If the negation could not overflow, simply shifting is OK.
if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
__ mov(result, Operand(dividend, ASR, shift));
return;
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
DeoptimizeIf(vs, instr->environment());
return;
}
__ mov(result, Operand(kMinInt / divisor), LeaveCC, vs);
__ mov(result, Operand(dividend, ASR, shift), LeaveCC, vc);
}
......
......@@ -3851,22 +3851,28 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
}
// If the divisor is negative, we have to negate and handle edge cases.
Label not_kmin_int, done;
__ Negs(result, dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr->environment());
}
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
// Note that we could emit branch-free code, but that would need one more
// register.
if (divisor == -1) {
DeoptimizeIf(vs, instr->environment());
} else {
__ B(vc, &not_kmin_int);
__ Mov(result, kMinInt / divisor);
__ B(&done);
}
// If the negation could not overflow, simply shifting is OK.
if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
__ Mov(result, Operand(dividend, ASR, shift));
return;
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
DeoptimizeIf(vs, instr->environment());
return;
}
// Using a conditional data processing instruction would need 1 more register.
Label not_kmin_int, done;
__ B(vc, &not_kmin_int);
__ Mov(result, kMinInt / divisor);
__ B(&done);
__ bind(&not_kmin_int);
__ Mov(result, Operand(dividend, ASR, shift));
__ bind(&done);
......
......@@ -1622,22 +1622,26 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
}
// If the divisor is negative, we have to negate and handle edge cases.
Label not_kmin_int, done;
__ neg(dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr->environment());
}
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
// Note that we could emit branch-free code, but that would need one more
// register.
if (divisor == -1) {
DeoptimizeIf(overflow, instr->environment());
} else {
__ j(no_overflow, &not_kmin_int, Label::kNear);
__ mov(dividend, Immediate(kMinInt / divisor));
__ jmp(&done, Label::kNear);
}
if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
__ sar(dividend, shift);
return;
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
DeoptimizeIf(overflow, instr->environment());
return;
}
Label not_kmin_int, done;
__ j(no_overflow, &not_kmin_int, Label::kNear);
__ mov(dividend, Immediate(kMinInt / divisor));
__ jmp(&done, Label::kNear);
__ bind(&not_kmin_int);
__ sar(dividend, shift);
__ bind(&done);
......
......@@ -1139,22 +1139,28 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
}
// If the divisor is negative, we have to negate and handle edge cases.
Label not_kmin_int, done;
__ negl(dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr->environment());
}
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
// Note that we could emit branch-free code, but that would need one more
// register.
__ j(no_overflow, &not_kmin_int, Label::kNear);
if (divisor == -1) {
DeoptimizeIf(no_condition, instr->environment());
} else {
__ movl(dividend, Immediate(kMinInt / divisor));
__ jmp(&done, Label::kNear);
}
// If the negation could not overflow, simply shifting is OK.
if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
__ sarl(dividend, Immediate(shift));
return;
}
// Note that we could emit branch-free code, but that would need one more
// register.
if (divisor == -1) {
DeoptimizeIf(overflow, instr->environment());
return;
}
Label not_kmin_int, done;
__ j(no_overflow, &not_kmin_int, Label::kNear);
__ movl(dividend, Immediate(kMinInt / divisor));
__ jmp(&done, Label::kNear);
__ bind(&not_kmin_int);
__ sarl(dividend, Immediate(shift));
__ bind(&done);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment