blob: e19368d107623f6975c687b8c455b52d13c2d1a9 [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/common-operator.h"
8#include "src/compiler/graph.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/compiler/node-properties.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010#include "src/compiler/simplified-operator.h"
Ben Murdochda12d292016-06-02 14:46:10 +010011#include "src/types.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012
13namespace v8 {
14namespace internal {
15namespace compiler {
16
17LoadElimination::~LoadElimination() {}
18
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019Reduction LoadElimination::Reduce(Node* node) {
20 switch (node->opcode()) {
21 case IrOpcode::kLoadField:
22 return ReduceLoadField(node);
23 default:
24 break;
25 }
26 return NoChange();
27}
28
Emily Bernierd0a1eb72015-03-24 16:35:39 -040029Reduction LoadElimination::ReduceLoadField(Node* node) {
30 DCHECK_EQ(IrOpcode::kLoadField, node->opcode());
31 FieldAccess const access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 Node* object = NodeProperties::GetValueInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040033 for (Node* effect = NodeProperties::GetEffectInput(node);;
34 effect = NodeProperties::GetEffectInput(effect)) {
35 switch (effect->opcode()) {
36 case IrOpcode::kLoadField: {
37 if (object == NodeProperties::GetValueInput(effect, 0) &&
38 access == FieldAccessOf(effect->op())) {
39 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(
59 common()->Guard(Type::Intersect(stored_value_type, load_type,
60 graph()->zone())),
61 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