blob: a451cfce732d18d7a25aaec7234474cbdb57157d [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/load-elimination.h"
6
Ben Murdochda12d292016-06-02 14:46:10 +01007#include "src/compiler/graph.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/compiler/node-properties.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include "src/compiler/simplified-operator.h"
Ben Murdochda12d292016-06-02 14:46:10 +010010#include "src/types.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16LoadElimination::~LoadElimination() {}
17
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018Reduction LoadElimination::Reduce(Node* node) {
19 switch (node->opcode()) {
20 case IrOpcode::kLoadField:
21 return ReduceLoadField(node);
22 default:
23 break;
24 }
25 return NoChange();
26}
27
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028Reduction LoadElimination::ReduceLoadField(Node* node) {
29 DCHECK_EQ(IrOpcode::kLoadField, node->opcode());
30 FieldAccess const access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031 Node* object = NodeProperties::GetValueInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040032 for (Node* effect = NodeProperties::GetEffectInput(node);;
33 effect = NodeProperties::GetEffectInput(effect)) {
34 switch (effect->opcode()) {
35 case IrOpcode::kLoadField: {
Ben Murdochc5610432016-08-08 18:44:38 +010036 FieldAccess const effect_access = FieldAccessOf(effect->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040037 if (object == NodeProperties::GetValueInput(effect, 0) &&
Ben Murdochc5610432016-08-08 18:44:38 +010038 access == effect_access && effect_access.type->Is(access.type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040039 Node* const value = effect;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 ReplaceWithValue(node, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041 return Replace(value);
42 }
43 break;
44 }
45 case IrOpcode::kStoreField: {
46 if (access == FieldAccessOf(effect->op())) {
47 if (object == NodeProperties::GetValueInput(effect, 0)) {
48 Node* const value = NodeProperties::GetValueInput(effect, 1);
Ben Murdochda12d292016-06-02 14:46:10 +010049 Type* stored_value_type = NodeProperties::GetType(value);
50 Type* load_type = NodeProperties::GetType(node);
51 // Make sure the replacement's type is a subtype of the node's
52 // type. Otherwise we could confuse optimizations that were
53 // based on the original type.
54 if (stored_value_type->Is(load_type)) {
55 ReplaceWithValue(node, value);
56 return Replace(value);
57 } else {
58 Node* renamed = graph()->NewNode(
Ben Murdochc5610432016-08-08 18:44:38 +010059 simplified()->TypeGuard(Type::Intersect(
60 stored_value_type, load_type, graph()->zone())),
Ben Murdochda12d292016-06-02 14:46:10 +010061 value, NodeProperties::GetControlInput(node));
62 ReplaceWithValue(node, renamed);
63 return Replace(renamed);
64 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065 }
66 // TODO(turbofan): Alias analysis to the rescue?
67 return NoChange();
68 }
69 break;
70 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 case IrOpcode::kBeginRegion:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 case IrOpcode::kStoreBuffer:
73 case IrOpcode::kStoreElement: {
74 // These can never interfere with field loads.
75 break;
76 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 case IrOpcode::kFinishRegion: {
78 // "Look through" FinishRegion nodes to make LoadElimination capable
79 // of looking into atomic regions.
80 if (object == effect) object = NodeProperties::GetValueInput(effect, 0);
81 break;
82 }
83 case IrOpcode::kAllocate: {
84 // Allocations don't interfere with field loads. In case we see the
85 // actual allocation for the {object} we can abort.
86 if (object == effect) return NoChange();
87 break;
88 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040089 default: {
90 if (!effect->op()->HasProperty(Operator::kNoWrite) ||
91 effect->op()->EffectInputCount() != 1) {
92 return NoChange();
93 }
94 break;
95 }
96 }
97 }
98 UNREACHABLE();
99 return NoChange();
100}
101
102} // namespace compiler
103} // namespace internal
104} // namespace v8