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 |