1 // 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 
7 #include "src/compiler/node-properties.h"
8 #include "src/compiler/simplified-operator.h"
9 
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13 
~LoadElimination()14 LoadElimination::~LoadElimination() {}
15 
16 
Reduce(Node * node)17 Reduction LoadElimination::Reduce(Node* node) {
18   switch (node->opcode()) {
19     case IrOpcode::kLoadField:
20       return ReduceLoadField(node);
21     default:
22       break;
23   }
24   return NoChange();
25 }
26 
27 
ReduceLoadField(Node * node)28 Reduction LoadElimination::ReduceLoadField(Node* node) {
29   DCHECK_EQ(IrOpcode::kLoadField, node->opcode());
30   FieldAccess const access = FieldAccessOf(node->op());
31   Node* object = NodeProperties::GetValueInput(node, 0);
32   for (Node* effect = NodeProperties::GetEffectInput(node);;
33        effect = NodeProperties::GetEffectInput(effect)) {
34     switch (effect->opcode()) {
35       case IrOpcode::kLoadField: {
36         if (object == NodeProperties::GetValueInput(effect, 0) &&
37             access == FieldAccessOf(effect->op())) {
38           Node* const value = effect;
39           ReplaceWithValue(node, value);
40           return Replace(value);
41         }
42         break;
43       }
44       case IrOpcode::kStoreField: {
45         if (access == FieldAccessOf(effect->op())) {
46           if (object == NodeProperties::GetValueInput(effect, 0)) {
47             Node* const value = NodeProperties::GetValueInput(effect, 1);
48             ReplaceWithValue(node, value);
49             return Replace(value);
50           }
51           // TODO(turbofan): Alias analysis to the rescue?
52           return NoChange();
53         }
54         break;
55       }
56       case IrOpcode::kBeginRegion:
57       case IrOpcode::kStoreBuffer:
58       case IrOpcode::kStoreElement: {
59         // These can never interfere with field loads.
60         break;
61       }
62       case IrOpcode::kFinishRegion: {
63         // "Look through" FinishRegion nodes to make LoadElimination capable
64         // of looking into atomic regions.
65         if (object == effect) object = NodeProperties::GetValueInput(effect, 0);
66         break;
67       }
68       case IrOpcode::kAllocate: {
69         // Allocations don't interfere with field loads. In case we see the
70         // actual allocation for the {object} we can abort.
71         if (object == effect) return NoChange();
72         break;
73       }
74       default: {
75         if (!effect->op()->HasProperty(Operator::kNoWrite) ||
76             effect->op()->EffectInputCount() != 1) {
77           return NoChange();
78         }
79         break;
80       }
81     }
82   }
83   UNREACHABLE();
84   return NoChange();
85 }
86 
87 }  // namespace compiler
88 }  // namespace internal
89 }  // namespace v8
90