Line data Source code
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/js-graph.h"
8 : #include "src/compiler/machine-operator.h"
9 : #include "src/compiler/node-matchers.h"
10 : #include "src/compiler/operator-properties.h"
11 : #include "src/compiler/simplified-operator.h"
12 : #include "src/compiler/type-cache.h"
13 : #include "src/conversions-inl.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 : namespace compiler {
18 :
19 : namespace {
20 :
21 96430 : Decision DecideObjectIsSmi(Node* const input) {
22 : NumberMatcher m(input);
23 96430 : if (m.HasValue()) {
24 7145 : return IsSmiDouble(m.Value()) ? Decision::kTrue : Decision::kFalse;
25 : }
26 89285 : if (m.IsAllocate()) return Decision::kFalse;
27 89285 : if (m.IsChangeBitToTagged()) return Decision::kFalse;
28 89283 : if (m.IsChangeInt31ToTaggedSigned()) return Decision::kTrue;
29 89281 : if (m.IsHeapConstant()) return Decision::kFalse;
30 88892 : return Decision::kUnknown;
31 : }
32 :
33 : } // namespace
34 :
35 887579 : SimplifiedOperatorReducer::SimplifiedOperatorReducer(Editor* editor,
36 : JSGraph* jsgraph)
37 887579 : : AdvancedReducer(editor), jsgraph_(jsgraph) {}
38 :
39 1775160 : SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
40 :
41 :
42 84120549 : Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
43 84120134 : switch (node->opcode()) {
44 : case IrOpcode::kBooleanNot: {
45 : HeapObjectMatcher m(node->InputAt(0));
46 24256 : if (m.Is(factory()->true_value())) return ReplaceBoolean(false);
47 18306 : if (m.Is(factory()->false_value())) return ReplaceBoolean(true);
48 13348 : if (m.IsBooleanNot()) return Replace(m.InputAt(0));
49 12714 : break;
50 : }
51 : case IrOpcode::kChangeBitToTagged: {
52 : Int32Matcher m(node->InputAt(0));
53 10757 : if (m.Is(0)) return Replace(jsgraph()->FalseConstant());
54 10628 : if (m.Is(1)) return Replace(jsgraph()->TrueConstant());
55 10322 : if (m.IsChangeTaggedToBit()) return Replace(m.InputAt(0));
56 : break;
57 : }
58 : case IrOpcode::kChangeTaggedToBit: {
59 : HeapObjectMatcher m(node->InputAt(0));
60 159226 : if (m.HasValue()) return ReplaceInt32(m.Value()->BooleanValue());
61 159204 : if (m.IsChangeBitToTagged()) return Replace(m.InputAt(0));
62 : break;
63 : }
64 : case IrOpcode::kChangeFloat64ToTagged: {
65 : Float64Matcher m(node->InputAt(0));
66 62432 : if (m.HasValue()) return ReplaceNumber(m.Value());
67 58530 : if (m.IsChangeTaggedToFloat64()) return Replace(m.node()->InputAt(0));
68 : break;
69 : }
70 : case IrOpcode::kChangeInt31ToTaggedSigned:
71 : case IrOpcode::kChangeInt32ToTagged: {
72 : Int32Matcher m(node->InputAt(0));
73 82191 : if (m.HasValue()) return ReplaceNumber(m.Value());
74 76546 : if (m.IsChangeTaggedToInt32() || m.IsChangeTaggedSignedToInt32()) {
75 : return Replace(m.InputAt(0));
76 : }
77 : break;
78 : }
79 : case IrOpcode::kChangeTaggedToFloat64:
80 : case IrOpcode::kTruncateTaggedToFloat64: {
81 : NumberMatcher m(node->InputAt(0));
82 48664 : if (m.HasValue()) return ReplaceFloat64(m.Value());
83 26321 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
84 : return Replace(m.node()->InputAt(0));
85 : }
86 26291 : if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
87 1 : return Change(node, machine()->ChangeInt32ToFloat64(), m.InputAt(0));
88 : }
89 26290 : if (m.IsChangeUint32ToTagged()) {
90 1 : return Change(node, machine()->ChangeUint32ToFloat64(), m.InputAt(0));
91 : }
92 : break;
93 : }
94 : case IrOpcode::kChangeTaggedSignedToInt32:
95 : case IrOpcode::kChangeTaggedToInt32: {
96 : NumberMatcher m(node->InputAt(0));
97 135314 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
98 133304 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
99 2 : return Change(node, machine()->ChangeFloat64ToInt32(), m.InputAt(0));
100 : }
101 133302 : if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
102 : return Replace(m.InputAt(0));
103 : }
104 : break;
105 : }
106 : case IrOpcode::kChangeTaggedToUint32: {
107 : NumberMatcher m(node->InputAt(0));
108 460 : if (m.HasValue()) return ReplaceUint32(DoubleToUint32(m.Value()));
109 418 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
110 2 : return Change(node, machine()->ChangeFloat64ToUint32(), m.InputAt(0));
111 : }
112 416 : if (m.IsChangeUint32ToTagged()) return Replace(m.InputAt(0));
113 : break;
114 : }
115 : case IrOpcode::kChangeUint32ToTagged: {
116 : Uint32Matcher m(node->InputAt(0));
117 1063 : if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
118 : break;
119 : }
120 : case IrOpcode::kTruncateTaggedToWord32: {
121 : NumberMatcher m(node->InputAt(0));
122 1653 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
123 1545 : if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged() ||
124 : m.IsChangeUint32ToTagged()) {
125 : return Replace(m.InputAt(0));
126 : }
127 1545 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
128 2 : return Change(node, machine()->TruncateFloat64ToWord32(), m.InputAt(0));
129 : }
130 : break;
131 : }
132 : case IrOpcode::kCheckedFloat64ToInt32: {
133 : Float64Matcher m(node->InputAt(0));
134 10928 : if (m.HasValue() && IsInt32Double(m.Value())) {
135 242 : Node* value = jsgraph()->Int32Constant(static_cast<int32_t>(m.Value()));
136 7197 : ReplaceWithValue(node, value);
137 : return Replace(value);
138 : }
139 : break;
140 : }
141 : case IrOpcode::kCheckedTaggedToInt32:
142 : case IrOpcode::kCheckedTaggedSignedToInt32: {
143 : NodeMatcher m(node->InputAt(0));
144 248205 : if (m.IsConvertTaggedHoleToUndefined()) {
145 88 : node->ReplaceInput(0, m.InputAt(0));
146 : return Changed(node);
147 : }
148 : break;
149 : }
150 : case IrOpcode::kCheckIf: {
151 : HeapObjectMatcher m(node->InputAt(0));
152 105436 : if (m.Is(factory()->true_value())) {
153 849 : Node* const effect = NodeProperties::GetEffectInput(node);
154 849 : return Replace(effect);
155 : }
156 104587 : break;
157 : }
158 : case IrOpcode::kCheckNumber: {
159 : NodeMatcher m(node->InputAt(0));
160 1223 : if (m.IsConvertTaggedHoleToUndefined()) {
161 0 : node->ReplaceInput(0, m.InputAt(0));
162 : return Changed(node);
163 : }
164 : break;
165 : }
166 : case IrOpcode::kCheckHeapObject: {
167 : Node* const input = node->InputAt(0);
168 37928 : if (DecideObjectIsSmi(input) == Decision::kFalse) {
169 : ReplaceWithValue(node, input);
170 : return Replace(input);
171 : }
172 : NodeMatcher m(input);
173 37923 : if (m.IsCheckHeapObject()) {
174 : ReplaceWithValue(node, input);
175 : return Replace(input);
176 : }
177 : break;
178 : }
179 : case IrOpcode::kCheckSmi: {
180 : Node* const input = node->InputAt(0);
181 47582 : if (DecideObjectIsSmi(input) == Decision::kTrue) {
182 : ReplaceWithValue(node, input);
183 : return Replace(input);
184 : }
185 : NodeMatcher m(input);
186 40607 : if (m.IsCheckSmi()) {
187 : ReplaceWithValue(node, input);
188 : return Replace(input);
189 40606 : } else if (m.IsConvertTaggedHoleToUndefined()) {
190 41 : node->ReplaceInput(0, m.InputAt(0));
191 : return Changed(node);
192 : }
193 : break;
194 : }
195 : case IrOpcode::kObjectIsSmi: {
196 : Node* const input = node->InputAt(0);
197 10920 : switch (DecideObjectIsSmi(input)) {
198 : case Decision::kTrue:
199 : return ReplaceBoolean(true);
200 : case Decision::kFalse:
201 : return ReplaceBoolean(false);
202 : case Decision::kUnknown:
203 : break;
204 : }
205 : break;
206 : }
207 : case IrOpcode::kNumberAbs: {
208 : NumberMatcher m(node->InputAt(0));
209 298 : if (m.HasValue()) return ReplaceNumber(std::fabs(m.Value()));
210 : break;
211 : }
212 : case IrOpcode::kReferenceEqual: {
213 195771 : HeapObjectBinopMatcher m(node);
214 196460 : if (m.left().node() == m.right().node()) return ReplaceBoolean(true);
215 195082 : break;
216 : }
217 : default:
218 : break;
219 : }
220 : return NoChange();
221 : }
222 :
223 0 : Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
224 : Node* a) {
225 : DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op));
226 : DCHECK_LE(1, node->InputCount());
227 8 : node->ReplaceInput(0, a);
228 8 : NodeProperties::ChangeOp(node, op);
229 0 : return Changed(node);
230 : }
231 :
232 5973 : Reduction SimplifiedOperatorReducer::ReplaceBoolean(bool value) {
233 5973 : return Replace(jsgraph()->BooleanConstant(value));
234 : }
235 :
236 22343 : Reduction SimplifiedOperatorReducer::ReplaceFloat64(double value) {
237 22343 : return Replace(jsgraph()->Float64Constant(value));
238 : }
239 :
240 :
241 2172 : Reduction SimplifiedOperatorReducer::ReplaceInt32(int32_t value) {
242 2172 : return Replace(jsgraph()->Int32Constant(value));
243 : }
244 :
245 :
246 4537 : Reduction SimplifiedOperatorReducer::ReplaceNumber(double value) {
247 4537 : return Replace(jsgraph()->Constant(value));
248 : }
249 :
250 :
251 5645 : Reduction SimplifiedOperatorReducer::ReplaceNumber(int32_t value) {
252 5645 : return Replace(jsgraph()->Constant(value));
253 : }
254 :
255 0 : Factory* SimplifiedOperatorReducer::factory() const {
256 0 : return isolate()->factory();
257 : }
258 :
259 0 : Graph* SimplifiedOperatorReducer::graph() const { return jsgraph()->graph(); }
260 :
261 142227 : Isolate* SimplifiedOperatorReducer::isolate() const {
262 142227 : return jsgraph()->isolate();
263 : }
264 :
265 8 : MachineOperatorBuilder* SimplifiedOperatorReducer::machine() const {
266 8 : return jsgraph()->machine();
267 : }
268 :
269 : } // namespace compiler
270 : } // namespace internal
271 : } // namespace v8
|