[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:
parent
7dbc223983
commit
4f97632880
@ -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);
|
||||
}
|
||||
|
@ -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>();
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user