if (instr->representation().IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
- if (instr->HasPowerOf2Divisor()) {
+ if (instr->RightIsPowerOf2()) {
ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
LOperand* value = UseRegisterAtStart(instr->left());
LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL);
}
-HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
- if (CpuFeatures::IsSupported(SUDIV)) {
- // A value with an integer representation does not need to be transformed.
- if (divisor->representation().IsInteger32()) {
- return divisor;
- // A change from an integer32 can be replaced by the integer32 value.
- } else if (divisor->IsChange() &&
- HChange::cast(divisor)->from().IsInteger32()) {
- return HChange::cast(divisor)->value();
- }
- }
-
- if (divisor->IsConstant() && HConstant::cast(divisor)->HasInteger32Value()) {
- HConstant* constant_val = HConstant::cast(divisor);
- int32_t int32_val = constant_val->Integer32Value();
- if (LChunkBuilder::HasMagicNumberForDivisor(int32_val) ||
- CpuFeatures::IsSupported(SUDIV)) {
- return constant_val->CopyToRepresentation(Representation::Integer32(),
- divisor->block()->zone());
- }
- }
-
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
+ // LMathFloorOfDiv can only handle a subset of divisors, so fall
+ // back to a flooring division in all other cases.
HValue* right = instr->right();
+ if (!right->IsInteger32Constant() ||
+ (!CpuFeatures::IsSupported(SUDIV) &&
+ !HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()))) {
+ LOperand* dividend = UseRegister(instr->left());
+ LOperand* divisor = UseRegister(right);
+ LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4);
+ LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
+ return AssignEnvironment(DefineAsRegister(div));
+ }
+
LOperand* dividend = UseRegister(instr->left());
LOperand* divisor = CpuFeatures::IsSupported(SUDIV)
? UseRegister(right)
: UseOrConstant(right);
LOperand* remainder = TempRegister();
- ASSERT(CpuFeatures::IsSupported(SUDIV) ||
- (right->IsConstant() &&
- HConstant::cast(right)->HasInteger32Value() &&
- HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value())));
return AssignEnvironment(DefineAsRegister(
new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
}
if (instr->representation().IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
- if (instr->HasPowerOf2Divisor()) {
+ if (instr->RightIsPowerOf2()) {
ASSERT(!right->CanBeZero());
LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
UseConstant(right));
LOperand* right() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
+ bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); }
+
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
DECLARE_HYDROGEN_ACCESSOR(Div)
};
LInstruction* DoRSub(HSub* instr);
static bool HasMagicNumberForDivisor(int32_t divisor);
- static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
LInstruction* DoMathFloor(HUnaryMathOperation* instr);
LInstruction* DoMathRound(HUnaryMathOperation* instr);
HMod* hmod = instr->hydrogen();
HValue* left = hmod->left();
HValue* right = hmod->right();
- if (hmod->HasPowerOf2Divisor()) {
+ if (hmod->RightIsPowerOf2()) {
// TODO(svenpanne) We should really do the strength reduction on the
// Hydrogen level.
Register left_reg = ToRegister(instr->left());
void LCodeGen::DoDivI(LDivI* instr) {
- if (instr->hydrogen()->HasPowerOf2Divisor()) {
+ if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) {
const Register dividend = ToRegister(instr->left());
const Register result = ToRegister(instr->result());
int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant();
const Register result = ToRegister(instr->result());
// Check for x / 0.
- if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+ if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(right, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
// Check for (0 / -x) that will produce negative zero.
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ if (instr->hydrogen_value()->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label positive;
- if (!instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+ if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
// Do the test only if it hadn't be done above.
__ cmp(right, Operand::Zero());
}
}
// Check for (kMinInt / -1).
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow) &&
+ if (instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow) &&
(!CpuFeatures::IsSupported(SUDIV) ||
- !instr->hydrogen()->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
+ !instr->hydrogen_value()->CheckFlag(
+ HValue::kAllUsesTruncatingToInt32))) {
// We don't need to check for overflow when truncating with sdiv
// support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
__ cmp(left, Operand(kMinInt));
CpuFeatureScope scope(masm(), SUDIV);
__ sdiv(result, left, right);
- if (!instr->hydrogen()->CheckFlag(
+ if (!instr->hydrogen_value()->CheckFlag(
HInstruction::kAllUsesTruncatingToInt32)) {
// Compute remainder and deopt if it's not zero.
const Register remainder = scratch0();
__ vcvt_s32_f64(double_scratch0().low(), vleft);
__ vmov(result, double_scratch0().low());
- if (!instr->hydrogen()->CheckFlag(
+ if (!instr->hydrogen_value()->CheckFlag(
HInstruction::kAllUsesTruncatingToInt32)) {
// Deopt if exact conversion to integer was not possible.
// Use vright as scratch register.
}
-static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
- // A value with an integer representation does not need to be transformed.
- if (dividend->representation().IsInteger32()) {
- return dividend;
- }
- // A change from an integer32 can be replaced by the integer32 value.
- if (dividend->IsChange() &&
- HChange::cast(dividend)->from().IsInteger32()) {
- return HChange::cast(dividend)->value();
- }
- return NULL;
-}
-
-
HValue* HUnaryMathOperation::Canonicalize() {
if (op() == kMathRound || op() == kMathFloor) {
HValue* val = value();
if (val->IsChange()) val = HChange::cast(val)->value();
-
- // If the input is smi or integer32 then we replace the instruction with its
- // input.
if (val->representation().IsSmiOrInteger32()) {
- if (!val->representation().Equals(representation())) {
- HChange* result = new(block()->zone()) HChange(
- val, representation(), false, false);
- result->InsertBefore(this);
- return result;
- }
- return val;
+ if (val->representation().Equals(representation())) return val;
+ return Prepend(new(block()->zone()) HChange(
+ val, representation(), false, false));
}
}
+ if (op() == kMathFloor && value()->IsDiv() && value()->UseCount() == 1) {
+ HDiv* hdiv = HDiv::cast(value());
+
+ HValue* left = hdiv->left();
+ if (left->representation().IsInteger32()) {
+ // A value with an integer representation does not need to be transformed.
+ } else if (left->IsChange() && HChange::cast(left)->from().IsInteger32()) {
+ // A change from an integer32 can be replaced by the integer32 value.
+ left = HChange::cast(left)->value();
+ } else if (hdiv->observed_input_representation(1).IsSmiOrInteger32()) {
+ left = Prepend(new(block()->zone()) HChange(
+ left, Representation::Integer32(), false, false));
+ } else {
+ return this;
+ }
- if (op() == kMathFloor) {
- HValue* val = value();
- if (val->IsDiv() && (val->UseCount() == 1)) {
- HDiv* hdiv = HDiv::cast(val);
- HValue* left = hdiv->left();
- HValue* right = hdiv->right();
- // Try to simplify left and right values of the division.
- HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left);
- if (new_left == NULL &&
- hdiv->observed_input_representation(1).IsSmiOrInteger32()) {
- new_left = new(block()->zone()) HChange(
- left, Representation::Integer32(), false, false);
- HChange::cast(new_left)->InsertBefore(this);
- }
- HValue* new_right =
- LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right);
- if (new_right == NULL &&
-#if V8_TARGET_ARCH_ARM
- CpuFeatures::IsSupported(SUDIV) &&
-#endif
- hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
- new_right = new(block()->zone()) HChange(
- right, Representation::Integer32(), false, false);
- HChange::cast(new_right)->InsertBefore(this);
- }
-
- // Return if left or right are not optimizable.
- if ((new_left == NULL) || (new_right == NULL)) return this;
-
- // Insert the new values in the graph.
- if (new_left->IsInstruction() &&
- !HInstruction::cast(new_left)->IsLinked()) {
- HInstruction::cast(new_left)->InsertBefore(this);
- }
- if (new_right->IsInstruction() &&
- !HInstruction::cast(new_right)->IsLinked()) {
- HInstruction::cast(new_right)->InsertBefore(this);
- }
- HMathFloorOfDiv* instr =
- HMathFloorOfDiv::New(block()->zone(), context(), new_left, new_right);
- instr->InsertBefore(this);
- return instr;
+ HValue* right = hdiv->right();
+ if (right->IsInteger32Constant()) {
+ right = Prepend(HConstant::cast(right)->CopyToRepresentation(
+ Representation::Integer32(), right->block()->zone()));
+ } else if (right->representation().IsInteger32()) {
+ // A value with an integer representation does not need to be transformed.
+ } else if (right->IsChange() &&
+ HChange::cast(right)->from().IsInteger32()) {
+ // A change from an integer32 can be replaced by the integer32 value.
+ right = HChange::cast(right)->value();
+ } else if (hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
+ right = Prepend(new(block()->zone()) HChange(
+ right, Representation::Integer32(), false, false));
+ } else {
+ return this;
}
+
+ return Prepend(HMathFloorOfDiv::New(
+ block()->zone(), context(), left, right));
}
return this;
}
key_load->elements_kind());
map_check->InsertBefore(this);
index->InsertBefore(this);
- HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
- object(), index);
- load->InsertBefore(this);
- return load;
+ return Prepend(new(block()->zone()) HLoadFieldByIndex(
+ object(), index));
}
}
}
// Forward declarations.
class HBasicBlock;
+class HDiv;
class HEnvironment;
class HInferRepresentationPhase;
class HInstruction;
bool IsLinked() const { return block() != NULL; }
void Unlink();
+
void InsertBefore(HInstruction* next);
+
+ template<class T> T* Prepend(T* instr) {
+ instr->InsertBefore(this);
+ return instr;
+ }
+
void InsertAfter(HInstruction* previous);
+ template<class T> T* Append(T* instr) {
+ instr->InsertAfter(this);
+ return instr;
+ }
+
// The position is a write-once variable.
virtual int position() const V8_OVERRIDE {
return position_.position();
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+ HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
+ HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
+
BuiltinFunctionId op_;
};
int32_t value,
Representation representation,
HInstruction* instruction) {
- HConstant* new_constant =
- HConstant::New(zone, context, value, representation);
- new_constant->InsertAfter(instruction);
- return new_constant;
+ return instruction->Append(HConstant::New(
+ zone, context, value, representation));
}
static HConstant* CreateAndInsertBefore(Zone* zone,
int32_t value,
Representation representation,
HInstruction* instruction) {
- HConstant* new_constant =
- HConstant::New(zone, context, value, representation);
- new_constant->InsertBefore(instruction);
- return new_constant;
+ return instruction->Prepend(HConstant::New(
+ zone, context, value, representation));
}
static HConstant* CreateAndInsertBefore(Zone* zone,
Unique<Object> unique,
bool is_not_in_new_space,
HInstruction* instruction) {
- HConstant* new_constant = new(zone) HConstant(unique,
- Representation::Tagged(), HType::Tagged(), false, is_not_in_new_space,
- false, false);
- new_constant->InsertBefore(instruction);
- return new_constant;
+ return instruction->Prepend(new(zone) HConstant(
+ unique, Representation::Tagged(), HType::Tagged(), false,
+ is_not_in_new_space, false, false));
}
Handle<Object> handle(Isolate* isolate) {
}
}
+ bool RightIsPowerOf2() {
+ if (!right()->IsInteger32Constant()) return false;
+ int32_t value = right()->GetInteger32Constant();
+ return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
+ }
+
DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
+
private:
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
};
HValue* left,
HValue* right);
- bool HasPowerOf2Divisor() {
- if (right()->IsConstant() &&
- HConstant::cast(right())->HasInteger32Value()) {
- int32_t value = HConstant::cast(right())->Integer32Value();
- return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
- }
-
- return false;
- }
-
virtual HValue* EnsureAndPropagateNotMinusZero(
BitVector* visited) V8_OVERRIDE;
HValue* left,
HValue* right);
- bool HasPowerOf2Divisor() {
- if (right()->IsInteger32Constant()) {
- int32_t value = right()->GetInteger32Constant();
- return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
- }
-
- return false;
- }
-
virtual HValue* EnsureAndPropagateNotMinusZero(
BitVector* visited) V8_OVERRIDE;
HMod* hmod = instr->hydrogen();
HValue* left = hmod->left();
HValue* right = hmod->right();
- if (hmod->HasPowerOf2Divisor()) {
+ if (hmod->RightIsPowerOf2()) {
// TODO(svenpanne) We should really do the strength reduction on the
// Hydrogen level.
Register left_reg = ToRegister(instr->left());
void LCodeGen::DoDivI(LDivI* instr) {
- if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) {
+ if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) {
Register dividend = ToRegister(instr->left());
int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant();
int32_t test_value = 0;
if (instr->representation().IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
- if (instr->HasPowerOf2Divisor()) {
+ if (instr->RightIsPowerOf2()) {
ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
LOperand* value = UseRegisterAtStart(instr->left());
LDivI* div =
}
-HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
- if (divisor->IsConstant() &&
- HConstant::cast(divisor)->HasInteger32Value()) {
- HConstant* constant_val = HConstant::cast(divisor);
- return constant_val->CopyToRepresentation(Representation::Integer32(),
- divisor->block()->zone());
- }
- // A value with an integer representation does not need to be transformed.
- if (divisor->representation().IsInteger32()) {
- return divisor;
- // A change from an integer32 can be replaced by the integer32 value.
- } else if (divisor->IsChange() &&
- HChange::cast(divisor)->from().IsInteger32()) {
- return HChange::cast(divisor)->value();
- }
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
HValue* right = instr->right();
if (!right->IsConstant()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
- if (instr->HasPowerOf2Divisor()) {
+ if (instr->RightIsPowerOf2()) {
ASSERT(!right->CanBeZero());
LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
UseOrConstant(right),
HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
#undef DECLARE_DO
- static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
-
LInstruction* DoMathFloor(HUnaryMathOperation* instr);
LInstruction* DoMathRound(HUnaryMathOperation* instr);
LInstruction* DoMathAbs(HUnaryMathOperation* instr);
HMod* hmod = instr->hydrogen();
HValue* left = hmod->left();
HValue* right = hmod->right();
- if (hmod->HasPowerOf2Divisor()) {
+ if (hmod->RightIsPowerOf2()) {
const Register left_reg = ToRegister(instr->left());
const Register result_reg = ToRegister(instr->result());
}
-HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
- // Only optimize when we have magic numbers for the divisor.
- // The standard integer division routine is usually slower than transitionning
- // to FPU.
- if (divisor->IsConstant() &&
- HConstant::cast(divisor)->HasInteger32Value()) {
- HConstant* constant_val = HConstant::cast(divisor);
- return constant_val->CopyToRepresentation(Representation::Integer32(),
- divisor->block()->zone());
- }
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
HValue* right = instr->right();
LOperand* dividend = UseRegister(instr->left());
if (instr->representation().IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
- if (instr->HasPowerOf2Divisor()) {
+ if (instr->RightIsPowerOf2()) {
ASSERT(!right->CanBeZero());
LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
UseConstant(right));
LInstruction* DoMultiplyAdd(HMul* mul, HValue* addend);
static bool HasMagicNumberForDivisor(int32_t divisor);
- static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
LInstruction* DoMathFloor(HUnaryMathOperation* instr);
LInstruction* DoMathRound(HUnaryMathOperation* instr);
HMod* hmod = instr->hydrogen();
HValue* left = hmod->left();
HValue* right = hmod->right();
- if (hmod->HasPowerOf2Divisor()) {
+ if (hmod->RightIsPowerOf2()) {
// TODO(svenpanne) We should really do the strength reduction on the
// Hydrogen level.
Register left_reg = ToRegister(instr->left());
void LCodeGen::DoDivI(LDivI* instr) {
- if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) {
+ if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) {
Register dividend = ToRegister(instr->left());
int32_t divisor =
HConstant::cast(instr->hydrogen()->right())->Integer32Value();
if (instr->representation().IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
- if (instr->HasPowerOf2Divisor()) {
+ if (instr->RightIsPowerOf2()) {
ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
LOperand* value = UseRegisterAtStart(instr->left());
LDivI* div =
}
-HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
- if (divisor->IsConstant() &&
- HConstant::cast(divisor)->HasInteger32Value()) {
- HConstant* constant_val = HConstant::cast(divisor);
- return constant_val->CopyToRepresentation(Representation::Integer32(),
- divisor->block()->zone());
- }
- // A value with an integer representation does not need to be transformed.
- if (divisor->representation().IsInteger32()) {
- return divisor;
- // A change from an integer32 can be replaced by the integer32 value.
- } else if (divisor->IsChange() &&
- HChange::cast(divisor)->from().IsInteger32()) {
- return HChange::cast(divisor)->value();
- }
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
HValue* right = instr->right();
if (!right->IsConstant()) {
if (instr->representation().IsSmiOrInteger32()) {
ASSERT(left->representation().Equals(instr->representation()));
ASSERT(right->representation().Equals(instr->representation()));
- if (instr->HasPowerOf2Divisor()) {
+ if (instr->RightIsPowerOf2()) {
ASSERT(!right->CanBeZero());
LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
UseOrConstant(right),
HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
#undef DECLARE_DO
- static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
-
LInstruction* DoMathFloor(HUnaryMathOperation* instr);
LInstruction* DoMathRound(HUnaryMathOperation* instr);
LInstruction* DoMathAbs(HUnaryMathOperation* instr);