[turbofan] Eliminate a few redundant bounds checks.

Usually loops run from 0 to some array length l, which means the
induction variable i will probably have type Unsigned32, just like
the length l. The CheckBounds operation lowers to an Uint32LessThan
comparison, so if we also lower the user level i < l comparison to
Uint32LessThan (whenever possible), we get some bounds check elimination
for free (via value numbering plus branch condition elimination).

This merges the branch condition elimination phase with the late
optimization phase to make this magic happen.

R=jarin@chromium.org
BUG=v8:4930,v8:5141

Review-Url: https://codereview.chromium.org/2135123002
Cr-Commit-Position: refs/heads/master@{#37629}
This commit is contained in:
bmeurer 2016-07-11 01:40:17 -07:00 committed by Commit bot
parent 7dbc223983
commit 4f97632880
3 changed files with 23 additions and 41 deletions

View File

@ -92,8 +92,7 @@ Reduction BranchElimination::ReduceDeoptimizeConditional(Node* node) {
// yet because we will have to recompute anyway once we compute the
// predecessor.
if (conditions == nullptr) {
DCHECK_NULL(node_conditions_.Get(node));
return NoChange();
return UpdateConditions(node, conditions);
}
Maybe<bool> condition_value = conditions->LookupCondition(condition);
if (condition_value.IsJust()) {
@ -123,8 +122,7 @@ Reduction BranchElimination::ReduceIf(Node* node, bool is_true_branch) {
// yet because we will have to recompute anyway once we compute the
// predecessor.
if (from_branch == nullptr) {
DCHECK(node_conditions_.Get(node) == nullptr);
return NoChange();
return UpdateConditions(node, nullptr);
}
Node* condition = branch->InputAt(0);
return UpdateConditions(
@ -145,8 +143,7 @@ Reduction BranchElimination::ReduceMerge(Node* node) {
// input.
for (int i = 0; i < node->InputCount(); i++) {
if (node_conditions_.Get(node->InputAt(i)) == nullptr) {
DCHECK(node_conditions_.Get(node) == nullptr);
return NoChange();
return UpdateConditions(node, nullptr);
}
}
@ -209,7 +206,8 @@ Reduction BranchElimination::UpdateConditions(
// Only signal that the node has Changed if the condition information has
// changed.
if (conditions != original) {
if (original == nullptr || *conditions != *original) {
if (conditions == nullptr || original == nullptr ||
*conditions != *original) {
node_conditions_.Set(node, conditions);
return Changed(node);
}

View File

@ -919,22 +919,6 @@ struct TypedLoweringPhase {
};
struct BranchEliminationPhase {
static const char* phase_name() { return "branch condition elimination"; }
void Run(PipelineData* data, Zone* temp_zone) {
JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common());
AddReducer(data, &graph_reducer, &branch_condition_elimination);
AddReducer(data, &graph_reducer, &dead_code_elimination);
graph_reducer.ReduceGraph();
}
};
struct EscapeAnalysisPhase {
static const char* phase_name() { return "escape analysis"; }
@ -1077,6 +1061,8 @@ struct LateOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common());
ValueNumberingReducer value_numbering(temp_zone);
@ -1086,6 +1072,7 @@ struct LateOptimizationPhase {
SelectLowering select_lowering(data->jsgraph()->graph(),
data->jsgraph()->common());
TailCallOptimization tco(data->common(), data->graph());
AddReducer(data, &graph_reducer, &branch_condition_elimination);
AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &value_numbering);
AddReducer(data, &graph_reducer, &machine_reducer);
@ -1511,9 +1498,6 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
RunPrintAndVerify("Store-store elimination", true);
}
Run<BranchEliminationPhase>();
RunPrintAndVerify("Branch conditions eliminated", true);
// Optimize control flow.
if (FLAG_turbo_cf_optimization) {
Run<ControlFlowOptimizationPhase>();

View File

@ -1270,16 +1270,16 @@ class RepresentationSelector {
case IrOpcode::kNumberLessThan:
case IrOpcode::kNumberLessThanOrEqual: {
// Number comparisons reduce to integer comparisons for integer inputs.
if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
// => signed Int32Cmp
VisitInt32Cmp(node);
if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
} else if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
// => unsigned Int32Cmp
VisitUint32Cmp(node);
if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
} else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
// => signed Int32Cmp
VisitInt32Cmp(node);
if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
} else {
// => Float64Cmp
VisitFloat64Cmp(node);
@ -1296,18 +1296,18 @@ class RepresentationSelector {
case IrOpcode::kSpeculativeNumberLessThanOrEqual:
case IrOpcode::kSpeculativeNumberEqual: {
// Number comparisons reduce to integer comparisons for integer inputs.
if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
// => signed Int32Cmp
VisitInt32Cmp(node);
if (lower()) ChangeToPureOp(node, Int32Op(node));
return;
} else if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
// => unsigned Int32Cmp
VisitUint32Cmp(node);
if (lower()) ChangeToPureOp(node, Uint32Op(node));
return;
} else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
// => signed Int32Cmp
VisitInt32Cmp(node);
if (lower()) ChangeToPureOp(node, Int32Op(node));
return;
}
// Try to use type feedback.
CompareOperationHints::Hint hint = CompareOperationHintOf(node->op());