| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/load-elimination.h" | 5 #include "src/compiler/load-elimination.h" |
| 6 | 6 |
| 7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/simplified-operator.h" | 10 #include "src/compiler/simplified-operator.h" |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 } | 188 } |
| 189 | 189 |
| 190 void LoadElimination::AbstractChecks::Print() const { | 190 void LoadElimination::AbstractChecks::Print() const { |
| 191 for (Node* const node : nodes_) { | 191 for (Node* const node : nodes_) { |
| 192 if (node != nullptr) { | 192 if (node != nullptr) { |
| 193 PrintF(" #%d:%s\n", node->id(), node->op()->mnemonic()); | 193 PrintF(" #%d:%s\n", node->id(), node->op()->mnemonic()); |
| 194 } | 194 } |
| 195 } | 195 } |
| 196 } | 196 } |
| 197 | 197 |
| 198 Node* LoadElimination::AbstractElements::Lookup(Node* object, | 198 namespace { |
| 199 Node* index) const { | 199 |
| 200 bool IsCompatible(MachineRepresentation r1, MachineRepresentation r2) { |
| 201 if (r1 == r2) return true; |
| 202 return IsAnyTagged(r1) && IsAnyTagged(r2); |
| 203 } |
| 204 |
| 205 } // namespace |
| 206 |
| 207 Node* LoadElimination::AbstractElements::Lookup( |
| 208 Node* object, Node* index, MachineRepresentation representation) const { |
| 200 for (Element const element : elements_) { | 209 for (Element const element : elements_) { |
| 201 if (element.object == nullptr) continue; | 210 if (element.object == nullptr) continue; |
| 202 DCHECK_NOT_NULL(element.index); | 211 DCHECK_NOT_NULL(element.index); |
| 203 DCHECK_NOT_NULL(element.value); | 212 DCHECK_NOT_NULL(element.value); |
| 204 if (MustAlias(object, element.object) && MustAlias(index, element.index)) { | 213 if (MustAlias(object, element.object) && MustAlias(index, element.index) && |
| 214 IsCompatible(representation, element.representation)) { |
| 205 return element.value; | 215 return element.value; |
| 206 } | 216 } |
| 207 } | 217 } |
| 208 return nullptr; | 218 return nullptr; |
| 209 } | 219 } |
| 210 | 220 |
| 211 LoadElimination::AbstractElements const* | 221 LoadElimination::AbstractElements const* |
| 212 LoadElimination::AbstractElements::Kill(Node* object, Node* index, | 222 LoadElimination::AbstractElements::Kill(Node* object, Node* index, |
| 213 Zone* zone) const { | 223 Zone* zone) const { |
| 214 for (Element const element : this->elements_) { | 224 for (Element const element : this->elements_) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 AbstractMaps const* that_maps = this->maps_->Kill(object, zone); | 473 AbstractMaps const* that_maps = this->maps_->Kill(object, zone); |
| 464 if (this->maps_ != that_maps) { | 474 if (this->maps_ != that_maps) { |
| 465 AbstractState* that = new (zone) AbstractState(*this); | 475 AbstractState* that = new (zone) AbstractState(*this); |
| 466 that->maps_ = that_maps; | 476 that->maps_ = that_maps; |
| 467 return that; | 477 return that; |
| 468 } | 478 } |
| 469 } | 479 } |
| 470 return this; | 480 return this; |
| 471 } | 481 } |
| 472 | 482 |
| 473 Node* LoadElimination::AbstractState::LookupElement(Node* object, | 483 Node* LoadElimination::AbstractState::LookupElement( |
| 474 Node* index) const { | 484 Node* object, Node* index, MachineRepresentation representation) const { |
| 475 if (this->elements_) { | 485 if (this->elements_) { |
| 476 return this->elements_->Lookup(object, index); | 486 return this->elements_->Lookup(object, index, representation); |
| 477 } | 487 } |
| 478 return nullptr; | 488 return nullptr; |
| 479 } | 489 } |
| 480 | 490 |
| 481 LoadElimination::AbstractState const* | 491 LoadElimination::AbstractState const* |
| 482 LoadElimination::AbstractState::AddElement(Node* object, Node* index, | 492 LoadElimination::AbstractState::AddElement(Node* object, Node* index, |
| 483 Node* value, Zone* zone) const { | 493 Node* value, |
| 494 MachineRepresentation representation, |
| 495 Zone* zone) const { |
| 484 AbstractState* that = new (zone) AbstractState(*this); | 496 AbstractState* that = new (zone) AbstractState(*this); |
| 485 if (that->elements_) { | 497 if (that->elements_) { |
| 486 that->elements_ = that->elements_->Extend(object, index, value, zone); | 498 that->elements_ = |
| 499 that->elements_->Extend(object, index, value, representation, zone); |
| 487 } else { | 500 } else { |
| 488 that->elements_ = new (zone) AbstractElements(object, index, value, zone); | 501 that->elements_ = |
| 502 new (zone) AbstractElements(object, index, value, representation, zone); |
| 489 } | 503 } |
| 490 return that; | 504 return that; |
| 491 } | 505 } |
| 492 | 506 |
| 493 LoadElimination::AbstractState const* | 507 LoadElimination::AbstractState const* |
| 494 LoadElimination::AbstractState::KillElement(Node* object, Node* index, | 508 LoadElimination::AbstractState::KillElement(Node* object, Node* index, |
| 495 Zone* zone) const { | 509 Zone* zone) const { |
| 496 if (this->elements_) { | 510 if (this->elements_) { |
| 497 AbstractElements const* that_elements = | 511 AbstractElements const* that_elements = |
| 498 this->elements_->Kill(object, index, zone); | 512 this->elements_->Kill(object, index, zone); |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 case MachineRepresentation::kWord32: | 830 case MachineRepresentation::kWord32: |
| 817 case MachineRepresentation::kWord64: | 831 case MachineRepresentation::kWord64: |
| 818 case MachineRepresentation::kFloat32: | 832 case MachineRepresentation::kFloat32: |
| 819 // TODO(turbofan): Add support for doing the truncations. | 833 // TODO(turbofan): Add support for doing the truncations. |
| 820 break; | 834 break; |
| 821 case MachineRepresentation::kFloat64: | 835 case MachineRepresentation::kFloat64: |
| 822 case MachineRepresentation::kSimd128: | 836 case MachineRepresentation::kSimd128: |
| 823 case MachineRepresentation::kTaggedSigned: | 837 case MachineRepresentation::kTaggedSigned: |
| 824 case MachineRepresentation::kTaggedPointer: | 838 case MachineRepresentation::kTaggedPointer: |
| 825 case MachineRepresentation::kTagged: | 839 case MachineRepresentation::kTagged: |
| 826 if (Node* replacement = state->LookupElement(object, index)) { | 840 if (Node* replacement = state->LookupElement( |
| 841 object, index, access.machine_type.representation())) { |
| 827 // Make sure we don't resurrect dead {replacement} nodes. | 842 // Make sure we don't resurrect dead {replacement} nodes. |
| 828 if (!replacement->IsDead()) { | 843 if (!replacement->IsDead()) { |
| 829 // We might need to guard the {replacement} if the type of the | 844 // We might need to guard the {replacement} if the type of the |
| 830 // {node} is more precise than the type of the {replacement}. | 845 // {node} is more precise than the type of the {replacement}. |
| 831 Type* const node_type = NodeProperties::GetType(node); | 846 Type* const node_type = NodeProperties::GetType(node); |
| 832 if (!NodeProperties::GetType(replacement)->Is(node_type)) { | 847 if (!NodeProperties::GetType(replacement)->Is(node_type)) { |
| 833 replacement = graph()->NewNode(common()->TypeGuard(node_type), | 848 replacement = graph()->NewNode(common()->TypeGuard(node_type), |
| 834 replacement, control); | 849 replacement, control); |
| 835 NodeProperties::SetType(replacement, node_type); | 850 NodeProperties::SetType(replacement, node_type); |
| 836 } | 851 } |
| 837 ReplaceWithValue(node, replacement, effect); | 852 ReplaceWithValue(node, replacement, effect); |
| 838 return Replace(replacement); | 853 return Replace(replacement); |
| 839 } | 854 } |
| 840 } | 855 } |
| 841 state = state->AddElement(object, index, node, zone()); | 856 state = state->AddElement(object, index, node, |
| 857 access.machine_type.representation(), zone()); |
| 842 return UpdateState(node, state); | 858 return UpdateState(node, state); |
| 843 } | 859 } |
| 844 return NoChange(); | 860 return NoChange(); |
| 845 } | 861 } |
| 846 | 862 |
| 847 Reduction LoadElimination::ReduceStoreElement(Node* node) { | 863 Reduction LoadElimination::ReduceStoreElement(Node* node) { |
| 848 ElementAccess const& access = ElementAccessOf(node->op()); | 864 ElementAccess const& access = ElementAccessOf(node->op()); |
| 849 Node* const object = NodeProperties::GetValueInput(node, 0); | 865 Node* const object = NodeProperties::GetValueInput(node, 0); |
| 850 Node* const index = NodeProperties::GetValueInput(node, 1); | 866 Node* const index = NodeProperties::GetValueInput(node, 1); |
| 851 Node* const new_value = NodeProperties::GetValueInput(node, 2); | 867 Node* const new_value = NodeProperties::GetValueInput(node, 2); |
| 852 Node* const effect = NodeProperties::GetEffectInput(node); | 868 Node* const effect = NodeProperties::GetEffectInput(node); |
| 853 AbstractState const* state = node_states_.Get(effect); | 869 AbstractState const* state = node_states_.Get(effect); |
| 854 if (state == nullptr) return NoChange(); | 870 if (state == nullptr) return NoChange(); |
| 855 Node* const old_value = state->LookupElement(object, index); | 871 Node* const old_value = |
| 872 state->LookupElement(object, index, access.machine_type.representation()); |
| 856 if (old_value == new_value) { | 873 if (old_value == new_value) { |
| 857 // This store is fully redundant. | 874 // This store is fully redundant. |
| 858 return Replace(effect); | 875 return Replace(effect); |
| 859 } | 876 } |
| 860 // Kill all potentially aliasing elements. | 877 // Kill all potentially aliasing elements. |
| 861 state = state->KillElement(object, index, zone()); | 878 state = state->KillElement(object, index, zone()); |
| 862 // Only record the new value if the store doesn't have an implicit truncation. | 879 // Only record the new value if the store doesn't have an implicit truncation. |
| 863 switch (access.machine_type.representation()) { | 880 switch (access.machine_type.representation()) { |
| 864 case MachineRepresentation::kNone: | 881 case MachineRepresentation::kNone: |
| 865 case MachineRepresentation::kSimd1x4: | 882 case MachineRepresentation::kSimd1x4: |
| 866 case MachineRepresentation::kSimd1x8: | 883 case MachineRepresentation::kSimd1x8: |
| 867 case MachineRepresentation::kSimd1x16: | 884 case MachineRepresentation::kSimd1x16: |
| 868 case MachineRepresentation::kBit: | 885 case MachineRepresentation::kBit: |
| 869 UNREACHABLE(); | 886 UNREACHABLE(); |
| 870 break; | 887 break; |
| 871 case MachineRepresentation::kWord8: | 888 case MachineRepresentation::kWord8: |
| 872 case MachineRepresentation::kWord16: | 889 case MachineRepresentation::kWord16: |
| 873 case MachineRepresentation::kWord32: | 890 case MachineRepresentation::kWord32: |
| 874 case MachineRepresentation::kWord64: | 891 case MachineRepresentation::kWord64: |
| 875 case MachineRepresentation::kFloat32: | 892 case MachineRepresentation::kFloat32: |
| 876 // TODO(turbofan): Add support for doing the truncations. | 893 // TODO(turbofan): Add support for doing the truncations. |
| 877 break; | 894 break; |
| 878 case MachineRepresentation::kFloat64: | 895 case MachineRepresentation::kFloat64: |
| 879 case MachineRepresentation::kSimd128: | 896 case MachineRepresentation::kSimd128: |
| 880 case MachineRepresentation::kTaggedSigned: | 897 case MachineRepresentation::kTaggedSigned: |
| 881 case MachineRepresentation::kTaggedPointer: | 898 case MachineRepresentation::kTaggedPointer: |
| 882 case MachineRepresentation::kTagged: | 899 case MachineRepresentation::kTagged: |
| 883 state = state->AddElement(object, index, new_value, zone()); | 900 state = state->AddElement(object, index, new_value, |
| 901 access.machine_type.representation(), zone()); |
| 884 break; | 902 break; |
| 885 } | 903 } |
| 886 return UpdateState(node, state); | 904 return UpdateState(node, state); |
| 887 } | 905 } |
| 888 | 906 |
| 889 Reduction LoadElimination::ReduceStoreTypedElement(Node* node) { | 907 Reduction LoadElimination::ReduceStoreTypedElement(Node* node) { |
| 890 Node* const effect = NodeProperties::GetEffectInput(node); | 908 Node* const effect = NodeProperties::GetEffectInput(node); |
| 891 AbstractState const* state = node_states_.Get(effect); | 909 AbstractState const* state = node_states_.Get(effect); |
| 892 if (state == nullptr) return NoChange(); | 910 if (state == nullptr) return NoChange(); |
| 893 return UpdateState(node, state); | 911 return UpdateState(node, state); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 return jsgraph()->common(); | 1129 return jsgraph()->common(); |
| 1112 } | 1130 } |
| 1113 | 1131 |
| 1114 Graph* LoadElimination::graph() const { return jsgraph()->graph(); } | 1132 Graph* LoadElimination::graph() const { return jsgraph()->graph(); } |
| 1115 | 1133 |
| 1116 Factory* LoadElimination::factory() const { return jsgraph()->factory(); } | 1134 Factory* LoadElimination::factory() const { return jsgraph()->factory(); } |
| 1117 | 1135 |
| 1118 } // namespace compiler | 1136 } // namespace compiler |
| 1119 } // namespace internal | 1137 } // namespace internal |
| 1120 } // namespace v8 | 1138 } // namespace v8 |
| OLD | NEW |