Commit 4f976328 authored by bmeurer's avatar bmeurer Committed by Commit bot

[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}
parent 7dbc2239
...@@ -92,8 +92,7 @@ Reduction BranchElimination::ReduceDeoptimizeConditional(Node* node) { ...@@ -92,8 +92,7 @@ Reduction BranchElimination::ReduceDeoptimizeConditional(Node* node) {
// yet because we will have to recompute anyway once we compute the // yet because we will have to recompute anyway once we compute the
// predecessor. // predecessor.
if (conditions == nullptr) { if (conditions == nullptr) {
DCHECK_NULL(node_conditions_.Get(node)); return UpdateConditions(node, conditions);
return NoChange();
} }
Maybe<bool> condition_value = conditions->LookupCondition(condition); Maybe<bool> condition_value = conditions->LookupCondition(condition);
if (condition_value.IsJust()) { if (condition_value.IsJust()) {
...@@ -123,8 +122,7 @@ Reduction BranchElimination::ReduceIf(Node* node, bool is_true_branch) { ...@@ -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 // yet because we will have to recompute anyway once we compute the
// predecessor. // predecessor.
if (from_branch == nullptr) { if (from_branch == nullptr) {
DCHECK(node_conditions_.Get(node) == nullptr); return UpdateConditions(node, nullptr);
return NoChange();
} }
Node* condition = branch->InputAt(0); Node* condition = branch->InputAt(0);
return UpdateConditions( return UpdateConditions(
...@@ -145,8 +143,7 @@ Reduction BranchElimination::ReduceMerge(Node* node) { ...@@ -145,8 +143,7 @@ Reduction BranchElimination::ReduceMerge(Node* node) {
// input. // input.
for (int i = 0; i < node->InputCount(); i++) { for (int i = 0; i < node->InputCount(); i++) {
if (node_conditions_.Get(node->InputAt(i)) == nullptr) { if (node_conditions_.Get(node->InputAt(i)) == nullptr) {
DCHECK(node_conditions_.Get(node) == nullptr); return UpdateConditions(node, nullptr);
return NoChange();
} }
} }
...@@ -209,7 +206,8 @@ Reduction BranchElimination::UpdateConditions( ...@@ -209,7 +206,8 @@ Reduction BranchElimination::UpdateConditions(
// Only signal that the node has Changed if the condition information has // Only signal that the node has Changed if the condition information has
// changed. // changed.
if (conditions != original) { if (conditions != original) {
if (original == nullptr || *conditions != *original) { if (conditions == nullptr || original == nullptr ||
*conditions != *original) {
node_conditions_.Set(node, conditions); node_conditions_.Set(node, conditions);
return Changed(node); return Changed(node);
} }
......
...@@ -919,22 +919,6 @@ struct TypedLoweringPhase { ...@@ -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 { struct EscapeAnalysisPhase {
static const char* phase_name() { return "escape analysis"; } static const char* phase_name() { return "escape analysis"; }
...@@ -1077,6 +1061,8 @@ struct LateOptimizationPhase { ...@@ -1077,6 +1061,8 @@ struct LateOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
JSGraphReducer graph_reducer(data->jsgraph(), 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(), DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common()); data->common());
ValueNumberingReducer value_numbering(temp_zone); ValueNumberingReducer value_numbering(temp_zone);
...@@ -1086,6 +1072,7 @@ struct LateOptimizationPhase { ...@@ -1086,6 +1072,7 @@ struct LateOptimizationPhase {
SelectLowering select_lowering(data->jsgraph()->graph(), SelectLowering select_lowering(data->jsgraph()->graph(),
data->jsgraph()->common()); data->jsgraph()->common());
TailCallOptimization tco(data->common(), data->graph()); TailCallOptimization tco(data->common(), data->graph());
AddReducer(data, &graph_reducer, &branch_condition_elimination);
AddReducer(data, &graph_reducer, &dead_code_elimination); AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &value_numbering); AddReducer(data, &graph_reducer, &value_numbering);
AddReducer(data, &graph_reducer, &machine_reducer); AddReducer(data, &graph_reducer, &machine_reducer);
...@@ -1511,9 +1498,6 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) { ...@@ -1511,9 +1498,6 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
RunPrintAndVerify("Store-store elimination", true); RunPrintAndVerify("Store-store elimination", true);
} }
Run<BranchEliminationPhase>();
RunPrintAndVerify("Branch conditions eliminated", true);
// Optimize control flow. // Optimize control flow.
if (FLAG_turbo_cf_optimization) { if (FLAG_turbo_cf_optimization) {
Run<ControlFlowOptimizationPhase>(); Run<ControlFlowOptimizationPhase>();
......
...@@ -1270,16 +1270,16 @@ class RepresentationSelector { ...@@ -1270,16 +1270,16 @@ class RepresentationSelector {
case IrOpcode::kNumberLessThan: case IrOpcode::kNumberLessThan:
case IrOpcode::kNumberLessThanOrEqual: { case IrOpcode::kNumberLessThanOrEqual: {
// Number comparisons reduce to integer comparisons for integer inputs. // Number comparisons reduce to integer comparisons for integer inputs.
if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32())) { TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
// => 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())) {
// => unsigned Int32Cmp // => unsigned Int32Cmp
VisitUint32Cmp(node); VisitUint32Cmp(node);
if (lower()) NodeProperties::ChangeOp(node, Uint32Op(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 { } else {
// => Float64Cmp // => Float64Cmp
VisitFloat64Cmp(node); VisitFloat64Cmp(node);
...@@ -1296,18 +1296,18 @@ class RepresentationSelector { ...@@ -1296,18 +1296,18 @@ class RepresentationSelector {
case IrOpcode::kSpeculativeNumberLessThanOrEqual: case IrOpcode::kSpeculativeNumberLessThanOrEqual:
case IrOpcode::kSpeculativeNumberEqual: { case IrOpcode::kSpeculativeNumberEqual: {
// Number comparisons reduce to integer comparisons for integer inputs. // Number comparisons reduce to integer comparisons for integer inputs.
if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32())) { TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
// => 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())) {
// => unsigned Int32Cmp // => unsigned Int32Cmp
VisitUint32Cmp(node); VisitUint32Cmp(node);
if (lower()) ChangeToPureOp(node, Uint32Op(node)); if (lower()) ChangeToPureOp(node, Uint32Op(node));
return; 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. // Try to use type feedback.
CompareOperationHints::Hint hint = CompareOperationHintOf(node->op()); CompareOperationHints::Hint hint = CompareOperationHintOf(node->op());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment