| Index: src/compiler/value-numbering-reducer.cc
|
| diff --git a/src/compiler/value-numbering-reducer.cc b/src/compiler/value-numbering-reducer.cc
|
| index f4cf1d486266c2331fe95e39deb4dbc9130b4c74..734b3e8e8ee870f04b500e2f784849d95dd77505 100644
|
| --- a/src/compiler/value-numbering-reducer.cc
|
| +++ b/src/compiler/value-numbering-reducer.cc
|
| @@ -88,8 +88,33 @@ Reduction ValueNumberingReducer::Reduce(Node* node) {
|
| DCHECK(size_ * kCapacityToSizeRatio < capacity_);
|
| return NoChange();
|
| }
|
| +
|
| if (entry == node) {
|
| - return NoChange();
|
| + // We need to check for a certain class of collisions here. Imagine the
|
| + // following scenario:
|
| + //
|
| + // 1. We insert node1 with op1 and certain inputs at index i.
|
| + // 2. We insert node2 with op2 and certain inputs at index i+1.
|
| + // 3. Some other reducer changes node1 to op2 and the inputs from node2.
|
| + //
|
| + // Now we are called again to reduce node1, and we would return NoChange
|
| + // in this case because we find node1 first, but what we should actually
|
| + // do is return Replace(node2) instead.
|
| + for (size_t j = (i + 1) & mask;; j = (j + 1) & mask) {
|
| + Node* entry = entries_[j];
|
| + if (!entry) {
|
| + // No collision, {node} is fine.
|
| + return NoChange();
|
| + }
|
| + if (entry->IsDead()) {
|
| + continue;
|
| + }
|
| + if (Equals(entry, node)) {
|
| + // Overwrite the colliding entry with the actual entry.
|
| + entries_[i] = entry;
|
| + return Replace(entry);
|
| + }
|
| + }
|
| }
|
|
|
| // Skip dead entries, but remember their indices so we can reuse them.
|
|
|