ad48379f4c11f3d874b7158165305a12aa2db946
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / simplified-operator-reducer.cc
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/simplified-operator-reducer.h"
6
7 #include "src/compiler/access-builder.h"
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/machine-operator.h"
10 #include "src/compiler/node-matchers.h"
11 #include "src/compiler/node-properties.h"
12 #include "src/compiler/operator-properties.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17
18 SimplifiedOperatorReducer::SimplifiedOperatorReducer(JSGraph* jsgraph)
19     : jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
20
21
22 SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
23
24
25 Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
26   switch (node->opcode()) {
27     case IrOpcode::kAnyToBoolean:
28       return ReduceAnyToBoolean(node);
29     case IrOpcode::kBooleanNot: {
30       HeapObjectMatcher<HeapObject> m(node->InputAt(0));
31       if (m.Is(Unique<HeapObject>::CreateImmovable(factory()->false_value()))) {
32         return Replace(jsgraph()->TrueConstant());
33       }
34       if (m.Is(Unique<HeapObject>::CreateImmovable(factory()->true_value()))) {
35         return Replace(jsgraph()->FalseConstant());
36       }
37       if (m.IsBooleanNot()) return Replace(m.node()->InputAt(0));
38       break;
39     }
40     case IrOpcode::kChangeBitToBool: {
41       Int32Matcher m(node->InputAt(0));
42       if (m.Is(0)) return Replace(jsgraph()->FalseConstant());
43       if (m.Is(1)) return Replace(jsgraph()->TrueConstant());
44       if (m.IsChangeBoolToBit()) return Replace(m.node()->InputAt(0));
45       break;
46     }
47     case IrOpcode::kChangeBoolToBit: {
48       HeapObjectMatcher<HeapObject> m(node->InputAt(0));
49       if (m.Is(Unique<HeapObject>::CreateImmovable(factory()->false_value()))) {
50         return ReplaceInt32(0);
51       }
52       if (m.Is(Unique<HeapObject>::CreateImmovable(factory()->true_value()))) {
53         return ReplaceInt32(1);
54       }
55       if (m.IsChangeBitToBool()) return Replace(m.node()->InputAt(0));
56       break;
57     }
58     case IrOpcode::kChangeFloat64ToTagged: {
59       Float64Matcher m(node->InputAt(0));
60       if (m.HasValue()) return ReplaceNumber(m.Value());
61       break;
62     }
63     case IrOpcode::kChangeInt32ToTagged: {
64       Int32Matcher m(node->InputAt(0));
65       if (m.HasValue()) return ReplaceNumber(m.Value());
66       break;
67     }
68     case IrOpcode::kChangeTaggedToFloat64: {
69       NumberMatcher m(node->InputAt(0));
70       if (m.HasValue()) return ReplaceFloat64(m.Value());
71       if (m.IsChangeFloat64ToTagged()) return Replace(m.node()->InputAt(0));
72       if (m.IsChangeInt32ToTagged()) {
73         return Change(node, machine()->ChangeInt32ToFloat64(),
74                       m.node()->InputAt(0));
75       }
76       if (m.IsChangeUint32ToTagged()) {
77         return Change(node, machine()->ChangeUint32ToFloat64(),
78                       m.node()->InputAt(0));
79       }
80       break;
81     }
82     case IrOpcode::kChangeTaggedToInt32: {
83       NumberMatcher m(node->InputAt(0));
84       if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
85       if (m.IsChangeFloat64ToTagged()) {
86         return Change(node, machine()->ChangeFloat64ToInt32(),
87                       m.node()->InputAt(0));
88       }
89       if (m.IsChangeInt32ToTagged()) return Replace(m.node()->InputAt(0));
90       break;
91     }
92     case IrOpcode::kChangeTaggedToUint32: {
93       NumberMatcher m(node->InputAt(0));
94       if (m.HasValue()) return ReplaceUint32(DoubleToUint32(m.Value()));
95       if (m.IsChangeFloat64ToTagged()) {
96         return Change(node, machine()->ChangeFloat64ToUint32(),
97                       m.node()->InputAt(0));
98       }
99       if (m.IsChangeUint32ToTagged()) return Replace(m.node()->InputAt(0));
100       break;
101     }
102     case IrOpcode::kChangeUint32ToTagged: {
103       Uint32Matcher m(node->InputAt(0));
104       if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
105       break;
106     }
107     default:
108       break;
109   }
110   return NoChange();
111 }
112
113
114 Reduction SimplifiedOperatorReducer::ReduceAnyToBoolean(Node* node) {
115   Node* const input = NodeProperties::GetValueInput(node, 0);
116   Type* const input_type = NodeProperties::GetBounds(input).upper;
117   if (input_type->Is(Type::Boolean())) {
118     // AnyToBoolean(x:boolean) => x
119     return Replace(input);
120   }
121   if (input_type->Is(Type::OrderedNumber())) {
122     // AnyToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x, #0))
123     Node* compare = graph()->NewNode(simplified()->NumberEqual(), input,
124                                      jsgraph()->ZeroConstant());
125     return Change(node, simplified()->BooleanNot(), compare);
126   }
127   if (input_type->Is(Type::String())) {
128     // AnyToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0))
129     FieldAccess const access = AccessBuilder::ForStringLength();
130     Node* length = graph()->NewNode(simplified()->LoadField(access), input,
131                                     graph()->start(), graph()->start());
132     Node* compare = graph()->NewNode(simplified()->NumberEqual(), length,
133                                      jsgraph()->ZeroConstant());
134     return Change(node, simplified()->BooleanNot(), compare);
135   }
136   return NoChange();
137 }
138
139
140 Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
141                                             Node* a) {
142   DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op));
143   DCHECK_LE(1, node->InputCount());
144   node->set_op(op);
145   node->ReplaceInput(0, a);
146   return Changed(node);
147 }
148
149
150 Reduction SimplifiedOperatorReducer::ReplaceFloat64(double value) {
151   return Replace(jsgraph()->Float64Constant(value));
152 }
153
154
155 Reduction SimplifiedOperatorReducer::ReplaceInt32(int32_t value) {
156   return Replace(jsgraph()->Int32Constant(value));
157 }
158
159
160 Reduction SimplifiedOperatorReducer::ReplaceNumber(double value) {
161   return Replace(jsgraph()->Constant(value));
162 }
163
164
165 Reduction SimplifiedOperatorReducer::ReplaceNumber(int32_t value) {
166   return Replace(jsgraph()->Constant(value));
167 }
168
169
170 Graph* SimplifiedOperatorReducer::graph() const { return jsgraph()->graph(); }
171
172
173 Factory* SimplifiedOperatorReducer::factory() const {
174   return jsgraph()->isolate()->factory();
175 }
176
177
178 CommonOperatorBuilder* SimplifiedOperatorReducer::common() const {
179   return jsgraph()->common();
180 }
181
182
183 MachineOperatorBuilder* SimplifiedOperatorReducer::machine() const {
184   return jsgraph()->machine();
185 }
186
187 }  // namespace compiler
188 }  // namespace internal
189 }  // namespace v8