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 88835301 : Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
67 : TruncationKind rep2) {
68 88835301 : if (LessGeneral(rep1, rep2)) return rep2;
69 10147192 : if (LessGeneral(rep2, rep1)) return rep1;
70 : // Handle the generalization of float64-representable values.
71 28 : if (LessGeneral(rep1, TruncationKind::kFloat64) &&
72 14 : LessGeneral(rep2, TruncationKind::kFloat64)) {
73 : return TruncationKind::kFloat64;
74 : }
75 : // Handle the generalization of any-representable values.
76 28 : if (LessGeneral(rep1, TruncationKind::kAny) &&
77 14 : 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 88835279 : IdentifyZeros Truncation::GeneralizeIdentifyZeros(IdentifyZeros i1,
87 : IdentifyZeros i2) {
88 88835279 : if (i1 == i2) {
89 62288541 : return i1;
90 : } else {
91 : return kDistinguishZeros;
92 : }
93 : }
94 :
95 : // static
96 101421919 : bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
97 101421919 : switch (rep1) {
98 : case TruncationKind::kNone:
99 : return true;
100 : case TruncationKind::kBool:
101 658816 : return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
102 : case TruncationKind::kWord32:
103 : return rep2 == TruncationKind::kWord32 ||
104 1009346 : rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
105 : case TruncationKind::kFloat64:
106 585231 : return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
107 : case TruncationKind::kAny:
108 52871144 : return rep2 == TruncationKind::kAny;
109 : }
110 0 : UNREACHABLE();
111 : }
112 :
113 : // static
114 0 : bool Truncation::LessGeneralIdentifyZeros(IdentifyZeros i1, IdentifyZeros i2) {
115 7 : return i1 == i2 || i1 == kIdentifyZeros;
116 : }
117 :
118 : namespace {
119 :
120 : bool IsWord(MachineRepresentation rep) {
121 : return rep == MachineRepresentation::kWord8 ||
122 17113132 : rep == MachineRepresentation::kWord16 ||
123 : rep == MachineRepresentation::kWord32;
124 : }
125 :
126 : } // namespace
127 :
128 456585 : RepresentationChanger::RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
129 456585 : : cache_(TypeCache::Get()),
130 : jsgraph_(jsgraph),
131 : isolate_(isolate),
132 : testing_type_errors_(false),
133 456608 : 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 15357406 : Node* RepresentationChanger::GetRepresentationFor(
140 : Node* node, MachineRepresentation output_rep, Type output_type,
141 : Node* use_node, UseInfo use_info) {
142 15357865 : 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 15357406 : if (use_info.type_check() == TypeCheckKind::kNone ||
150 : output_rep != MachineRepresentation::kWord32) {
151 15262596 : if (use_info.representation() == output_rep) {
152 : // Representations are the same. That's a no-op.
153 : return node;
154 : }
155 16736046 : 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 15323041 : 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 69308 : 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 36592 : 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 12882539 : 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 1382 : use_info.truncation());
183 : case MachineRepresentation::kFloat64:
184 : return GetFloat64RepresentationFor(node, output_rep, output_type,
185 266720 : use_node, use_info);
186 : case MachineRepresentation::kBit:
187 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
188 290563 : 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 1577304 : 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 198633 : use_info);
199 : case MachineRepresentation::kSimd128:
200 : case MachineRepresentation::kNone:
201 : return node;
202 : }
203 0 : UNREACHABLE();
204 : }
205 :
206 69308 : Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
207 69308 : Node* node, MachineRepresentation output_rep, Type output_type,
208 0 : Node* use_node, UseInfo use_info) {
209 : // Eagerly fold representation changes for constants.
210 69308 : switch (node->opcode()) {
211 : case IrOpcode::kNumberConstant:
212 7 : if (output_type.Is(Type::SignedSmall())) {
213 : return node;
214 : }
215 : break;
216 : default:
217 : break;
218 : }
219 : // Select the correct X -> Tagged operator.
220 : const Operator* op;
221 69308 : if (output_type.Is(Type::None())) {
222 : // This is an impossible value; it should not be used at runtime.
223 : return jsgraph()->graph()->NewNode(
224 : jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedSigned),
225 0 : node);
226 69308 : } else if (IsWord(output_rep)) {
227 41891 : if (output_type.Is(Type::Signed31())) {
228 24801 : op = simplified()->ChangeInt31ToTaggedSigned();
229 17090 : } else if (output_type.Is(Type::Signed32())) {
230 : if (SmiValuesAre32Bits()) {
231 17076 : op = simplified()->ChangeInt32ToTagged();
232 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
233 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
234 : } else {
235 : return TypeError(node, output_rep, output_type,
236 : MachineRepresentation::kTaggedSigned);
237 : }
238 28 : } else if (output_type.Is(Type::Unsigned32()) &&
239 14 : use_info.type_check() == TypeCheckKind::kSignedSmall) {
240 14 : op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
241 : } else {
242 : return TypeError(node, output_rep, output_type,
243 0 : MachineRepresentation::kTaggedSigned);
244 : }
245 27417 : } else if (output_rep == MachineRepresentation::kWord64) {
246 1745 : if (output_type.Is(Type::Signed31())) {
247 : // int64 -> int32 -> tagged signed
248 5 : node = InsertTruncateInt64ToInt32(node);
249 5 : op = simplified()->ChangeInt31ToTaggedSigned();
250 1740 : } else if (output_type.Is(Type::Signed32()) && SmiValuesAre32Bits()) {
251 : // int64 -> int32 -> tagged signed
252 5 : node = InsertTruncateInt64ToInt32(node);
253 5 : op = simplified()->ChangeInt32ToTagged();
254 1735 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
255 3470 : if (output_type.Is(cache_->kPositiveSafeInteger)) {
256 5 : op = simplified()->CheckedUint64ToTaggedSigned(use_info.feedback());
257 3460 : } else if (output_type.Is(cache_->kSafeInteger)) {
258 1730 : op = simplified()->CheckedInt64ToTaggedSigned(use_info.feedback());
259 : } else {
260 : return TypeError(node, output_rep, output_type,
261 0 : MachineRepresentation::kTaggedSigned);
262 : }
263 : } else {
264 : return TypeError(node, output_rep, output_type,
265 0 : MachineRepresentation::kTaggedSigned);
266 : }
267 25672 : } else if (output_rep == MachineRepresentation::kFloat64) {
268 88 : if (output_type.Is(Type::Signed31())) {
269 : // float64 -> int32 -> tagged signed
270 0 : node = InsertChangeFloat64ToInt32(node);
271 0 : op = simplified()->ChangeInt31ToTaggedSigned();
272 88 : } else if (output_type.Is(Type::Signed32())) {
273 : // float64 -> int32 -> tagged signed
274 0 : node = InsertChangeFloat64ToInt32(node);
275 : if (SmiValuesAre32Bits()) {
276 0 : op = simplified()->ChangeInt32ToTagged();
277 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
278 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
279 : } else {
280 : return TypeError(node, output_rep, output_type,
281 : MachineRepresentation::kTaggedSigned);
282 : }
283 88 : } else if (output_type.Is(Type::Unsigned32()) &&
284 0 : use_info.type_check() == TypeCheckKind::kSignedSmall) {
285 : // float64 -> uint32 -> tagged signed
286 0 : node = InsertChangeFloat64ToUint32(node);
287 0 : op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
288 88 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
289 : op = simplified()->CheckedFloat64ToInt32(
290 88 : output_type.Maybe(Type::MinusZero())
291 : ? CheckForMinusZeroMode::kCheckForMinusZero
292 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
293 176 : use_info.feedback());
294 88 : node = InsertConversion(node, op, use_node);
295 : if (SmiValuesAre32Bits()) {
296 88 : op = simplified()->ChangeInt32ToTagged();
297 : } else {
298 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
299 : }
300 : } else {
301 : return TypeError(node, output_rep, output_type,
302 0 : MachineRepresentation::kTaggedSigned);
303 : }
304 25584 : } else if (output_rep == MachineRepresentation::kFloat32) {
305 0 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
306 0 : op = machine()->ChangeFloat32ToFloat64();
307 0 : node = InsertConversion(node, op, use_node);
308 : op = simplified()->CheckedFloat64ToInt32(
309 0 : output_type.Maybe(Type::MinusZero())
310 : ? CheckForMinusZeroMode::kCheckForMinusZero
311 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
312 0 : use_info.feedback());
313 0 : node = InsertConversion(node, op, use_node);
314 : if (SmiValuesAre32Bits()) {
315 0 : op = simplified()->ChangeInt32ToTagged();
316 : } else {
317 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
318 : }
319 : } else {
320 : return TypeError(node, output_rep, output_type,
321 0 : MachineRepresentation::kTaggedSigned);
322 : }
323 25584 : } else if (CanBeTaggedPointer(output_rep)) {
324 25584 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
325 25569 : op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
326 15 : } else if (output_type.Is(Type::SignedSmall())) {
327 15 : op = simplified()->ChangeTaggedToTaggedSigned();
328 : } else {
329 : return TypeError(node, output_rep, output_type,
330 0 : MachineRepresentation::kTaggedSigned);
331 : }
332 0 : } else if (output_rep == MachineRepresentation::kBit) {
333 0 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
334 : // TODO(turbofan): Consider adding a Bailout operator that just deopts.
335 : // Also use that for MachineRepresentation::kPointer case above.
336 0 : node = InsertChangeBitToTagged(node);
337 0 : op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
338 : } else {
339 : return TypeError(node, output_rep, output_type,
340 0 : MachineRepresentation::kTaggedSigned);
341 : }
342 : } else {
343 : return TypeError(node, output_rep, output_type,
344 0 : MachineRepresentation::kTaggedSigned);
345 : }
346 69308 : return InsertConversion(node, op, use_node);
347 : }
348 :
349 36592 : Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
350 36592 : Node* node, MachineRepresentation output_rep, Type output_type,
351 5 : Node* use_node, UseInfo use_info) {
352 : // Eagerly fold representation changes for constants.
353 36592 : switch (node->opcode()) {
354 : case IrOpcode::kHeapConstant:
355 : case IrOpcode::kDelayedStringConstant:
356 : return node; // No change necessary.
357 : case IrOpcode::kInt32Constant:
358 : case IrOpcode::kFloat64Constant:
359 : case IrOpcode::kFloat32Constant:
360 0 : UNREACHABLE();
361 : default:
362 : break;
363 : }
364 : // Select the correct X -> TaggedPointer operator.
365 : Operator const* op;
366 36592 : if (output_type.Is(Type::None())) {
367 : // This is an impossible value; it should not be used at runtime.
368 : return jsgraph()->graph()->NewNode(
369 : jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
370 0 : node);
371 36592 : } else if (output_rep == MachineRepresentation::kBit) {
372 0 : if (output_type.Is(Type::Boolean())) {
373 0 : op = simplified()->ChangeBitToTagged();
374 : } else {
375 : return TypeError(node, output_rep, output_type,
376 0 : MachineRepresentation::kTagged);
377 : }
378 36592 : } else if (IsWord(output_rep)) {
379 14 : if (output_type.Is(Type::Unsigned32())) {
380 : // uint32 -> float64 -> tagged
381 0 : node = InsertChangeUint32ToFloat64(node);
382 14 : } else if (output_type.Is(Type::Signed32())) {
383 : // int32 -> float64 -> tagged
384 14 : node = InsertChangeInt32ToFloat64(node);
385 : } else {
386 : return TypeError(node, output_rep, output_type,
387 0 : MachineRepresentation::kTaggedPointer);
388 : }
389 14 : op = simplified()->ChangeFloat64ToTaggedPointer();
390 36578 : } else if (output_rep == MachineRepresentation::kWord64) {
391 10 : if (output_type.Is(cache_->kSafeInteger)) {
392 : // int64 -> float64 -> tagged pointer
393 5 : op = machine()->ChangeInt64ToFloat64();
394 5 : node = jsgraph()->graph()->NewNode(op, node);
395 5 : op = simplified()->ChangeFloat64ToTaggedPointer();
396 : } else {
397 : return TypeError(node, output_rep, output_type,
398 0 : MachineRepresentation::kTaggedPointer);
399 : }
400 36573 : } else if (output_rep == MachineRepresentation::kFloat32) {
401 0 : if (output_type.Is(Type::Number())) {
402 : // float32 -> float64 -> tagged
403 0 : node = InsertChangeFloat32ToFloat64(node);
404 0 : op = simplified()->ChangeFloat64ToTaggedPointer();
405 : } else {
406 : return TypeError(node, output_rep, output_type,
407 0 : MachineRepresentation::kTaggedPointer);
408 : }
409 36573 : } else if (output_rep == MachineRepresentation::kFloat64) {
410 77 : if (output_type.Is(Type::Number())) {
411 : // float64 -> tagged
412 77 : op = simplified()->ChangeFloat64ToTaggedPointer();
413 : } else {
414 : return TypeError(node, output_rep, output_type,
415 0 : MachineRepresentation::kTaggedPointer);
416 : }
417 72992 : } else if (CanBeTaggedSigned(output_rep) &&
418 36496 : use_info.type_check() == TypeCheckKind::kHeapObject) {
419 36496 : if (!output_type.Maybe(Type::SignedSmall())) {
420 : return node;
421 : }
422 : // TODO(turbofan): Consider adding a Bailout operator that just deopts
423 : // for TaggedSigned output representation.
424 36122 : op = simplified()->CheckedTaggedToTaggedPointer(use_info.feedback());
425 : } else {
426 : return TypeError(node, output_rep, output_type,
427 0 : MachineRepresentation::kTaggedPointer);
428 : }
429 36218 : return InsertConversion(node, op, use_node);
430 : }
431 :
432 12882506 : Node* RepresentationChanger::GetTaggedRepresentationFor(
433 12882506 : Node* node, MachineRepresentation output_rep, Type output_type,
434 131270 : Truncation truncation) {
435 : // Eagerly fold representation changes for constants.
436 12882506 : switch (node->opcode()) {
437 : case IrOpcode::kNumberConstant:
438 : case IrOpcode::kHeapConstant:
439 : case IrOpcode::kDelayedStringConstant:
440 : return node; // No change necessary.
441 : case IrOpcode::kInt32Constant:
442 : case IrOpcode::kFloat64Constant:
443 : case IrOpcode::kFloat32Constant:
444 0 : UNREACHABLE();
445 : break;
446 : default:
447 : break;
448 : }
449 2424585 : if (output_rep == MachineRepresentation::kTaggedSigned ||
450 : output_rep == MachineRepresentation::kTaggedPointer) {
451 : // this is a no-op.
452 : return node;
453 : }
454 : // Select the correct X -> Tagged operator.
455 : const Operator* op;
456 131020 : if (output_type.Is(Type::None())) {
457 : // This is an impossible value; it should not be used at runtime.
458 : return jsgraph()->graph()->NewNode(
459 759 : jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
460 130767 : } else if (output_rep == MachineRepresentation::kBit) {
461 17459 : if (output_type.Is(Type::Boolean())) {
462 17459 : op = simplified()->ChangeBitToTagged();
463 : } else {
464 : return TypeError(node, output_rep, output_type,
465 0 : MachineRepresentation::kTagged);
466 : }
467 113308 : } else if (IsWord(output_rep)) {
468 39441 : if (output_type.Is(Type::Signed31())) {
469 17636 : op = simplified()->ChangeInt31ToTaggedSigned();
470 21805 : } else if (output_type.Is(Type::Signed32())) {
471 20836 : op = simplified()->ChangeInt32ToTagged();
472 976 : } else if (output_type.Is(Type::Unsigned32()) ||
473 7 : truncation.IsUsedAsWord32()) {
474 : // Either the output is uint32 or the uses only care about the
475 : // low 32 bits (so we can pick uint32 safely).
476 969 : op = simplified()->ChangeUint32ToTagged();
477 : } else {
478 : return TypeError(node, output_rep, output_type,
479 0 : MachineRepresentation::kTagged);
480 : }
481 73867 : } else if (output_rep == MachineRepresentation::kWord64) {
482 472 : if (output_type.Is(Type::Signed31())) {
483 : // int64 -> int32 -> tagged signed
484 5 : node = InsertTruncateInt64ToInt32(node);
485 5 : op = simplified()->ChangeInt31ToTaggedSigned();
486 467 : } else if (output_type.Is(Type::Signed32())) {
487 : // int64 -> int32 -> tagged
488 5 : node = InsertTruncateInt64ToInt32(node);
489 5 : op = simplified()->ChangeInt32ToTagged();
490 462 : } else if (output_type.Is(Type::Unsigned32())) {
491 : // int64 -> uint32 -> tagged
492 12 : node = InsertTruncateInt64ToInt32(node);
493 12 : op = simplified()->ChangeUint32ToTagged();
494 900 : } else if (output_type.Is(cache_->kPositiveSafeInteger)) {
495 : // uint64 -> tagged
496 89 : op = simplified()->ChangeUint64ToTagged();
497 722 : } else if (output_type.Is(cache_->kSafeInteger)) {
498 : // int64 -> tagged
499 356 : op = simplified()->ChangeInt64ToTagged();
500 : } else {
501 : return TypeError(node, output_rep, output_type,
502 5 : MachineRepresentation::kTagged);
503 : }
504 73395 : } else if (output_rep ==
505 : MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
506 368 : node = InsertChangeFloat32ToFloat64(node);
507 : op = simplified()->ChangeFloat64ToTagged(
508 368 : output_type.Maybe(Type::MinusZero())
509 : ? CheckForMinusZeroMode::kCheckForMinusZero
510 736 : : CheckForMinusZeroMode::kDontCheckForMinusZero);
511 73027 : } else if (output_rep == MachineRepresentation::kFloat64) {
512 73028 : if (output_type.Is(Type::Signed31())) { // float64 -> int32 -> tagged
513 31 : node = InsertChangeFloat64ToInt32(node);
514 31 : op = simplified()->ChangeInt31ToTaggedSigned();
515 72998 : } else if (output_type.Is(
516 : Type::Signed32())) { // float64 -> int32 -> tagged
517 781 : node = InsertChangeFloat64ToInt32(node);
518 781 : op = simplified()->ChangeInt32ToTagged();
519 72218 : } else if (output_type.Is(
520 : Type::Unsigned32())) { // float64 -> uint32 -> tagged
521 23 : node = InsertChangeFloat64ToUint32(node);
522 23 : op = simplified()->ChangeUint32ToTagged();
523 72196 : } else if (output_type.Is(Type::Number())) {
524 : op = simplified()->ChangeFloat64ToTagged(
525 72196 : output_type.Maybe(Type::MinusZero())
526 : ? CheckForMinusZeroMode::kCheckForMinusZero
527 144392 : : CheckForMinusZeroMode::kDontCheckForMinusZero);
528 : } else {
529 : return TypeError(node, output_rep, output_type,
530 0 : MachineRepresentation::kTagged);
531 : }
532 : } else {
533 : return TypeError(node, output_rep, output_type,
534 0 : MachineRepresentation::kTagged);
535 : }
536 261528 : return jsgraph()->graph()->NewNode(op, node);
537 : }
538 :
539 1382 : Node* RepresentationChanger::GetFloat32RepresentationFor(
540 1382 : Node* node, MachineRepresentation output_rep, Type output_type,
541 1413 : Truncation truncation) {
542 : // Eagerly fold representation changes for constants.
543 1382 : switch (node->opcode()) {
544 : case IrOpcode::kNumberConstant:
545 : return jsgraph()->Float32Constant(
546 2268 : DoubleToFloat32(OpParameter<double>(node->op())));
547 : case IrOpcode::kInt32Constant:
548 : case IrOpcode::kFloat64Constant:
549 : case IrOpcode::kFloat32Constant:
550 0 : UNREACHABLE();
551 : break;
552 : default:
553 : break;
554 : }
555 : // Select the correct X -> Float32 operator.
556 : const Operator* op = nullptr;
557 248 : if (output_type.Is(Type::None())) {
558 : // This is an impossible value; it should not be used at runtime.
559 : return jsgraph()->graph()->NewNode(
560 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
561 248 : } else if (IsWord(output_rep)) {
562 31 : if (output_type.Is(Type::Signed32())) {
563 : // int32 -> float64 -> float32
564 26 : op = machine()->ChangeInt32ToFloat64();
565 26 : node = jsgraph()->graph()->NewNode(op, node);
566 26 : op = machine()->TruncateFloat64ToFloat32();
567 5 : } else if (output_type.Is(Type::Unsigned32()) ||
568 0 : truncation.IsUsedAsWord32()) {
569 : // Either the output is uint32 or the uses only care about the
570 : // low 32 bits (so we can pick uint32 safely).
571 :
572 : // uint32 -> float64 -> float32
573 5 : op = machine()->ChangeUint32ToFloat64();
574 5 : node = jsgraph()->graph()->NewNode(op, node);
575 5 : op = machine()->TruncateFloat64ToFloat32();
576 : }
577 217 : } else if (IsAnyTagged(output_rep)) {
578 5 : if (output_type.Is(Type::NumberOrOddball())) {
579 : // tagged -> float64 -> float32
580 5 : if (output_type.Is(Type::Number())) {
581 5 : op = simplified()->ChangeTaggedToFloat64();
582 : } else {
583 0 : op = simplified()->TruncateTaggedToFloat64();
584 : }
585 5 : node = jsgraph()->graph()->NewNode(op, node);
586 5 : op = machine()->TruncateFloat64ToFloat32();
587 : }
588 212 : } else if (output_rep == MachineRepresentation::kFloat64) {
589 197 : op = machine()->TruncateFloat64ToFloat32();
590 15 : } else if (output_rep == MachineRepresentation::kWord64) {
591 10 : if (output_type.Is(cache_->kSafeInteger)) {
592 : // int64 -> float64 -> float32
593 5 : op = machine()->ChangeInt64ToFloat64();
594 5 : node = jsgraph()->graph()->NewNode(op, node);
595 5 : op = machine()->TruncateFloat64ToFloat32();
596 : }
597 : }
598 248 : if (op == nullptr) {
599 : return TypeError(node, output_rep, output_type,
600 10 : MachineRepresentation::kFloat32);
601 : }
602 476 : return jsgraph()->graph()->NewNode(op, node);
603 : }
604 :
605 266718 : Node* RepresentationChanger::GetFloat64RepresentationFor(
606 : Node* node, MachineRepresentation output_rep, Type output_type,
607 148359 : Node* use_node, UseInfo use_info) {
608 : NumberMatcher m(node);
609 266718 : if (m.HasValue()) {
610 148112 : switch (use_info.type_check()) {
611 : case TypeCheckKind::kNone:
612 : case TypeCheckKind::kNumber:
613 : case TypeCheckKind::kNumberOrOddball:
614 148112 : return jsgraph()->Float64Constant(m.Value());
615 : case TypeCheckKind::kHeapObject:
616 : case TypeCheckKind::kSigned32:
617 : case TypeCheckKind::kSigned64:
618 : case TypeCheckKind::kSignedSmall:
619 : break;
620 : }
621 : }
622 : // Select the correct X -> Float64 operator.
623 : const Operator* op = nullptr;
624 118606 : if (output_type.Is(Type::None())) {
625 : // This is an impossible value; it should not be used at runtime.
626 : return jsgraph()->graph()->NewNode(
627 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
628 118606 : } else if (IsWord(output_rep)) {
629 79548 : if (output_type.Is(Type::Signed32()) ||
630 15 : (output_type.Is(Type::Signed32OrMinusZero()) &&
631 : use_info.truncation().IdentifiesZeroAndMinusZero())) {
632 38886 : op = machine()->ChangeInt32ToFloat64();
633 587 : } else if (output_type.Is(Type::Unsigned32()) ||
634 : use_info.truncation().IsUsedAsWord32()) {
635 : // Either the output is uint32 or the uses only care about the
636 : // low 32 bits (so we can pick uint32 safely).
637 587 : op = machine()->ChangeUint32ToFloat64();
638 : }
639 79131 : } else if (output_rep == MachineRepresentation::kBit) {
640 0 : op = machine()->ChangeUint32ToFloat64();
641 158262 : } else if (output_rep == MachineRepresentation::kTagged ||
642 84073 : output_rep == MachineRepresentation::kTaggedSigned ||
643 : output_rep == MachineRepresentation::kTaggedPointer) {
644 76358 : if (output_type.Is(Type::Undefined())) {
645 : return jsgraph()->Float64Constant(
646 247 : std::numeric_limits<double>::quiet_NaN());
647 :
648 76111 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
649 1555 : node = InsertChangeTaggedSignedToInt32(node);
650 1555 : op = machine()->ChangeInt32ToFloat64();
651 74556 : } else if (output_type.Is(Type::Number())) {
652 11034 : op = simplified()->ChangeTaggedToFloat64();
653 63522 : } else if (output_type.Is(Type::NumberOrOddball())) {
654 : // TODO(jarin) Here we should check that truncation is Number.
655 1512 : op = simplified()->TruncateTaggedToFloat64();
656 124020 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
657 53463 : (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
658 53463 : !output_type.Maybe(Type::BooleanOrNullOrNumber()))) {
659 : op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber,
660 8988 : use_info.feedback());
661 53022 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
662 : op = simplified()->CheckedTaggedToFloat64(
663 53022 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
664 : }
665 2773 : } else if (output_rep == MachineRepresentation::kFloat32) {
666 2243 : op = machine()->ChangeFloat32ToFloat64();
667 530 : } else if (output_rep == MachineRepresentation::kWord64) {
668 1060 : if (output_type.Is(cache_->kSafeInteger)) {
669 530 : op = machine()->ChangeInt64ToFloat64();
670 : }
671 : }
672 118356 : if (op == nullptr) {
673 : return TypeError(node, output_rep, output_type,
674 0 : MachineRepresentation::kFloat64);
675 : }
676 118356 : return InsertConversion(node, op, use_node);
677 : }
678 :
679 2507121 : Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
680 2507121 : return jsgraph()->Int32Constant(DoubleToInt32(value));
681 : }
682 :
683 7 : Node* RepresentationChanger::InsertUnconditionalDeopt(Node* node,
684 28 : DeoptimizeReason reason) {
685 7 : Node* effect = NodeProperties::GetEffectInput(node);
686 7 : Node* control = NodeProperties::GetControlInput(node);
687 : effect =
688 : jsgraph()->graph()->NewNode(simplified()->CheckIf(reason),
689 28 : jsgraph()->Int32Constant(0), effect, control);
690 : Node* unreachable = effect = jsgraph()->graph()->NewNode(
691 14 : jsgraph()->common()->Unreachable(), effect, control);
692 7 : NodeProperties::ReplaceEffectInput(node, effect);
693 7 : return unreachable;
694 : }
695 :
696 1577310 : Node* RepresentationChanger::GetWord32RepresentationFor(
697 1577310 : Node* node, MachineRepresentation output_rep, Type output_type,
698 60 : Node* use_node, UseInfo use_info) {
699 : // Eagerly fold representation changes for constants.
700 1577310 : switch (node->opcode()) {
701 : case IrOpcode::kInt32Constant:
702 : case IrOpcode::kInt64Constant:
703 : case IrOpcode::kFloat32Constant:
704 : case IrOpcode::kFloat64Constant:
705 0 : UNREACHABLE();
706 : break;
707 : case IrOpcode::kNumberConstant: {
708 1253713 : double const fv = OpParameter<double>(node->op());
709 2507426 : if (use_info.type_check() == TypeCheckKind::kNone ||
710 1254 : ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
711 1186 : use_info.type_check() == TypeCheckKind::kSigned32 ||
712 491 : use_info.type_check() == TypeCheckKind::kNumber ||
713 85310 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) &&
714 : IsInt32Double(fv))) {
715 1253560 : return MakeTruncatedInt32Constant(fv);
716 : }
717 : break;
718 : }
719 : default:
720 : break;
721 : }
722 :
723 : // Select the correct X -> Word32 operator.
724 : const Operator* op = nullptr;
725 323742 : if (output_type.Is(Type::None())) {
726 : // This is an impossible value; it should not be used at runtime.
727 : return jsgraph()->graph()->NewNode(
728 69 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
729 323719 : } else if (output_rep == MachineRepresentation::kBit) {
730 68 : CHECK(output_type.Is(Type::Boolean()));
731 68 : if (use_info.truncation().IsUsedAsWord32()) {
732 : return node;
733 : } else {
734 7 : CHECK(Truncation::Any(kIdentifyZeros)
735 : .IsLessGeneralThan(use_info.truncation()));
736 7 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
737 : Node* unreachable =
738 7 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
739 : return jsgraph()->graph()->NewNode(
740 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32),
741 21 : unreachable);
742 : }
743 323651 : } else if (output_rep == MachineRepresentation::kFloat64) {
744 11839 : if (output_type.Is(Type::Signed32())) {
745 814 : op = machine()->ChangeFloat64ToInt32();
746 11025 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
747 : use_info.type_check() == TypeCheckKind::kSigned32) {
748 : op = simplified()->CheckedFloat64ToInt32(
749 2420 : output_type.Maybe(Type::MinusZero())
750 : ? use_info.minus_zero_check()
751 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
752 4840 : use_info.feedback());
753 8605 : } else if (output_type.Is(Type::Unsigned32())) {
754 12 : op = machine()->ChangeFloat64ToUint32();
755 8593 : } else if (use_info.truncation().IsUsedAsWord32()) {
756 8593 : op = machine()->TruncateFloat64ToWord32();
757 : } else {
758 : return TypeError(node, output_rep, output_type,
759 0 : MachineRepresentation::kWord32);
760 : }
761 311812 : } else if (output_rep == MachineRepresentation::kFloat32) {
762 15 : node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
763 15 : if (output_type.Is(Type::Signed32())) {
764 5 : op = machine()->ChangeFloat64ToInt32();
765 10 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
766 : use_info.type_check() == TypeCheckKind::kSigned32) {
767 : op = simplified()->CheckedFloat64ToInt32(
768 0 : output_type.Maybe(Type::MinusZero())
769 : ? use_info.minus_zero_check()
770 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
771 0 : use_info.feedback());
772 10 : } else if (output_type.Is(Type::Unsigned32())) {
773 5 : op = machine()->ChangeFloat64ToUint32();
774 5 : } else if (use_info.truncation().IsUsedAsWord32()) {
775 5 : op = machine()->TruncateFloat64ToWord32();
776 : } else {
777 : return TypeError(node, output_rep, output_type,
778 0 : MachineRepresentation::kWord32);
779 : }
780 311797 : } else if (IsAnyTagged(output_rep)) {
781 316078 : if (output_rep == MachineRepresentation::kTaggedSigned &&
782 : output_type.Is(Type::SignedSmall())) {
783 82497 : op = simplified()->ChangeTaggedSignedToInt32();
784 151079 : } else if (output_type.Is(Type::Signed32())) {
785 2425 : op = simplified()->ChangeTaggedToInt32();
786 148654 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
787 143177 : op = simplified()->CheckedTaggedSignedToInt32(use_info.feedback());
788 5477 : } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
789 : op = simplified()->CheckedTaggedToInt32(
790 2705 : output_type.Maybe(Type::MinusZero())
791 : ? use_info.minus_zero_check()
792 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
793 5410 : use_info.feedback());
794 2772 : } else if (output_type.Is(Type::Unsigned32())) {
795 690 : op = simplified()->ChangeTaggedToUint32();
796 2082 : } else if (use_info.truncation().IsUsedAsWord32()) {
797 2082 : if (output_type.Is(Type::NumberOrOddball())) {
798 529 : op = simplified()->TruncateTaggedToWord32();
799 1553 : } else if (use_info.type_check() == TypeCheckKind::kNumber) {
800 : op = simplified()->CheckedTruncateTaggedToWord32(
801 865 : CheckTaggedInputMode::kNumber, use_info.feedback());
802 688 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
803 : op = simplified()->CheckedTruncateTaggedToWord32(
804 688 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
805 : } else {
806 : return TypeError(node, output_rep, output_type,
807 0 : MachineRepresentation::kWord32);
808 : }
809 : } else {
810 : return TypeError(node, output_rep, output_type,
811 0 : MachineRepresentation::kWord32);
812 : }
813 78216 : } else if (output_rep == MachineRepresentation::kWord32) {
814 : // Only the checked case should get here, the non-checked case is
815 : // handled in GetRepresentationFor.
816 77919 : if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
817 : use_info.type_check() == TypeCheckKind::kSigned32) {
818 : bool indentify_zeros = use_info.truncation().IdentifiesZeroAndMinusZero();
819 155766 : if (output_type.Is(Type::Signed32()) ||
820 133 : (indentify_zeros && output_type.Is(Type::Signed32OrMinusZero()))) {
821 : return node;
822 348 : } else if (output_type.Is(Type::Unsigned32()) ||
823 0 : (indentify_zeros &&
824 : output_type.Is(Type::Unsigned32OrMinusZero()))) {
825 174 : op = simplified()->CheckedUint32ToInt32(use_info.feedback());
826 : } else {
827 : return TypeError(node, output_rep, output_type,
828 0 : MachineRepresentation::kWord32);
829 : }
830 36 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
831 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
832 : return node;
833 : }
834 297 : } else if (output_rep == MachineRepresentation::kWord8 ||
835 : output_rep == MachineRepresentation::kWord16) {
836 : DCHECK_EQ(MachineRepresentation::kWord32, use_info.representation());
837 : DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall ||
838 : use_info.type_check() == TypeCheckKind::kSigned32);
839 : return node;
840 297 : } else if (output_rep == MachineRepresentation::kWord64) {
841 566 : if (output_type.Is(Type::Signed32()) ||
842 : output_type.Is(Type::Unsigned32())) {
843 44 : op = machine()->TruncateInt64ToInt32();
844 754 : } else if (output_type.Is(cache_->kSafeInteger) &&
845 : use_info.truncation().IsUsedAsWord32()) {
846 231 : op = machine()->TruncateInt64ToInt32();
847 22 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
848 : use_info.type_check() == TypeCheckKind::kSigned32) {
849 34 : if (output_type.Is(cache_->kPositiveSafeInteger)) {
850 5 : op = simplified()->CheckedUint64ToInt32(use_info.feedback());
851 24 : } else if (output_type.Is(cache_->kSafeInteger)) {
852 12 : op = simplified()->CheckedInt64ToInt32(use_info.feedback());
853 : } else {
854 : return TypeError(node, output_rep, output_type,
855 0 : MachineRepresentation::kWord32);
856 : }
857 : } else {
858 : return TypeError(node, output_rep, output_type,
859 5 : MachineRepresentation::kWord32);
860 : }
861 : }
862 :
863 245898 : if (op == nullptr) {
864 : return TypeError(node, output_rep, output_type,
865 0 : MachineRepresentation::kWord32);
866 : }
867 245898 : return InsertConversion(node, op, use_node);
868 : }
869 :
870 508863 : Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
871 508852 : Node* use_node) {
872 508863 : if (op->ControlInputCount() > 0) {
873 : // If the operator can deoptimize (which means it has control
874 : // input), we need to connect it to the effect and control chains.
875 275690 : Node* effect = NodeProperties::GetEffectInput(use_node);
876 275682 : Node* control = NodeProperties::GetControlInput(use_node);
877 275679 : Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
878 275684 : NodeProperties::ReplaceEffectInput(use_node, conversion);
879 275688 : return conversion;
880 : }
881 466340 : return jsgraph()->graph()->NewNode(op, node);
882 : }
883 :
884 290562 : Node* RepresentationChanger::GetBitRepresentationFor(
885 581342 : Node* node, MachineRepresentation output_rep, Type output_type) {
886 : // Eagerly fold representation changes for constants.
887 290562 : switch (node->opcode()) {
888 : case IrOpcode::kHeapConstant: {
889 : HeapObjectMatcher m(node);
890 118653 : if (m.Is(factory()->false_value())) {
891 196265 : return jsgraph()->Int32Constant(0);
892 41041 : } else if (m.Is(factory()->true_value())) {
893 41041 : return jsgraph()->Int32Constant(1);
894 : }
895 0 : break;
896 : }
897 : default:
898 : break;
899 : }
900 : // Select the correct X -> Bit operator.
901 : const Operator* op;
902 171909 : if (output_type.Is(Type::None())) {
903 : // This is an impossible value; it should not be used at runtime.
904 : return jsgraph()->graph()->NewNode(
905 570 : jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
906 171719 : } else if (output_rep == MachineRepresentation::kTagged ||
907 : output_rep == MachineRepresentation::kTaggedPointer) {
908 171705 : if (output_type.Is(Type::BooleanOrNullOrUndefined())) {
909 : // true is the only trueish Oddball.
910 129862 : op = simplified()->ChangeTaggedToBit();
911 : } else {
912 83236 : if (output_rep == MachineRepresentation::kTagged &&
913 41393 : output_type.Maybe(Type::SignedSmall())) {
914 41371 : op = simplified()->TruncateTaggedToBit();
915 : } else {
916 : // The {output_type} either doesn't include the Smi range,
917 : // or the {output_rep} is known to be TaggedPointer.
918 473 : op = simplified()->TruncateTaggedPointerToBit();
919 : }
920 : }
921 14 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
922 : node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
923 0 : jsgraph()->IntPtrConstant(0));
924 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
925 0 : jsgraph()->Int32Constant(0));
926 14 : } else if (IsWord(output_rep)) {
927 : node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
928 0 : jsgraph()->Int32Constant(0));
929 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
930 0 : jsgraph()->Int32Constant(0));
931 14 : } else if (output_rep == MachineRepresentation::kWord64) {
932 : node = jsgraph()->graph()->NewNode(machine()->Word64Equal(), node,
933 0 : jsgraph()->Int64Constant(0));
934 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
935 0 : jsgraph()->Int32Constant(0));
936 14 : } else if (output_rep == MachineRepresentation::kFloat32) {
937 0 : node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
938 : return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
939 0 : jsgraph()->Float32Constant(0.0), node);
940 14 : } else if (output_rep == MachineRepresentation::kFloat64) {
941 28 : node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
942 : return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
943 56 : jsgraph()->Float64Constant(0.0), node);
944 : } else {
945 : return TypeError(node, output_rep, output_type,
946 0 : MachineRepresentation::kBit);
947 : }
948 343411 : return jsgraph()->graph()->NewNode(op, node);
949 : }
950 :
951 198633 : Node* RepresentationChanger::GetWord64RepresentationFor(
952 198633 : Node* node, MachineRepresentation output_rep, Type output_type,
953 159713 : Node* use_node, UseInfo use_info) {
954 : // Eagerly fold representation changes for constants.
955 198633 : switch (node->opcode()) {
956 : case IrOpcode::kInt32Constant:
957 : case IrOpcode::kInt64Constant:
958 : case IrOpcode::kFloat32Constant:
959 : case IrOpcode::kFloat64Constant:
960 0 : UNREACHABLE();
961 : break;
962 : case IrOpcode::kNumberConstant: {
963 159523 : double const fv = OpParameter<double>(node->op());
964 159523 : int64_t const iv = static_cast<int64_t>(fv);
965 159523 : if (static_cast<double>(iv) == fv) {
966 159523 : return jsgraph()->Int64Constant(iv);
967 : }
968 : break;
969 : }
970 : default:
971 : break;
972 : }
973 :
974 : // Select the correct X -> Word64 operator.
975 : const Operator* op;
976 39110 : if (output_type.Is(Type::None())) {
977 : // This is an impossible value; it should not be used at runtime.
978 : return jsgraph()->graph()->NewNode(
979 285 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord64), node);
980 39015 : } else if (output_rep == MachineRepresentation::kBit) {
981 : return node; // Sloppy comparison -> word64
982 39010 : } else if (IsWord(output_rep)) {
983 36897 : if (output_type.Is(Type::Unsigned32())) {
984 35438 : op = machine()->ChangeUint32ToUint64();
985 1459 : } else if (output_type.Is(Type::Signed32())) {
986 1454 : op = machine()->ChangeInt32ToInt64();
987 : } else {
988 : return TypeError(node, output_rep, output_type,
989 5 : MachineRepresentation::kWord64);
990 : }
991 2113 : } else if (output_rep == MachineRepresentation::kFloat32) {
992 64 : if (output_type.Is(cache_->kInt64)) {
993 : // float32 -> float64 -> int64
994 15 : node = InsertChangeFloat32ToFloat64(node);
995 15 : op = machine()->ChangeFloat64ToInt64();
996 34 : } else if (output_type.Is(cache_->kUint64)) {
997 : // float32 -> float64 -> uint64
998 5 : node = InsertChangeFloat32ToFloat64(node);
999 5 : op = machine()->ChangeFloat64ToUint64();
1000 12 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1001 : // float32 -> float64 -> int64
1002 12 : node = InsertChangeFloat32ToFloat64(node);
1003 : op = simplified()->CheckedFloat64ToInt64(
1004 12 : output_type.Maybe(Type::MinusZero())
1005 : ? use_info.minus_zero_check()
1006 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1007 24 : use_info.feedback());
1008 : } else {
1009 : return TypeError(node, output_rep, output_type,
1010 0 : MachineRepresentation::kWord64);
1011 : }
1012 2081 : } else if (output_rep == MachineRepresentation::kFloat64) {
1013 106 : if (output_type.Is(cache_->kInt64)) {
1014 36 : op = machine()->ChangeFloat64ToInt64();
1015 34 : } else if (output_type.Is(cache_->kUint64)) {
1016 5 : op = machine()->ChangeFloat64ToUint64();
1017 12 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1018 : op = simplified()->CheckedFloat64ToInt64(
1019 12 : output_type.Maybe(Type::MinusZero())
1020 : ? use_info.minus_zero_check()
1021 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1022 24 : use_info.feedback());
1023 : } else {
1024 : return TypeError(node, output_rep, output_type,
1025 0 : MachineRepresentation::kWord64);
1026 : }
1027 2028 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1028 1905 : if (output_type.Is(Type::SignedSmall())) {
1029 1905 : op = simplified()->ChangeTaggedSignedToInt64();
1030 : } else {
1031 : return TypeError(node, output_rep, output_type,
1032 0 : MachineRepresentation::kWord64);
1033 : }
1034 123 : } else if (CanBeTaggedPointer(output_rep)) {
1035 246 : if (output_type.Is(cache_->kInt64)) {
1036 33 : op = simplified()->ChangeTaggedToInt64();
1037 90 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1038 : op = simplified()->CheckedTaggedToInt64(
1039 80 : output_type.Maybe(Type::MinusZero())
1040 : ? use_info.minus_zero_check()
1041 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1042 160 : use_info.feedback());
1043 : } else {
1044 : return TypeError(node, output_rep, output_type,
1045 10 : MachineRepresentation::kWord64);
1046 : }
1047 : } else {
1048 : return TypeError(node, output_rep, output_type,
1049 0 : MachineRepresentation::kWord64);
1050 : }
1051 38995 : return InsertConversion(node, op, use_node);
1052 : }
1053 :
1054 213786 : const Operator* RepresentationChanger::Int32OperatorFor(
1055 : IrOpcode::Value opcode) {
1056 213786 : switch (opcode) {
1057 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1058 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1059 : case IrOpcode::kNumberAdd:
1060 101081 : return machine()->Int32Add();
1061 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1062 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1063 : case IrOpcode::kNumberSubtract:
1064 5046 : return machine()->Int32Sub();
1065 : case IrOpcode::kSpeculativeNumberMultiply:
1066 : case IrOpcode::kNumberMultiply:
1067 836 : return machine()->Int32Mul();
1068 : case IrOpcode::kSpeculativeNumberDivide:
1069 : case IrOpcode::kNumberDivide:
1070 0 : return machine()->Int32Div();
1071 : case IrOpcode::kSpeculativeNumberModulus:
1072 : case IrOpcode::kNumberModulus:
1073 0 : return machine()->Int32Mod();
1074 : case IrOpcode::kSpeculativeNumberBitwiseOr: // Fall through.
1075 : case IrOpcode::kNumberBitwiseOr:
1076 18201 : return machine()->Word32Or();
1077 : case IrOpcode::kSpeculativeNumberBitwiseXor: // Fall through.
1078 : case IrOpcode::kNumberBitwiseXor:
1079 2502 : return machine()->Word32Xor();
1080 : case IrOpcode::kSpeculativeNumberBitwiseAnd: // Fall through.
1081 : case IrOpcode::kNumberBitwiseAnd:
1082 9800 : return machine()->Word32And();
1083 : case IrOpcode::kNumberEqual:
1084 : case IrOpcode::kSpeculativeNumberEqual:
1085 9954 : return machine()->Word32Equal();
1086 : case IrOpcode::kNumberLessThan:
1087 : case IrOpcode::kSpeculativeNumberLessThan:
1088 64993 : return machine()->Int32LessThan();
1089 : case IrOpcode::kNumberLessThanOrEqual:
1090 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1091 1373 : return machine()->Int32LessThanOrEqual();
1092 : default:
1093 0 : UNREACHABLE();
1094 : }
1095 : }
1096 :
1097 151696 : const Operator* RepresentationChanger::Int32OverflowOperatorFor(
1098 : IrOpcode::Value opcode) {
1099 151696 : switch (opcode) {
1100 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1101 142683 : return simplified()->CheckedInt32Add();
1102 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1103 7606 : return simplified()->CheckedInt32Sub();
1104 : case IrOpcode::kSpeculativeNumberDivide:
1105 251 : return simplified()->CheckedInt32Div();
1106 : case IrOpcode::kSpeculativeNumberModulus:
1107 1156 : return simplified()->CheckedInt32Mod();
1108 : default:
1109 0 : UNREACHABLE();
1110 : }
1111 : }
1112 :
1113 2535 : const Operator* RepresentationChanger::Int64OperatorFor(
1114 : IrOpcode::Value opcode) {
1115 2535 : switch (opcode) {
1116 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1117 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1118 : case IrOpcode::kNumberAdd:
1119 1890 : return machine()->Int64Add();
1120 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1121 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1122 : case IrOpcode::kNumberSubtract:
1123 645 : return machine()->Int64Sub();
1124 : default:
1125 0 : UNREACHABLE();
1126 : }
1127 : }
1128 :
1129 15207 : const Operator* RepresentationChanger::TaggedSignedOperatorFor(
1130 : IrOpcode::Value opcode) {
1131 15207 : switch (opcode) {
1132 : case IrOpcode::kSpeculativeNumberLessThan:
1133 : return machine()->Is32() ? machine()->Int32LessThan()
1134 5493 : : machine()->Int64LessThan();
1135 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1136 : return machine()->Is32() ? machine()->Int32LessThanOrEqual()
1137 455 : : machine()->Int64LessThanOrEqual();
1138 : case IrOpcode::kSpeculativeNumberEqual:
1139 : return machine()->Is32() ? machine()->Word32Equal()
1140 9259 : : machine()->Word64Equal();
1141 : default:
1142 0 : UNREACHABLE();
1143 : }
1144 : }
1145 :
1146 40098 : const Operator* RepresentationChanger::Uint32OperatorFor(
1147 : IrOpcode::Value opcode) {
1148 40098 : switch (opcode) {
1149 : case IrOpcode::kNumberAdd:
1150 0 : return machine()->Int32Add();
1151 : case IrOpcode::kNumberSubtract:
1152 0 : return machine()->Int32Sub();
1153 : case IrOpcode::kSpeculativeNumberMultiply:
1154 : case IrOpcode::kNumberMultiply:
1155 0 : return machine()->Int32Mul();
1156 : case IrOpcode::kSpeculativeNumberDivide:
1157 : case IrOpcode::kNumberDivide:
1158 0 : return machine()->Uint32Div();
1159 : case IrOpcode::kSpeculativeNumberModulus:
1160 : case IrOpcode::kNumberModulus:
1161 0 : return machine()->Uint32Mod();
1162 : case IrOpcode::kNumberEqual:
1163 : case IrOpcode::kSpeculativeNumberEqual:
1164 13934 : return machine()->Word32Equal();
1165 : case IrOpcode::kNumberLessThan:
1166 : case IrOpcode::kSpeculativeNumberLessThan:
1167 22921 : return machine()->Uint32LessThan();
1168 : case IrOpcode::kNumberLessThanOrEqual:
1169 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1170 2359 : return machine()->Uint32LessThanOrEqual();
1171 : case IrOpcode::kNumberClz32:
1172 33 : return machine()->Word32Clz();
1173 : case IrOpcode::kNumberImul:
1174 851 : return machine()->Int32Mul();
1175 : default:
1176 0 : UNREACHABLE();
1177 : }
1178 : }
1179 :
1180 107 : const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
1181 : IrOpcode::Value opcode) {
1182 107 : switch (opcode) {
1183 : case IrOpcode::kSpeculativeNumberDivide:
1184 63 : return simplified()->CheckedUint32Div();
1185 : case IrOpcode::kSpeculativeNumberModulus:
1186 44 : return simplified()->CheckedUint32Mod();
1187 : default:
1188 0 : UNREACHABLE();
1189 : }
1190 : }
1191 :
1192 173907 : const Operator* RepresentationChanger::Float64OperatorFor(
1193 : IrOpcode::Value opcode) {
1194 173907 : switch (opcode) {
1195 : case IrOpcode::kSpeculativeNumberAdd:
1196 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1197 : case IrOpcode::kNumberAdd:
1198 74081 : return machine()->Float64Add();
1199 : case IrOpcode::kSpeculativeNumberSubtract:
1200 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1201 : case IrOpcode::kNumberSubtract:
1202 2072 : return machine()->Float64Sub();
1203 : case IrOpcode::kSpeculativeNumberMultiply:
1204 : case IrOpcode::kNumberMultiply:
1205 13326 : return machine()->Float64Mul();
1206 : case IrOpcode::kSpeculativeNumberDivide:
1207 : case IrOpcode::kNumberDivide:
1208 16511 : return machine()->Float64Div();
1209 : case IrOpcode::kSpeculativeNumberModulus:
1210 : case IrOpcode::kNumberModulus:
1211 1831 : return machine()->Float64Mod();
1212 : case IrOpcode::kNumberEqual:
1213 : case IrOpcode::kSpeculativeNumberEqual:
1214 17151 : return machine()->Float64Equal();
1215 : case IrOpcode::kNumberLessThan:
1216 : case IrOpcode::kSpeculativeNumberLessThan:
1217 4098 : return machine()->Float64LessThan();
1218 : case IrOpcode::kNumberLessThanOrEqual:
1219 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1220 363 : return machine()->Float64LessThanOrEqual();
1221 : case IrOpcode::kNumberAbs:
1222 189 : return machine()->Float64Abs();
1223 : case IrOpcode::kNumberAcos:
1224 0 : return machine()->Float64Acos();
1225 : case IrOpcode::kNumberAcosh:
1226 0 : return machine()->Float64Acosh();
1227 : case IrOpcode::kNumberAsin:
1228 0 : return machine()->Float64Asin();
1229 : case IrOpcode::kNumberAsinh:
1230 0 : return machine()->Float64Asinh();
1231 : case IrOpcode::kNumberAtan:
1232 0 : return machine()->Float64Atan();
1233 : case IrOpcode::kNumberAtanh:
1234 0 : return machine()->Float64Atanh();
1235 : case IrOpcode::kNumberAtan2:
1236 2 : return machine()->Float64Atan2();
1237 : case IrOpcode::kNumberCbrt:
1238 0 : return machine()->Float64Cbrt();
1239 : case IrOpcode::kNumberCeil:
1240 6674 : return machine()->Float64RoundUp().placeholder();
1241 : case IrOpcode::kNumberCos:
1242 9 : return machine()->Float64Cos();
1243 : case IrOpcode::kNumberCosh:
1244 7 : return machine()->Float64Cosh();
1245 : case IrOpcode::kNumberExp:
1246 39 : return machine()->Float64Exp();
1247 : case IrOpcode::kNumberExpm1:
1248 14 : return machine()->Float64Expm1();
1249 : case IrOpcode::kNumberFloor:
1250 26990 : return machine()->Float64RoundDown().placeholder();
1251 : case IrOpcode::kNumberFround:
1252 1351 : return machine()->TruncateFloat64ToFloat32();
1253 : case IrOpcode::kNumberLog:
1254 167 : return machine()->Float64Log();
1255 : case IrOpcode::kNumberLog1p:
1256 0 : return machine()->Float64Log1p();
1257 : case IrOpcode::kNumberLog2:
1258 0 : return machine()->Float64Log2();
1259 : case IrOpcode::kNumberLog10:
1260 0 : return machine()->Float64Log10();
1261 : case IrOpcode::kNumberMax:
1262 74 : return machine()->Float64Max();
1263 : case IrOpcode::kNumberMin:
1264 153 : return machine()->Float64Min();
1265 : case IrOpcode::kNumberPow:
1266 983 : return machine()->Float64Pow();
1267 : case IrOpcode::kNumberSin:
1268 34 : return machine()->Float64Sin();
1269 : case IrOpcode::kNumberSinh:
1270 7 : return machine()->Float64Sinh();
1271 : case IrOpcode::kNumberSqrt:
1272 62 : return machine()->Float64Sqrt();
1273 : case IrOpcode::kNumberTan:
1274 29 : return machine()->Float64Tan();
1275 : case IrOpcode::kNumberTanh:
1276 7 : return machine()->Float64Tanh();
1277 : case IrOpcode::kNumberTrunc:
1278 6912 : return machine()->Float64RoundTruncate().placeholder();
1279 : case IrOpcode::kNumberSilenceNaN:
1280 771 : return machine()->Float64SilenceNaN();
1281 : default:
1282 0 : UNREACHABLE();
1283 : }
1284 : }
1285 :
1286 35 : Node* RepresentationChanger::TypeError(Node* node,
1287 : MachineRepresentation output_rep,
1288 : Type output_type,
1289 : MachineRepresentation use) {
1290 35 : type_error_ = true;
1291 35 : if (!testing_type_errors_) {
1292 0 : std::ostringstream out_str;
1293 0 : out_str << output_rep << " (";
1294 0 : output_type.PrintTo(out_str);
1295 0 : out_str << ")";
1296 :
1297 0 : std::ostringstream use_str;
1298 0 : use_str << use;
1299 :
1300 0 : FATAL(
1301 : "RepresentationChangerError: node #%d:%s of "
1302 : "%s cannot be changed to %s",
1303 : node->id(), node->op()->mnemonic(), out_str.str().c_str(),
1304 0 : use_str.str().c_str());
1305 : }
1306 35 : return node;
1307 : }
1308 :
1309 0 : Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
1310 0 : return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
1311 : }
1312 :
1313 830 : Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
1314 1245 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
1315 : }
1316 :
1317 46 : Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
1318 69 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
1319 : }
1320 :
1321 1624 : Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
1322 2436 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
1323 : }
1324 :
1325 28 : Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) {
1326 42 : return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
1327 : }
1328 :
1329 3110 : Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
1330 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
1331 4665 : node);
1332 : }
1333 :
1334 0 : Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
1335 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
1336 0 : node);
1337 : }
1338 :
1339 0 : Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) {
1340 0 : return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
1341 : }
1342 :
1343 64 : Node* RepresentationChanger::InsertTruncateInt64ToInt32(Node* node) {
1344 96 : return jsgraph()->graph()->NewNode(machine()->TruncateInt64ToInt32(), node);
1345 : }
1346 :
1347 : } // namespace compiler
1348 : } // namespace internal
1349 183867 : } // namespace v8
|