| Index: src/compiler/redundancy-elimination.cc
|
| diff --git a/src/compiler/redundancy-elimination.cc b/src/compiler/redundancy-elimination.cc
|
| index 6dcf2bf4cf0c111da9c018c0feb8e946d22ad061..acd051ac4408bb2b0d4bd05bba4166752e13d306 100644
|
| --- a/src/compiler/redundancy-elimination.cc
|
| +++ b/src/compiler/redundancy-elimination.cc
|
| @@ -36,6 +36,11 @@ Reduction RedundancyElimination::Reduce(Node* node) {
|
| case IrOpcode::kCheckedTaggedToInt32:
|
| case IrOpcode::kCheckedUint32ToInt32:
|
| return ReduceCheckNode(node);
|
| + case IrOpcode::kSpeculativeNumberAdd:
|
| + case IrOpcode::kSpeculativeNumberSubtract:
|
| + // For increments and decrements by a constant, try to learn from the last
|
| + // bounds check.
|
| + return TryReuseBoundsCheckForFirstInput(node);
|
| case IrOpcode::kEffectPhi:
|
| return ReduceEffectPhi(node);
|
| case IrOpcode::kDead:
|
| @@ -133,6 +138,17 @@ Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const {
|
| return nullptr;
|
| }
|
|
|
| +Node* RedundancyElimination::EffectPathChecks::LookupBoundsCheckFor(
|
| + Node* node) const {
|
| + for (Check const* check = head_; check != nullptr; check = check->next) {
|
| + if (check->node->opcode() == IrOpcode::kCheckBounds &&
|
| + check->node->InputAt(0) == node) {
|
| + return check->node;
|
| + }
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| RedundancyElimination::EffectPathChecks const*
|
| RedundancyElimination::PathChecksForEffectNodes::Get(Node* node) const {
|
| size_t const id = node->id();
|
| @@ -158,10 +174,41 @@ Reduction RedundancyElimination::ReduceCheckNode(Node* node) {
|
| ReplaceWithValue(node, check);
|
| return Replace(check);
|
| }
|
| +
|
| // Learn from this check.
|
| return UpdateChecks(node, checks->AddCheck(zone(), node));
|
| }
|
|
|
| +Reduction RedundancyElimination::TryReuseBoundsCheckForFirstInput(Node* node) {
|
| + DCHECK(node->opcode() == IrOpcode::kSpeculativeNumberAdd ||
|
| + node->opcode() == IrOpcode::kSpeculativeNumberSubtract);
|
| +
|
| + DCHECK_EQ(1, node->op()->EffectInputCount());
|
| + DCHECK_EQ(1, node->op()->EffectOutputCount());
|
| +
|
| + Node* const effect = NodeProperties::GetEffectInput(node);
|
| + EffectPathChecks const* checks = node_checks_.Get(effect);
|
| +
|
| + // If we do not know anything about the predecessor, do not propagate just yet
|
| + // because we will have to recompute anyway once we compute the predecessor.
|
| + if (checks == nullptr) return NoChange();
|
| +
|
| + Node* left = node->InputAt(0);
|
| + Node* right = node->InputAt(1);
|
| + // Only use bounds checks for increments/decrements by a constant.
|
| + if (right->opcode() == IrOpcode::kNumberConstant) {
|
| + if (Node* bounds_check = checks->LookupBoundsCheckFor(left)) {
|
| + // Only use the bounds checked type if it is better.
|
| + if (NodeProperties::GetType(bounds_check)
|
| + ->Is(NodeProperties::GetType(left))) {
|
| + node->ReplaceInput(0, bounds_check);
|
| + }
|
| + }
|
| + }
|
| +
|
| + return UpdateChecks(node, checks);
|
| +}
|
| +
|
| Reduction RedundancyElimination::ReduceEffectPhi(Node* node) {
|
| Node* const control = NodeProperties::GetControlInput(node);
|
| if (control->opcode() == IrOpcode::kLoop) {
|
|
|