Commit b7761100 authored by leszeks's avatar leszeks Committed by Commit bot

[turbofan] Do not replace actual duplicates when value numbering

The value numbering reducer has collision checks for nodes that mutated,
but kept the same hash, and are now equivalent to another node. However,
it can also accidentally hit itself, if it mutated, changed hash, but
ran over the location it was previously in.

After this patch, it checks to see if it is comparing against itself,
and skips over itself. Additionally, if this check is at the end of the
collisions, it opportunistically removes the duplicate entry and reduces
the size pressure on the list. We can do the same opportunistic clean up
if we happen to find a colliding equivalent entry, since we move it from
its original position to a new one.

Drive-by change: Ensure that the collision replacement checks types in
the same way that normal replacement does.

Review-Url: https://codereview.chromium.org/2475653002
Cr-Commit-Position: refs/heads/master@{#40757}
parent 9311bc11
...@@ -112,10 +112,31 @@ Reduction ValueNumberingReducer::Reduce(Node* node) { ...@@ -112,10 +112,31 @@ Reduction ValueNumberingReducer::Reduce(Node* node) {
if (entry->IsDead()) { if (entry->IsDead()) {
continue; 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)) { if (Equals(entry, node)) {
// Overwrite the colliding entry with the actual entry. Reduction reduction = ReplaceIfTypesMatch(node, entry);
entries_[i] = entry; if (reduction.Changed()) {
return Replace(entry); // 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) { ...@@ -126,28 +147,32 @@ Reduction ValueNumberingReducer::Reduce(Node* node) {
continue; continue;
} }
if (Equals(entry, node)) { if (Equals(entry, node)) {
// Make sure the replacement has at least as good type as the original return ReplaceIfTypesMatch(node, entry);
// 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)) { Reduction ValueNumberingReducer::ReplaceIfTypesMatch(Node* node,
// Ideally, we would set an intersection of {entry_type} and Node* replacement) {
// {node_type} here. However, typing of NumberConstants assigns // Make sure the replacement has at least as good type as the original node.
// different types to constants with the same value (it creates if (NodeProperties::IsTyped(replacement) && NodeProperties::IsTyped(node)) {
// a fresh heap number), which would make the intersection empty. Type* replacement_type = NodeProperties::GetType(replacement);
// To be safe, we use the smaller type if the types are comparable. Type* node_type = NodeProperties::GetType(node);
if (node_type->Is(entry_type)) { if (!replacement_type->Is(node_type)) {
NodeProperties::SetType(entry, node_type); // Ideally, we would set an intersection of {replacement_type} and
} else { // {node_type} here. However, typing of NumberConstants assigns different
// Types are not comparable => do not replace. // types to constants with the same value (it creates a fresh heap
return NoChange(); // 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);
} }
......
...@@ -24,6 +24,7 @@ class V8_EXPORT_PRIVATE ValueNumberingReducer final ...@@ -24,6 +24,7 @@ class V8_EXPORT_PRIVATE ValueNumberingReducer final
private: private:
enum { kInitialCapacity = 256u }; enum { kInitialCapacity = 256u };
Reduction ReplaceIfTypesMatch(Node* node, Node* replacement);
void Grow(); void Grow();
Zone* temp_zone() const { return temp_zone_; } Zone* temp_zone() const { return temp_zone_; }
Zone* graph_zone() const { return graph_zone_; } Zone* graph_zone() const { return graph_zone_; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment