Index: src/crankshaft/hydrogen-instructions.cc |
diff --git a/src/crankshaft/hydrogen-instructions.cc b/src/crankshaft/hydrogen-instructions.cc |
index 9cd15026db24d3ff07117ec1e006d91110850e4f..4df90877e31dc4bba42a2928858fbabc7afbe165 100644 |
--- a/src/crankshaft/hydrogen-instructions.cc |
+++ b/src/crankshaft/hydrogen-instructions.cc |
@@ -775,7 +775,6 @@ bool HInstruction::CanDeoptimize() { |
case HValue::kArgumentsLength: |
case HValue::kArgumentsObject: |
case HValue::kBlockEntry: |
- case HValue::kBoundsCheckBaseIndexInformation: |
case HValue::kCallNewArray: |
case HValue::kCapturedObject: |
case HValue::kClassOfTestAndBranch: |
@@ -924,59 +923,6 @@ std::ostream& HInvokeFunction::PrintDataTo(std::ostream& os) const { // NOLINT |
return os; |
} |
-void HBoundsCheck::ApplyIndexChange() { |
- if (skip_check()) return; |
- |
- DecompositionResult decomposition; |
- bool index_is_decomposable = index()->TryDecompose(&decomposition); |
- if (index_is_decomposable) { |
- DCHECK(decomposition.base() == base()); |
- if (decomposition.offset() == offset() && |
- decomposition.scale() == scale()) return; |
- } else { |
- return; |
- } |
- |
- ReplaceAllUsesWith(index()); |
- |
- HValue* current_index = decomposition.base(); |
- int actual_offset = decomposition.offset() + offset(); |
- int actual_scale = decomposition.scale() + scale(); |
- |
- HGraph* graph = block()->graph(); |
- Isolate* isolate = graph->isolate(); |
- Zone* zone = graph->zone(); |
- HValue* context = graph->GetInvalidContext(); |
- if (actual_offset != 0) { |
- HConstant* add_offset = |
- HConstant::New(isolate, zone, context, actual_offset); |
- add_offset->InsertBefore(this); |
- HInstruction* add = |
- HAdd::New(isolate, zone, context, current_index, add_offset); |
- add->InsertBefore(this); |
- add->AssumeRepresentation(index()->representation()); |
- add->ClearFlag(kCanOverflow); |
- current_index = add; |
- } |
- |
- if (actual_scale != 0) { |
- HConstant* sar_scale = HConstant::New(isolate, zone, context, actual_scale); |
- sar_scale->InsertBefore(this); |
- HInstruction* sar = |
- HSar::New(isolate, zone, context, current_index, sar_scale); |
- sar->InsertBefore(this); |
- sar->AssumeRepresentation(index()->representation()); |
- current_index = sar; |
- } |
- |
- SetOperandAt(0, current_index); |
- |
- base_ = NULL; |
- offset_ = 0; |
- scale_ = 0; |
-} |
- |
- |
std::ostream& HBoundsCheck::PrintDataTo(std::ostream& os) const { // NOLINT |
os << NameOf(index()) << " " << NameOf(length()); |
if (base() != NULL && (offset() != 0 || scale() != 0)) { |
@@ -1032,14 +978,6 @@ Range* HBoundsCheck::InferRange(Zone* zone) { |
} |
-std::ostream& HBoundsCheckBaseIndexInformation::PrintDataTo( |
- std::ostream& os) const { // NOLINT |
- // TODO(svenpanne) This 2nd base_index() looks wrong... |
- return os << "base: " << NameOf(base_index()) |
- << ", check: " << NameOf(base_index()); |
-} |
- |
- |
std::ostream& HCallWithDescriptor::PrintDataTo( |
std::ostream& os) const { // NOLINT |
for (int i = 0; i < OperandCount(); i++) { |
@@ -1963,452 +1901,6 @@ Range* HMod::InferRange(Zone* zone) { |
} |
-InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { |
- if (phi->block()->loop_information() == NULL) return NULL; |
- if (phi->OperandCount() != 2) return NULL; |
- int32_t candidate_increment; |
- |
- candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); |
- if (candidate_increment != 0) { |
- return new(phi->block()->graph()->zone()) |
- InductionVariableData(phi, phi->OperandAt(1), candidate_increment); |
- } |
- |
- candidate_increment = ComputeIncrement(phi, phi->OperandAt(1)); |
- if (candidate_increment != 0) { |
- return new(phi->block()->graph()->zone()) |
- InductionVariableData(phi, phi->OperandAt(0), candidate_increment); |
- } |
- |
- return NULL; |
-} |
- |
- |
-/* |
- * This function tries to match the following patterns (and all the relevant |
- * variants related to |, & and + being commutative): |
- * base | constant_or_mask |
- * base & constant_and_mask |
- * (base + constant_offset) & constant_and_mask |
- * (base - constant_offset) & constant_and_mask |
- */ |
-void InductionVariableData::DecomposeBitwise( |
- HValue* value, |
- BitwiseDecompositionResult* result) { |
- HValue* base = IgnoreOsrValue(value); |
- result->base = value; |
- |
- if (!base->representation().IsInteger32()) return; |
- |
- if (base->IsBitwise()) { |
- bool allow_offset = false; |
- int32_t mask = 0; |
- |
- HBitwise* bitwise = HBitwise::cast(base); |
- if (bitwise->right()->IsInteger32Constant()) { |
- mask = bitwise->right()->GetInteger32Constant(); |
- base = bitwise->left(); |
- } else if (bitwise->left()->IsInteger32Constant()) { |
- mask = bitwise->left()->GetInteger32Constant(); |
- base = bitwise->right(); |
- } else { |
- return; |
- } |
- if (bitwise->op() == Token::BIT_AND) { |
- result->and_mask = mask; |
- allow_offset = true; |
- } else if (bitwise->op() == Token::BIT_OR) { |
- result->or_mask = mask; |
- } else { |
- return; |
- } |
- |
- result->context = bitwise->context(); |
- |
- if (allow_offset) { |
- if (base->IsAdd()) { |
- HAdd* add = HAdd::cast(base); |
- if (add->right()->IsInteger32Constant()) { |
- base = add->left(); |
- } else if (add->left()->IsInteger32Constant()) { |
- base = add->right(); |
- } |
- } else if (base->IsSub()) { |
- HSub* sub = HSub::cast(base); |
- if (sub->right()->IsInteger32Constant()) { |
- base = sub->left(); |
- } |
- } |
- } |
- |
- result->base = base; |
- } |
-} |
- |
- |
-void InductionVariableData::AddCheck(HBoundsCheck* check, |
- int32_t upper_limit) { |
- DCHECK(limit_validity() != NULL); |
- if (limit_validity() != check->block() && |
- !limit_validity()->Dominates(check->block())) return; |
- if (!phi()->block()->current_loop()->IsNestedInThisLoop( |
- check->block()->current_loop())) return; |
- |
- ChecksRelatedToLength* length_checks = checks(); |
- while (length_checks != NULL) { |
- if (length_checks->length() == check->length()) break; |
- length_checks = length_checks->next(); |
- } |
- if (length_checks == NULL) { |
- length_checks = new(check->block()->zone()) |
- ChecksRelatedToLength(check->length(), checks()); |
- checks_ = length_checks; |
- } |
- |
- length_checks->AddCheck(check, upper_limit); |
-} |
- |
- |
-void InductionVariableData::ChecksRelatedToLength::CloseCurrentBlock() { |
- if (checks() != NULL) { |
- InductionVariableCheck* c = checks(); |
- HBasicBlock* current_block = c->check()->block(); |
- while (c != NULL && c->check()->block() == current_block) { |
- c->set_upper_limit(current_upper_limit_); |
- c = c->next(); |
- } |
- } |
-} |
- |
- |
-void InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock( |
- Token::Value token, |
- int32_t mask, |
- HValue* index_base, |
- HValue* context) { |
- DCHECK(first_check_in_block() != NULL); |
- HValue* previous_index = first_check_in_block()->index(); |
- DCHECK(context != NULL); |
- |
- Zone* zone = index_base->block()->graph()->zone(); |
- Isolate* isolate = index_base->block()->graph()->isolate(); |
- set_added_constant(HConstant::New(isolate, zone, context, mask)); |
- if (added_index() != NULL) { |
- added_constant()->InsertBefore(added_index()); |
- } else { |
- added_constant()->InsertBefore(first_check_in_block()); |
- } |
- |
- if (added_index() == NULL) { |
- first_check_in_block()->ReplaceAllUsesWith(first_check_in_block()->index()); |
- HInstruction* new_index = HBitwise::New(isolate, zone, context, token, |
- index_base, added_constant()); |
- DCHECK(new_index->IsBitwise()); |
- new_index->ClearAllSideEffects(); |
- new_index->AssumeRepresentation(Representation::Integer32()); |
- set_added_index(HBitwise::cast(new_index)); |
- added_index()->InsertBefore(first_check_in_block()); |
- } |
- DCHECK(added_index()->op() == token); |
- |
- added_index()->SetOperandAt(1, index_base); |
- added_index()->SetOperandAt(2, added_constant()); |
- first_check_in_block()->SetOperandAt(0, added_index()); |
- if (previous_index->HasNoUses()) { |
- previous_index->DeleteAndReplaceWith(NULL); |
- } |
-} |
- |
-void InductionVariableData::ChecksRelatedToLength::AddCheck( |
- HBoundsCheck* check, |
- int32_t upper_limit) { |
- BitwiseDecompositionResult decomposition; |
- InductionVariableData::DecomposeBitwise(check->index(), &decomposition); |
- |
- if (first_check_in_block() == NULL || |
- first_check_in_block()->block() != check->block()) { |
- CloseCurrentBlock(); |
- |
- first_check_in_block_ = check; |
- set_added_index(NULL); |
- set_added_constant(NULL); |
- current_and_mask_in_block_ = decomposition.and_mask; |
- current_or_mask_in_block_ = decomposition.or_mask; |
- current_upper_limit_ = upper_limit; |
- |
- InductionVariableCheck* new_check = new(check->block()->graph()->zone()) |
- InductionVariableCheck(check, checks_, upper_limit); |
- checks_ = new_check; |
- return; |
- } |
- |
- if (upper_limit > current_upper_limit()) { |
- current_upper_limit_ = upper_limit; |
- } |
- |
- if (decomposition.and_mask != 0 && |
- current_or_mask_in_block() == 0) { |
- if (current_and_mask_in_block() == 0 || |
- decomposition.and_mask > current_and_mask_in_block()) { |
- UseNewIndexInCurrentBlock(Token::BIT_AND, |
- decomposition.and_mask, |
- decomposition.base, |
- decomposition.context); |
- current_and_mask_in_block_ = decomposition.and_mask; |
- } |
- check->set_skip_check(); |
- } |
- if (current_and_mask_in_block() == 0) { |
- if (decomposition.or_mask > current_or_mask_in_block()) { |
- UseNewIndexInCurrentBlock(Token::BIT_OR, |
- decomposition.or_mask, |
- decomposition.base, |
- decomposition.context); |
- current_or_mask_in_block_ = decomposition.or_mask; |
- } |
- check->set_skip_check(); |
- } |
- |
- if (!check->skip_check()) { |
- InductionVariableCheck* new_check = new(check->block()->graph()->zone()) |
- InductionVariableCheck(check, checks_, upper_limit); |
- checks_ = new_check; |
- } |
-} |
- |
- |
-/* |
- * This method detects if phi is an induction variable, with phi_operand as |
- * its "incremented" value (the other operand would be the "base" value). |
- * |
- * It cheks is phi_operand has the form "phi + constant". |
- * If yes, the constant is the increment that the induction variable gets at |
- * every loop iteration. |
- * Otherwise it returns 0. |
- */ |
-int32_t InductionVariableData::ComputeIncrement(HPhi* phi, |
- HValue* phi_operand) { |
- if (!phi_operand->representation().IsSmiOrInteger32()) return 0; |
- |
- if (phi_operand->IsAdd()) { |
- HAdd* operation = HAdd::cast(phi_operand); |
- if (operation->left() == phi && |
- operation->right()->IsInteger32Constant()) { |
- return operation->right()->GetInteger32Constant(); |
- } else if (operation->right() == phi && |
- operation->left()->IsInteger32Constant()) { |
- return operation->left()->GetInteger32Constant(); |
- } |
- } else if (phi_operand->IsSub()) { |
- HSub* operation = HSub::cast(phi_operand); |
- if (operation->left() == phi && |
- operation->right()->IsInteger32Constant()) { |
- int constant = operation->right()->GetInteger32Constant(); |
- if (constant == kMinInt) return 0; |
- return -constant; |
- } |
- } |
- |
- return 0; |
-} |
- |
- |
-/* |
- * Swaps the information in "update" with the one contained in "this". |
- * The swapping is important because this method is used while doing a |
- * dominator tree traversal, and "update" will retain the old data that |
- * will be restored while backtracking. |
- */ |
-void InductionVariableData::UpdateAdditionalLimit( |
- InductionVariableLimitUpdate* update) { |
- DCHECK(update->updated_variable == this); |
- if (update->limit_is_upper) { |
- swap(&additional_upper_limit_, &update->limit); |
- swap(&additional_upper_limit_is_included_, &update->limit_is_included); |
- } else { |
- swap(&additional_lower_limit_, &update->limit); |
- swap(&additional_lower_limit_is_included_, &update->limit_is_included); |
- } |
-} |
- |
- |
-int32_t InductionVariableData::ComputeUpperLimit(int32_t and_mask, |
- int32_t or_mask) { |
- // Should be Smi::kMaxValue but it must fit 32 bits; lower is safe anyway. |
- const int32_t MAX_LIMIT = 1 << 30; |
- |
- int32_t result = MAX_LIMIT; |
- |
- if (limit() != NULL && |
- limit()->IsInteger32Constant()) { |
- int32_t limit_value = limit()->GetInteger32Constant(); |
- if (!limit_included()) { |
- limit_value--; |
- } |
- if (limit_value < result) result = limit_value; |
- } |
- |
- if (additional_upper_limit() != NULL && |
- additional_upper_limit()->IsInteger32Constant()) { |
- int32_t limit_value = additional_upper_limit()->GetInteger32Constant(); |
- if (!additional_upper_limit_is_included()) { |
- limit_value--; |
- } |
- if (limit_value < result) result = limit_value; |
- } |
- |
- if (and_mask > 0 && and_mask < MAX_LIMIT) { |
- if (and_mask < result) result = and_mask; |
- return result; |
- } |
- |
- // Add the effect of the or_mask. |
- result |= or_mask; |
- |
- return result >= MAX_LIMIT ? kNoLimit : result; |
-} |
- |
- |
-HValue* InductionVariableData::IgnoreOsrValue(HValue* v) { |
- if (!v->IsPhi()) return v; |
- HPhi* phi = HPhi::cast(v); |
- if (phi->OperandCount() != 2) return v; |
- if (phi->OperandAt(0)->block()->is_osr_entry()) { |
- return phi->OperandAt(1); |
- } else if (phi->OperandAt(1)->block()->is_osr_entry()) { |
- return phi->OperandAt(0); |
- } else { |
- return v; |
- } |
-} |
- |
- |
-InductionVariableData* InductionVariableData::GetInductionVariableData( |
- HValue* v) { |
- v = IgnoreOsrValue(v); |
- if (v->IsPhi()) { |
- return HPhi::cast(v)->induction_variable_data(); |
- } |
- return NULL; |
-} |
- |
- |
-/* |
- * Check if a conditional branch to "current_branch" with token "token" is |
- * the branch that keeps the induction loop running (and, conversely, will |
- * terminate it if the "other_branch" is taken). |
- * |
- * Three conditions must be met: |
- * - "current_branch" must be in the induction loop. |
- * - "other_branch" must be out of the induction loop. |
- * - "token" and the induction increment must be "compatible": the token should |
- * be a condition that keeps the execution inside the loop until the limit is |
- * reached. |
- */ |
-bool InductionVariableData::CheckIfBranchIsLoopGuard( |
- Token::Value token, |
- HBasicBlock* current_branch, |
- HBasicBlock* other_branch) { |
- if (!phi()->block()->current_loop()->IsNestedInThisLoop( |
- current_branch->current_loop())) { |
- return false; |
- } |
- |
- if (phi()->block()->current_loop()->IsNestedInThisLoop( |
- other_branch->current_loop())) { |
- return false; |
- } |
- |
- if (increment() > 0 && (token == Token::LT || token == Token::LTE)) { |
- return true; |
- } |
- if (increment() < 0 && (token == Token::GT || token == Token::GTE)) { |
- return true; |
- } |
- if (Token::IsInequalityOp(token) && (increment() == 1 || increment() == -1)) { |
- return true; |
- } |
- |
- return false; |
-} |
- |
- |
-void InductionVariableData::ComputeLimitFromPredecessorBlock( |
- HBasicBlock* block, |
- LimitFromPredecessorBlock* result) { |
- if (block->predecessors()->length() != 1) return; |
- HBasicBlock* predecessor = block->predecessors()->at(0); |
- HInstruction* end = predecessor->last(); |
- |
- if (!end->IsCompareNumericAndBranch()) return; |
- HCompareNumericAndBranch* branch = HCompareNumericAndBranch::cast(end); |
- |
- Token::Value token = branch->token(); |
- if (!Token::IsArithmeticCompareOp(token)) return; |
- |
- HBasicBlock* other_target; |
- if (block == branch->SuccessorAt(0)) { |
- other_target = branch->SuccessorAt(1); |
- } else { |
- other_target = branch->SuccessorAt(0); |
- token = Token::NegateCompareOp(token); |
- DCHECK(block == branch->SuccessorAt(1)); |
- } |
- |
- InductionVariableData* data; |
- |
- data = GetInductionVariableData(branch->left()); |
- HValue* limit = branch->right(); |
- if (data == NULL) { |
- data = GetInductionVariableData(branch->right()); |
- token = Token::ReverseCompareOp(token); |
- limit = branch->left(); |
- } |
- |
- if (data != NULL) { |
- result->variable = data; |
- result->token = token; |
- result->limit = limit; |
- result->other_target = other_target; |
- } |
-} |
- |
- |
-/* |
- * Compute the limit that is imposed on an induction variable when entering |
- * "block" (if any). |
- * If the limit is the "proper" induction limit (the one that makes the loop |
- * terminate when the induction variable reaches it) it is stored directly in |
- * the induction variable data. |
- * Otherwise the limit is written in "additional_limit" and the method |
- * returns true. |
- */ |
-bool InductionVariableData::ComputeInductionVariableLimit( |
- HBasicBlock* block, |
- InductionVariableLimitUpdate* additional_limit) { |
- LimitFromPredecessorBlock limit; |
- ComputeLimitFromPredecessorBlock(block, &limit); |
- if (!limit.LimitIsValid()) return false; |
- |
- if (limit.variable->CheckIfBranchIsLoopGuard(limit.token, |
- block, |
- limit.other_target)) { |
- limit.variable->limit_ = limit.limit; |
- limit.variable->limit_included_ = limit.LimitIsIncluded(); |
- limit.variable->limit_validity_ = block; |
- limit.variable->induction_exit_block_ = block->predecessors()->at(0); |
- limit.variable->induction_exit_target_ = limit.other_target; |
- return false; |
- } else { |
- additional_limit->updated_variable = limit.variable; |
- additional_limit->limit = limit.limit; |
- additional_limit->limit_is_upper = limit.LimitIsUpper(); |
- additional_limit->limit_is_included = limit.LimitIsIncluded(); |
- return true; |
- } |
-} |
- |
- |
Range* HMathMinMax::InferRange(Zone* zone) { |
if (representation().IsSmiOrInteger32()) { |
Range* a = left()->range(); |