[crankshaft] Delete unused Hydrogen-BCH code

Bounds check hoisting was known to be buggy and has never been turned on.
Since Crankshaft is deprecated, nobody is going to spend time fixing it,
so let's just get rid of it.

BUG=v8:4155,v8:4849
LOG=n
R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34948}
This commit is contained in:
jkummerow 2016-03-21 08:05:59 -07:00 committed by Commit bot
parent 3360ba08e8
commit 6703cce1b7
18 changed files with 0 additions and 1333 deletions

View File

@ -918,8 +918,6 @@ source_set("v8_base") {
"src/crankshaft/hydrogen-alias-analysis.h",
"src/crankshaft/hydrogen-bce.cc",
"src/crankshaft/hydrogen-bce.h",
"src/crankshaft/hydrogen-bch.cc",
"src/crankshaft/hydrogen-bch.h",
"src/crankshaft/hydrogen-canonicalize.cc",
"src/crankshaft/hydrogen-canonicalize.h",
"src/crankshaft/hydrogen-check-elimination.cc",

View File

@ -1825,13 +1825,6 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -819,13 +819,6 @@ LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
info()->MarkAsRequiresFrame();
LOperand* args = NULL;

View File

@ -1,379 +0,0 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/crankshaft/hydrogen-bch.h"
namespace v8 {
namespace internal {
/*
* This class is a table with one element for eack basic block.
*
* It is used to check if, inside one loop, all execution paths contain
* a bounds check for a particular [index, length] combination.
* The reason is that if there is a path that stays in the loop without
* executing a check then the check cannot be hoisted out of the loop (it
* would likely fail and cause a deopt for no good reason).
* We also check is there are paths that exit the loop early, and if yes we
* perform the hoisting only if graph()->use_optimistic_licm() is true.
* The reason is that such paths are realtively common and harmless (like in
* a "search" method that scans an array until an element is found), but in
* some cases they could cause a deopt if we hoist the check so this is a
* situation we need to detect.
*/
class InductionVariableBlocksTable BASE_EMBEDDED {
public:
class Element {
public:
static const int kNoBlock = -1;
HBasicBlock* block() { return block_; }
void set_block(HBasicBlock* block) { block_ = block; }
bool is_start() { return is_start_; }
bool is_proper_exit() { return is_proper_exit_; }
bool is_in_loop() { return is_in_loop_; }
bool has_check() { return has_check_; }
void set_has_check() { has_check_ = true; }
InductionVariableLimitUpdate* additional_limit() {
return &additional_limit_;
}
/*
* Initializes the table element for a given loop (identified by its
* induction variable).
*/
void InitializeLoop(InductionVariableData* data) {
DCHECK(data->limit() != NULL);
HLoopInformation* loop = data->phi()->block()->current_loop();
is_start_ = (block() == loop->loop_header());
is_proper_exit_ = (block() == data->induction_exit_target());
is_in_loop_ = loop->IsNestedInThisLoop(block()->current_loop());
has_check_ = false;
}
// Utility methods to iterate over dominated blocks.
void ResetCurrentDominatedBlock() { current_dominated_block_ = kNoBlock; }
HBasicBlock* CurrentDominatedBlock() {
DCHECK(current_dominated_block_ != kNoBlock);
return current_dominated_block_ < block()->dominated_blocks()->length() ?
block()->dominated_blocks()->at(current_dominated_block_) : NULL;
}
HBasicBlock* NextDominatedBlock() {
current_dominated_block_++;
return CurrentDominatedBlock();
}
Element()
: block_(NULL), is_start_(false), is_proper_exit_(false),
has_check_(false), additional_limit_(),
current_dominated_block_(kNoBlock) {}
private:
HBasicBlock* block_;
bool is_start_;
bool is_proper_exit_;
bool is_in_loop_;
bool has_check_;
InductionVariableLimitUpdate additional_limit_;
int current_dominated_block_;
};
HGraph* graph() const { return graph_; }
Counters* counters() const { return graph()->isolate()->counters(); }
HBasicBlock* loop_header() const { return loop_header_; }
Element* at(int index) const { return &(elements_.at(index)); }
Element* at(HBasicBlock* block) const { return at(block->block_id()); }
void AddCheckAt(HBasicBlock* block) {
at(block->block_id())->set_has_check();
}
/*
* Initializes the table for a given loop (identified by its induction
* variable).
*/
void InitializeLoop(InductionVariableData* data) {
for (int i = 0; i < graph()->blocks()->length(); i++) {
at(i)->InitializeLoop(data);
}
loop_header_ = data->phi()->block()->current_loop()->loop_header();
}
enum Hoistability {
HOISTABLE,
OPTIMISTICALLY_HOISTABLE,
NOT_HOISTABLE
};
/*
* This method checks if it is appropriate to hoist the bounds checks on an
* induction variable out of the loop.
* The problem is that in the loop code graph there could be execution paths
* where the check is not performed, but hoisting the check has the same
* semantics as performing it at every loop iteration, which could cause
* unnecessary check failures (which would mean unnecessary deoptimizations).
* The method returns OK if there are no paths that perform an iteration
* (loop back to the header) without meeting a check, or UNSAFE is set if
* early exit paths are found.
*/
Hoistability CheckHoistability() {
for (int i = 0; i < elements_.length(); i++) {
at(i)->ResetCurrentDominatedBlock();
}
bool unsafe = false;
HBasicBlock* current = loop_header();
while (current != NULL) {
HBasicBlock* next;
if (at(current)->has_check() || !at(current)->is_in_loop()) {
// We found a check or we reached a dominated block out of the loop,
// therefore this block is safe and we can backtrack.
next = NULL;
} else {
for (int i = 0; i < current->end()->SuccessorCount(); i ++) {
Element* successor = at(current->end()->SuccessorAt(i));
if (!successor->is_in_loop()) {
if (!successor->is_proper_exit()) {
// We found a path that exits the loop early, and is not the exit
// related to the induction limit, therefore hoisting checks is
// an optimistic assumption.
unsafe = true;
}
}
if (successor->is_start()) {
// We found a path that does one loop iteration without meeting any
// check, therefore hoisting checks would be likely to cause
// unnecessary deopts.
return NOT_HOISTABLE;
}
}
next = at(current)->NextDominatedBlock();
}
// If we have no next block we need to backtrack the tree traversal.
while (next == NULL) {
current = current->dominator();
if (current != NULL) {
next = at(current)->NextDominatedBlock();
} else {
// We reached the root: next stays NULL.
next = NULL;
break;
}
}
current = next;
}
return unsafe ? OPTIMISTICALLY_HOISTABLE : HOISTABLE;
}
explicit InductionVariableBlocksTable(HGraph* graph)
: graph_(graph), loop_header_(NULL),
elements_(graph->blocks()->length(), graph->zone()) {
for (int i = 0; i < graph->blocks()->length(); i++) {
Element element;
element.set_block(graph->blocks()->at(i));
elements_.Add(element, graph->zone());
DCHECK(at(i)->block()->block_id() == i);
}
}
// Tries to hoist a check out of its induction loop.
void ProcessRelatedChecks(
InductionVariableData::InductionVariableCheck* check,
InductionVariableData* data) {
HValue* length = check->check()->length();
check->set_processed();
HBasicBlock* header =
data->phi()->block()->current_loop()->loop_header();
HBasicBlock* pre_header = header->predecessors()->at(0);
// Check that the limit is defined in the loop preheader.
if (!data->limit()->IsInteger32Constant()) {
HBasicBlock* limit_block = data->limit()->block();
if (limit_block != pre_header &&
!limit_block->Dominates(pre_header)) {
return;
}
}
// Check that the length and limit have compatible representations.
if (!(data->limit()->representation().Equals(
length->representation()) ||
data->limit()->IsInteger32Constant())) {
return;
}
// Check that the length is defined in the loop preheader.
if (check->check()->length()->block() != pre_header &&
!check->check()->length()->block()->Dominates(pre_header)) {
return;
}
// Add checks to the table.
for (InductionVariableData::InductionVariableCheck* current_check = check;
current_check != NULL;
current_check = current_check->next()) {
if (current_check->check()->length() != length) continue;
AddCheckAt(current_check->check()->block());
current_check->set_processed();
}
// Check that we will not cause unwanted deoptimizations.
Hoistability hoistability = CheckHoistability();
if (hoistability == NOT_HOISTABLE ||
(hoistability == OPTIMISTICALLY_HOISTABLE &&
!graph()->use_optimistic_licm())) {
return;
}
// We will do the hoisting, but we must see if the limit is "limit" or if
// all checks are done on constants: if all check are done against the same
// constant limit we will use that instead of the induction limit.
bool has_upper_constant_limit = true;
int32_t upper_constant_limit =
check->HasUpperLimit() ? check->upper_limit() : 0;
for (InductionVariableData::InductionVariableCheck* current_check = check;
current_check != NULL;
current_check = current_check->next()) {
has_upper_constant_limit =
has_upper_constant_limit && current_check->HasUpperLimit() &&
current_check->upper_limit() == upper_constant_limit;
counters()->bounds_checks_eliminated()->Increment();
current_check->check()->set_skip_check();
}
// Choose the appropriate limit.
Zone* zone = graph()->zone();
HValue* context = graph()->GetInvalidContext();
HValue* limit = data->limit();
if (has_upper_constant_limit) {
HConstant* new_limit = HConstant::New(graph()->isolate(), zone, context,
upper_constant_limit);
new_limit->InsertBefore(pre_header->end());
limit = new_limit;
}
// If necessary, redefine the limit in the preheader.
if (limit->IsInteger32Constant() &&
limit->block() != pre_header &&
!limit->block()->Dominates(pre_header)) {
HConstant* new_limit = HConstant::New(graph()->isolate(), zone, context,
limit->GetInteger32Constant());
new_limit->InsertBefore(pre_header->end());
limit = new_limit;
}
// Do the hoisting.
HBoundsCheck* hoisted_check = HBoundsCheck::New(
graph()->isolate(), zone, context, limit, check->check()->length());
hoisted_check->InsertBefore(pre_header->end());
hoisted_check->set_allow_equality(true);
counters()->bounds_checks_hoisted()->Increment();
}
void CollectInductionVariableData(HBasicBlock* bb) {
bool additional_limit = false;
for (int i = 0; i < bb->phis()->length(); i++) {
HPhi* phi = bb->phis()->at(i);
phi->DetectInductionVariable();
}
additional_limit = InductionVariableData::ComputeInductionVariableLimit(
bb, at(bb)->additional_limit());
if (additional_limit) {
at(bb)->additional_limit()->updated_variable->
UpdateAdditionalLimit(at(bb)->additional_limit());
}
for (HInstruction* i = bb->first(); i != NULL; i = i->next()) {
if (!i->IsBoundsCheck()) continue;
HBoundsCheck* check = HBoundsCheck::cast(i);
InductionVariableData::BitwiseDecompositionResult decomposition;
InductionVariableData::DecomposeBitwise(check->index(), &decomposition);
if (!decomposition.base->IsPhi()) continue;
HPhi* phi = HPhi::cast(decomposition.base);
if (!phi->IsInductionVariable()) continue;
InductionVariableData* data = phi->induction_variable_data();
// For now ignore loops decrementing the index.
if (data->increment() <= 0) continue;
if (!data->LowerLimitIsNonNegativeConstant()) continue;
// TODO(mmassi): skip OSR values for check->length().
if (check->length() == data->limit() ||
check->length() == data->additional_upper_limit()) {
counters()->bounds_checks_eliminated()->Increment();
check->set_skip_check();
continue;
}
if (!phi->IsLimitedInductionVariable()) continue;
int32_t limit = data->ComputeUpperLimit(decomposition.and_mask,
decomposition.or_mask);
phi->induction_variable_data()->AddCheck(check, limit);
}
for (int i = 0; i < bb->dominated_blocks()->length(); i++) {
CollectInductionVariableData(bb->dominated_blocks()->at(i));
}
if (additional_limit) {
at(bb->block_id())->additional_limit()->updated_variable->
UpdateAdditionalLimit(at(bb->block_id())->additional_limit());
}
}
void EliminateRedundantBoundsChecks(HBasicBlock* bb) {
for (int i = 0; i < bb->phis()->length(); i++) {
HPhi* phi = bb->phis()->at(i);
if (!phi->IsLimitedInductionVariable()) continue;
InductionVariableData* induction_data = phi->induction_variable_data();
InductionVariableData::ChecksRelatedToLength* current_length_group =
induction_data->checks();
while (current_length_group != NULL) {
current_length_group->CloseCurrentBlock();
InductionVariableData::InductionVariableCheck* current_base_check =
current_length_group->checks();
InitializeLoop(induction_data);
while (current_base_check != NULL) {
ProcessRelatedChecks(current_base_check, induction_data);
while (current_base_check != NULL &&
current_base_check->processed()) {
current_base_check = current_base_check->next();
}
}
current_length_group = current_length_group->next();
}
}
}
private:
HGraph* graph_;
HBasicBlock* loop_header_;
ZoneList<Element> elements_;
};
void HBoundsCheckHoistingPhase::HoistRedundantBoundsChecks() {
InductionVariableBlocksTable table(graph());
table.CollectInductionVariableData(graph()->entry_block());
for (int i = 0; i < graph()->blocks()->length(); i++) {
table.EliminateRedundantBoundsChecks(graph()->blocks()->at(i));
}
}
} // namespace internal
} // namespace v8

View File

@ -1,33 +0,0 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CRANKSHAFT_HYDROGEN_BCH_H_
#define V8_CRANKSHAFT_HYDROGEN_BCH_H_
#include "src/crankshaft/hydrogen.h"
namespace v8 {
namespace internal {
class HBoundsCheckHoistingPhase : public HPhase {
public:
explicit HBoundsCheckHoistingPhase(HGraph* graph)
: HPhase("H_Bounds checks hoisting", graph) { }
void Run() {
HoistRedundantBoundsChecks();
}
private:
void HoistRedundantBoundsChecks();
DISALLOW_COPY_AND_ASSIGN(HBoundsCheckHoistingPhase);
};
} // namespace internal
} // namespace v8
#endif // V8_CRANKSHAFT_HYDROGEN_BCE_H_

View File

@ -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();

View File

@ -56,7 +56,6 @@ class LChunkBuilder;
V(Bitwise) \
V(BlockEntry) \
V(BoundsCheck) \
V(BoundsCheckBaseIndexInformation) \
V(Branch) \
V(CallWithDescriptor) \
V(CallNewArray) \
@ -732,14 +731,6 @@ class HValue : public ZoneObject {
virtual void Verify() = 0;
#endif
virtual bool TryDecompose(DecompositionResult* decomposition) {
if (RedefinedOperand() != NULL) {
return RedefinedOperand()->TryDecompose(decomposition);
} else {
return false;
}
}
// Returns true conservatively if the program might be able to observe a
// ToString() operation on this value.
bool ToStringCanBeObserved() const {
@ -2948,226 +2939,6 @@ class HCheckHeapObject final : public HUnaryOperation {
};
class InductionVariableData;
struct InductionVariableLimitUpdate {
InductionVariableData* updated_variable;
HValue* limit;
bool limit_is_upper;
bool limit_is_included;
InductionVariableLimitUpdate()
: updated_variable(NULL), limit(NULL),
limit_is_upper(false), limit_is_included(false) {}
};
class HBoundsCheck;
class HPhi;
class HBitwise;
class InductionVariableData final : public ZoneObject {
public:
class InductionVariableCheck : public ZoneObject {
public:
HBoundsCheck* check() { return check_; }
InductionVariableCheck* next() { return next_; }
bool HasUpperLimit() { return upper_limit_ >= 0; }
int32_t upper_limit() {
DCHECK(HasUpperLimit());
return upper_limit_;
}
void set_upper_limit(int32_t upper_limit) {
upper_limit_ = upper_limit;
}
bool processed() { return processed_; }
void set_processed() { processed_ = true; }
InductionVariableCheck(HBoundsCheck* check,
InductionVariableCheck* next,
int32_t upper_limit = kNoLimit)
: check_(check), next_(next), upper_limit_(upper_limit),
processed_(false) {}
private:
HBoundsCheck* check_;
InductionVariableCheck* next_;
int32_t upper_limit_;
bool processed_;
};
class ChecksRelatedToLength : public ZoneObject {
public:
HValue* length() { return length_; }
ChecksRelatedToLength* next() { return next_; }
InductionVariableCheck* checks() { return checks_; }
void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
void CloseCurrentBlock();
ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
: length_(length), next_(next), checks_(NULL),
first_check_in_block_(NULL),
added_index_(NULL),
added_constant_(NULL),
current_and_mask_in_block_(0),
current_or_mask_in_block_(0) {}
private:
void UseNewIndexInCurrentBlock(Token::Value token,
int32_t mask,
HValue* index_base,
HValue* context);
HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
HBitwise* added_index() { return added_index_; }
void set_added_index(HBitwise* index) { added_index_ = index; }
HConstant* added_constant() { return added_constant_; }
void set_added_constant(HConstant* constant) { added_constant_ = constant; }
int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
int32_t current_upper_limit() { return current_upper_limit_; }
HValue* length_;
ChecksRelatedToLength* next_;
InductionVariableCheck* checks_;
HBoundsCheck* first_check_in_block_;
HBitwise* added_index_;
HConstant* added_constant_;
int32_t current_and_mask_in_block_;
int32_t current_or_mask_in_block_;
int32_t current_upper_limit_;
};
struct LimitFromPredecessorBlock {
InductionVariableData* variable;
Token::Value token;
HValue* limit;
HBasicBlock* other_target;
bool LimitIsValid() { return token != Token::ILLEGAL; }
bool LimitIsIncluded() {
return Token::IsEqualityOp(token) ||
token == Token::GTE || token == Token::LTE;
}
bool LimitIsUpper() {
return token == Token::LTE || token == Token::LT || token == Token::NE;
}
LimitFromPredecessorBlock()
: variable(NULL),
token(Token::ILLEGAL),
limit(NULL),
other_target(NULL) {}
};
static const int32_t kNoLimit = -1;
static InductionVariableData* ExaminePhi(HPhi* phi);
static void ComputeLimitFromPredecessorBlock(
HBasicBlock* block,
LimitFromPredecessorBlock* result);
static bool ComputeInductionVariableLimit(
HBasicBlock* block,
InductionVariableLimitUpdate* additional_limit);
struct BitwiseDecompositionResult {
HValue* base;
int32_t and_mask;
int32_t or_mask;
HValue* context;
BitwiseDecompositionResult()
: base(NULL), and_mask(0), or_mask(0), context(NULL) {}
};
static void DecomposeBitwise(HValue* value,
BitwiseDecompositionResult* result);
void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
bool CheckIfBranchIsLoopGuard(Token::Value token,
HBasicBlock* current_branch,
HBasicBlock* other_branch);
void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
HPhi* phi() { return phi_; }
HValue* base() { return base_; }
int32_t increment() { return increment_; }
HValue* limit() { return limit_; }
bool limit_included() { return limit_included_; }
HBasicBlock* limit_validity() { return limit_validity_; }
HBasicBlock* induction_exit_block() { return induction_exit_block_; }
HBasicBlock* induction_exit_target() { return induction_exit_target_; }
ChecksRelatedToLength* checks() { return checks_; }
HValue* additional_upper_limit() { return additional_upper_limit_; }
bool additional_upper_limit_is_included() {
return additional_upper_limit_is_included_;
}
HValue* additional_lower_limit() { return additional_lower_limit_; }
bool additional_lower_limit_is_included() {
return additional_lower_limit_is_included_;
}
bool LowerLimitIsNonNegativeConstant() {
if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
return true;
}
if (additional_lower_limit() != NULL &&
additional_lower_limit()->IsInteger32Constant() &&
additional_lower_limit()->GetInteger32Constant() >= 0) {
// Ignoring the corner case of !additional_lower_limit_is_included()
// is safe, handling it adds unneeded complexity.
return true;
}
return false;
}
int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
private:
template <class T> void swap(T* a, T* b) {
T c(*a);
*a = *b;
*b = c;
}
InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
: phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
limit_(NULL), limit_included_(false), limit_validity_(NULL),
induction_exit_block_(NULL), induction_exit_target_(NULL),
checks_(NULL),
additional_upper_limit_(NULL),
additional_upper_limit_is_included_(false),
additional_lower_limit_(NULL),
additional_lower_limit_is_included_(false) {}
static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
static HValue* IgnoreOsrValue(HValue* v);
static InductionVariableData* GetInductionVariableData(HValue* v);
HPhi* phi_;
HValue* base_;
int32_t increment_;
HValue* limit_;
bool limit_included_;
HBasicBlock* limit_validity_;
HBasicBlock* induction_exit_block_;
HBasicBlock* induction_exit_target_;
ChecksRelatedToLength* checks_;
HValue* additional_upper_limit_;
bool additional_upper_limit_is_included_;
HValue* additional_lower_limit_;
bool additional_lower_limit_is_included_;
};
class HPhi final : public HValue {
public:
HPhi(int merged_index, Zone* zone)
@ -3201,21 +2972,6 @@ class HPhi final : public HValue {
int merged_index() const { return merged_index_; }
InductionVariableData* induction_variable_data() {
return induction_variable_data_;
}
bool IsInductionVariable() {
return induction_variable_data_ != NULL;
}
bool IsLimitedInductionVariable() {
return IsInductionVariable() &&
induction_variable_data_->limit() != NULL;
}
void DetectInductionVariable() {
DCHECK(induction_variable_data_ == NULL);
induction_variable_data_ = InductionVariableData::ExaminePhi(this);
}
std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
#ifdef DEBUG
@ -3261,7 +3017,6 @@ class HPhi final : public HValue {
int merged_index_ = 0;
int phi_id_ = -1;
InductionVariableData* induction_variable_data_ = nullptr;
Representation representation_from_indirect_uses_ = Representation::None();
Representation representation_from_non_phi_uses_ = Representation::None();
@ -3938,9 +3693,6 @@ class HAccessArgumentsAt final : public HTemplateInstruction<3> {
};
class HBoundsCheckBaseIndexInformation;
class HBoundsCheck final : public HTemplateInstruction<2> {
public:
DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
@ -3952,24 +3704,6 @@ class HBoundsCheck final : public HTemplateInstruction<2> {
int offset() const { return offset_; }
int scale() const { return scale_; }
void ApplyIndexChange();
bool DetectCompoundIndex() {
DCHECK(base() == NULL);
DecompositionResult decomposition;
if (index()->TryDecompose(&decomposition)) {
base_ = decomposition.base();
offset_ = decomposition.offset();
scale_ = decomposition.scale();
return true;
} else {
base_ = index();
offset_ = 0;
scale_ = 0;
return false;
}
}
Representation RequiredInputRepresentation(int index) override {
return representation();
}
@ -3988,8 +3722,6 @@ class HBoundsCheck final : public HTemplateInstruction<2> {
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
protected:
friend class HBoundsCheckBaseIndexInformation;
Range* InferRange(Zone* zone) override;
bool DataEquals(HValue* other) override { return true; }
@ -4018,34 +3750,6 @@ class HBoundsCheck final : public HTemplateInstruction<2> {
};
class HBoundsCheckBaseIndexInformation final : public HTemplateInstruction<2> {
public:
explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
DecompositionResult decomposition;
if (check->index()->TryDecompose(&decomposition)) {
SetOperandAt(0, decomposition.base());
SetOperandAt(1, check);
} else {
UNREACHABLE();
}
}
HValue* base_index() const { return OperandAt(0); }
HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
Representation RequiredInputRepresentation(int index) override {
return representation();
}
std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
int RedefinedOperandIndex() override { return 0; }
bool IsPurelyInformativeDefinition() override { return true; }
};
class HBitwiseBinaryOperation : public HBinaryOperation {
public:
HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
@ -4668,18 +4372,6 @@ class HAdd final : public HArithmeticBinaryOperation {
HValue* Canonicalize() override;
bool TryDecompose(DecompositionResult* decomposition) override {
if (left()->IsInteger32Constant()) {
decomposition->Apply(right(), left()->GetInteger32Constant());
return true;
} else if (right()->IsInteger32Constant()) {
decomposition->Apply(left(), right()->GetInteger32Constant());
return true;
} else {
return false;
}
}
void RepresentationChanged(Representation to) override {
if (to.IsTagged() &&
(left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
@ -4759,15 +4451,6 @@ class HSub final : public HArithmeticBinaryOperation {
HValue* Canonicalize() override;
bool TryDecompose(DecompositionResult* decomposition) override {
if (right()->IsInteger32Constant()) {
decomposition->Apply(left(), -right()->GetInteger32Constant());
return true;
} else {
return false;
}
}
DECLARE_CONCRETE_INSTRUCTION(Sub)
protected:
@ -5022,18 +4705,6 @@ class HShr final : public HBitwiseBinaryOperation {
static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
HValue* left, HValue* right);
bool TryDecompose(DecompositionResult* decomposition) override {
if (right()->IsInteger32Constant()) {
if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
// This is intended to look for HAdd and HSub, to handle compounds
// like ((base + offset) >> scale) with one single decomposition.
left()->TryDecompose(decomposition);
return true;
}
}
return false;
}
Range* InferRange(Zone* zone) override;
void UpdateRepresentation(Representation new_rep,
@ -5059,18 +4730,6 @@ class HSar final : public HBitwiseBinaryOperation {
static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
HValue* left, HValue* right);
bool TryDecompose(DecompositionResult* decomposition) override {
if (right()->IsInteger32Constant()) {
if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
// This is intended to look for HAdd and HSub, to handle compounds
// like ((base + offset) >> scale) with one single decomposition.
left()->TryDecompose(decomposition);
return true;
}
}
return false;
}
Range* InferRange(Zone* zone) override;
void UpdateRepresentation(Representation new_rep,

View File

@ -11,7 +11,6 @@
#include "src/ast/scopeinfo.h"
#include "src/code-factory.h"
#include "src/crankshaft/hydrogen-bce.h"
#include "src/crankshaft/hydrogen-bch.h"
#include "src/crankshaft/hydrogen-canonicalize.h"
#include "src/crankshaft/hydrogen-check-elimination.h"
#include "src/crankshaft/hydrogen-dce.h"
@ -4528,7 +4527,6 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
Run<HStackCheckEliminationPhase>();
if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();

View File

@ -294,8 +294,6 @@ class HLoopInformation final : public ZoneObject {
};
class BoundsCheckTable;
class InductionVariableBlocksTable;
class HGraph final : public ZoneObject {
public:
explicit HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor);

View File

@ -1810,13 +1810,6 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -1772,13 +1772,6 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -1778,13 +1778,6 @@ return result;
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -1764,13 +1764,6 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -1615,12 +1615,6 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
return result;
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -1797,13 +1797,6 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -1790,13 +1790,6 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
HBoundsCheckBaseIndexInformation* instr) {
UNREACHABLE();
return NULL;
}
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
// The control instruction marking the end of a block that completed
// abruptly (e.g., threw an exception). There is nothing specific to do.

View File

@ -367,8 +367,6 @@ DEFINE_BOOL(use_osr, true, "use on-stack replacement")
DEFINE_BOOL(array_bounds_checks_elimination, true,
"perform array bounds checks elimination")
DEFINE_BOOL(trace_bce, false, "trace array bounds check elimination")
DEFINE_BOOL(array_bounds_checks_hoisting, false,
"perform array bounds checks hoisting")
DEFINE_BOOL(array_index_dehoisting, true, "perform array index dehoisting")
DEFINE_BOOL(analyze_environment_liveness, true,
"analyze liveness of environment slots and zap dead values")

View File

@ -745,8 +745,6 @@
'../../src/crankshaft/hydrogen-alias-analysis.h',
'../../src/crankshaft/hydrogen-bce.cc',
'../../src/crankshaft/hydrogen-bce.h',
'../../src/crankshaft/hydrogen-bch.cc',
'../../src/crankshaft/hydrogen-bch.h',
'../../src/crankshaft/hydrogen-canonicalize.cc',
'../../src/crankshaft/hydrogen-canonicalize.h',
'../../src/crankshaft/hydrogen-check-elimination.cc',