Index: src/compiler/redundancy-elimination.cc |
diff --git a/src/compiler/redundancy-elimination.cc b/src/compiler/redundancy-elimination.cc |
index 4c50b19fa52dc8e5bc48b527ed4c23afb3bafbe0..d9cfa92481aba6b553f32274692ddc4e4a5b59b2 100644 |
--- a/src/compiler/redundancy-elimination.cc |
+++ b/src/compiler/redundancy-elimination.cc |
@@ -34,6 +34,16 @@ Reduction RedundancyElimination::Reduce(Node* node) { |
case IrOpcode::kCheckedTaggedToInt32: |
case IrOpcode::kCheckedUint32ToInt32: |
return ReduceCheckNode(node); |
+ case IrOpcode::kSpeculativeNumberAdd: |
+ case IrOpcode::kSpeculativeNumberSubtract: |
+ case IrOpcode::kSpeculativeNumberMultiply: |
+ case IrOpcode::kSpeculativeNumberModulus: |
+ case IrOpcode::kSpeculativeNumberDivide: |
+ case IrOpcode::kSpeculativeNumberShiftLeft: |
+ case IrOpcode::kSpeculativeNumberEqual: |
+ case IrOpcode::kSpeculativeNumberLessThan: |
+ case IrOpcode::kSpeculativeNumberLessThanOrEqual: |
+ return ReduceSpeculativeNode(node); |
case IrOpcode::kEffectPhi: |
return ReduceEffectPhi(node); |
case IrOpcode::kDead: |
@@ -119,11 +129,22 @@ bool IsCompatibleCheck(Node const* a, Node const* b) { |
return true; |
} |
+bool IsCompatibleSpeculative(Node const* a, Node const* b) { |
+ if (a->opcode() != b->opcode()) return false; |
+ DCHECK_EQ(a->InputCount(), b->InputCount()); |
+ for (int i = a->op()->ValueInputCount(); --i >= 0;) { |
+ if (a->InputAt(i) != b->InputAt(i)) return false; |
+ } |
+ return true; |
+} |
+ |
} // namespace |
-Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const { |
+template <typename Predicate> |
Jarin
2016/07/26 09:39:21
Do we really need to have templates for this? How
|
+Node* RedundancyElimination::EffectPathChecks::LookupCheck( |
+ Node* node, Predicate predicate) const { |
for (Check const* check = head_; check != nullptr; check = check->next) { |
- if (IsCompatibleCheck(check->node, node)) { |
+ if (predicate(check->node, node)) { |
DCHECK(!check->node->IsDead()); |
return check->node; |
} |
@@ -152,7 +173,7 @@ Reduction RedundancyElimination::ReduceCheckNode(Node* node) { |
// because we will have to recompute anyway once we compute the predecessor. |
if (checks == nullptr) return NoChange(); |
// See if we have another check that dominates us. |
- if (Node* check = checks->LookupCheck(node)) { |
+ if (Node* check = checks->LookupCheck(node, IsCompatibleCheck)) { |
ReplaceWithValue(node, check); |
return Replace(check); |
} |
@@ -160,6 +181,21 @@ Reduction RedundancyElimination::ReduceCheckNode(Node* node) { |
return UpdateChecks(node, checks->AddCheck(zone(), node)); |
} |
+Reduction RedundancyElimination::ReduceSpeculativeNode(Node* node) { |
+ 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(); |
+ // See if we have another speculative {node} that dominates us. |
+ if (Node* check = checks->LookupCheck(node, IsCompatibleSpeculative)) { |
+ ReplaceWithValue(node, check); |
+ return Replace(check); |
+ } |
+ // Learn from this speculative {node}. |
+ return UpdateChecks(node, checks->AddCheck(zone(), node)); |
+} |
+ |
Reduction RedundancyElimination::ReduceEffectPhi(Node* node) { |
Node* const control = NodeProperties::GetControlInput(node); |
if (control->opcode() == IrOpcode::kLoop) { |