| Index: src/compiler/value-numbering-reducer.cc
|
| diff --git a/src/compiler/value-numbering-reducer.cc b/src/compiler/value-numbering-reducer.cc
|
| index b9161df6a29c4f73270cb54096f659016e0630bd..30473f2798ba96ed160e47ef4e4ae4e1bf3d9bf9 100644
|
| --- a/src/compiler/value-numbering-reducer.cc
|
| +++ b/src/compiler/value-numbering-reducer.cc
|
| @@ -112,10 +112,31 @@ Reduction ValueNumberingReducer::Reduce(Node* node) {
|
| if (entry->IsDead()) {
|
| continue;
|
| }
|
| + if (entry == node) {
|
| + // Collision with ourselves, doesn't count as a real collision.
|
| + // Opportunistically clean-up the duplicate entry if we're at the end
|
| + // of a bucket.
|
| + if (!entries_[(j + 1) & mask]) {
|
| + entries_[j] = nullptr;
|
| + size_--;
|
| + return NoChange();
|
| + }
|
| + // Otherwise, keep searching for another collision.
|
| + continue;
|
| + }
|
| if (Equals(entry, node)) {
|
| - // Overwrite the colliding entry with the actual entry.
|
| - entries_[i] = entry;
|
| - return Replace(entry);
|
| + Reduction reduction = ReplaceIfTypesMatch(node, entry);
|
| + if (reduction.Changed()) {
|
| + // Overwrite the colliding entry with the actual entry.
|
| + entries_[i] = entry;
|
| + // Opportunistically clean-up the duplicate entry if we're at the
|
| + // end of a bucket.
|
| + if (!entries_[(j + 1) & mask]) {
|
| + entries_[j] = nullptr;
|
| + size_--;
|
| + }
|
| + }
|
| + return reduction;
|
| }
|
| }
|
| }
|
| @@ -126,28 +147,32 @@ Reduction ValueNumberingReducer::Reduce(Node* node) {
|
| continue;
|
| }
|
| if (Equals(entry, node)) {
|
| - // Make sure the replacement has at least as good type as the original
|
| - // node.
|
| - if (NodeProperties::IsTyped(entry) && NodeProperties::IsTyped(node)) {
|
| - Type* entry_type = NodeProperties::GetType(entry);
|
| - Type* node_type = NodeProperties::GetType(node);
|
| - if (!entry_type->Is(node_type)) {
|
| - // Ideally, we would set an intersection of {entry_type} and
|
| - // {node_type} here. However, typing of NumberConstants assigns
|
| - // different types to constants with the same value (it creates
|
| - // a fresh heap number), which would make the intersection empty.
|
| - // To be safe, we use the smaller type if the types are comparable.
|
| - if (node_type->Is(entry_type)) {
|
| - NodeProperties::SetType(entry, node_type);
|
| - } else {
|
| - // Types are not comparable => do not replace.
|
| - return NoChange();
|
| - }
|
| - }
|
| + return ReplaceIfTypesMatch(node, entry);
|
| + }
|
| + }
|
| +}
|
| +
|
| +Reduction ValueNumberingReducer::ReplaceIfTypesMatch(Node* node,
|
| + Node* replacement) {
|
| + // Make sure the replacement has at least as good type as the original node.
|
| + if (NodeProperties::IsTyped(replacement) && NodeProperties::IsTyped(node)) {
|
| + Type* replacement_type = NodeProperties::GetType(replacement);
|
| + Type* node_type = NodeProperties::GetType(node);
|
| + if (!replacement_type->Is(node_type)) {
|
| + // Ideally, we would set an intersection of {replacement_type} and
|
| + // {node_type} here. However, typing of NumberConstants assigns different
|
| + // types to constants with the same value (it creates a fresh heap
|
| + // number), which would make the intersection empty. To be safe, we use
|
| + // the smaller type if the types are comparable.
|
| + if (node_type->Is(replacement_type)) {
|
| + NodeProperties::SetType(replacement, node_type);
|
| + } else {
|
| + // Types are not comparable => do not replace.
|
| + return NoChange();
|
| }
|
| - return Replace(entry);
|
| }
|
| }
|
| + return Replace(replacement);
|
| }
|
|
|
|
|
|
|