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 99942150 : Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
67 : TruncationKind rep2) {
68 99942150 : if (LessGeneral(rep1, rep2)) return rep2;
69 11503472 : 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 99942769 : IdentifyZeros Truncation::GeneralizeIdentifyZeros(IdentifyZeros i1,
87 : IdentifyZeros i2) {
88 99942769 : if (i1 == i2) {
89 70217025 : return i1;
90 : } else {
91 : return kDistinguishZeros;
92 : }
93 : }
94 :
95 : // static
96 113910078 : bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
97 113910078 : switch (rep1) {
98 : case TruncationKind::kNone:
99 : return true;
100 : case TruncationKind::kBool:
101 710253 : return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
102 : case TruncationKind::kWord32:
103 : return rep2 == TruncationKind::kWord32 ||
104 826891 : rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
105 : case TruncationKind::kFloat64:
106 572162 : return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
107 : case TruncationKind::kAny:
108 59586697 : 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 17546982 : rep == MachineRepresentation::kWord16 ||
123 : rep == MachineRepresentation::kWord32;
124 : }
125 :
126 : } // namespace
127 :
128 464622 : RepresentationChanger::RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
129 464622 : : cache_(TypeCache::Get()),
130 : jsgraph_(jsgraph),
131 : isolate_(isolate),
132 : testing_type_errors_(false),
133 464623 : 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 16040884 : Node* RepresentationChanger::GetRepresentationFor(
140 : Node* node, MachineRepresentation output_rep, Type output_type,
141 : Node* use_node, UseInfo use_info) {
142 16041427 : 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 16040884 : if (use_info.type_check() == TypeCheckKind::kNone ||
150 : output_rep != MachineRepresentation::kWord32) {
151 15946450 : if (use_info.representation() == output_rep) {
152 : // Representations are the same. That's a no-op.
153 : return node;
154 : }
155 17191774 : 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 16009276 : 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 69487 : 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 35502 : 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 13795519 : use_info.truncation());
179 : case MachineRepresentation::kCompressedSigned:
180 : DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
181 : use_info.type_check() == TypeCheckKind::kSignedSmall);
182 : return GetCompressedSignedRepresentationFor(node, output_rep, output_type,
183 10 : use_node, use_info);
184 : case MachineRepresentation::kCompressedPointer:
185 : DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
186 : use_info.type_check() == TypeCheckKind::kHeapObject);
187 : return GetCompressedPointerRepresentationFor(
188 5 : node, output_rep, output_type, use_node, use_info);
189 : case MachineRepresentation::kCompressed:
190 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
191 : return GetCompressedRepresentationFor(node, output_rep, output_type,
192 5 : use_info.truncation());
193 : case MachineRepresentation::kFloat32:
194 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
195 : return GetFloat32RepresentationFor(node, output_rep, output_type,
196 1402 : use_info.truncation());
197 : case MachineRepresentation::kFloat64:
198 : return GetFloat64RepresentationFor(node, output_rep, output_type,
199 251853 : use_node, use_info);
200 : case MachineRepresentation::kBit:
201 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
202 321173 : return GetBitRepresentationFor(node, output_rep, output_type);
203 : case MachineRepresentation::kWord8:
204 : case MachineRepresentation::kWord16:
205 : case MachineRepresentation::kWord32:
206 : return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
207 1349250 : use_info);
208 : case MachineRepresentation::kWord64:
209 : DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
210 : use_info.type_check() == TypeCheckKind::kSigned64);
211 : return GetWord64RepresentationFor(node, output_rep, output_type, use_node,
212 185070 : use_info);
213 : case MachineRepresentation::kSimd128:
214 : case MachineRepresentation::kNone:
215 : return node;
216 : }
217 0 : UNREACHABLE();
218 : }
219 :
220 69487 : Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
221 : Node* node, MachineRepresentation output_rep, Type output_type,
222 : Node* use_node, UseInfo use_info) {
223 : // Eagerly fold representation changes for constants.
224 69487 : switch (node->opcode()) {
225 : case IrOpcode::kNumberConstant:
226 7 : if (output_type.Is(Type::SignedSmall())) {
227 : return node;
228 : }
229 : break;
230 : default:
231 : break;
232 : }
233 : // Select the correct X -> Tagged operator.
234 : const Operator* op;
235 69487 : if (output_type.Is(Type::None())) {
236 : // This is an impossible value; it should not be used at runtime.
237 0 : return jsgraph()->graph()->NewNode(
238 : jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedSigned),
239 0 : node);
240 69487 : } else if (IsWord(output_rep)) {
241 44882 : if (output_type.Is(Type::Signed31())) {
242 26413 : op = simplified()->ChangeInt31ToTaggedSigned();
243 18469 : } else if (output_type.Is(Type::Signed32())) {
244 : if (SmiValuesAre32Bits()) {
245 18462 : op = simplified()->ChangeInt32ToTagged();
246 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
247 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
248 : } else {
249 : return TypeError(node, output_rep, output_type,
250 : MachineRepresentation::kTaggedSigned);
251 : }
252 7 : } else if (output_type.Is(Type::Unsigned32()) &&
253 : use_info.type_check() == TypeCheckKind::kSignedSmall) {
254 7 : op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
255 : } else {
256 : return TypeError(node, output_rep, output_type,
257 0 : MachineRepresentation::kTaggedSigned);
258 : }
259 24605 : } else if (output_rep == MachineRepresentation::kWord64) {
260 171 : if (output_type.Is(Type::Signed31())) {
261 : // int64 -> int32 -> tagged signed
262 5 : node = InsertTruncateInt64ToInt32(node);
263 5 : op = simplified()->ChangeInt31ToTaggedSigned();
264 166 : } else if (output_type.Is(Type::Signed32()) && SmiValuesAre32Bits()) {
265 : // int64 -> int32 -> tagged signed
266 5 : node = InsertTruncateInt64ToInt32(node);
267 5 : op = simplified()->ChangeInt32ToTagged();
268 161 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
269 322 : if (output_type.Is(cache_->kPositiveSafeInteger)) {
270 5 : op = simplified()->CheckedUint64ToTaggedSigned(use_info.feedback());
271 312 : } else if (output_type.Is(cache_->kSafeInteger)) {
272 156 : op = simplified()->CheckedInt64ToTaggedSigned(use_info.feedback());
273 : } else {
274 : return TypeError(node, output_rep, output_type,
275 0 : MachineRepresentation::kTaggedSigned);
276 : }
277 : } else {
278 : return TypeError(node, output_rep, output_type,
279 0 : MachineRepresentation::kTaggedSigned);
280 : }
281 24434 : } else if (output_rep == MachineRepresentation::kFloat64) {
282 23 : if (output_type.Is(Type::Signed31())) {
283 : // float64 -> int32 -> tagged signed
284 0 : node = InsertChangeFloat64ToInt32(node);
285 0 : op = simplified()->ChangeInt31ToTaggedSigned();
286 23 : } else if (output_type.Is(Type::Signed32())) {
287 : // float64 -> int32 -> tagged signed
288 0 : node = InsertChangeFloat64ToInt32(node);
289 : if (SmiValuesAre32Bits()) {
290 0 : op = simplified()->ChangeInt32ToTagged();
291 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
292 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
293 : } else {
294 : return TypeError(node, output_rep, output_type,
295 : MachineRepresentation::kTaggedSigned);
296 : }
297 23 : } else if (output_type.Is(Type::Unsigned32()) &&
298 : use_info.type_check() == TypeCheckKind::kSignedSmall) {
299 : // float64 -> uint32 -> tagged signed
300 0 : node = InsertChangeFloat64ToUint32(node);
301 0 : op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
302 23 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
303 23 : op = simplified()->CheckedFloat64ToInt32(
304 23 : output_type.Maybe(Type::MinusZero())
305 : ? CheckForMinusZeroMode::kCheckForMinusZero
306 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
307 23 : use_info.feedback());
308 23 : node = InsertConversion(node, op, use_node);
309 : if (SmiValuesAre32Bits()) {
310 23 : op = simplified()->ChangeInt32ToTagged();
311 : } else {
312 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
313 : }
314 : } else {
315 : return TypeError(node, output_rep, output_type,
316 0 : MachineRepresentation::kTaggedSigned);
317 : }
318 24411 : } else if (output_rep == MachineRepresentation::kFloat32) {
319 0 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
320 0 : op = machine()->ChangeFloat32ToFloat64();
321 0 : node = InsertConversion(node, op, use_node);
322 0 : op = simplified()->CheckedFloat64ToInt32(
323 0 : output_type.Maybe(Type::MinusZero())
324 : ? CheckForMinusZeroMode::kCheckForMinusZero
325 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
326 0 : use_info.feedback());
327 0 : node = InsertConversion(node, op, use_node);
328 : if (SmiValuesAre32Bits()) {
329 0 : op = simplified()->ChangeInt32ToTagged();
330 : } else {
331 : op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
332 : }
333 : } else {
334 : return TypeError(node, output_rep, output_type,
335 0 : MachineRepresentation::kTaggedSigned);
336 : }
337 24411 : } else if (CanBeTaggedPointer(output_rep)) {
338 24401 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
339 24387 : op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
340 14 : } else if (output_type.Is(Type::SignedSmall())) {
341 14 : op = simplified()->ChangeTaggedToTaggedSigned();
342 : } else {
343 : return TypeError(node, output_rep, output_type,
344 0 : MachineRepresentation::kTaggedSigned);
345 : }
346 10 : } else if (output_rep == MachineRepresentation::kBit) {
347 0 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
348 : // TODO(turbofan): Consider adding a Bailout operator that just deopts.
349 : // Also use that for MachineRepresentation::kPointer case above.
350 0 : node = InsertChangeBitToTagged(node);
351 0 : op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
352 : } else {
353 : return TypeError(node, output_rep, output_type,
354 0 : MachineRepresentation::kTaggedSigned);
355 : }
356 10 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
357 5 : op = machine()->ChangeCompressedSignedToTaggedSigned();
358 5 : } else if (output_rep == MachineRepresentation::kCompressed) {
359 5 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
360 0 : op = simplified()->CheckedCompressedToTaggedSigned(use_info.feedback());
361 5 : } else if (output_type.Is(Type::SignedSmall())) {
362 5 : op = simplified()->ChangeCompressedToTaggedSigned();
363 : } else {
364 : return TypeError(node, output_rep, output_type,
365 0 : MachineRepresentation::kTaggedSigned);
366 : }
367 : } else {
368 : return TypeError(node, output_rep, output_type,
369 0 : MachineRepresentation::kTaggedSigned);
370 : }
371 69487 : return InsertConversion(node, op, use_node);
372 : }
373 :
374 35502 : Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
375 : Node* node, MachineRepresentation output_rep, Type output_type,
376 : Node* use_node, UseInfo use_info) {
377 : // Eagerly fold representation changes for constants.
378 35502 : switch (node->opcode()) {
379 : case IrOpcode::kHeapConstant:
380 : case IrOpcode::kDelayedStringConstant:
381 : return node; // No change necessary.
382 : case IrOpcode::kInt32Constant:
383 : case IrOpcode::kFloat64Constant:
384 : case IrOpcode::kFloat32Constant:
385 0 : UNREACHABLE();
386 : default:
387 : break;
388 : }
389 : // Select the correct X -> TaggedPointer operator.
390 : Operator const* op;
391 35502 : if (output_type.Is(Type::None())) {
392 : // This is an impossible value; it should not be used at runtime.
393 0 : return jsgraph()->graph()->NewNode(
394 : jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
395 0 : node);
396 35502 : } else if (output_rep == MachineRepresentation::kBit) {
397 0 : if (output_type.Is(Type::Boolean())) {
398 0 : op = simplified()->ChangeBitToTagged();
399 : } else {
400 : return TypeError(node, output_rep, output_type,
401 0 : MachineRepresentation::kTagged);
402 : }
403 35502 : } else if (IsWord(output_rep)) {
404 14 : if (output_type.Is(Type::Unsigned32())) {
405 : // uint32 -> float64 -> tagged
406 0 : node = InsertChangeUint32ToFloat64(node);
407 14 : } else if (output_type.Is(Type::Signed32())) {
408 : // int32 -> float64 -> tagged
409 14 : node = InsertChangeInt32ToFloat64(node);
410 : } else {
411 : return TypeError(node, output_rep, output_type,
412 0 : MachineRepresentation::kTaggedPointer);
413 : }
414 14 : op = simplified()->ChangeFloat64ToTaggedPointer();
415 35488 : } else if (output_rep == MachineRepresentation::kWord64) {
416 10 : if (output_type.Is(cache_->kSafeInteger)) {
417 : // int64 -> float64 -> tagged pointer
418 5 : op = machine()->ChangeInt64ToFloat64();
419 : node = jsgraph()->graph()->NewNode(op, node);
420 5 : op = simplified()->ChangeFloat64ToTaggedPointer();
421 : } else {
422 : return TypeError(node, output_rep, output_type,
423 0 : MachineRepresentation::kTaggedPointer);
424 : }
425 35483 : } else if (output_rep == MachineRepresentation::kFloat32) {
426 0 : if (output_type.Is(Type::Number())) {
427 : // float32 -> float64 -> tagged
428 0 : node = InsertChangeFloat32ToFloat64(node);
429 0 : op = simplified()->ChangeFloat64ToTaggedPointer();
430 : } else {
431 : return TypeError(node, output_rep, output_type,
432 0 : MachineRepresentation::kTaggedPointer);
433 : }
434 35483 : } else if (output_rep == MachineRepresentation::kFloat64) {
435 77 : if (output_type.Is(Type::Number())) {
436 : // float64 -> tagged
437 77 : op = simplified()->ChangeFloat64ToTaggedPointer();
438 : } else {
439 : return TypeError(node, output_rep, output_type,
440 0 : MachineRepresentation::kTaggedPointer);
441 : }
442 35406 : } else if (CanBeTaggedSigned(output_rep) &&
443 : use_info.type_check() == TypeCheckKind::kHeapObject) {
444 35401 : if (!output_type.Maybe(Type::SignedSmall())) {
445 : return node;
446 : }
447 : // TODO(turbofan): Consider adding a Bailout operator that just deopts
448 : // for TaggedSigned output representation.
449 34852 : op = simplified()->CheckedTaggedToTaggedPointer(use_info.feedback());
450 5 : } else if (output_rep == MachineRepresentation::kCompressedPointer) {
451 5 : op = machine()->ChangeCompressedPointerToTaggedPointer();
452 0 : } else if (output_rep == MachineRepresentation::kCompressed &&
453 : use_info.type_check() == TypeCheckKind::kHeapObject) {
454 0 : if (!output_type.Maybe(Type::SignedSmall())) {
455 : return node;
456 : }
457 : // TODO(turbofan): Consider adding a Bailout operator that just deopts
458 : // for CompressedSigned output representation.
459 0 : op = simplified()->CheckedCompressedToTaggedPointer(use_info.feedback());
460 : } else {
461 : return TypeError(node, output_rep, output_type,
462 0 : MachineRepresentation::kTaggedPointer);
463 : }
464 34953 : return InsertConversion(node, op, use_node);
465 : }
466 :
467 13795512 : Node* RepresentationChanger::GetTaggedRepresentationFor(
468 : Node* node, MachineRepresentation output_rep, Type output_type,
469 : Truncation truncation) {
470 : // Eagerly fold representation changes for constants.
471 13795512 : switch (node->opcode()) {
472 : case IrOpcode::kNumberConstant:
473 : case IrOpcode::kHeapConstant:
474 : case IrOpcode::kDelayedStringConstant:
475 : return node; // No change necessary.
476 : case IrOpcode::kInt32Constant:
477 : case IrOpcode::kFloat64Constant:
478 : case IrOpcode::kFloat32Constant:
479 0 : UNREACHABLE();
480 : break;
481 : default:
482 : break;
483 : }
484 3194527 : if (output_rep == MachineRepresentation::kTaggedSigned ||
485 : output_rep == MachineRepresentation::kTaggedPointer) {
486 : // this is a no-op.
487 : return node;
488 : }
489 : // Select the correct X -> Tagged operator.
490 : const Operator* op;
491 118316 : if (output_type.Is(Type::None())) {
492 : // This is an impossible value; it should not be used at runtime.
493 310 : return jsgraph()->graph()->NewNode(
494 310 : jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
495 118006 : } else if (output_rep == MachineRepresentation::kBit) {
496 10533 : if (output_type.Is(Type::Boolean())) {
497 10533 : op = simplified()->ChangeBitToTagged();
498 : } else {
499 : return TypeError(node, output_rep, output_type,
500 0 : MachineRepresentation::kTagged);
501 : }
502 107473 : } else if (IsWord(output_rep)) {
503 35203 : if (output_type.Is(Type::Signed31())) {
504 16262 : op = simplified()->ChangeInt31ToTaggedSigned();
505 38609 : } else if (output_type.Is(Type::Signed32()) ||
506 7 : (output_type.Is(Type::Signed32OrMinusZero()) &&
507 : truncation.IdentifiesZeroAndMinusZero())) {
508 18221 : op = simplified()->ChangeInt32ToTagged();
509 727 : } else if (output_type.Is(Type::Unsigned32()) ||
510 0 : (output_type.Is(Type::Unsigned32OrMinusZero()) &&
511 727 : truncation.IdentifiesZeroAndMinusZero()) ||
512 : truncation.IsUsedAsWord32()) {
513 : // Either the output is uint32 or the uses only care about the
514 : // low 32 bits (so we can pick uint32 safely).
515 720 : op = simplified()->ChangeUint32ToTagged();
516 : } else {
517 : return TypeError(node, output_rep, output_type,
518 0 : MachineRepresentation::kTagged);
519 : }
520 72270 : } else if (output_rep == MachineRepresentation::kWord64) {
521 143 : if (output_type.Is(Type::Signed31())) {
522 : // int64 -> int32 -> tagged signed
523 5 : node = InsertTruncateInt64ToInt32(node);
524 5 : op = simplified()->ChangeInt31ToTaggedSigned();
525 138 : } else if (output_type.Is(Type::Signed32())) {
526 : // int64 -> int32 -> tagged
527 5 : node = InsertTruncateInt64ToInt32(node);
528 5 : op = simplified()->ChangeInt32ToTagged();
529 133 : } else if (output_type.Is(Type::Unsigned32())) {
530 : // int64 -> uint32 -> tagged
531 12 : node = InsertTruncateInt64ToInt32(node);
532 12 : op = simplified()->ChangeUint32ToTagged();
533 242 : } else if (output_type.Is(cache_->kPositiveSafeInteger)) {
534 : // uint64 -> tagged
535 58 : op = simplified()->ChangeUint64ToTagged();
536 126 : } else if (output_type.Is(cache_->kSafeInteger)) {
537 : // int64 -> tagged
538 58 : op = simplified()->ChangeInt64ToTagged();
539 : } else {
540 : return TypeError(node, output_rep, output_type,
541 5 : MachineRepresentation::kTagged);
542 : }
543 72127 : } else if (output_rep ==
544 : MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
545 382 : node = InsertChangeFloat32ToFloat64(node);
546 382 : op = simplified()->ChangeFloat64ToTagged(
547 382 : output_type.Maybe(Type::MinusZero())
548 : ? CheckForMinusZeroMode::kCheckForMinusZero
549 382 : : CheckForMinusZeroMode::kDontCheckForMinusZero);
550 71745 : } else if (output_rep == MachineRepresentation::kFloat64) {
551 71740 : if (output_type.Is(Type::Signed31())) { // float64 -> int32 -> tagged
552 28 : node = InsertChangeFloat64ToInt32(node);
553 28 : op = simplified()->ChangeInt31ToTaggedSigned();
554 71712 : } else if (output_type.Is(
555 : Type::Signed32())) { // float64 -> int32 -> tagged
556 780 : node = InsertChangeFloat64ToInt32(node);
557 780 : op = simplified()->ChangeInt32ToTagged();
558 70932 : } else if (output_type.Is(
559 : Type::Unsigned32())) { // float64 -> uint32 -> tagged
560 20 : node = InsertChangeFloat64ToUint32(node);
561 20 : op = simplified()->ChangeUint32ToTagged();
562 141838 : } else if (output_type.Is(Type::Number()) ||
563 14 : (output_type.Is(Type::NumberOrOddball()) &&
564 : truncation.IsUsedAsFloat64())) {
565 70912 : op = simplified()->ChangeFloat64ToTagged(
566 70912 : output_type.Maybe(Type::MinusZero())
567 : ? CheckForMinusZeroMode::kCheckForMinusZero
568 70912 : : CheckForMinusZeroMode::kDontCheckForMinusZero);
569 : } else {
570 : return TypeError(node, output_rep, output_type,
571 0 : MachineRepresentation::kTagged);
572 : }
573 5 : } else if (IsAnyCompressed(output_rep)) {
574 5 : op = machine()->ChangeCompressedToTagged();
575 : } else {
576 : return TypeError(node, output_rep, output_type,
577 0 : MachineRepresentation::kTagged);
578 : }
579 118001 : return jsgraph()->graph()->NewNode(op, node);
580 : }
581 :
582 10 : Node* RepresentationChanger::GetCompressedSignedRepresentationFor(
583 : Node* node, MachineRepresentation output_rep, Type output_type,
584 : Node* use_node, UseInfo use_info) {
585 : // Select the correct X -> Compressed operator.
586 : const Operator* op;
587 10 : if (output_type.Is(Type::None())) {
588 : // This is an impossible value; it should not be used at runtime.
589 0 : return jsgraph()->graph()->NewNode(
590 : jsgraph()->common()->DeadValue(
591 : MachineRepresentation::kCompressedSigned),
592 0 : node);
593 10 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
594 5 : op = machine()->ChangeTaggedSignedToCompressedSigned();
595 5 : } else if (output_rep == MachineRepresentation::kTagged) {
596 5 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
597 0 : op = simplified()->CheckedTaggedToCompressedSigned(use_info.feedback());
598 5 : } else if (output_type.Is(Type::SignedSmall())) {
599 5 : op = simplified()->ChangeTaggedToCompressedSigned();
600 : } else {
601 : return TypeError(node, output_rep, output_type,
602 0 : MachineRepresentation::kTaggedSigned);
603 : }
604 0 : } else if (output_rep == MachineRepresentation::kBit) {
605 : // TODO(v8:8977): specialize here and below
606 : node = GetTaggedSignedRepresentationFor(node, output_rep, output_type,
607 0 : use_node, use_info);
608 0 : op = machine()->ChangeTaggedSignedToCompressedSigned();
609 0 : } else if (IsWord(output_rep)) {
610 : node = GetTaggedSignedRepresentationFor(node, output_rep, output_type,
611 0 : use_node, use_info);
612 0 : op = machine()->ChangeTaggedSignedToCompressedSigned();
613 0 : } else if (output_rep == MachineRepresentation::kWord64) {
614 : node = GetTaggedSignedRepresentationFor(node, output_rep, output_type,
615 0 : use_node, use_info);
616 0 : op = machine()->ChangeTaggedSignedToCompressedSigned();
617 0 : } else if (output_rep == MachineRepresentation::kFloat32) {
618 : node = GetTaggedSignedRepresentationFor(node, output_rep, output_type,
619 0 : use_node, use_info);
620 0 : op = machine()->ChangeTaggedSignedToCompressedSigned();
621 0 : } else if (output_rep == MachineRepresentation::kFloat64) {
622 : node = GetTaggedSignedRepresentationFor(node, output_rep, output_type,
623 0 : use_node, use_info);
624 0 : op = machine()->ChangeTaggedSignedToCompressedSigned();
625 : } else {
626 : return TypeError(node, output_rep, output_type,
627 0 : MachineRepresentation::kCompressedSigned);
628 : }
629 10 : return InsertConversion(node, op, use_node);
630 : }
631 :
632 5 : Node* RepresentationChanger::GetCompressedPointerRepresentationFor(
633 : Node* node, MachineRepresentation output_rep, Type output_type,
634 : Node* use_node, UseInfo use_info) {
635 : // Select the correct X -> CompressedPointer operator.
636 : Operator const* op;
637 5 : if (output_type.Is(Type::None())) {
638 : // This is an impossible value; it should not be used at runtime.
639 0 : return jsgraph()->graph()->NewNode(
640 : jsgraph()->common()->DeadValue(
641 : MachineRepresentation::kCompressedPointer),
642 0 : node);
643 5 : } else if (output_rep == MachineRepresentation::kTaggedPointer) {
644 5 : op = machine()->ChangeTaggedPointerToCompressedPointer();
645 0 : } else if (output_rep == MachineRepresentation::kTagged &&
646 : use_info.type_check() == TypeCheckKind::kHeapObject) {
647 0 : if (!output_type.Maybe(Type::SignedSmall())) {
648 : return node;
649 : }
650 : // TODO(turbofan): Consider adding a Bailout operator that just deopts
651 : // for TaggedSigned output representation.
652 0 : op = simplified()->CheckedTaggedToCompressedPointer(use_info.feedback());
653 : return TypeError(node, output_rep, output_type,
654 0 : MachineRepresentation::kCompressedPointer);
655 : }
656 5 : return InsertConversion(node, op, use_node);
657 : }
658 :
659 5 : Node* RepresentationChanger::GetCompressedRepresentationFor(
660 : Node* node, MachineRepresentation output_rep, Type output_type,
661 : Truncation truncation) {
662 5 : if (output_rep == MachineRepresentation::kCompressedSigned ||
663 : output_rep == MachineRepresentation::kCompressedPointer) {
664 : // this is a no-op.
665 : return node;
666 : }
667 : // Select the correct X -> Compressed operator.
668 : const Operator* op;
669 5 : if (output_type.Is(Type::None())) {
670 : // This is an impossible value; it should not be used at runtime.
671 0 : return jsgraph()->graph()->NewNode(
672 : jsgraph()->common()->DeadValue(MachineRepresentation::kCompressed),
673 0 : node);
674 5 : } else if (output_rep == MachineRepresentation::kBit) {
675 : // TODO(v8:8977): specialize here and below
676 : node =
677 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
678 0 : op = machine()->ChangeTaggedToCompressed();
679 5 : } else if (IsWord(output_rep)) {
680 : node =
681 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
682 0 : op = machine()->ChangeTaggedToCompressed();
683 5 : } else if (output_rep == MachineRepresentation::kWord64) {
684 : node =
685 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
686 0 : op = machine()->ChangeTaggedToCompressed();
687 5 : } else if (output_rep == MachineRepresentation::kFloat32) {
688 : node =
689 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
690 0 : op = machine()->ChangeTaggedToCompressed();
691 5 : } else if (output_rep == MachineRepresentation::kFloat64) {
692 : node =
693 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
694 0 : op = machine()->ChangeTaggedToCompressed();
695 5 : } else if (IsAnyTagged(output_rep)) {
696 5 : op = machine()->ChangeTaggedToCompressed();
697 : } else {
698 : return TypeError(node, output_rep, output_type,
699 0 : MachineRepresentation::kCompressed);
700 : }
701 5 : return jsgraph()->graph()->NewNode(op, node);
702 : }
703 :
704 1402 : Node* RepresentationChanger::GetFloat32RepresentationFor(
705 : Node* node, MachineRepresentation output_rep, Type output_type,
706 : Truncation truncation) {
707 : // Eagerly fold representation changes for constants.
708 1402 : switch (node->opcode()) {
709 : case IrOpcode::kNumberConstant:
710 2308 : return jsgraph()->Float32Constant(
711 1154 : DoubleToFloat32(OpParameter<double>(node->op())));
712 : case IrOpcode::kInt32Constant:
713 : case IrOpcode::kFloat64Constant:
714 : case IrOpcode::kFloat32Constant:
715 0 : UNREACHABLE();
716 : break;
717 : default:
718 : break;
719 : }
720 : // Select the correct X -> Float32 operator.
721 : const Operator* op = nullptr;
722 248 : if (output_type.Is(Type::None())) {
723 : // This is an impossible value; it should not be used at runtime.
724 0 : return jsgraph()->graph()->NewNode(
725 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
726 248 : } else if (IsWord(output_rep)) {
727 31 : if (output_type.Is(Type::Signed32())) {
728 : // int32 -> float64 -> float32
729 26 : op = machine()->ChangeInt32ToFloat64();
730 : node = jsgraph()->graph()->NewNode(op, node);
731 26 : op = machine()->TruncateFloat64ToFloat32();
732 5 : } else if (output_type.Is(Type::Unsigned32()) ||
733 : truncation.IsUsedAsWord32()) {
734 : // Either the output is uint32 or the uses only care about the
735 : // low 32 bits (so we can pick uint32 safely).
736 :
737 : // uint32 -> float64 -> float32
738 5 : op = machine()->ChangeUint32ToFloat64();
739 : node = jsgraph()->graph()->NewNode(op, node);
740 5 : op = machine()->TruncateFloat64ToFloat32();
741 : }
742 217 : } else if (IsAnyTagged(output_rep)) {
743 5 : if (output_type.Is(Type::NumberOrOddball())) {
744 : // tagged -> float64 -> float32
745 5 : if (output_type.Is(Type::Number())) {
746 5 : op = simplified()->ChangeTaggedToFloat64();
747 : } else {
748 0 : op = simplified()->TruncateTaggedToFloat64();
749 : }
750 : node = jsgraph()->graph()->NewNode(op, node);
751 5 : op = machine()->TruncateFloat64ToFloat32();
752 : }
753 212 : } else if (output_rep == MachineRepresentation::kCompressed) {
754 : // TODO(v8:8977): Specialise here
755 0 : op = machine()->ChangeCompressedToTagged();
756 : node = jsgraph()->graph()->NewNode(op, node);
757 : return GetFloat32RepresentationFor(node, MachineRepresentation::kTagged,
758 0 : output_type, truncation);
759 212 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
760 : // TODO(v8:8977): Specialise here
761 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
762 : node = jsgraph()->graph()->NewNode(op, node);
763 : return GetFloat32RepresentationFor(
764 0 : node, MachineRepresentation::kTaggedSigned, output_type, truncation);
765 212 : } else if (output_rep == MachineRepresentation::kFloat64) {
766 197 : op = machine()->TruncateFloat64ToFloat32();
767 15 : } else if (output_rep == MachineRepresentation::kWord64) {
768 10 : if (output_type.Is(cache_->kSafeInteger)) {
769 : // int64 -> float64 -> float32
770 5 : op = machine()->ChangeInt64ToFloat64();
771 : node = jsgraph()->graph()->NewNode(op, node);
772 5 : op = machine()->TruncateFloat64ToFloat32();
773 : }
774 : }
775 248 : if (op == nullptr) {
776 : return TypeError(node, output_rep, output_type,
777 10 : MachineRepresentation::kFloat32);
778 : }
779 238 : return jsgraph()->graph()->NewNode(op, node);
780 : }
781 :
782 251856 : Node* RepresentationChanger::GetFloat64RepresentationFor(
783 : Node* node, MachineRepresentation output_rep, Type output_type,
784 : Node* use_node, UseInfo use_info) {
785 : NumberMatcher m(node);
786 251856 : if (m.HasValue()) {
787 : switch (use_info.type_check()) {
788 : case TypeCheckKind::kNone:
789 : case TypeCheckKind::kNumber:
790 : case TypeCheckKind::kNumberOrOddball:
791 145349 : return jsgraph()->Float64Constant(m.Value());
792 : case TypeCheckKind::kHeapObject:
793 : case TypeCheckKind::kSigned32:
794 : case TypeCheckKind::kSigned64:
795 : case TypeCheckKind::kSignedSmall:
796 : break;
797 : }
798 : }
799 : // Select the correct X -> Float64 operator.
800 : const Operator* op = nullptr;
801 106506 : if (output_type.Is(Type::None())) {
802 : // This is an impossible value; it should not be used at runtime.
803 0 : return jsgraph()->graph()->NewNode(
804 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
805 106506 : } else if (IsWord(output_rep)) {
806 70843 : if (output_type.Is(Type::Signed32()) ||
807 12 : (output_type.Is(Type::Signed32OrMinusZero()) &&
808 : use_info.truncation().IdentifiesZeroAndMinusZero())) {
809 35288 : op = machine()->ChangeInt32ToFloat64();
810 85 : } else if (output_type.Is(Type::Unsigned32()) ||
811 : use_info.truncation().IsUsedAsWord32()) {
812 : // Either the output is uint32 or the uses only care about the
813 : // low 32 bits (so we can pick uint32 safely).
814 85 : op = machine()->ChangeUint32ToFloat64();
815 : }
816 71133 : } else if (output_rep == MachineRepresentation::kBit) {
817 0 : CHECK(output_type.Is(Type::Boolean()));
818 0 : if (use_info.truncation().IsUsedAsFloat64()) {
819 0 : op = machine()->ChangeUint32ToFloat64();
820 : } else {
821 0 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
822 : Node* unreachable =
823 0 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotAHeapNumber);
824 0 : return jsgraph()->graph()->NewNode(
825 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
826 0 : unreachable);
827 : }
828 142266 : } else if (output_rep == MachineRepresentation::kTagged ||
829 75515 : output_rep == MachineRepresentation::kTaggedSigned ||
830 : output_rep == MachineRepresentation::kTaggedPointer) {
831 68848 : if (output_type.Is(Type::Undefined())) {
832 244 : return jsgraph()->Float64Constant(
833 244 : std::numeric_limits<double>::quiet_NaN());
834 :
835 68604 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
836 1330 : node = InsertChangeTaggedSignedToInt32(node);
837 1330 : op = machine()->ChangeInt32ToFloat64();
838 67274 : } else if (output_type.Is(Type::Number())) {
839 11506 : op = simplified()->ChangeTaggedToFloat64();
840 55768 : } else if (output_type.Is(Type::NumberOrOddball())) {
841 : // TODO(jarin) Here we should check that truncation is Number.
842 1438 : op = simplified()->TruncateTaggedToFloat64();
843 108660 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
844 46498 : (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
845 46498 : !output_type.Maybe(Type::BooleanOrNullOrNumber()))) {
846 : op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber,
847 8296 : use_info.feedback());
848 46034 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
849 : op = simplified()->CheckedTaggedToFloat64(
850 46034 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
851 : }
852 2285 : } else if (output_rep == MachineRepresentation::kCompressed) {
853 : // TODO(v8:8977): Specialise here
854 0 : op = machine()->ChangeCompressedToTagged();
855 : node = jsgraph()->graph()->NewNode(op, node);
856 : return GetFloat64RepresentationFor(node, MachineRepresentation::kTagged,
857 0 : output_type, use_node, use_info);
858 2285 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
859 : // TODO(v8:8977): Specialise here
860 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
861 : node = jsgraph()->graph()->NewNode(op, node);
862 : return GetFloat64RepresentationFor(node,
863 : MachineRepresentation::kTaggedSigned,
864 0 : output_type, use_node, use_info);
865 2285 : } else if (output_rep == MachineRepresentation::kFloat32) {
866 2201 : op = machine()->ChangeFloat32ToFloat64();
867 84 : } else if (output_rep == MachineRepresentation::kWord64) {
868 168 : if (output_type.Is(cache_->kSafeInteger)) {
869 84 : op = machine()->ChangeInt64ToFloat64();
870 : }
871 : }
872 106262 : if (op == nullptr) {
873 : return TypeError(node, output_rep, output_type,
874 0 : MachineRepresentation::kFloat64);
875 : }
876 106262 : return InsertConversion(node, op, use_node);
877 : }
878 :
879 0 : Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
880 1036242 : return jsgraph()->Int32Constant(DoubleToInt32(value));
881 : }
882 :
883 7 : Node* RepresentationChanger::InsertUnconditionalDeopt(Node* node,
884 : DeoptimizeReason reason) {
885 7 : Node* effect = NodeProperties::GetEffectInput(node);
886 7 : Node* control = NodeProperties::GetControlInput(node);
887 : effect =
888 14 : jsgraph()->graph()->NewNode(simplified()->CheckIf(reason),
889 : jsgraph()->Int32Constant(0), effect, control);
890 7 : Node* unreachable = effect = jsgraph()->graph()->NewNode(
891 : jsgraph()->common()->Unreachable(), effect, control);
892 7 : NodeProperties::ReplaceEffectInput(node, effect);
893 7 : return unreachable;
894 : }
895 :
896 1349300 : Node* RepresentationChanger::GetWord32RepresentationFor(
897 : Node* node, MachineRepresentation output_rep, Type output_type,
898 : Node* use_node, UseInfo use_info) {
899 : // Eagerly fold representation changes for constants.
900 1349300 : switch (node->opcode()) {
901 : case IrOpcode::kInt32Constant:
902 : case IrOpcode::kInt64Constant:
903 : case IrOpcode::kFloat32Constant:
904 : case IrOpcode::kFloat64Constant:
905 0 : UNREACHABLE();
906 : break;
907 : case IrOpcode::kNumberConstant: {
908 1036376 : double const fv = OpParameter<double>(node->op());
909 2072752 : if (use_info.type_check() == TypeCheckKind::kNone ||
910 993 : ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
911 945 : use_info.type_check() == TypeCheckKind::kSigned32 ||
912 270 : use_info.type_check() == TypeCheckKind::kNumber ||
913 84773 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) &&
914 : IsInt32Double(fv))) {
915 1036199 : return MakeTruncatedInt32Constant(fv);
916 : }
917 : break;
918 : }
919 : default:
920 : break;
921 : }
922 :
923 : // Select the correct X -> Word32 operator.
924 : const Operator* op = nullptr;
925 313036 : if (output_type.Is(Type::None())) {
926 : // This is an impossible value; it should not be used at runtime.
927 21 : return jsgraph()->graph()->NewNode(
928 21 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
929 313015 : } else if (output_rep == MachineRepresentation::kBit) {
930 60 : CHECK(output_type.Is(Type::Boolean()));
931 60 : if (use_info.truncation().IsUsedAsWord32()) {
932 : return node;
933 : } else {
934 0 : CHECK(Truncation::Any(kIdentifyZeros)
935 : .IsLessGeneralThan(use_info.truncation()));
936 0 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
937 : Node* unreachable =
938 0 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
939 0 : return jsgraph()->graph()->NewNode(
940 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32),
941 0 : unreachable);
942 : }
943 312955 : } else if (output_rep == MachineRepresentation::kFloat64) {
944 8865 : if (output_type.Is(Type::Signed32())) {
945 804 : op = machine()->ChangeFloat64ToInt32();
946 8061 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
947 : use_info.type_check() == TypeCheckKind::kSigned32) {
948 2427 : op = simplified()->CheckedFloat64ToInt32(
949 2427 : output_type.Maybe(Type::MinusZero())
950 : ? use_info.minus_zero_check()
951 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
952 2427 : use_info.feedback());
953 5634 : } else if (output_type.Is(Type::Unsigned32())) {
954 6 : op = machine()->ChangeFloat64ToUint32();
955 5628 : } else if (use_info.truncation().IsUsedAsWord32()) {
956 5628 : op = machine()->TruncateFloat64ToWord32();
957 : } else {
958 : return TypeError(node, output_rep, output_type,
959 0 : MachineRepresentation::kWord32);
960 : }
961 304090 : } else if (output_rep == MachineRepresentation::kFloat32) {
962 15 : node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
963 15 : if (output_type.Is(Type::Signed32())) {
964 5 : op = machine()->ChangeFloat64ToInt32();
965 10 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
966 : use_info.type_check() == TypeCheckKind::kSigned32) {
967 0 : op = simplified()->CheckedFloat64ToInt32(
968 0 : output_type.Maybe(Type::MinusZero())
969 : ? use_info.minus_zero_check()
970 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
971 0 : use_info.feedback());
972 10 : } else if (output_type.Is(Type::Unsigned32())) {
973 5 : op = machine()->ChangeFloat64ToUint32();
974 5 : } else if (use_info.truncation().IsUsedAsWord32()) {
975 5 : op = machine()->TruncateFloat64ToWord32();
976 : } else {
977 : return TypeError(node, output_rep, output_type,
978 0 : MachineRepresentation::kWord32);
979 : }
980 304075 : } else if (IsAnyTagged(output_rep)) {
981 304013 : if (output_rep == MachineRepresentation::kTaggedSigned &&
982 : output_type.Is(Type::SignedSmall())) {
983 77615 : op = simplified()->ChangeTaggedSignedToInt32();
984 148771 : } else if (output_type.Is(Type::Signed32())) {
985 2363 : op = simplified()->ChangeTaggedToInt32();
986 146408 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
987 141429 : op = simplified()->CheckedTaggedSignedToInt32(use_info.feedback());
988 4979 : } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
989 2520 : op = simplified()->CheckedTaggedToInt32(
990 2520 : output_type.Maybe(Type::MinusZero())
991 : ? use_info.minus_zero_check()
992 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
993 2520 : use_info.feedback());
994 2459 : } else if (output_type.Is(Type::Unsigned32())) {
995 516 : op = simplified()->ChangeTaggedToUint32();
996 1943 : } else if (use_info.truncation().IsUsedAsWord32()) {
997 1943 : if (output_type.Is(Type::NumberOrOddball())) {
998 611 : op = simplified()->TruncateTaggedToWord32();
999 1332 : } else if (use_info.type_check() == TypeCheckKind::kNumber) {
1000 : op = simplified()->CheckedTruncateTaggedToWord32(
1001 865 : CheckTaggedInputMode::kNumber, use_info.feedback());
1002 467 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
1003 : op = simplified()->CheckedTruncateTaggedToWord32(
1004 467 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
1005 : } else {
1006 : return TypeError(node, output_rep, output_type,
1007 0 : MachineRepresentation::kWord32);
1008 : }
1009 : } else {
1010 : return TypeError(node, output_rep, output_type,
1011 0 : MachineRepresentation::kWord32);
1012 : }
1013 77677 : } else if (output_rep == MachineRepresentation::kCompressed) {
1014 : // TODO(v8:8977): Specialise here
1015 0 : op = machine()->ChangeCompressedToTagged();
1016 : node = jsgraph()->graph()->NewNode(op, node);
1017 : return GetWord32RepresentationFor(node, MachineRepresentation::kTagged,
1018 0 : output_type, use_node, use_info);
1019 77677 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
1020 : // TODO(v8:8977): Specialise here
1021 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
1022 : node = jsgraph()->graph()->NewNode(op, node);
1023 : return GetWord32RepresentationFor(node,
1024 : MachineRepresentation::kTaggedSigned,
1025 0 : output_type, use_node, use_info);
1026 77677 : } else if (output_rep == MachineRepresentation::kWord32) {
1027 : // Only the checked case should get here, the non-checked case is
1028 : // handled in GetRepresentationFor.
1029 77611 : if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
1030 : use_info.type_check() == TypeCheckKind::kSigned32) {
1031 : bool indentify_zeros = use_info.truncation().IdentifiesZeroAndMinusZero();
1032 155150 : if (output_type.Is(Type::Signed32()) ||
1033 276 : (indentify_zeros && output_type.Is(Type::Signed32OrMinusZero()))) {
1034 : return node;
1035 830 : } else if (output_type.Is(Type::Unsigned32()) ||
1036 0 : (indentify_zeros &&
1037 : output_type.Is(Type::Unsigned32OrMinusZero()))) {
1038 415 : op = simplified()->CheckedUint32ToInt32(use_info.feedback());
1039 : } else {
1040 : return TypeError(node, output_rep, output_type,
1041 0 : MachineRepresentation::kWord32);
1042 : }
1043 36 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
1044 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
1045 : return node;
1046 : }
1047 66 : } else if (output_rep == MachineRepresentation::kWord8 ||
1048 : output_rep == MachineRepresentation::kWord16) {
1049 : DCHECK_EQ(MachineRepresentation::kWord32, use_info.representation());
1050 : DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall ||
1051 : use_info.type_check() == TypeCheckKind::kSigned32);
1052 : return node;
1053 66 : } else if (output_rep == MachineRepresentation::kWord64) {
1054 103 : if (output_type.Is(Type::Signed32()) ||
1055 : output_type.Is(Type::Unsigned32())) {
1056 38 : op = machine()->TruncateInt64ToInt32();
1057 79 : } else if (output_type.Is(cache_->kSafeInteger) &&
1058 : use_info.truncation().IsUsedAsWord32()) {
1059 5 : op = machine()->TruncateInt64ToInt32();
1060 23 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
1061 : use_info.type_check() == TypeCheckKind::kSigned32) {
1062 36 : if (output_type.Is(cache_->kPositiveSafeInteger)) {
1063 5 : op = simplified()->CheckedUint64ToInt32(use_info.feedback());
1064 26 : } else if (output_type.Is(cache_->kSafeInteger)) {
1065 13 : op = simplified()->CheckedInt64ToInt32(use_info.feedback());
1066 : } else {
1067 : return TypeError(node, output_rep, output_type,
1068 0 : MachineRepresentation::kWord32);
1069 : }
1070 : } else {
1071 : return TypeError(node, output_rep, output_type,
1072 5 : MachineRepresentation::kWord32);
1073 : }
1074 : }
1075 :
1076 235746 : if (op == nullptr) {
1077 : return TypeError(node, output_rep, output_type,
1078 0 : MachineRepresentation::kWord32);
1079 : }
1080 235746 : return InsertConversion(node, op, use_node);
1081 : }
1082 :
1083 482447 : Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
1084 : Node* use_node) {
1085 482447 : if (op->ControlInputCount() > 0) {
1086 : // If the operator can deoptimize (which means it has control
1087 : // input), we need to connect it to the effect and control chains.
1088 262031 : Node* effect = NodeProperties::GetEffectInput(use_node);
1089 262009 : Node* control = NodeProperties::GetControlInput(use_node);
1090 : Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
1091 262033 : NodeProperties::ReplaceEffectInput(use_node, conversion);
1092 262009 : return conversion;
1093 : }
1094 220416 : return jsgraph()->graph()->NewNode(op, node);
1095 : }
1096 :
1097 321173 : Node* RepresentationChanger::GetBitRepresentationFor(
1098 : Node* node, MachineRepresentation output_rep, Type output_type) {
1099 : // Eagerly fold representation changes for constants.
1100 321173 : switch (node->opcode()) {
1101 : case IrOpcode::kHeapConstant: {
1102 : HeapObjectMatcher m(node);
1103 131777 : if (m.Is(factory()->false_value())) {
1104 90385 : return jsgraph()->Int32Constant(0);
1105 41392 : } else if (m.Is(factory()->true_value())) {
1106 41392 : return jsgraph()->Int32Constant(1);
1107 : }
1108 : break;
1109 : }
1110 : default:
1111 : break;
1112 : }
1113 : // Select the correct X -> Bit operator.
1114 : const Operator* op;
1115 189396 : if (output_type.Is(Type::None())) {
1116 : // This is an impossible value; it should not be used at runtime.
1117 219 : return jsgraph()->graph()->NewNode(
1118 219 : jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
1119 189177 : } else if (output_rep == MachineRepresentation::kTagged ||
1120 : output_rep == MachineRepresentation::kTaggedPointer) {
1121 189163 : if (output_type.Is(Type::BooleanOrNullOrUndefined())) {
1122 : // true is the only trueish Oddball.
1123 140825 : op = simplified()->ChangeTaggedToBit();
1124 : } else {
1125 96305 : if (output_rep == MachineRepresentation::kTagged &&
1126 47967 : output_type.Maybe(Type::SignedSmall())) {
1127 47945 : op = simplified()->TruncateTaggedToBit();
1128 : } else {
1129 : // The {output_type} either doesn't include the Smi range,
1130 : // or the {output_rep} is known to be TaggedPointer.
1131 393 : op = simplified()->TruncateTaggedPointerToBit();
1132 : }
1133 : }
1134 14 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1135 0 : node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
1136 : jsgraph()->IntPtrConstant(0));
1137 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1138 0 : jsgraph()->Int32Constant(0));
1139 14 : } else if (output_rep == MachineRepresentation::kCompressed) {
1140 : // TODO(v8:8977): Specialise here
1141 0 : op = machine()->ChangeCompressedToTagged();
1142 : node = jsgraph()->graph()->NewNode(op, node);
1143 : return GetBitRepresentationFor(node, MachineRepresentation::kTagged,
1144 0 : output_type);
1145 14 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
1146 : // TODO(v8:8977): Specialise here
1147 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
1148 : node = jsgraph()->graph()->NewNode(op, node);
1149 : return GetBitRepresentationFor(node, MachineRepresentation::kTaggedSigned,
1150 0 : output_type);
1151 14 : } else if (IsWord(output_rep)) {
1152 0 : node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1153 : jsgraph()->Int32Constant(0));
1154 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1155 0 : jsgraph()->Int32Constant(0));
1156 14 : } else if (output_rep == MachineRepresentation::kWord64) {
1157 0 : node = jsgraph()->graph()->NewNode(machine()->Word64Equal(), node,
1158 : jsgraph()->Int64Constant(0));
1159 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1160 0 : jsgraph()->Int32Constant(0));
1161 14 : } else if (output_rep == MachineRepresentation::kFloat32) {
1162 0 : node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
1163 0 : return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
1164 0 : jsgraph()->Float32Constant(0.0), node);
1165 14 : } else if (output_rep == MachineRepresentation::kFloat64) {
1166 14 : node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
1167 14 : return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
1168 14 : jsgraph()->Float64Constant(0.0), node);
1169 : } else {
1170 : return TypeError(node, output_rep, output_type,
1171 0 : MachineRepresentation::kBit);
1172 : }
1173 189163 : return jsgraph()->graph()->NewNode(op, node);
1174 : }
1175 :
1176 185070 : Node* RepresentationChanger::GetWord64RepresentationFor(
1177 : Node* node, MachineRepresentation output_rep, Type output_type,
1178 : Node* use_node, UseInfo use_info) {
1179 : // Eagerly fold representation changes for constants.
1180 185070 : switch (node->opcode()) {
1181 : case IrOpcode::kInt32Constant:
1182 : case IrOpcode::kInt64Constant:
1183 : case IrOpcode::kFloat32Constant:
1184 : case IrOpcode::kFloat64Constant:
1185 0 : UNREACHABLE();
1186 : break;
1187 : case IrOpcode::kNumberConstant: {
1188 149014 : double const fv = OpParameter<double>(node->op());
1189 : using limits = std::numeric_limits<int64_t>;
1190 149014 : if (fv <= limits::max() && fv >= limits::min()) {
1191 149007 : int64_t const iv = static_cast<int64_t>(fv);
1192 149007 : if (static_cast<double>(iv) == fv) {
1193 149007 : return jsgraph()->Int64Constant(iv);
1194 : }
1195 : }
1196 : break;
1197 : }
1198 : default:
1199 : break;
1200 : }
1201 :
1202 : // Select the correct X -> Word64 operator.
1203 : const Operator* op;
1204 36063 : if (output_type.Is(Type::None())) {
1205 : // This is an impossible value; it should not be used at runtime.
1206 83 : return jsgraph()->graph()->NewNode(
1207 83 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord64), node);
1208 35980 : } else if (output_rep == MachineRepresentation::kBit) {
1209 7 : CHECK(output_type.Is(Type::Boolean()));
1210 7 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
1211 : Node* unreachable =
1212 7 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
1213 7 : return jsgraph()->graph()->NewNode(
1214 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1215 7 : unreachable);
1216 35973 : } else if (IsWord(output_rep)) {
1217 35442 : if (output_type.Is(Type::Unsigned32())) {
1218 34646 : op = machine()->ChangeUint32ToUint64();
1219 796 : } else if (output_type.Is(Type::Signed32())) {
1220 791 : op = machine()->ChangeInt32ToInt64();
1221 : } else {
1222 : return TypeError(node, output_rep, output_type,
1223 5 : MachineRepresentation::kWord64);
1224 : }
1225 531 : } else if (output_rep == MachineRepresentation::kFloat32) {
1226 66 : if (output_type.Is(cache_->kInt64)) {
1227 : // float32 -> float64 -> int64
1228 15 : node = InsertChangeFloat32ToFloat64(node);
1229 15 : op = machine()->ChangeFloat64ToInt64();
1230 36 : } else if (output_type.Is(cache_->kUint64)) {
1231 : // float32 -> float64 -> uint64
1232 5 : node = InsertChangeFloat32ToFloat64(node);
1233 5 : op = machine()->ChangeFloat64ToUint64();
1234 13 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1235 : // float32 -> float64 -> int64
1236 13 : node = InsertChangeFloat32ToFloat64(node);
1237 13 : op = simplified()->CheckedFloat64ToInt64(
1238 13 : output_type.Maybe(Type::MinusZero())
1239 : ? use_info.minus_zero_check()
1240 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1241 13 : use_info.feedback());
1242 : } else {
1243 : return TypeError(node, output_rep, output_type,
1244 0 : MachineRepresentation::kWord64);
1245 : }
1246 498 : } else if (output_rep == MachineRepresentation::kFloat64) {
1247 118 : if (output_type.Is(cache_->kInt64)) {
1248 41 : op = machine()->ChangeFloat64ToInt64();
1249 36 : } else if (output_type.Is(cache_->kUint64)) {
1250 5 : op = machine()->ChangeFloat64ToUint64();
1251 13 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1252 13 : op = simplified()->CheckedFloat64ToInt64(
1253 13 : output_type.Maybe(Type::MinusZero())
1254 : ? use_info.minus_zero_check()
1255 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1256 13 : use_info.feedback());
1257 : } else {
1258 : return TypeError(node, output_rep, output_type,
1259 0 : MachineRepresentation::kWord64);
1260 : }
1261 439 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1262 309 : if (output_type.Is(Type::SignedSmall())) {
1263 309 : op = simplified()->ChangeTaggedSignedToInt64();
1264 : } else {
1265 : return TypeError(node, output_rep, output_type,
1266 0 : MachineRepresentation::kWord64);
1267 : }
1268 130 : } else if (CanBeTaggedPointer(output_rep)) {
1269 260 : if (output_type.Is(cache_->kInt64)) {
1270 23 : op = simplified()->ChangeTaggedToInt64();
1271 107 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1272 97 : op = simplified()->CheckedTaggedToInt64(
1273 97 : output_type.Maybe(Type::MinusZero())
1274 : ? use_info.minus_zero_check()
1275 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1276 97 : use_info.feedback());
1277 : } else {
1278 : return TypeError(node, output_rep, output_type,
1279 10 : MachineRepresentation::kWord64);
1280 : }
1281 0 : } else if (output_rep == MachineRepresentation::kCompressed) {
1282 : // TODO(v8:8977): Specialise here
1283 0 : op = machine()->ChangeCompressedToTagged();
1284 : node = jsgraph()->graph()->NewNode(op, node);
1285 : return GetWord64RepresentationFor(node, MachineRepresentation::kTagged,
1286 0 : output_type, use_node, use_info);
1287 0 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
1288 : // TODO(v8:8977): Specialise here
1289 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
1290 : node = jsgraph()->graph()->NewNode(op, node);
1291 : return GetWord64RepresentationFor(node,
1292 : MachineRepresentation::kTaggedSigned,
1293 0 : output_type, use_node, use_info);
1294 : } else {
1295 : return TypeError(node, output_rep, output_type,
1296 0 : MachineRepresentation::kWord64);
1297 : }
1298 35958 : return InsertConversion(node, op, use_node);
1299 : }
1300 :
1301 212128 : const Operator* RepresentationChanger::Int32OperatorFor(
1302 : IrOpcode::Value opcode) {
1303 212128 : switch (opcode) {
1304 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1305 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1306 : case IrOpcode::kNumberAdd:
1307 102770 : return machine()->Int32Add();
1308 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1309 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1310 : case IrOpcode::kNumberSubtract:
1311 4737 : return machine()->Int32Sub();
1312 : case IrOpcode::kSpeculativeNumberMultiply:
1313 : case IrOpcode::kNumberMultiply:
1314 993 : return machine()->Int32Mul();
1315 : case IrOpcode::kSpeculativeNumberDivide:
1316 : case IrOpcode::kNumberDivide:
1317 0 : return machine()->Int32Div();
1318 : case IrOpcode::kSpeculativeNumberModulus:
1319 : case IrOpcode::kNumberModulus:
1320 0 : return machine()->Int32Mod();
1321 : case IrOpcode::kSpeculativeNumberBitwiseOr: // Fall through.
1322 : case IrOpcode::kNumberBitwiseOr:
1323 19042 : return machine()->Word32Or();
1324 : case IrOpcode::kSpeculativeNumberBitwiseXor: // Fall through.
1325 : case IrOpcode::kNumberBitwiseXor:
1326 1121 : return machine()->Word32Xor();
1327 : case IrOpcode::kSpeculativeNumberBitwiseAnd: // Fall through.
1328 : case IrOpcode::kNumberBitwiseAnd:
1329 8726 : return machine()->Word32And();
1330 : case IrOpcode::kNumberEqual:
1331 : case IrOpcode::kSpeculativeNumberEqual:
1332 9758 : return machine()->Word32Equal();
1333 : case IrOpcode::kNumberLessThan:
1334 : case IrOpcode::kSpeculativeNumberLessThan:
1335 63495 : return machine()->Int32LessThan();
1336 : case IrOpcode::kNumberLessThanOrEqual:
1337 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1338 1486 : return machine()->Int32LessThanOrEqual();
1339 : default:
1340 0 : UNREACHABLE();
1341 : }
1342 : }
1343 :
1344 150112 : const Operator* RepresentationChanger::Int32OverflowOperatorFor(
1345 : IrOpcode::Value opcode) {
1346 150112 : switch (opcode) {
1347 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1348 140900 : return simplified()->CheckedInt32Add();
1349 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1350 7705 : return simplified()->CheckedInt32Sub();
1351 : case IrOpcode::kSpeculativeNumberDivide:
1352 244 : return simplified()->CheckedInt32Div();
1353 : case IrOpcode::kSpeculativeNumberModulus:
1354 1263 : return simplified()->CheckedInt32Mod();
1355 : default:
1356 0 : UNREACHABLE();
1357 : }
1358 : }
1359 :
1360 478 : const Operator* RepresentationChanger::Int64OperatorFor(
1361 : IrOpcode::Value opcode) {
1362 : switch (opcode) {
1363 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1364 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1365 : case IrOpcode::kNumberAdd:
1366 258 : return machine()->Int64Add();
1367 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1368 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1369 : case IrOpcode::kNumberSubtract:
1370 220 : return machine()->Int64Sub();
1371 : default:
1372 0 : UNREACHABLE();
1373 : }
1374 : }
1375 :
1376 14457 : const Operator* RepresentationChanger::TaggedSignedOperatorFor(
1377 : IrOpcode::Value opcode) {
1378 14457 : switch (opcode) {
1379 : case IrOpcode::kSpeculativeNumberLessThan:
1380 : return machine()->Is32() ? machine()->Int32LessThan()
1381 5291 : : machine()->Int64LessThan();
1382 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1383 : return machine()->Is32() ? machine()->Int32LessThanOrEqual()
1384 240 : : machine()->Int64LessThanOrEqual();
1385 : case IrOpcode::kSpeculativeNumberEqual:
1386 : return machine()->Is32() ? machine()->Word32Equal()
1387 8926 : : machine()->Word64Equal();
1388 : default:
1389 0 : UNREACHABLE();
1390 : }
1391 : }
1392 :
1393 36139 : const Operator* RepresentationChanger::Uint32OperatorFor(
1394 : IrOpcode::Value opcode) {
1395 36139 : switch (opcode) {
1396 : case IrOpcode::kNumberAdd:
1397 0 : return machine()->Int32Add();
1398 : case IrOpcode::kNumberSubtract:
1399 0 : return machine()->Int32Sub();
1400 : case IrOpcode::kSpeculativeNumberMultiply:
1401 : case IrOpcode::kNumberMultiply:
1402 0 : return machine()->Int32Mul();
1403 : case IrOpcode::kSpeculativeNumberDivide:
1404 : case IrOpcode::kNumberDivide:
1405 0 : return machine()->Uint32Div();
1406 : case IrOpcode::kSpeculativeNumberModulus:
1407 : case IrOpcode::kNumberModulus:
1408 0 : return machine()->Uint32Mod();
1409 : case IrOpcode::kNumberEqual:
1410 : case IrOpcode::kSpeculativeNumberEqual:
1411 12845 : return machine()->Word32Equal();
1412 : case IrOpcode::kNumberLessThan:
1413 : case IrOpcode::kSpeculativeNumberLessThan:
1414 20821 : return machine()->Uint32LessThan();
1415 : case IrOpcode::kNumberLessThanOrEqual:
1416 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1417 1573 : return machine()->Uint32LessThanOrEqual();
1418 : case IrOpcode::kNumberClz32:
1419 28 : return machine()->Word32Clz();
1420 : case IrOpcode::kNumberImul:
1421 872 : return machine()->Int32Mul();
1422 : default:
1423 0 : UNREACHABLE();
1424 : }
1425 : }
1426 :
1427 113 : const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
1428 : IrOpcode::Value opcode) {
1429 113 : switch (opcode) {
1430 : case IrOpcode::kSpeculativeNumberDivide:
1431 69 : return simplified()->CheckedUint32Div();
1432 : case IrOpcode::kSpeculativeNumberModulus:
1433 44 : return simplified()->CheckedUint32Mod();
1434 : default:
1435 0 : UNREACHABLE();
1436 : }
1437 : }
1438 :
1439 167961 : const Operator* RepresentationChanger::Float64OperatorFor(
1440 : IrOpcode::Value opcode) {
1441 167961 : switch (opcode) {
1442 : case IrOpcode::kSpeculativeNumberAdd:
1443 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1444 : case IrOpcode::kNumberAdd:
1445 73094 : return machine()->Float64Add();
1446 : case IrOpcode::kSpeculativeNumberSubtract:
1447 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1448 : case IrOpcode::kNumberSubtract:
1449 1198 : return machine()->Float64Sub();
1450 : case IrOpcode::kSpeculativeNumberMultiply:
1451 : case IrOpcode::kNumberMultiply:
1452 11613 : return machine()->Float64Mul();
1453 : case IrOpcode::kSpeculativeNumberDivide:
1454 : case IrOpcode::kNumberDivide:
1455 15341 : return machine()->Float64Div();
1456 : case IrOpcode::kSpeculativeNumberModulus:
1457 : case IrOpcode::kNumberModulus:
1458 563 : return machine()->Float64Mod();
1459 : case IrOpcode::kNumberEqual:
1460 : case IrOpcode::kSpeculativeNumberEqual:
1461 16995 : return machine()->Float64Equal();
1462 : case IrOpcode::kNumberLessThan:
1463 : case IrOpcode::kSpeculativeNumberLessThan:
1464 3767 : return machine()->Float64LessThan();
1465 : case IrOpcode::kNumberLessThanOrEqual:
1466 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1467 264 : return machine()->Float64LessThanOrEqual();
1468 : case IrOpcode::kNumberAbs:
1469 190 : return machine()->Float64Abs();
1470 : case IrOpcode::kNumberAcos:
1471 0 : return machine()->Float64Acos();
1472 : case IrOpcode::kNumberAcosh:
1473 0 : return machine()->Float64Acosh();
1474 : case IrOpcode::kNumberAsin:
1475 7 : return machine()->Float64Asin();
1476 : case IrOpcode::kNumberAsinh:
1477 0 : return machine()->Float64Asinh();
1478 : case IrOpcode::kNumberAtan:
1479 0 : return machine()->Float64Atan();
1480 : case IrOpcode::kNumberAtanh:
1481 0 : return machine()->Float64Atanh();
1482 : case IrOpcode::kNumberAtan2:
1483 0 : return machine()->Float64Atan2();
1484 : case IrOpcode::kNumberCbrt:
1485 0 : return machine()->Float64Cbrt();
1486 : case IrOpcode::kNumberCeil:
1487 6675 : return machine()->Float64RoundUp().placeholder();
1488 : case IrOpcode::kNumberCos:
1489 14 : return machine()->Float64Cos();
1490 : case IrOpcode::kNumberCosh:
1491 7 : return machine()->Float64Cosh();
1492 : case IrOpcode::kNumberExp:
1493 32 : return machine()->Float64Exp();
1494 : case IrOpcode::kNumberExpm1:
1495 14 : return machine()->Float64Expm1();
1496 : case IrOpcode::kNumberFloor:
1497 27872 : return machine()->Float64RoundDown().placeholder();
1498 : case IrOpcode::kNumberFround:
1499 1288 : return machine()->TruncateFloat64ToFloat32();
1500 : case IrOpcode::kNumberLog:
1501 131 : return machine()->Float64Log();
1502 : case IrOpcode::kNumberLog1p:
1503 0 : return machine()->Float64Log1p();
1504 : case IrOpcode::kNumberLog2:
1505 0 : return machine()->Float64Log2();
1506 : case IrOpcode::kNumberLog10:
1507 0 : return machine()->Float64Log10();
1508 : case IrOpcode::kNumberMax:
1509 72 : return machine()->Float64Max();
1510 : case IrOpcode::kNumberMin:
1511 148 : return machine()->Float64Min();
1512 : case IrOpcode::kNumberPow:
1513 912 : return machine()->Float64Pow();
1514 : case IrOpcode::kNumberSin:
1515 31 : return machine()->Float64Sin();
1516 : case IrOpcode::kNumberSinh:
1517 7 : return machine()->Float64Sinh();
1518 : case IrOpcode::kNumberSqrt:
1519 51 : return machine()->Float64Sqrt();
1520 : case IrOpcode::kNumberTan:
1521 28 : return machine()->Float64Tan();
1522 : case IrOpcode::kNumberTanh:
1523 7 : return machine()->Float64Tanh();
1524 : case IrOpcode::kNumberTrunc:
1525 6914 : return machine()->Float64RoundTruncate().placeholder();
1526 : case IrOpcode::kNumberSilenceNaN:
1527 726 : return machine()->Float64SilenceNaN();
1528 : default:
1529 0 : UNREACHABLE();
1530 : }
1531 : }
1532 :
1533 35 : Node* RepresentationChanger::TypeError(Node* node,
1534 : MachineRepresentation output_rep,
1535 : Type output_type,
1536 : MachineRepresentation use) {
1537 35 : type_error_ = true;
1538 35 : if (!testing_type_errors_) {
1539 0 : std::ostringstream out_str;
1540 0 : out_str << output_rep << " (";
1541 0 : output_type.PrintTo(out_str);
1542 0 : out_str << ")";
1543 :
1544 0 : std::ostringstream use_str;
1545 0 : use_str << use;
1546 :
1547 : FATAL(
1548 : "RepresentationChangerError: node #%d:%s of "
1549 : "%s cannot be changed to %s",
1550 : node->id(), node->op()->mnemonic(), out_str.str().c_str(),
1551 0 : use_str.str().c_str());
1552 : }
1553 35 : return node;
1554 : }
1555 :
1556 0 : Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
1557 0 : return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
1558 : }
1559 :
1560 430 : Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
1561 860 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
1562 : }
1563 :
1564 20 : Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
1565 40 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
1566 : }
1567 :
1568 808 : Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
1569 1616 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
1570 : }
1571 :
1572 14 : Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) {
1573 28 : return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
1574 : }
1575 :
1576 1330 : Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
1577 1330 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
1578 1330 : node);
1579 : }
1580 :
1581 0 : Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
1582 0 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
1583 0 : node);
1584 : }
1585 :
1586 0 : Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) {
1587 0 : return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
1588 : }
1589 :
1590 32 : Node* RepresentationChanger::InsertTruncateInt64ToInt32(Node* node) {
1591 64 : return jsgraph()->graph()->NewNode(machine()->TruncateInt64ToInt32(), node);
1592 : }
1593 :
1594 : } // namespace compiler
1595 : } // namespace internal
1596 121996 : } // namespace v8
|