Line data Source code
1 : // Copyright 2015 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/representation-change.h"
6 :
7 : #include <sstream>
8 :
9 : #include "src/base/bits.h"
10 : #include "src/code-factory.h"
11 : #include "src/compiler/machine-operator.h"
12 : #include "src/compiler/node-matchers.h"
13 : #include "src/compiler/type-cache.h"
14 : #include "src/heap/factory-inl.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 : namespace compiler {
19 :
20 0 : const char* Truncation::description() const {
21 0 : switch (kind()) {
22 : case TruncationKind::kNone:
23 : return "no-value-use";
24 : case TruncationKind::kBool:
25 0 : return "truncate-to-bool";
26 : case TruncationKind::kWord32:
27 0 : return "truncate-to-word32";
28 : case TruncationKind::kFloat64:
29 0 : switch (identify_zeros()) {
30 : case kIdentifyZeros:
31 : return "truncate-to-float64 (identify zeros)";
32 : case kDistinguishZeros:
33 0 : return "truncate-to-float64 (distinguish zeros)";
34 : }
35 : case TruncationKind::kAny:
36 0 : switch (identify_zeros()) {
37 : case kIdentifyZeros:
38 : return "no-truncation (but identify zeros)";
39 : case kDistinguishZeros:
40 0 : return "no-truncation (but distinguish zeros)";
41 : }
42 : }
43 0 : UNREACHABLE();
44 : }
45 :
46 : // Partial order for truncations:
47 : //
48 : // kAny <-------+
49 : // ^ |
50 : // | |
51 : // kFloat64 |
52 : // ^ |
53 : // / |
54 : // kWord32 kBool
55 : // ^ ^
56 : // \ /
57 : // \ /
58 : // \ /
59 : // \ /
60 : // \ /
61 : // kNone
62 : //
63 : // TODO(jarin) We might consider making kBool < kFloat64.
64 :
65 : // static
66 105387536 : Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
67 : TruncationKind rep2) {
68 105387536 : if (LessGeneral(rep1, rep2)) return rep2;
69 11610585 : if (LessGeneral(rep2, rep1)) return rep1;
70 : // Handle the generalization of float64-representable values.
71 14 : if (LessGeneral(rep1, TruncationKind::kFloat64) &&
72 7 : LessGeneral(rep2, TruncationKind::kFloat64)) {
73 : return TruncationKind::kFloat64;
74 : }
75 : // Handle the generalization of any-representable values.
76 14 : if (LessGeneral(rep1, TruncationKind::kAny) &&
77 7 : LessGeneral(rep2, TruncationKind::kAny)) {
78 : return TruncationKind::kAny;
79 : }
80 : // All other combinations are illegal.
81 0 : FATAL("Tried to combine incompatible truncations");
82 : return TruncationKind::kNone;
83 : }
84 :
85 : // static
86 105388108 : IdentifyZeros Truncation::GeneralizeIdentifyZeros(IdentifyZeros i1,
87 : IdentifyZeros i2) {
88 105388108 : if (i1 == i2) {
89 74947237 : return i1;
90 : } else {
91 : return kDistinguishZeros;
92 : }
93 : }
94 :
95 : // static
96 119320126 : bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
97 119320126 : switch (rep1) {
98 : case TruncationKind::kNone:
99 : return true;
100 : case TruncationKind::kBool:
101 700587 : return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
102 : case TruncationKind::kWord32:
103 : return rep2 == TruncationKind::kWord32 ||
104 840763 : rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
105 : case TruncationKind::kFloat64:
106 588402 : return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
107 : case TruncationKind::kAny:
108 63260061 : return rep2 == TruncationKind::kAny;
109 : }
110 0 : UNREACHABLE();
111 : }
112 :
113 : // static
114 0 : bool Truncation::LessGeneralIdentifyZeros(IdentifyZeros i1, IdentifyZeros i2) {
115 0 : return i1 == i2 || i1 == kIdentifyZeros;
116 : }
117 :
118 : namespace {
119 :
120 : bool IsWord(MachineRepresentation rep) {
121 : return rep == MachineRepresentation::kWord8 ||
122 18532844 : rep == MachineRepresentation::kWord16 ||
123 : rep == MachineRepresentation::kWord32;
124 : }
125 :
126 : } // namespace
127 :
128 464309 : RepresentationChanger::RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
129 464309 : : cache_(TypeCache::Get()),
130 : jsgraph_(jsgraph),
131 : isolate_(isolate),
132 : testing_type_errors_(false),
133 464329 : type_error_(false) {}
134 :
135 : // Changes representation from {output_rep} to {use_rep}. The {truncation}
136 : // parameter is only used for sanity checking - if the changer cannot figure
137 : // out signedness for the word32->float64 conversion, then we check that the
138 : // uses truncate to word32 (so they do not care about signedness).
139 17006187 : Node* RepresentationChanger::GetRepresentationFor(
140 : Node* node, MachineRepresentation output_rep, Type output_type,
141 : Node* use_node, UseInfo use_info) {
142 17006726 : if (output_rep == MachineRepresentation::kNone && !output_type.IsNone()) {
143 : // The output representation should be set if the type is inhabited (i.e.,
144 : // if the value is possible).
145 0 : return TypeError(node, output_rep, output_type, use_info.representation());
146 : }
147 :
148 : // Handle the no-op shortcuts when no checking is necessary.
149 17006187 : if (use_info.type_check() == TypeCheckKind::kNone ||
150 : output_rep != MachineRepresentation::kWord32) {
151 16911302 : if (use_info.representation() == output_rep) {
152 : // Representations are the same. That's a no-op.
153 : return node;
154 : }
155 18165946 : if (IsWord(use_info.representation()) && IsWord(output_rep)) {
156 : // Both are words less than or equal to 32-bits.
157 : // Since loads of integers from memory implicitly sign or zero extend the
158 : // value to the full machine word size and stores implicitly truncate,
159 : // no representation change is necessary.
160 : return node;
161 : }
162 : }
163 :
164 16971290 : switch (use_info.representation()) {
165 : case MachineRepresentation::kTaggedSigned:
166 : DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
167 : use_info.type_check() == TypeCheckKind::kSignedSmall);
168 : return GetTaggedSignedRepresentationFor(node, output_rep, output_type,
169 69392 : use_node, use_info);
170 : case MachineRepresentation::kTaggedPointer:
171 : DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
172 : use_info.type_check() == TypeCheckKind::kHeapObject);
173 : return GetTaggedPointerRepresentationFor(node, output_rep, output_type,
174 35541 : use_node, use_info);
175 : case MachineRepresentation::kTagged:
176 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
177 : return GetTaggedRepresentationFor(node, output_rep, output_type,
178 14743595 : use_info.truncation());
179 : case MachineRepresentation::kFloat32:
180 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
181 : return GetFloat32RepresentationFor(node, output_rep, output_type,
182 1402 : use_info.truncation());
183 : case MachineRepresentation::kFloat64:
184 : return GetFloat64RepresentationFor(node, output_rep, output_type,
185 261791 : use_node, use_info);
186 : case MachineRepresentation::kBit:
187 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
188 314984 : return GetBitRepresentationFor(node, output_rep, output_type);
189 : case MachineRepresentation::kWord8:
190 : case MachineRepresentation::kWord16:
191 : case MachineRepresentation::kWord32:
192 : return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
193 1360765 : use_info);
194 : case MachineRepresentation::kWord64:
195 : DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
196 : use_info.type_check() == TypeCheckKind::kSigned64);
197 : return GetWord64RepresentationFor(node, output_rep, output_type, use_node,
198 183820 : use_info);
199 : // TODO(solanes): Create the code for the compressed values
200 : case MachineRepresentation::kCompressedSigned:
201 : case MachineRepresentation::kCompressedPointer:
202 : case MachineRepresentation::kCompressed:
203 0 : UNREACHABLE();
204 : case MachineRepresentation::kSimd128:
205 : case MachineRepresentation::kNone:
206 : return node;
207 : }
208 0 : UNREACHABLE();
209 : }
210 :
211 69392 : Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
212 : Node* node, MachineRepresentation output_rep, Type output_type,
213 : Node* use_node, UseInfo use_info) {
214 : // Eagerly fold representation changes for constants.
215 69392 : switch (node->opcode()) {
216 : case IrOpcode::kNumberConstant:
217 32 : if (output_type.Is(Type::SignedSmall())) {
218 : return node;
219 : }
220 : break;
221 : default:
222 : break;
223 : }
224 : // Select the correct X -> Tagged operator.
225 : const Operator* op;
226 69392 : if (output_type.Is(Type::None())) {
227 : // This is an impossible value; it should not be used at runtime.
228 0 : return jsgraph()->graph()->NewNode(
229 : jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedSigned),
230 0 : node);
231 69392 : } else if (IsWord(output_rep)) {
232 45052 : if (output_type.Is(Type::Signed31())) {
233 30399 : op = simplified()->ChangeInt31ToTaggedSigned();
234 14653 : } else if (output_type.Is(Type::Signed32())) {
235 : if (SmiValuesAre32Bits()) {
236 : op = simplified()->ChangeInt32ToTagged();
237 14646 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
238 14646 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
239 : } else {
240 : return TypeError(node, output_rep, output_type,
241 0 : MachineRepresentation::kTaggedSigned);
242 : }
243 7 : } else if (output_type.Is(Type::Unsigned32()) &&
244 : use_info.type_check() == TypeCheckKind::kSignedSmall) {
245 7 : op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
246 : } else {
247 : return TypeError(node, output_rep, output_type,
248 0 : MachineRepresentation::kTaggedSigned);
249 : }
250 24340 : } else if (output_rep == MachineRepresentation::kWord64) {
251 15 : if (output_type.Is(Type::Signed31())) {
252 : // int64 -> int32 -> tagged signed
253 5 : node = InsertTruncateInt64ToInt32(node);
254 5 : op = simplified()->ChangeInt31ToTaggedSigned();
255 : } else if (output_type.Is(Type::Signed32()) && SmiValuesAre32Bits()) {
256 : // int64 -> int32 -> tagged signed
257 : node = InsertTruncateInt64ToInt32(node);
258 : op = simplified()->ChangeInt32ToTagged();
259 10 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
260 20 : if (output_type.Is(cache_->kPositiveSafeInteger)) {
261 5 : op = simplified()->CheckedUint64ToTaggedSigned(use_info.feedback());
262 10 : } else if (output_type.Is(cache_->kSafeInteger)) {
263 5 : op = simplified()->CheckedInt64ToTaggedSigned(use_info.feedback());
264 : } else {
265 : return TypeError(node, output_rep, output_type,
266 0 : MachineRepresentation::kTaggedSigned);
267 : }
268 : } else {
269 : return TypeError(node, output_rep, output_type,
270 0 : MachineRepresentation::kTaggedSigned);
271 : }
272 24325 : } else if (output_rep == MachineRepresentation::kFloat64) {
273 23 : if (output_type.Is(Type::Signed31())) {
274 : // float64 -> int32 -> tagged signed
275 0 : node = InsertChangeFloat64ToInt32(node);
276 0 : op = simplified()->ChangeInt31ToTaggedSigned();
277 23 : } else if (output_type.Is(Type::Signed32())) {
278 : // float64 -> int32 -> tagged signed
279 0 : node = InsertChangeFloat64ToInt32(node);
280 : if (SmiValuesAre32Bits()) {
281 : op = simplified()->ChangeInt32ToTagged();
282 0 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
283 0 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
284 : } else {
285 : return TypeError(node, output_rep, output_type,
286 0 : MachineRepresentation::kTaggedSigned);
287 : }
288 23 : } else if (output_type.Is(Type::Unsigned32()) &&
289 : use_info.type_check() == TypeCheckKind::kSignedSmall) {
290 : // float64 -> uint32 -> tagged signed
291 0 : node = InsertChangeFloat64ToUint32(node);
292 0 : op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
293 23 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
294 23 : op = simplified()->CheckedFloat64ToInt32(
295 23 : output_type.Maybe(Type::MinusZero())
296 : ? CheckForMinusZeroMode::kCheckForMinusZero
297 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
298 23 : use_info.feedback());
299 23 : node = InsertConversion(node, op, use_node);
300 : if (SmiValuesAre32Bits()) {
301 : op = simplified()->ChangeInt32ToTagged();
302 : } else {
303 23 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
304 : }
305 : } else {
306 : return TypeError(node, output_rep, output_type,
307 0 : MachineRepresentation::kTaggedSigned);
308 : }
309 24302 : } else if (output_rep == MachineRepresentation::kFloat32) {
310 0 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
311 0 : op = machine()->ChangeFloat32ToFloat64();
312 0 : node = InsertConversion(node, op, use_node);
313 0 : op = simplified()->CheckedFloat64ToInt32(
314 0 : output_type.Maybe(Type::MinusZero())
315 : ? CheckForMinusZeroMode::kCheckForMinusZero
316 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
317 0 : use_info.feedback());
318 0 : node = InsertConversion(node, op, use_node);
319 : if (SmiValuesAre32Bits()) {
320 : op = simplified()->ChangeInt32ToTagged();
321 : } else {
322 0 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
323 : }
324 : } else {
325 : return TypeError(node, output_rep, output_type,
326 0 : MachineRepresentation::kTaggedSigned);
327 : }
328 24302 : } else if (CanBeTaggedPointer(output_rep)) {
329 24302 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
330 24288 : op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
331 14 : } else if (output_type.Is(Type::SignedSmall())) {
332 14 : op = simplified()->ChangeTaggedToTaggedSigned();
333 : } else {
334 : return TypeError(node, output_rep, output_type,
335 0 : MachineRepresentation::kTaggedSigned);
336 : }
337 0 : } else if (output_rep == MachineRepresentation::kBit) {
338 0 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
339 : // TODO(turbofan): Consider adding a Bailout operator that just deopts.
340 : // Also use that for MachineRepresentation::kPointer case above.
341 0 : node = InsertChangeBitToTagged(node);
342 0 : op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
343 : } else {
344 : return TypeError(node, output_rep, output_type,
345 0 : MachineRepresentation::kTaggedSigned);
346 : }
347 : } else {
348 : return TypeError(node, output_rep, output_type,
349 0 : MachineRepresentation::kTaggedSigned);
350 : }
351 69391 : return InsertConversion(node, op, use_node);
352 : }
353 :
354 35541 : Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
355 : Node* node, MachineRepresentation output_rep, Type output_type,
356 : Node* use_node, UseInfo use_info) {
357 : // Eagerly fold representation changes for constants.
358 35541 : switch (node->opcode()) {
359 : case IrOpcode::kHeapConstant:
360 : case IrOpcode::kDelayedStringConstant:
361 : return node; // No change necessary.
362 : case IrOpcode::kInt32Constant:
363 : case IrOpcode::kFloat64Constant:
364 : case IrOpcode::kFloat32Constant:
365 0 : UNREACHABLE();
366 : default:
367 : break;
368 : }
369 : // Select the correct X -> TaggedPointer operator.
370 : Operator const* op;
371 35541 : if (output_type.Is(Type::None())) {
372 : // This is an impossible value; it should not be used at runtime.
373 0 : return jsgraph()->graph()->NewNode(
374 : jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
375 0 : node);
376 35541 : } else if (output_rep == MachineRepresentation::kBit) {
377 0 : if (output_type.Is(Type::Boolean())) {
378 0 : op = simplified()->ChangeBitToTagged();
379 : } else {
380 : return TypeError(node, output_rep, output_type,
381 0 : MachineRepresentation::kTagged);
382 : }
383 35541 : } else if (IsWord(output_rep)) {
384 14 : if (output_type.Is(Type::Unsigned32())) {
385 : // uint32 -> float64 -> tagged
386 0 : node = InsertChangeUint32ToFloat64(node);
387 14 : } else if (output_type.Is(Type::Signed32())) {
388 : // int32 -> float64 -> tagged
389 14 : node = InsertChangeInt32ToFloat64(node);
390 : } else {
391 : return TypeError(node, output_rep, output_type,
392 0 : MachineRepresentation::kTaggedPointer);
393 : }
394 14 : op = simplified()->ChangeFloat64ToTaggedPointer();
395 35527 : } else if (output_rep == MachineRepresentation::kWord64) {
396 10 : if (output_type.Is(cache_->kSafeInteger)) {
397 : // int64 -> float64 -> tagged pointer
398 5 : op = machine()->ChangeInt64ToFloat64();
399 : node = jsgraph()->graph()->NewNode(op, node);
400 5 : op = simplified()->ChangeFloat64ToTaggedPointer();
401 : } else {
402 : return TypeError(node, output_rep, output_type,
403 0 : MachineRepresentation::kTaggedPointer);
404 : }
405 35522 : } else if (output_rep == MachineRepresentation::kFloat32) {
406 0 : if (output_type.Is(Type::Number())) {
407 : // float32 -> float64 -> tagged
408 0 : node = InsertChangeFloat32ToFloat64(node);
409 0 : op = simplified()->ChangeFloat64ToTaggedPointer();
410 : } else {
411 : return TypeError(node, output_rep, output_type,
412 0 : MachineRepresentation::kTaggedPointer);
413 : }
414 35522 : } else if (output_rep == MachineRepresentation::kFloat64) {
415 168 : if (output_type.Is(Type::Number())) {
416 : // float64 -> tagged
417 168 : op = simplified()->ChangeFloat64ToTaggedPointer();
418 : } else {
419 : return TypeError(node, output_rep, output_type,
420 0 : MachineRepresentation::kTaggedPointer);
421 : }
422 35354 : } else if (CanBeTaggedSigned(output_rep) &&
423 : use_info.type_check() == TypeCheckKind::kHeapObject) {
424 35354 : if (!output_type.Maybe(Type::SignedSmall())) {
425 : return node;
426 : }
427 : // TODO(turbofan): Consider adding a Bailout operator that just deopts
428 : // for TaggedSigned output representation.
429 34805 : op = simplified()->CheckedTaggedToTaggedPointer(use_info.feedback());
430 : } else {
431 : return TypeError(node, output_rep, output_type,
432 0 : MachineRepresentation::kTaggedPointer);
433 : }
434 34992 : return InsertConversion(node, op, use_node);
435 : }
436 :
437 14743568 : Node* RepresentationChanger::GetTaggedRepresentationFor(
438 : Node* node, MachineRepresentation output_rep, Type output_type,
439 : Truncation truncation) {
440 : // Eagerly fold representation changes for constants.
441 14743568 : switch (node->opcode()) {
442 : case IrOpcode::kNumberConstant:
443 : case IrOpcode::kHeapConstant:
444 : case IrOpcode::kDelayedStringConstant:
445 : return node; // No change necessary.
446 : case IrOpcode::kInt32Constant:
447 : case IrOpcode::kFloat64Constant:
448 : case IrOpcode::kFloat32Constant:
449 0 : UNREACHABLE();
450 : break;
451 : default:
452 : break;
453 : }
454 3194367 : if (output_rep == MachineRepresentation::kTaggedSigned ||
455 : output_rep == MachineRepresentation::kTaggedPointer) {
456 : // this is a no-op.
457 : return node;
458 : }
459 : // Select the correct X -> Tagged operator.
460 : const Operator* op;
461 124881 : if (output_type.Is(Type::None())) {
462 : // This is an impossible value; it should not be used at runtime.
463 308 : return jsgraph()->graph()->NewNode(
464 308 : jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
465 124573 : } else if (output_rep == MachineRepresentation::kBit) {
466 10513 : if (output_type.Is(Type::Boolean())) {
467 10513 : op = simplified()->ChangeBitToTagged();
468 : } else {
469 : return TypeError(node, output_rep, output_type,
470 0 : MachineRepresentation::kTagged);
471 : }
472 114060 : } else if (IsWord(output_rep)) {
473 39053 : if (output_type.Is(Type::Signed31())) {
474 16528 : op = simplified()->ChangeInt31ToTaggedSigned();
475 46050 : } else if (output_type.Is(Type::Signed32()) ||
476 7 : (output_type.Is(Type::Signed32OrMinusZero()) &&
477 : truncation.IdentifiesZeroAndMinusZero())) {
478 21532 : op = simplified()->ChangeInt32ToTagged();
479 1000 : } else if (output_type.Is(Type::Unsigned32()) ||
480 0 : (output_type.Is(Type::Unsigned32OrMinusZero()) &&
481 1000 : truncation.IdentifiesZeroAndMinusZero()) ||
482 : truncation.IsUsedAsWord32()) {
483 : // Either the output is uint32 or the uses only care about the
484 : // low 32 bits (so we can pick uint32 safely).
485 993 : op = simplified()->ChangeUint32ToTagged();
486 : } else {
487 : return TypeError(node, output_rep, output_type,
488 0 : MachineRepresentation::kTagged);
489 : }
490 75007 : } else if (output_rep == MachineRepresentation::kWord64) {
491 451 : if (output_type.Is(Type::Signed31())) {
492 : // int64 -> int32 -> tagged signed
493 5 : node = InsertTruncateInt64ToInt32(node);
494 5 : op = simplified()->ChangeInt31ToTaggedSigned();
495 446 : } else if (output_type.Is(Type::Signed32())) {
496 : // int64 -> int32 -> tagged
497 5 : node = InsertTruncateInt64ToInt32(node);
498 5 : op = simplified()->ChangeInt32ToTagged();
499 441 : } else if (output_type.Is(Type::Unsigned32())) {
500 : // int64 -> uint32 -> tagged
501 12 : node = InsertTruncateInt64ToInt32(node);
502 12 : op = simplified()->ChangeUint32ToTagged();
503 858 : } else if (output_type.Is(cache_->kPositiveSafeInteger)) {
504 : // uint64 -> tagged
505 88 : op = simplified()->ChangeUint64ToTagged();
506 682 : } else if (output_type.Is(cache_->kSafeInteger)) {
507 : // int64 -> tagged
508 336 : op = simplified()->ChangeInt64ToTagged();
509 : } else {
510 : return TypeError(node, output_rep, output_type,
511 5 : MachineRepresentation::kTagged);
512 : }
513 74556 : } else if (output_rep ==
514 : MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
515 378 : node = InsertChangeFloat32ToFloat64(node);
516 378 : op = simplified()->ChangeFloat64ToTagged(
517 378 : output_type.Maybe(Type::MinusZero())
518 : ? CheckForMinusZeroMode::kCheckForMinusZero
519 378 : : CheckForMinusZeroMode::kDontCheckForMinusZero);
520 74178 : } else if (output_rep == MachineRepresentation::kFloat64) {
521 74178 : if (output_type.Is(Type::Signed31())) { // float64 -> int32 -> tagged
522 31 : node = InsertChangeFloat64ToInt32(node);
523 31 : op = simplified()->ChangeInt31ToTaggedSigned();
524 74147 : } else if (output_type.Is(
525 : Type::Signed32())) { // float64 -> int32 -> tagged
526 499 : node = InsertChangeFloat64ToInt32(node);
527 499 : op = simplified()->ChangeInt32ToTagged();
528 73648 : } else if (output_type.Is(
529 : Type::Unsigned32())) { // float64 -> uint32 -> tagged
530 23 : node = InsertChangeFloat64ToUint32(node);
531 23 : op = simplified()->ChangeUint32ToTagged();
532 147264 : } else if (output_type.Is(Type::Number()) ||
533 14 : (output_type.Is(Type::NumberOrOddball()) &&
534 : truncation.IsUsedAsFloat64())) {
535 73625 : op = simplified()->ChangeFloat64ToTagged(
536 73625 : output_type.Maybe(Type::MinusZero())
537 : ? CheckForMinusZeroMode::kCheckForMinusZero
538 73625 : : CheckForMinusZeroMode::kDontCheckForMinusZero);
539 : } else {
540 : return TypeError(node, output_rep, output_type,
541 0 : MachineRepresentation::kTagged);
542 : }
543 : } else {
544 : return TypeError(node, output_rep, output_type,
545 0 : MachineRepresentation::kTagged);
546 : }
547 124567 : return jsgraph()->graph()->NewNode(op, node);
548 : }
549 :
550 1402 : Node* RepresentationChanger::GetFloat32RepresentationFor(
551 : Node* node, MachineRepresentation output_rep, Type output_type,
552 : Truncation truncation) {
553 : // Eagerly fold representation changes for constants.
554 1402 : switch (node->opcode()) {
555 : case IrOpcode::kNumberConstant:
556 2308 : return jsgraph()->Float32Constant(
557 1154 : DoubleToFloat32(OpParameter<double>(node->op())));
558 : case IrOpcode::kInt32Constant:
559 : case IrOpcode::kFloat64Constant:
560 : case IrOpcode::kFloat32Constant:
561 0 : UNREACHABLE();
562 : break;
563 : default:
564 : break;
565 : }
566 : // Select the correct X -> Float32 operator.
567 : const Operator* op = nullptr;
568 248 : if (output_type.Is(Type::None())) {
569 : // This is an impossible value; it should not be used at runtime.
570 0 : return jsgraph()->graph()->NewNode(
571 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
572 248 : } else if (IsWord(output_rep)) {
573 31 : if (output_type.Is(Type::Signed32())) {
574 : // int32 -> float64 -> float32
575 26 : op = machine()->ChangeInt32ToFloat64();
576 : node = jsgraph()->graph()->NewNode(op, node);
577 26 : op = machine()->TruncateFloat64ToFloat32();
578 5 : } else if (output_type.Is(Type::Unsigned32()) ||
579 : truncation.IsUsedAsWord32()) {
580 : // Either the output is uint32 or the uses only care about the
581 : // low 32 bits (so we can pick uint32 safely).
582 :
583 : // uint32 -> float64 -> float32
584 5 : op = machine()->ChangeUint32ToFloat64();
585 : node = jsgraph()->graph()->NewNode(op, node);
586 5 : op = machine()->TruncateFloat64ToFloat32();
587 : }
588 217 : } else if (IsAnyTagged(output_rep)) {
589 5 : if (output_type.Is(Type::NumberOrOddball())) {
590 : // tagged -> float64 -> float32
591 5 : if (output_type.Is(Type::Number())) {
592 5 : op = simplified()->ChangeTaggedToFloat64();
593 : } else {
594 0 : op = simplified()->TruncateTaggedToFloat64();
595 : }
596 : node = jsgraph()->graph()->NewNode(op, node);
597 5 : op = machine()->TruncateFloat64ToFloat32();
598 : }
599 212 : } else if (output_rep == MachineRepresentation::kFloat64) {
600 197 : op = machine()->TruncateFloat64ToFloat32();
601 15 : } else if (output_rep == MachineRepresentation::kWord64) {
602 10 : if (output_type.Is(cache_->kSafeInteger)) {
603 : // int64 -> float64 -> float32
604 5 : op = machine()->ChangeInt64ToFloat64();
605 : node = jsgraph()->graph()->NewNode(op, node);
606 5 : op = machine()->TruncateFloat64ToFloat32();
607 : }
608 : }
609 248 : if (op == nullptr) {
610 : return TypeError(node, output_rep, output_type,
611 10 : MachineRepresentation::kFloat32);
612 : }
613 238 : return jsgraph()->graph()->NewNode(op, node);
614 : }
615 :
616 261789 : Node* RepresentationChanger::GetFloat64RepresentationFor(
617 : Node* node, MachineRepresentation output_rep, Type output_type,
618 : Node* use_node, UseInfo use_info) {
619 : NumberMatcher m(node);
620 261789 : if (m.HasValue()) {
621 : switch (use_info.type_check()) {
622 : case TypeCheckKind::kNone:
623 : case TypeCheckKind::kNumber:
624 : case TypeCheckKind::kNumberOrOddball:
625 150258 : return jsgraph()->Float64Constant(m.Value());
626 : case TypeCheckKind::kHeapObject:
627 : case TypeCheckKind::kSigned32:
628 : case TypeCheckKind::kSigned64:
629 : case TypeCheckKind::kSignedSmall:
630 : break;
631 : }
632 : }
633 : // Select the correct X -> Float64 operator.
634 : const Operator* op = nullptr;
635 111531 : if (output_type.Is(Type::None())) {
636 : // This is an impossible value; it should not be used at runtime.
637 0 : return jsgraph()->graph()->NewNode(
638 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
639 111531 : } else if (IsWord(output_rep)) {
640 77845 : if (output_type.Is(Type::Signed32()) ||
641 15 : (output_type.Is(Type::Signed32OrMinusZero()) &&
642 : use_info.truncation().IdentifiesZeroAndMinusZero())) {
643 38042 : op = machine()->ChangeInt32ToFloat64();
644 582 : } else if (output_type.Is(Type::Unsigned32()) ||
645 : use_info.truncation().IsUsedAsWord32()) {
646 : // Either the output is uint32 or the uses only care about the
647 : // low 32 bits (so we can pick uint32 safely).
648 582 : op = machine()->ChangeUint32ToFloat64();
649 : }
650 72907 : } else if (output_rep == MachineRepresentation::kBit) {
651 0 : CHECK(output_type.Is(Type::Boolean()));
652 0 : if (use_info.truncation().IsUsedAsFloat64()) {
653 0 : op = machine()->ChangeUint32ToFloat64();
654 : } else {
655 0 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
656 : Node* unreachable =
657 0 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotAHeapNumber);
658 0 : return jsgraph()->graph()->NewNode(
659 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
660 0 : unreachable);
661 : }
662 145814 : } else if (output_rep == MachineRepresentation::kTagged ||
663 77921 : output_rep == MachineRepresentation::kTaggedSigned ||
664 : output_rep == MachineRepresentation::kTaggedPointer) {
665 70308 : if (output_type.Is(Type::Undefined())) {
666 244 : return jsgraph()->Float64Constant(
667 244 : std::numeric_limits<double>::quiet_NaN());
668 :
669 70064 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
670 1228 : node = InsertChangeTaggedSignedToInt32(node);
671 1228 : op = machine()->ChangeInt32ToFloat64();
672 68836 : } else if (output_type.Is(Type::Number())) {
673 11726 : op = simplified()->ChangeTaggedToFloat64();
674 57110 : } else if (output_type.Is(Type::NumberOrOddball())) {
675 : // TODO(jarin) Here we should check that truncation is Number.
676 1468 : op = simplified()->TruncateTaggedToFloat64();
677 111284 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
678 46941 : (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
679 46941 : !output_type.Maybe(Type::BooleanOrNullOrNumber()))) {
680 : op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber,
681 9166 : use_info.feedback());
682 46476 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
683 : op = simplified()->CheckedTaggedToFloat64(
684 46476 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
685 : }
686 2599 : } else if (output_rep == MachineRepresentation::kFloat32) {
687 2174 : op = machine()->ChangeFloat32ToFloat64();
688 425 : } else if (output_rep == MachineRepresentation::kWord64) {
689 850 : if (output_type.Is(cache_->kSafeInteger)) {
690 425 : op = machine()->ChangeInt64ToFloat64();
691 : }
692 : }
693 111287 : if (op == nullptr) {
694 : return TypeError(node, output_rep, output_type,
695 0 : MachineRepresentation::kFloat64);
696 : }
697 111287 : return InsertConversion(node, op, use_node);
698 : }
699 :
700 0 : Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
701 1040905 : return jsgraph()->Int32Constant(DoubleToInt32(value));
702 : }
703 :
704 7 : Node* RepresentationChanger::InsertUnconditionalDeopt(Node* node,
705 : DeoptimizeReason reason) {
706 7 : Node* effect = NodeProperties::GetEffectInput(node);
707 7 : Node* control = NodeProperties::GetControlInput(node);
708 : effect =
709 14 : jsgraph()->graph()->NewNode(simplified()->CheckIf(reason),
710 : jsgraph()->Int32Constant(0), effect, control);
711 7 : Node* unreachable = effect = jsgraph()->graph()->NewNode(
712 : jsgraph()->common()->Unreachable(), effect, control);
713 7 : NodeProperties::ReplaceEffectInput(node, effect);
714 7 : return unreachable;
715 : }
716 :
717 1360750 : Node* RepresentationChanger::GetWord32RepresentationFor(
718 : Node* node, MachineRepresentation output_rep, Type output_type,
719 : Node* use_node, UseInfo use_info) {
720 : // Eagerly fold representation changes for constants.
721 1360750 : switch (node->opcode()) {
722 : case IrOpcode::kInt32Constant:
723 : case IrOpcode::kInt64Constant:
724 : case IrOpcode::kFloat32Constant:
725 : case IrOpcode::kFloat64Constant:
726 0 : UNREACHABLE();
727 : break;
728 : case IrOpcode::kNumberConstant: {
729 1041036 : double const fv = OpParameter<double>(node->op());
730 2082072 : if (use_info.type_check() == TypeCheckKind::kNone ||
731 1512 : ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
732 1464 : use_info.type_check() == TypeCheckKind::kSigned32 ||
733 444 : use_info.type_check() == TypeCheckKind::kNumber ||
734 84643 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) &&
735 : IsInt32Double(fv))) {
736 1040897 : return MakeTruncatedInt32Constant(fv);
737 : }
738 : break;
739 : }
740 : default:
741 : break;
742 : }
743 :
744 : // Select the correct X -> Word32 operator.
745 : const Operator* op = nullptr;
746 319828 : if (output_type.Is(Type::None())) {
747 : // This is an impossible value; it should not be used at runtime.
748 21 : return jsgraph()->graph()->NewNode(
749 21 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
750 319807 : } else if (output_rep == MachineRepresentation::kBit) {
751 58 : CHECK(output_type.Is(Type::Boolean()));
752 58 : if (use_info.truncation().IsUsedAsWord32()) {
753 : return node;
754 : } else {
755 0 : CHECK(Truncation::Any(kIdentifyZeros)
756 : .IsLessGeneralThan(use_info.truncation()));
757 0 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
758 : Node* unreachable =
759 0 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
760 0 : return jsgraph()->graph()->NewNode(
761 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32),
762 0 : unreachable);
763 : }
764 319749 : } else if (output_rep == MachineRepresentation::kFloat64) {
765 12617 : if (output_type.Is(Type::Signed32())) {
766 536 : op = machine()->ChangeFloat64ToInt32();
767 12081 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
768 : use_info.type_check() == TypeCheckKind::kSigned32) {
769 2165 : op = simplified()->CheckedFloat64ToInt32(
770 2165 : output_type.Maybe(Type::MinusZero())
771 : ? use_info.minus_zero_check()
772 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
773 2165 : use_info.feedback());
774 9916 : } else if (output_type.Is(Type::Unsigned32())) {
775 12 : op = machine()->ChangeFloat64ToUint32();
776 9904 : } else if (use_info.truncation().IsUsedAsWord32()) {
777 9904 : op = machine()->TruncateFloat64ToWord32();
778 : } else {
779 : return TypeError(node, output_rep, output_type,
780 0 : MachineRepresentation::kWord32);
781 : }
782 307132 : } else if (output_rep == MachineRepresentation::kFloat32) {
783 15 : node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
784 15 : if (output_type.Is(Type::Signed32())) {
785 5 : op = machine()->ChangeFloat64ToInt32();
786 10 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
787 : use_info.type_check() == TypeCheckKind::kSigned32) {
788 0 : op = simplified()->CheckedFloat64ToInt32(
789 0 : output_type.Maybe(Type::MinusZero())
790 : ? use_info.minus_zero_check()
791 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
792 0 : use_info.feedback());
793 10 : } else if (output_type.Is(Type::Unsigned32())) {
794 5 : op = machine()->ChangeFloat64ToUint32();
795 5 : } else if (use_info.truncation().IsUsedAsWord32()) {
796 5 : op = machine()->TruncateFloat64ToWord32();
797 : } else {
798 : return TypeError(node, output_rep, output_type,
799 0 : MachineRepresentation::kWord32);
800 : }
801 307117 : } else if (IsAnyTagged(output_rep)) {
802 312308 : if (output_rep == MachineRepresentation::kTaggedSigned &&
803 : output_type.Is(Type::SignedSmall())) {
804 81687 : op = simplified()->ChangeTaggedSignedToInt32();
805 148930 : } else if (output_type.Is(Type::Signed32())) {
806 2346 : op = simplified()->ChangeTaggedToInt32();
807 146584 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
808 141167 : op = simplified()->CheckedTaggedSignedToInt32(use_info.feedback());
809 5417 : } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
810 2458 : op = simplified()->CheckedTaggedToInt32(
811 2458 : output_type.Maybe(Type::MinusZero())
812 : ? use_info.minus_zero_check()
813 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
814 2458 : use_info.feedback());
815 2959 : } else if (output_type.Is(Type::Unsigned32())) {
816 578 : op = simplified()->ChangeTaggedToUint32();
817 2381 : } else if (use_info.truncation().IsUsedAsWord32()) {
818 2381 : if (output_type.Is(Type::NumberOrOddball())) {
819 405 : op = simplified()->TruncateTaggedToWord32();
820 1976 : } else if (use_info.type_check() == TypeCheckKind::kNumber) {
821 : op = simplified()->CheckedTruncateTaggedToWord32(
822 1335 : CheckTaggedInputMode::kNumber, use_info.feedback());
823 641 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
824 : op = simplified()->CheckedTruncateTaggedToWord32(
825 641 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
826 : } else {
827 : return TypeError(node, output_rep, output_type,
828 0 : MachineRepresentation::kWord32);
829 : }
830 : } else {
831 : return TypeError(node, output_rep, output_type,
832 0 : MachineRepresentation::kWord32);
833 : }
834 76496 : } else if (output_rep == MachineRepresentation::kWord32) {
835 : // Only the checked case should get here, the non-checked case is
836 : // handled in GetRepresentationFor.
837 76206 : if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
838 : use_info.type_check() == TypeCheckKind::kSigned32) {
839 : bool indentify_zeros = use_info.truncation().IdentifiesZeroAndMinusZero();
840 152170 : if (output_type.Is(Type::Signed32()) ||
841 135 : (indentify_zeros && output_type.Is(Type::Signed32OrMinusZero()))) {
842 : return node;
843 352 : } else if (output_type.Is(Type::Unsigned32()) ||
844 0 : (indentify_zeros &&
845 : output_type.Is(Type::Unsigned32OrMinusZero()))) {
846 176 : op = simplified()->CheckedUint32ToInt32(use_info.feedback());
847 : } else {
848 : return TypeError(node, output_rep, output_type,
849 0 : MachineRepresentation::kWord32);
850 : }
851 121 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
852 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
853 : return node;
854 : }
855 290 : } else if (output_rep == MachineRepresentation::kWord8 ||
856 : output_rep == MachineRepresentation::kWord16) {
857 : DCHECK_EQ(MachineRepresentation::kWord32, use_info.representation());
858 : DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall ||
859 : use_info.type_check() == TypeCheckKind::kSigned32);
860 : return node;
861 290 : } else if (output_rep == MachineRepresentation::kWord64) {
862 551 : if (output_type.Is(Type::Signed32()) ||
863 : output_type.Is(Type::Unsigned32())) {
864 35 : op = machine()->TruncateInt64ToInt32();
865 760 : } else if (output_type.Is(cache_->kSafeInteger) &&
866 : use_info.truncation().IsUsedAsWord32()) {
867 231 : op = machine()->TruncateInt64ToInt32();
868 24 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
869 : use_info.type_check() == TypeCheckKind::kSigned32) {
870 38 : if (output_type.Is(cache_->kPositiveSafeInteger)) {
871 5 : op = simplified()->CheckedUint64ToInt32(use_info.feedback());
872 28 : } else if (output_type.Is(cache_->kSafeInteger)) {
873 14 : op = simplified()->CheckedInt64ToInt32(use_info.feedback());
874 : } else {
875 : return TypeError(node, output_rep, output_type,
876 0 : MachineRepresentation::kWord32);
877 : }
878 : } else {
879 : return TypeError(node, output_rep, output_type,
880 5 : MachineRepresentation::kWord32);
881 : }
882 : }
883 :
884 243711 : if (op == nullptr) {
885 : return TypeError(node, output_rep, output_type,
886 0 : MachineRepresentation::kWord32);
887 : }
888 243711 : return InsertConversion(node, op, use_node);
889 : }
890 :
891 495500 : Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
892 : Node* use_node) {
893 495500 : if (op->ControlInputCount() > 0) {
894 : // If the operator can deoptimize (which means it has control
895 : // input), we need to connect it to the effect and control chains.
896 277591 : Node* effect = NodeProperties::GetEffectInput(use_node);
897 277590 : Node* control = NodeProperties::GetControlInput(use_node);
898 : Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
899 277603 : NodeProperties::ReplaceEffectInput(use_node, conversion);
900 277584 : return conversion;
901 : }
902 217909 : return jsgraph()->graph()->NewNode(op, node);
903 : }
904 :
905 314984 : Node* RepresentationChanger::GetBitRepresentationFor(
906 : Node* node, MachineRepresentation output_rep, Type output_type) {
907 : // Eagerly fold representation changes for constants.
908 314984 : switch (node->opcode()) {
909 : case IrOpcode::kHeapConstant: {
910 : HeapObjectMatcher m(node);
911 127439 : if (m.Is(factory()->false_value())) {
912 87098 : return jsgraph()->Int32Constant(0);
913 40341 : } else if (m.Is(factory()->true_value())) {
914 40341 : return jsgraph()->Int32Constant(1);
915 : }
916 : break;
917 : }
918 : default:
919 : break;
920 : }
921 : // Select the correct X -> Bit operator.
922 : const Operator* op;
923 187545 : if (output_type.Is(Type::None())) {
924 : // This is an impossible value; it should not be used at runtime.
925 217 : return jsgraph()->graph()->NewNode(
926 217 : jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
927 187328 : } else if (output_rep == MachineRepresentation::kTagged ||
928 : output_rep == MachineRepresentation::kTaggedPointer) {
929 187314 : if (output_type.Is(Type::BooleanOrNullOrUndefined())) {
930 : // true is the only trueish Oddball.
931 139577 : op = simplified()->ChangeTaggedToBit();
932 : } else {
933 95084 : if (output_rep == MachineRepresentation::kTagged &&
934 47347 : output_type.Maybe(Type::SignedSmall())) {
935 47325 : op = simplified()->TruncateTaggedToBit();
936 : } else {
937 : // The {output_type} either doesn't include the Smi range,
938 : // or the {output_rep} is known to be TaggedPointer.
939 412 : op = simplified()->TruncateTaggedPointerToBit();
940 : }
941 : }
942 14 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
943 0 : node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
944 : jsgraph()->IntPtrConstant(0));
945 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
946 0 : jsgraph()->Int32Constant(0));
947 14 : } else if (IsWord(output_rep)) {
948 0 : node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
949 : jsgraph()->Int32Constant(0));
950 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
951 0 : jsgraph()->Int32Constant(0));
952 14 : } else if (output_rep == MachineRepresentation::kWord64) {
953 0 : node = jsgraph()->graph()->NewNode(machine()->Word64Equal(), node,
954 : jsgraph()->Int64Constant(0));
955 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
956 0 : jsgraph()->Int32Constant(0));
957 14 : } else if (output_rep == MachineRepresentation::kFloat32) {
958 0 : node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
959 0 : return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
960 0 : jsgraph()->Float32Constant(0.0), node);
961 14 : } else if (output_rep == MachineRepresentation::kFloat64) {
962 14 : node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
963 14 : return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
964 14 : jsgraph()->Float64Constant(0.0), node);
965 : } else {
966 : return TypeError(node, output_rep, output_type,
967 0 : MachineRepresentation::kBit);
968 : }
969 187314 : return jsgraph()->graph()->NewNode(op, node);
970 : }
971 :
972 183820 : Node* RepresentationChanger::GetWord64RepresentationFor(
973 : Node* node, MachineRepresentation output_rep, Type output_type,
974 : Node* use_node, UseInfo use_info) {
975 : // Eagerly fold representation changes for constants.
976 183820 : switch (node->opcode()) {
977 : case IrOpcode::kInt32Constant:
978 : case IrOpcode::kInt64Constant:
979 : case IrOpcode::kFloat32Constant:
980 : case IrOpcode::kFloat64Constant:
981 0 : UNREACHABLE();
982 : break;
983 : case IrOpcode::kNumberConstant: {
984 147645 : double const fv = OpParameter<double>(node->op());
985 : using limits = std::numeric_limits<int64_t>;
986 147645 : if (fv <= limits::max() && fv >= limits::min()) {
987 147638 : int64_t const iv = static_cast<int64_t>(fv);
988 147638 : if (static_cast<double>(iv) == fv) {
989 147638 : return jsgraph()->Int64Constant(iv);
990 : }
991 : }
992 : break;
993 : }
994 : default:
995 : break;
996 : }
997 :
998 : // Select the correct X -> Word64 operator.
999 : const Operator* op;
1000 36182 : if (output_type.Is(Type::None())) {
1001 : // This is an impossible value; it should not be used at runtime.
1002 63 : return jsgraph()->graph()->NewNode(
1003 63 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord64), node);
1004 36119 : } else if (output_rep == MachineRepresentation::kBit) {
1005 7 : CHECK(output_type.Is(Type::Boolean()));
1006 7 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
1007 : Node* unreachable =
1008 7 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
1009 7 : return jsgraph()->graph()->NewNode(
1010 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1011 7 : unreachable);
1012 36112 : } else if (IsWord(output_rep)) {
1013 35713 : if (output_type.Is(Type::Unsigned32())) {
1014 34370 : op = machine()->ChangeUint32ToUint64();
1015 1343 : } else if (output_type.Is(Type::Signed32())) {
1016 1338 : op = machine()->ChangeInt32ToInt64();
1017 : } else {
1018 : return TypeError(node, output_rep, output_type,
1019 5 : MachineRepresentation::kWord64);
1020 : }
1021 399 : } else if (output_rep == MachineRepresentation::kFloat32) {
1022 66 : if (output_type.Is(cache_->kInt64)) {
1023 : // float32 -> float64 -> int64
1024 15 : node = InsertChangeFloat32ToFloat64(node);
1025 15 : op = machine()->ChangeFloat64ToInt64();
1026 36 : } else if (output_type.Is(cache_->kUint64)) {
1027 : // float32 -> float64 -> uint64
1028 5 : node = InsertChangeFloat32ToFloat64(node);
1029 5 : op = machine()->ChangeFloat64ToUint64();
1030 13 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1031 : // float32 -> float64 -> int64
1032 13 : node = InsertChangeFloat32ToFloat64(node);
1033 13 : op = simplified()->CheckedFloat64ToInt64(
1034 13 : output_type.Maybe(Type::MinusZero())
1035 : ? use_info.minus_zero_check()
1036 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1037 13 : use_info.feedback());
1038 : } else {
1039 : return TypeError(node, output_rep, output_type,
1040 0 : MachineRepresentation::kWord64);
1041 : }
1042 366 : } else if (output_rep == MachineRepresentation::kFloat64) {
1043 120 : if (output_type.Is(cache_->kInt64)) {
1044 42 : op = machine()->ChangeFloat64ToInt64();
1045 36 : } else if (output_type.Is(cache_->kUint64)) {
1046 5 : op = machine()->ChangeFloat64ToUint64();
1047 13 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1048 13 : op = simplified()->CheckedFloat64ToInt64(
1049 13 : output_type.Maybe(Type::MinusZero())
1050 : ? use_info.minus_zero_check()
1051 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1052 13 : use_info.feedback());
1053 : } else {
1054 : return TypeError(node, output_rep, output_type,
1055 0 : MachineRepresentation::kWord64);
1056 : }
1057 306 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1058 112 : if (output_type.Is(Type::SignedSmall())) {
1059 112 : op = simplified()->ChangeTaggedSignedToInt64();
1060 : } else {
1061 : return TypeError(node, output_rep, output_type,
1062 0 : MachineRepresentation::kWord64);
1063 : }
1064 194 : } else if (CanBeTaggedPointer(output_rep)) {
1065 388 : if (output_type.Is(cache_->kInt64)) {
1066 23 : op = simplified()->ChangeTaggedToInt64();
1067 171 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1068 161 : op = simplified()->CheckedTaggedToInt64(
1069 161 : output_type.Maybe(Type::MinusZero())
1070 : ? use_info.minus_zero_check()
1071 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1072 161 : use_info.feedback());
1073 : } else {
1074 : return TypeError(node, output_rep, output_type,
1075 10 : MachineRepresentation::kWord64);
1076 : }
1077 : } else {
1078 : return TypeError(node, output_rep, output_type,
1079 0 : MachineRepresentation::kWord64);
1080 : }
1081 36097 : return InsertConversion(node, op, use_node);
1082 : }
1083 :
1084 233466 : const Operator* RepresentationChanger::Int32OperatorFor(
1085 : IrOpcode::Value opcode) {
1086 233466 : switch (opcode) {
1087 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1088 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1089 : case IrOpcode::kNumberAdd:
1090 114298 : return machine()->Int32Add();
1091 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1092 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1093 : case IrOpcode::kNumberSubtract:
1094 9442 : return machine()->Int32Sub();
1095 : case IrOpcode::kSpeculativeNumberMultiply:
1096 : case IrOpcode::kNumberMultiply:
1097 1081 : return machine()->Int32Mul();
1098 : case IrOpcode::kSpeculativeNumberDivide:
1099 : case IrOpcode::kNumberDivide:
1100 0 : return machine()->Int32Div();
1101 : case IrOpcode::kSpeculativeNumberModulus:
1102 : case IrOpcode::kNumberModulus:
1103 0 : return machine()->Int32Mod();
1104 : case IrOpcode::kSpeculativeNumberBitwiseOr: // Fall through.
1105 : case IrOpcode::kNumberBitwiseOr:
1106 20439 : return machine()->Word32Or();
1107 : case IrOpcode::kSpeculativeNumberBitwiseXor: // Fall through.
1108 : case IrOpcode::kNumberBitwiseXor:
1109 2551 : return machine()->Word32Xor();
1110 : case IrOpcode::kSpeculativeNumberBitwiseAnd: // Fall through.
1111 : case IrOpcode::kNumberBitwiseAnd:
1112 10108 : return machine()->Word32And();
1113 : case IrOpcode::kNumberEqual:
1114 : case IrOpcode::kSpeculativeNumberEqual:
1115 9770 : return machine()->Word32Equal();
1116 : case IrOpcode::kNumberLessThan:
1117 : case IrOpcode::kSpeculativeNumberLessThan:
1118 64208 : return machine()->Int32LessThan();
1119 : case IrOpcode::kNumberLessThanOrEqual:
1120 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1121 1569 : return machine()->Int32LessThanOrEqual();
1122 : default:
1123 0 : UNREACHABLE();
1124 : }
1125 : }
1126 :
1127 136890 : const Operator* RepresentationChanger::Int32OverflowOperatorFor(
1128 : IrOpcode::Value opcode) {
1129 136890 : switch (opcode) {
1130 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1131 131942 : return simplified()->CheckedInt32Add();
1132 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1133 3462 : return simplified()->CheckedInt32Sub();
1134 : case IrOpcode::kSpeculativeNumberDivide:
1135 242 : return simplified()->CheckedInt32Div();
1136 : case IrOpcode::kSpeculativeNumberModulus:
1137 1244 : return simplified()->CheckedInt32Mod();
1138 : default:
1139 0 : UNREACHABLE();
1140 : }
1141 : }
1142 :
1143 837 : const Operator* RepresentationChanger::Int64OperatorFor(
1144 : IrOpcode::Value opcode) {
1145 : switch (opcode) {
1146 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1147 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1148 : case IrOpcode::kNumberAdd:
1149 386 : return machine()->Int64Add();
1150 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1151 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1152 : case IrOpcode::kNumberSubtract:
1153 451 : return machine()->Int64Sub();
1154 : default:
1155 0 : UNREACHABLE();
1156 : }
1157 : }
1158 :
1159 14130 : const Operator* RepresentationChanger::TaggedSignedOperatorFor(
1160 : IrOpcode::Value opcode) {
1161 14130 : switch (opcode) {
1162 : case IrOpcode::kSpeculativeNumberLessThan:
1163 : return machine()->Is32() ? machine()->Int32LessThan()
1164 5281 : : machine()->Int64LessThan();
1165 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1166 : return machine()->Is32() ? machine()->Int32LessThanOrEqual()
1167 328 : : machine()->Int64LessThanOrEqual();
1168 : case IrOpcode::kSpeculativeNumberEqual:
1169 : return machine()->Is32() ? machine()->Word32Equal()
1170 8521 : : machine()->Word64Equal();
1171 : default:
1172 0 : UNREACHABLE();
1173 : }
1174 : }
1175 :
1176 36370 : const Operator* RepresentationChanger::Uint32OperatorFor(
1177 : IrOpcode::Value opcode) {
1178 36370 : switch (opcode) {
1179 : case IrOpcode::kNumberAdd:
1180 0 : return machine()->Int32Add();
1181 : case IrOpcode::kNumberSubtract:
1182 0 : return machine()->Int32Sub();
1183 : case IrOpcode::kSpeculativeNumberMultiply:
1184 : case IrOpcode::kNumberMultiply:
1185 0 : return machine()->Int32Mul();
1186 : case IrOpcode::kSpeculativeNumberDivide:
1187 : case IrOpcode::kNumberDivide:
1188 0 : return machine()->Uint32Div();
1189 : case IrOpcode::kSpeculativeNumberModulus:
1190 : case IrOpcode::kNumberModulus:
1191 0 : return machine()->Uint32Mod();
1192 : case IrOpcode::kNumberEqual:
1193 : case IrOpcode::kSpeculativeNumberEqual:
1194 12835 : return machine()->Word32Equal();
1195 : case IrOpcode::kNumberLessThan:
1196 : case IrOpcode::kSpeculativeNumberLessThan:
1197 21083 : return machine()->Uint32LessThan();
1198 : case IrOpcode::kNumberLessThanOrEqual:
1199 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1200 1546 : return machine()->Uint32LessThanOrEqual();
1201 : case IrOpcode::kNumberClz32:
1202 34 : return machine()->Word32Clz();
1203 : case IrOpcode::kNumberImul:
1204 872 : return machine()->Int32Mul();
1205 : default:
1206 0 : UNREACHABLE();
1207 : }
1208 : }
1209 :
1210 138 : const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
1211 : IrOpcode::Value opcode) {
1212 138 : switch (opcode) {
1213 : case IrOpcode::kSpeculativeNumberDivide:
1214 94 : return simplified()->CheckedUint32Div();
1215 : case IrOpcode::kSpeculativeNumberModulus:
1216 44 : return simplified()->CheckedUint32Mod();
1217 : default:
1218 0 : UNREACHABLE();
1219 : }
1220 : }
1221 :
1222 175619 : const Operator* RepresentationChanger::Float64OperatorFor(
1223 : IrOpcode::Value opcode) {
1224 175619 : switch (opcode) {
1225 : case IrOpcode::kSpeculativeNumberAdd:
1226 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1227 : case IrOpcode::kNumberAdd:
1228 74487 : return machine()->Float64Add();
1229 : case IrOpcode::kSpeculativeNumberSubtract:
1230 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1231 : case IrOpcode::kNumberSubtract:
1232 2058 : return machine()->Float64Sub();
1233 : case IrOpcode::kSpeculativeNumberMultiply:
1234 : case IrOpcode::kNumberMultiply:
1235 13730 : return machine()->Float64Mul();
1236 : case IrOpcode::kSpeculativeNumberDivide:
1237 : case IrOpcode::kNumberDivide:
1238 16354 : return machine()->Float64Div();
1239 : case IrOpcode::kSpeculativeNumberModulus:
1240 : case IrOpcode::kNumberModulus:
1241 1852 : return machine()->Float64Mod();
1242 : case IrOpcode::kNumberEqual:
1243 : case IrOpcode::kSpeculativeNumberEqual:
1244 17238 : return machine()->Float64Equal();
1245 : case IrOpcode::kNumberLessThan:
1246 : case IrOpcode::kSpeculativeNumberLessThan:
1247 3899 : return machine()->Float64LessThan();
1248 : case IrOpcode::kNumberLessThanOrEqual:
1249 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1250 269 : return machine()->Float64LessThanOrEqual();
1251 : case IrOpcode::kNumberAbs:
1252 189 : return machine()->Float64Abs();
1253 : case IrOpcode::kNumberAcos:
1254 0 : return machine()->Float64Acos();
1255 : case IrOpcode::kNumberAcosh:
1256 0 : return machine()->Float64Acosh();
1257 : case IrOpcode::kNumberAsin:
1258 7 : return machine()->Float64Asin();
1259 : case IrOpcode::kNumberAsinh:
1260 0 : return machine()->Float64Asinh();
1261 : case IrOpcode::kNumberAtan:
1262 0 : return machine()->Float64Atan();
1263 : case IrOpcode::kNumberAtanh:
1264 0 : return machine()->Float64Atanh();
1265 : case IrOpcode::kNumberAtan2:
1266 0 : return machine()->Float64Atan2();
1267 : case IrOpcode::kNumberCbrt:
1268 0 : return machine()->Float64Cbrt();
1269 : case IrOpcode::kNumberCeil:
1270 6955 : return machine()->Float64RoundUp().placeholder();
1271 : case IrOpcode::kNumberCos:
1272 14 : return machine()->Float64Cos();
1273 : case IrOpcode::kNumberCosh:
1274 7 : return machine()->Float64Cosh();
1275 : case IrOpcode::kNumberExp:
1276 33 : return machine()->Float64Exp();
1277 : case IrOpcode::kNumberExpm1:
1278 14 : return machine()->Float64Expm1();
1279 : case IrOpcode::kNumberFloor:
1280 28153 : return machine()->Float64RoundDown().placeholder();
1281 : case IrOpcode::kNumberFround:
1282 1285 : return machine()->TruncateFloat64ToFloat32();
1283 : case IrOpcode::kNumberLog:
1284 163 : return machine()->Float64Log();
1285 : case IrOpcode::kNumberLog1p:
1286 0 : return machine()->Float64Log1p();
1287 : case IrOpcode::kNumberLog2:
1288 0 : return machine()->Float64Log2();
1289 : case IrOpcode::kNumberLog10:
1290 0 : return machine()->Float64Log10();
1291 : case IrOpcode::kNumberMax:
1292 72 : return machine()->Float64Max();
1293 : case IrOpcode::kNumberMin:
1294 149 : return machine()->Float64Min();
1295 : case IrOpcode::kNumberPow:
1296 910 : return machine()->Float64Pow();
1297 : case IrOpcode::kNumberSin:
1298 33 : return machine()->Float64Sin();
1299 : case IrOpcode::kNumberSinh:
1300 7 : return machine()->Float64Sinh();
1301 : case IrOpcode::kNumberSqrt:
1302 51 : return machine()->Float64Sqrt();
1303 : case IrOpcode::kNumberTan:
1304 28 : return machine()->Float64Tan();
1305 : case IrOpcode::kNumberTanh:
1306 7 : return machine()->Float64Tanh();
1307 : case IrOpcode::kNumberTrunc:
1308 6914 : return machine()->Float64RoundTruncate().placeholder();
1309 : case IrOpcode::kNumberSilenceNaN:
1310 741 : return machine()->Float64SilenceNaN();
1311 : default:
1312 0 : UNREACHABLE();
1313 : }
1314 : }
1315 :
1316 35 : Node* RepresentationChanger::TypeError(Node* node,
1317 : MachineRepresentation output_rep,
1318 : Type output_type,
1319 : MachineRepresentation use) {
1320 35 : type_error_ = true;
1321 35 : if (!testing_type_errors_) {
1322 0 : std::ostringstream out_str;
1323 0 : out_str << output_rep << " (";
1324 0 : output_type.PrintTo(out_str);
1325 0 : out_str << ")";
1326 :
1327 0 : std::ostringstream use_str;
1328 0 : use_str << use;
1329 :
1330 : FATAL(
1331 : "RepresentationChangerError: node #%d:%s of "
1332 : "%s cannot be changed to %s",
1333 : node->id(), node->op()->mnemonic(), out_str.str().c_str(),
1334 0 : use_str.str().c_str());
1335 : }
1336 35 : return node;
1337 : }
1338 :
1339 0 : Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
1340 0 : return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
1341 : }
1342 :
1343 426 : Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
1344 852 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
1345 : }
1346 :
1347 23 : Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
1348 46 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
1349 : }
1350 :
1351 530 : Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
1352 1060 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
1353 : }
1354 :
1355 14 : Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) {
1356 28 : return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
1357 : }
1358 :
1359 1228 : Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
1360 1228 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
1361 1228 : node);
1362 : }
1363 :
1364 0 : Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
1365 0 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
1366 0 : node);
1367 : }
1368 :
1369 0 : Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) {
1370 0 : return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
1371 : }
1372 :
1373 27 : Node* RepresentationChanger::InsertTruncateInt64ToInt32(Node* node) {
1374 54 : return jsgraph()->graph()->NewNode(machine()->TruncateInt64ToInt32(), node);
1375 : }
1376 :
1377 : } // namespace compiler
1378 : } // namespace internal
1379 120216 : } // namespace v8
|