Remove uses of RangeCanInclude() in flooring division by power of 2.
Drive-By-Fix: Improve ARM code generation for flooring division by power of 2. BUG=v8:3204 LOG=y R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/196653009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19877 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
078ecbb9c3
commit
929313bd6b
@ -1749,12 +1749,13 @@ LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
|
|||||||
ASSERT(instr->right()->representation().Equals(instr->representation()));
|
ASSERT(instr->right()->representation().Equals(instr->representation()));
|
||||||
LOperand* dividend = UseRegisterAtStart(instr->left());
|
LOperand* dividend = UseRegisterAtStart(instr->left());
|
||||||
int32_t divisor = instr->right()->GetInteger32Constant();
|
int32_t divisor = instr->right()->GetInteger32Constant();
|
||||||
LInstruction* result =
|
LInstruction* result = DefineAsRegister(new(zone()) LFlooringDivByPowerOf2I(
|
||||||
DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(dividend, divisor));
|
dividend, divisor));
|
||||||
bool can_deopt =
|
if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
||||||
(instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
(instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
|
||||||
(instr->left()->RangeCanInclude(kMinInt) && divisor == -1);
|
result = AssignEnvironment(result);
|
||||||
return can_deopt ? AssignEnvironment(result) : result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3839,37 +3839,37 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
|
void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
|
||||||
Register dividend = ToRegister32(instr->dividend());
|
Register dividend = ToRegister32(instr->dividend());
|
||||||
|
Register result = ToRegister32(instr->result());
|
||||||
int32_t divisor = instr->divisor();
|
int32_t divisor = instr->divisor();
|
||||||
ASSERT(dividend.is(ToRegister32(instr->result())));
|
|
||||||
|
|
||||||
// If the divisor is positive, things are easy: There can be no deopts and we
|
// If the divisor is positive, things are easy: There can be no deopts and we
|
||||||
// can simply do an arithmetic right shift.
|
// can simply do an arithmetic right shift.
|
||||||
if (divisor == 1) return;
|
if (divisor == 1) return;
|
||||||
int32_t shift = WhichPowerOf2Abs(divisor);
|
int32_t shift = WhichPowerOf2Abs(divisor);
|
||||||
if (divisor > 1) {
|
if (divisor > 1) {
|
||||||
__ Mov(dividend, Operand(dividend, ASR, shift));
|
__ Mov(result, Operand(dividend, ASR, shift));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the divisor is negative, we have to negate and handle edge cases.
|
// If the divisor is negative, we have to negate and handle edge cases.
|
||||||
Label not_kmin_int, done;
|
Label not_kmin_int, done;
|
||||||
__ Negs(dividend, dividend);
|
__ Negs(result, dividend);
|
||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
DeoptimizeIf(eq, instr->environment());
|
DeoptimizeIf(eq, instr->environment());
|
||||||
}
|
}
|
||||||
if (instr->hydrogen()->left()->RangeCanInclude(kMinInt)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
|
||||||
// Note that we could emit branch-free code, but that would need one more
|
// Note that we could emit branch-free code, but that would need one more
|
||||||
// register.
|
// register.
|
||||||
__ B(vc, ¬_kmin_int);
|
|
||||||
if (divisor == -1) {
|
if (divisor == -1) {
|
||||||
Deoptimize(instr->environment());
|
DeoptimizeIf(vs, instr->environment());
|
||||||
} else {
|
} else {
|
||||||
__ Mov(dividend, kMinInt / divisor);
|
__ B(vc, ¬_kmin_int);
|
||||||
|
__ Mov(result, kMinInt / divisor);
|
||||||
__ B(&done);
|
__ B(&done);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__ bind(¬_kmin_int);
|
__ bind(¬_kmin_int);
|
||||||
__ Mov(dividend, Operand(dividend, ASR, shift));
|
__ Mov(result, Operand(dividend, ASR, shift));
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1316,13 +1316,13 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
|
|||||||
LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
|
LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
|
||||||
LOperand* dividend = UseRegisterAtStart(instr->left());
|
LOperand* dividend = UseRegisterAtStart(instr->left());
|
||||||
int32_t divisor = instr->right()->GetInteger32Constant();
|
int32_t divisor = instr->right()->GetInteger32Constant();
|
||||||
LInstruction* result =
|
LInstruction* result = DefineAsRegister(new(zone()) LFlooringDivByPowerOf2I(
|
||||||
DefineSameAsFirst(
|
dividend, divisor));
|
||||||
new(zone()) LFlooringDivByPowerOf2I(dividend, divisor));
|
if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
||||||
bool can_deopt =
|
(instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
|
||||||
(instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
result = AssignEnvironment(result);
|
||||||
(instr->left()->RangeCanInclude(kMinInt) && divisor == -1);
|
}
|
||||||
return can_deopt ? AssignEnvironment(result) : result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1458,38 +1458,36 @@ void LCodeGen::DoMultiplySubD(LMultiplySubD* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
|
void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
|
||||||
Register dividend = ToRegister(instr->dividend());
|
Register dividend = ToRegister(instr->dividend());
|
||||||
|
Register result = ToRegister(instr->result());
|
||||||
int32_t divisor = instr->divisor();
|
int32_t divisor = instr->divisor();
|
||||||
ASSERT(dividend.is(ToRegister(instr->result())));
|
|
||||||
|
|
||||||
// If the divisor is positive, things are easy: There can be no deopts and we
|
// If the divisor is positive, things are easy: There can be no deopts and we
|
||||||
// can simply do an arithmetic right shift.
|
// can simply do an arithmetic right shift.
|
||||||
if (divisor == 1) return;
|
if (divisor == 1) return;
|
||||||
int32_t shift = WhichPowerOf2Abs(divisor);
|
int32_t shift = WhichPowerOf2Abs(divisor);
|
||||||
if (divisor > 1) {
|
if (divisor > 1) {
|
||||||
__ mov(dividend, Operand(dividend, ASR, shift));
|
__ mov(result, Operand(dividend, ASR, shift));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the divisor is negative, we have to negate and handle edge cases.
|
// If the divisor is negative, we have to negate and handle edge cases.
|
||||||
Label not_kmin_int, done;
|
__ rsb(result, dividend, Operand::Zero(), SetCC);
|
||||||
__ rsb(dividend, dividend, Operand::Zero(), SetCC);
|
|
||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
DeoptimizeIf(eq, instr->environment());
|
DeoptimizeIf(eq, instr->environment());
|
||||||
}
|
}
|
||||||
if (instr->hydrogen()->left()->RangeCanInclude(kMinInt)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
|
||||||
// Note that we could emit branch-free code, but that would need one more
|
// Note that we could emit branch-free code, but that would need one more
|
||||||
// register.
|
// register.
|
||||||
__ b(vc, ¬_kmin_int);
|
|
||||||
if (divisor == -1) {
|
if (divisor == -1) {
|
||||||
DeoptimizeIf(al, instr->environment());
|
DeoptimizeIf(vs, instr->environment());
|
||||||
|
__ mov(result, Operand(dividend, ASR, shift));
|
||||||
} else {
|
} else {
|
||||||
__ mov(dividend, Operand(kMinInt / divisor));
|
__ mov(result, Operand(kMinInt / divisor), LeaveCC, vs);
|
||||||
__ b(&done);
|
__ mov(result, Operand(dividend, ASR, shift), LeaveCC, vc);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
__ mov(result, Operand(dividend, ASR, shift));
|
||||||
}
|
}
|
||||||
__ bind(¬_kmin_int);
|
|
||||||
__ mov(dividend, Operand(dividend, ASR, shift));
|
|
||||||
__ bind(&done);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1799,7 +1799,7 @@ Range* HMul::InferRange(Zone* zone) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Range* HBinaryOperation::InferRangeForDiv(Zone* zone) {
|
Range* HDiv::InferRange(Zone* zone) {
|
||||||
if (representation().IsInteger32()) {
|
if (representation().IsInteger32()) {
|
||||||
Range* a = left()->range();
|
Range* a = left()->range();
|
||||||
Range* b = right()->range();
|
Range* b = right()->range();
|
||||||
@ -1821,13 +1821,29 @@ Range* HBinaryOperation::InferRangeForDiv(Zone* zone) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Range* HDiv::InferRange(Zone* zone) {
|
|
||||||
return InferRangeForDiv(zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Range* HMathFloorOfDiv::InferRange(Zone* zone) {
|
Range* HMathFloorOfDiv::InferRange(Zone* zone) {
|
||||||
return InferRangeForDiv(zone);
|
if (representation().IsInteger32()) {
|
||||||
|
Range* a = left()->range();
|
||||||
|
Range* b = right()->range();
|
||||||
|
Range* result = new(zone) Range();
|
||||||
|
result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
|
||||||
|
(a->CanBeMinusZero() ||
|
||||||
|
(a->CanBeZero() && b->CanBeNegative())));
|
||||||
|
if (!a->Includes(kMinInt)) {
|
||||||
|
ClearFlag(kLeftCanBeMinInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!a->Includes(kMinInt) || !b->Includes(-1)) {
|
||||||
|
ClearFlag(kCanOverflow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!b->CanBeZero()) {
|
||||||
|
ClearFlag(kCanBeDivByZero);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return HValue::InferRange(zone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -622,6 +622,7 @@ class HValue : public ZoneObject {
|
|||||||
kCanOverflow,
|
kCanOverflow,
|
||||||
kBailoutOnMinusZero,
|
kBailoutOnMinusZero,
|
||||||
kCanBeDivByZero,
|
kCanBeDivByZero,
|
||||||
|
kLeftCanBeMinInt,
|
||||||
kAllowUndefinedAsNaN,
|
kAllowUndefinedAsNaN,
|
||||||
kIsArguments,
|
kIsArguments,
|
||||||
kTruncatingToInt32,
|
kTruncatingToInt32,
|
||||||
@ -855,9 +856,6 @@ class HValue : public ZoneObject {
|
|||||||
// TODO(svenpanne) We should really use the null object pattern here.
|
// TODO(svenpanne) We should really use the null object pattern here.
|
||||||
bool HasRange() const { return range_ != NULL; }
|
bool HasRange() const { return range_ != NULL; }
|
||||||
bool CanBeNegative() const { return !HasRange() || range()->CanBeNegative(); }
|
bool CanBeNegative() const { return !HasRange() || range()->CanBeNegative(); }
|
||||||
bool RangeCanInclude(int value) const {
|
|
||||||
return !HasRange() || range()->Includes(value);
|
|
||||||
}
|
|
||||||
void AddNewRange(Range* r, Zone* zone);
|
void AddNewRange(Range* r, Zone* zone);
|
||||||
void RemoveLastAddedRange();
|
void RemoveLastAddedRange();
|
||||||
void ComputeInitialRange(Zone* zone);
|
void ComputeInitialRange(Zone* zone);
|
||||||
@ -3765,9 +3763,6 @@ class HBinaryOperation : public HTemplateInstruction<3> {
|
|||||||
|
|
||||||
DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
|
DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
|
||||||
|
|
||||||
protected:
|
|
||||||
Range* InferRangeForDiv(Zone* zone);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IgnoreObservedOutputRepresentation(Representation current_rep);
|
bool IgnoreObservedOutputRepresentation(Representation current_rep);
|
||||||
|
|
||||||
@ -4109,6 +4104,7 @@ class HMathFloorOfDiv V8_FINAL : public HBinaryOperation {
|
|||||||
SetFlag(kUseGVN);
|
SetFlag(kUseGVN);
|
||||||
SetFlag(kCanOverflow);
|
SetFlag(kCanOverflow);
|
||||||
SetFlag(kCanBeDivByZero);
|
SetFlag(kCanBeDivByZero);
|
||||||
|
SetFlag(kLeftCanBeMinInt);
|
||||||
SetFlag(kAllowUndefinedAsNaN);
|
SetFlag(kAllowUndefinedAsNaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1637,13 +1637,13 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
|
|||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
DeoptimizeIf(zero, instr->environment());
|
DeoptimizeIf(zero, instr->environment());
|
||||||
}
|
}
|
||||||
if (instr->hydrogen()->left()->RangeCanInclude(kMinInt)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
|
||||||
// Note that we could emit branch-free code, but that would need one more
|
// Note that we could emit branch-free code, but that would need one more
|
||||||
// register.
|
// register.
|
||||||
__ j(no_overflow, ¬_kmin_int, Label::kNear);
|
|
||||||
if (divisor == -1) {
|
if (divisor == -1) {
|
||||||
DeoptimizeIf(no_condition, instr->environment());
|
DeoptimizeIf(overflow, instr->environment());
|
||||||
} else {
|
} else {
|
||||||
|
__ j(no_overflow, ¬_kmin_int, Label::kNear);
|
||||||
__ mov(dividend, Immediate(kMinInt / divisor));
|
__ mov(dividend, Immediate(kMinInt / divisor));
|
||||||
__ jmp(&done, Label::kNear);
|
__ jmp(&done, Label::kNear);
|
||||||
}
|
}
|
||||||
|
@ -1409,12 +1409,13 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
|
|||||||
LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
|
LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
|
||||||
LOperand* dividend = UseRegisterAtStart(instr->left());
|
LOperand* dividend = UseRegisterAtStart(instr->left());
|
||||||
int32_t divisor = instr->right()->GetInteger32Constant();
|
int32_t divisor = instr->right()->GetInteger32Constant();
|
||||||
LInstruction* result =
|
LInstruction* result = DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(
|
||||||
DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(dividend, divisor));
|
dividend, divisor));
|
||||||
bool can_deopt =
|
if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
||||||
(instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
(instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
|
||||||
(instr->left()->RangeCanInclude(kMinInt) && divisor == -1);
|
result = AssignEnvironment(result);
|
||||||
return can_deopt ? AssignEnvironment(result) : result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1129,7 +1129,7 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
|
|||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
DeoptimizeIf(zero, instr->environment());
|
DeoptimizeIf(zero, instr->environment());
|
||||||
}
|
}
|
||||||
if (instr->hydrogen()->left()->RangeCanInclude(kMinInt)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
|
||||||
// Note that we could emit branch-free code, but that would need one more
|
// Note that we could emit branch-free code, but that would need one more
|
||||||
// register.
|
// register.
|
||||||
__ j(no_overflow, ¬_kmin_int, Label::kNear);
|
__ j(no_overflow, ¬_kmin_int, Label::kNear);
|
||||||
|
@ -1330,12 +1330,13 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
|
|||||||
LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
|
LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
|
||||||
LOperand* dividend = UseRegisterAtStart(instr->left());
|
LOperand* dividend = UseRegisterAtStart(instr->left());
|
||||||
int32_t divisor = instr->right()->GetInteger32Constant();
|
int32_t divisor = instr->right()->GetInteger32Constant();
|
||||||
LInstruction* result =
|
LInstruction* result = DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(
|
||||||
DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(dividend, divisor));
|
dividend, divisor));
|
||||||
bool can_deopt =
|
if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
||||||
(instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
|
(instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
|
||||||
(instr->left()->RangeCanInclude(kMinInt) && divisor == -1);
|
result = AssignEnvironment(result);
|
||||||
return can_deopt ? AssignEnvironment(result) : result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user