blob: 5db9dfbf5660db5a9be31f146bb1d4965eaf0619 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/compiler/simplified-operator-reducer.h"
6
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/compiler/js-graph.h"
8#include "src/compiler/machine-operator.h"
9#include "src/compiler/node-matchers.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/compiler/operator-properties.h"
Ben Murdochc5610432016-08-08 18:44:38 +010011#include "src/compiler/simplified-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/conversions-inl.h"
Ben Murdochda12d292016-06-02 14:46:10 +010013#include "src/type-cache.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014
15namespace v8 {
16namespace internal {
17namespace compiler {
18
Ben Murdoch61f157c2016-09-16 13:49:30 +010019namespace {
20
21Decision DecideObjectIsSmi(Node* const input) {
22 NumberMatcher m(input);
23 if (m.HasValue()) {
24 return IsSmiDouble(m.Value()) ? Decision::kTrue : Decision::kFalse;
25 }
26 if (m.IsAllocate()) return Decision::kFalse;
27 if (m.IsChangeBitToTagged()) return Decision::kFalse;
28 if (m.IsChangeInt31ToTaggedSigned()) return Decision::kTrue;
29 if (m.IsHeapConstant()) return Decision::kFalse;
30 return Decision::kUnknown;
31}
32
33} // namespace
34
35SimplifiedOperatorReducer::SimplifiedOperatorReducer(Editor* editor,
36 JSGraph* jsgraph)
37 : AdvancedReducer(editor),
38 jsgraph_(jsgraph),
39 type_cache_(TypeCache::Get()) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040040
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
42
43
44Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
45 switch (node->opcode()) {
46 case IrOpcode::kBooleanNot: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 HeapObjectMatcher m(node->InputAt(0));
48 if (m.HasValue()) {
49 return Replace(jsgraph()->BooleanConstant(!m.Value()->BooleanValue()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 if (m.IsBooleanNot()) return Replace(m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000052 break;
53 }
Ben Murdochc5610432016-08-08 18:44:38 +010054 case IrOpcode::kChangeBitToTagged: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 Int32Matcher m(node->InputAt(0));
56 if (m.Is(0)) return Replace(jsgraph()->FalseConstant());
57 if (m.Is(1)) return Replace(jsgraph()->TrueConstant());
Ben Murdochc5610432016-08-08 18:44:38 +010058 if (m.IsChangeTaggedToBit()) return Replace(m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059 break;
60 }
Ben Murdochc5610432016-08-08 18:44:38 +010061 case IrOpcode::kChangeTaggedToBit: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 HeapObjectMatcher m(node->InputAt(0));
63 if (m.HasValue()) return ReplaceInt32(m.Value()->BooleanValue());
Ben Murdochc5610432016-08-08 18:44:38 +010064 if (m.IsChangeBitToTagged()) return Replace(m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 break;
66 }
67 case IrOpcode::kChangeFloat64ToTagged: {
68 Float64Matcher m(node->InputAt(0));
69 if (m.HasValue()) return ReplaceNumber(m.Value());
Ben Murdochc5610432016-08-08 18:44:38 +010070 if (m.IsChangeTaggedToFloat64()) return Replace(m.node()->InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 break;
72 }
Ben Murdochc5610432016-08-08 18:44:38 +010073 case IrOpcode::kChangeInt31ToTaggedSigned:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074 case IrOpcode::kChangeInt32ToTagged: {
75 Int32Matcher m(node->InputAt(0));
76 if (m.HasValue()) return ReplaceNumber(m.Value());
Ben Murdochc5610432016-08-08 18:44:38 +010077 if (m.IsChangeTaggedToInt32() || m.IsChangeTaggedSignedToInt32()) {
78 return Replace(m.InputAt(0));
79 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 break;
81 }
Ben Murdoch61f157c2016-09-16 13:49:30 +010082 case IrOpcode::kChangeTaggedToFloat64:
83 case IrOpcode::kTruncateTaggedToFloat64: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 NumberMatcher m(node->InputAt(0));
85 if (m.HasValue()) return ReplaceFloat64(m.Value());
86 if (m.IsChangeFloat64ToTagged()) return Replace(m.node()->InputAt(0));
Ben Murdochc5610432016-08-08 18:44:38 +010087 if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 return Change(node, machine()->ChangeInt32ToFloat64(), m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089 }
90 if (m.IsChangeUint32ToTagged()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091 return Change(node, machine()->ChangeUint32ToFloat64(), m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092 }
93 break;
94 }
95 case IrOpcode::kChangeTaggedToInt32: {
96 NumberMatcher m(node->InputAt(0));
97 if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
98 if (m.IsChangeFloat64ToTagged()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 return Change(node, machine()->ChangeFloat64ToInt32(), m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 }
Ben Murdochc5610432016-08-08 18:44:38 +0100101 if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
102 return Replace(m.InputAt(0));
103 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 break;
105 }
106 case IrOpcode::kChangeTaggedToUint32: {
107 NumberMatcher m(node->InputAt(0));
108 if (m.HasValue()) return ReplaceUint32(DoubleToUint32(m.Value()));
109 if (m.IsChangeFloat64ToTagged()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 return Change(node, machine()->ChangeFloat64ToUint32(), m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 if (m.IsChangeUint32ToTagged()) return Replace(m.InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113 break;
114 }
115 case IrOpcode::kChangeUint32ToTagged: {
116 Uint32Matcher m(node->InputAt(0));
117 if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
118 break;
119 }
Ben Murdochc5610432016-08-08 18:44:38 +0100120 case IrOpcode::kTruncateTaggedToWord32: {
121 NumberMatcher m(node->InputAt(0));
122 if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
123 if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged() ||
124 m.IsChangeUint32ToTagged()) {
125 return Replace(m.InputAt(0));
126 }
127 if (m.IsChangeFloat64ToTagged()) {
128 return Change(node, machine()->TruncateFloat64ToWord32(), m.InputAt(0));
129 }
130 break;
131 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100132 case IrOpcode::kCheckTaggedPointer: {
133 Node* const input = node->InputAt(0);
134 if (DecideObjectIsSmi(input) == Decision::kFalse) {
135 ReplaceWithValue(node, input);
136 return Replace(input);
137 }
138 break;
139 }
140 case IrOpcode::kCheckTaggedSigned: {
141 Node* const input = node->InputAt(0);
142 if (DecideObjectIsSmi(input) == Decision::kTrue) {
143 ReplaceWithValue(node, input);
144 return Replace(input);
145 }
146 break;
147 }
148 case IrOpcode::kObjectIsSmi: {
149 Node* const input = node->InputAt(0);
150 switch (DecideObjectIsSmi(input)) {
151 case Decision::kTrue:
152 return ReplaceBoolean(true);
153 case Decision::kFalse:
154 return ReplaceBoolean(false);
155 case Decision::kUnknown:
156 break;
157 }
158 break;
159 }
160 case IrOpcode::kNumberAbs: {
161 NumberMatcher m(node->InputAt(0));
162 if (m.HasValue()) return ReplaceNumber(std::fabs(m.Value()));
163 break;
164 }
Ben Murdochda12d292016-06-02 14:46:10 +0100165 case IrOpcode::kNumberCeil:
166 case IrOpcode::kNumberFloor:
167 case IrOpcode::kNumberRound:
168 case IrOpcode::kNumberTrunc: {
169 Node* const input = NodeProperties::GetValueInput(node, 0);
170 Type* const input_type = NodeProperties::GetType(input);
171 if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
172 return Replace(input);
173 }
174 break;
175 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 case IrOpcode::kReferenceEqual:
177 return ReduceReferenceEqual(node);
Ben Murdochc5610432016-08-08 18:44:38 +0100178 case IrOpcode::kTypeGuard:
179 return ReduceTypeGuard(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 default:
181 break;
182 }
183 return NoChange();
184}
185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186Reduction SimplifiedOperatorReducer::ReduceReferenceEqual(Node* node) {
187 DCHECK_EQ(IrOpcode::kReferenceEqual, node->opcode());
188 Node* const left = NodeProperties::GetValueInput(node, 0);
189 Node* const right = NodeProperties::GetValueInput(node, 1);
190 HeapObjectMatcher match_left(left);
191 HeapObjectMatcher match_right(right);
192 if (match_left.HasValue() && match_right.HasValue()) {
193 if (match_left.Value().is_identical_to(match_right.Value())) {
194 return Replace(jsgraph()->TrueConstant());
195 } else {
196 return Replace(jsgraph()->FalseConstant());
197 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400198 }
199 return NoChange();
200}
201
Ben Murdochc5610432016-08-08 18:44:38 +0100202Reduction SimplifiedOperatorReducer::ReduceTypeGuard(Node* node) {
203 DCHECK_EQ(IrOpcode::kTypeGuard, node->opcode());
204 Node* const input = NodeProperties::GetValueInput(node, 0);
205 Type* const input_type = NodeProperties::GetTypeOrAny(input);
206 Type* const guard_type = TypeOf(node->op());
207 if (input_type->Is(guard_type)) return Replace(input);
208 return NoChange();
209}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400210
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000211Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
212 Node* a) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op));
214 DCHECK_LE(1, node->InputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 node->ReplaceInput(0, a);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 NodeProperties::ChangeOp(node, op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 return Changed(node);
218}
219
Ben Murdoch61f157c2016-09-16 13:49:30 +0100220Reduction SimplifiedOperatorReducer::ReplaceBoolean(bool value) {
221 return Replace(jsgraph()->BooleanConstant(value));
222}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000223
224Reduction SimplifiedOperatorReducer::ReplaceFloat64(double value) {
225 return Replace(jsgraph()->Float64Constant(value));
226}
227
228
229Reduction SimplifiedOperatorReducer::ReplaceInt32(int32_t value) {
230 return Replace(jsgraph()->Int32Constant(value));
231}
232
233
234Reduction SimplifiedOperatorReducer::ReplaceNumber(double value) {
235 return Replace(jsgraph()->Constant(value));
236}
237
238
239Reduction SimplifiedOperatorReducer::ReplaceNumber(int32_t value) {
240 return Replace(jsgraph()->Constant(value));
241}
242
243
244Graph* SimplifiedOperatorReducer::graph() const { return jsgraph()->graph(); }
245
246
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247MachineOperatorBuilder* SimplifiedOperatorReducer::machine() const {
248 return jsgraph()->machine();
249}
250
251} // namespace compiler
252} // namespace internal
253} // namespace v8