Commit f88eb5f2 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Merge map information for phis when merging effects.

When merging effect phis, we currently do not try to merge information
for any variables that are merged by phis on the same control merge.

This CL implements a very limited version of merging map information
for nodes: If all the map information for all inputs of the phi
is the same, we assign that map information to the phi itself. This
is somewhat consistent with merging map information for a node:
there we also combine the information only if in all incoming
paths we have teh same set of maps.

In theory, we could union the sets of maps. Also, we could consider
merging other information (such as abstract fields).

This yields some small improvement (~2%) on the Octane deltablue
benchmark.

Bug: v8:5267
Change-Id: I9447732e3f0d06eb44632db492782fa35529f9fd
Reviewed-on: https://chromium-review.googlesource.com/622792
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47475}
parent 1bc01952
......@@ -378,6 +378,29 @@ LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill(
return this;
}
LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Merge(
AbstractMaps const* that, Zone* zone) const {
if (this->Equals(that)) return this;
AbstractMaps* copy = new (zone) AbstractMaps(zone);
for (auto this_it : this->info_for_node_) {
Node* this_object = this_it.first;
ZoneHandleSet<Map> this_maps = this_it.second;
auto that_it = that->info_for_node_.find(this_object);
if (that_it != that->info_for_node_.end() && that_it->second == this_maps) {
copy->info_for_node_.insert(this_it);
}
}
return copy;
}
LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Extend(
Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
AbstractMaps* that = new (zone) AbstractMaps(zone);
that->info_for_node_ = this->info_for_node_;
that->info_for_node_.insert(std::make_pair(object, maps));
return that;
}
void LoadElimination::AbstractMaps::Print() const {
for (auto pair : info_for_node_) {
PrintF(" #%d:%s\n", pair.first->id(), pair.first->op()->mnemonic());
......@@ -960,6 +983,27 @@ Reduction LoadElimination::ReduceStoreTypedElement(Node* node) {
return UpdateState(node, state);
}
LoadElimination::AbstractState const* LoadElimination::UpdateStateForPhi(
AbstractState const* state, Node* effect_phi, Node* phi) {
int predecessor_count = phi->InputCount() - 1;
// TODO(jarin) Consider doing a union here. At the moment, we just keep this
// consistent with AbstractState::Merge.
// Check if all the inputs have the same maps.
AbstractState const* input_state =
node_states_.Get(NodeProperties::GetEffectInput(effect_phi, 0));
ZoneHandleSet<Map> object_maps;
if (!input_state->LookupMaps(phi->InputAt(0), &object_maps)) return state;
for (int i = 1; i < predecessor_count; i++) {
input_state =
node_states_.Get(NodeProperties::GetEffectInput(effect_phi, i));
ZoneHandleSet<Map> input_maps;
if (!input_state->LookupMaps(phi->InputAt(i), &input_maps)) return state;
if (input_maps != object_maps) return state;
}
return state->AddMaps(phi, object_maps, zone());
}
Reduction LoadElimination::ReduceEffectPhi(Node* node) {
Node* const effect0 = NodeProperties::GetEffectInput(node, 0);
Node* const control = NodeProperties::GetControlInput(node);
......@@ -988,7 +1032,17 @@ Reduction LoadElimination::ReduceEffectPhi(Node* node) {
Node* const input = NodeProperties::GetEffectInput(node, i);
state->Merge(node_states_.Get(input), zone());
}
return UpdateState(node, state);
// For each phi, try to compute the new state for the phi from
// the inputs.
AbstractState const* state_with_phis = state;
for (Node* use : control->uses()) {
if (use->opcode() == IrOpcode::kPhi) {
state_with_phis = UpdateStateForPhi(state_with_phis, node, use);
}
}
return UpdateState(node, state_with_phis);
}
Reduction LoadElimination::ReduceStart(Node* node) {
......
......@@ -194,31 +194,13 @@ class V8_EXPORT_PRIVATE LoadElimination final
}
AbstractMaps const* Extend(Node* object, ZoneHandleSet<Map> maps,
Zone* zone) const {
AbstractMaps* that = new (zone) AbstractMaps(zone);
that->info_for_node_ = this->info_for_node_;
that->info_for_node_.insert(std::make_pair(object, maps));
return that;
}
Zone* zone) const;
bool Lookup(Node* object, ZoneHandleSet<Map>* object_maps) const;
AbstractMaps const* Kill(Node* object, Zone* zone) const;
bool Equals(AbstractMaps const* that) const {
return this == that || this->info_for_node_ == that->info_for_node_;
}
AbstractMaps const* Merge(AbstractMaps const* that, Zone* zone) const {
if (this->Equals(that)) return this;
AbstractMaps* copy = new (zone) AbstractMaps(zone);
for (auto this_it : this->info_for_node_) {
Node* this_object = this_it.first;
ZoneHandleSet<Map> this_maps = this_it.second;
auto that_it = that->info_for_node_.find(this_object);
if (that_it != that->info_for_node_.end() &&
that_it->second == this_maps) {
copy->info_for_node_.insert(this_it);
}
}
return copy;
}
AbstractMaps const* Merge(AbstractMaps const* that, Zone* zone) const;
void Print() const;
......@@ -302,6 +284,8 @@ class V8_EXPORT_PRIVATE LoadElimination final
AbstractState const* ComputeLoopState(Node* node,
AbstractState const* state) const;
AbstractState const* UpdateStateForPhi(AbstractState const* state,
Node* effect_phi, Node* phi);
static int FieldIndexOf(int offset);
static int FieldIndexOf(FieldAccess const& access);
......
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