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 100077757 : Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
67 : TruncationKind rep2) {
68 100077757 : if (LessGeneral(rep1, rep2)) return rep2;
69 11521781 : 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 100078708 : IdentifyZeros Truncation::GeneralizeIdentifyZeros(IdentifyZeros i1,
87 : IdentifyZeros i2) {
88 100078708 : if (i1 == i2) {
89 70319720 : return i1;
90 : } else {
91 : return kDistinguishZeros;
92 : }
93 : }
94 :
95 : // static
96 114074376 : bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
97 114074376 : switch (rep1) {
98 : case TruncationKind::kNone:
99 : return true;
100 : case TruncationKind::kBool:
101 711345 : return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
102 : case TruncationKind::kWord32:
103 : return rep2 == TruncationKind::kWord32 ||
104 825934 : rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
105 : case TruncationKind::kFloat64:
106 576546 : return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
107 : case TruncationKind::kAny:
108 59677961 : 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 17571624 : rep == MachineRepresentation::kWord16 ||
123 : rep == MachineRepresentation::kWord32;
124 : }
125 :
126 : } // namespace
127 :
128 464941 : RepresentationChanger::RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
129 464941 : : cache_(TypeCache::Get()),
130 : jsgraph_(jsgraph),
131 : isolate_(isolate),
132 : testing_type_errors_(false),
133 464950 : 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 16063857 : Node* RepresentationChanger::GetRepresentationFor(
140 : Node* node, MachineRepresentation output_rep, Type output_type,
141 : Node* use_node, UseInfo use_info) {
142 16064344 : 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 16063857 : if (use_info.type_check() == TypeCheckKind::kNone ||
150 : output_rep != MachineRepresentation::kWord32) {
151 15968956 : if (use_info.representation() == output_rep) {
152 : // Representations are the same. That's a no-op.
153 : return node;
154 : }
155 17217023 : 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 16032741 : 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 69043 : 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 35185 : 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 13815399 : 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 252548 : use_node, use_info);
200 : case MachineRepresentation::kBit:
201 : DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
202 321724 : 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 1351899 : 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 185521 : use_info);
213 : case MachineRepresentation::kSimd128:
214 : case MachineRepresentation::kNone:
215 : return node;
216 : }
217 0 : UNREACHABLE();
218 : }
219 :
220 69043 : 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 69043 : 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 69043 : 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 69043 : } else if (IsWord(output_rep)) {
241 44425 : if (output_type.Is(Type::Signed31())) {
242 25978 : op = simplified()->ChangeInt31ToTaggedSigned();
243 18447 : } else if (output_type.Is(Type::Signed32())) {
244 : if (SmiValuesAre32Bits()) {
245 18440 : 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 24618 : } 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 24447 : } 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 24424 : } 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 24424 : } else if (CanBeTaggedPointer(output_rep)) {
338 24414 : if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
339 24400 : 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 (CanBeCompressedPointer(output_rep)) {
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 69043 : return InsertConversion(node, op, use_node);
372 : }
373 :
374 35185 : 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 35185 : 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 35185 : 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 35185 : } 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 35185 : } 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 35171 : } 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 35166 : } 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 35166 : } 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 35089 : } else if (CanBeTaggedSigned(output_rep) &&
443 : use_info.type_check() == TypeCheckKind::kHeapObject) {
444 35084 : 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 34745 : op = simplified()->CheckedTaggedToTaggedPointer(use_info.feedback());
450 5 : } else if (output_rep == MachineRepresentation::kCompressedPointer) {
451 5 : op = machine()->ChangeCompressedPointerToTaggedPointer();
452 0 : } else if (CanBeCompressedSigned(output_rep) &&
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 34846 : return InsertConversion(node, op, use_node);
465 : }
466 :
467 13815392 : Node* RepresentationChanger::GetTaggedRepresentationFor(
468 : Node* node, MachineRepresentation output_rep, Type output_type,
469 : Truncation truncation) {
470 : // Eagerly fold representation changes for constants.
471 13815392 : 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 3202855 : 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 118276 : if (output_type.Is(Type::None())) {
492 : // This is an impossible value; it should not be used at runtime.
493 252 : return jsgraph()->graph()->NewNode(
494 252 : jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
495 118024 : } else if (output_rep == MachineRepresentation::kBit) {
496 10548 : if (output_type.Is(Type::Boolean())) {
497 10548 : op = simplified()->ChangeBitToTagged();
498 : } else {
499 : return TypeError(node, output_rep, output_type,
500 0 : MachineRepresentation::kTagged);
501 : }
502 107476 : } else if (IsWord(output_rep)) {
503 35242 : if (output_type.Is(Type::Signed31())) {
504 16292 : op = simplified()->ChangeInt31ToTaggedSigned();
505 38629 : } else if (output_type.Is(Type::Signed32()) ||
506 7 : (output_type.Is(Type::Signed32OrMinusZero()) &&
507 : truncation.IdentifiesZeroAndMinusZero())) {
508 18228 : op = simplified()->ChangeInt32ToTagged();
509 729 : } else if (output_type.Is(Type::Unsigned32()) ||
510 0 : (output_type.Is(Type::Unsigned32OrMinusZero()) &&
511 729 : 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 722 : op = simplified()->ChangeUint32ToTagged();
516 : } else {
517 : return TypeError(node, output_rep, output_type,
518 0 : MachineRepresentation::kTagged);
519 : }
520 72234 : } 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 72091 : } 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 71709 : } else if (output_rep == MachineRepresentation::kFloat64) {
551 71704 : if (output_type.Is(Type::Signed31())) { // float64 -> int32 -> tagged
552 28 : node = InsertChangeFloat64ToInt32(node);
553 28 : op = simplified()->ChangeInt31ToTaggedSigned();
554 71676 : } else if (output_type.Is(
555 : Type::Signed32())) { // float64 -> int32 -> tagged
556 779 : node = InsertChangeFloat64ToInt32(node);
557 779 : op = simplified()->ChangeInt32ToTagged();
558 70897 : } else if (output_type.Is(
559 : Type::Unsigned32())) { // float64 -> uint32 -> tagged
560 20 : node = InsertChangeFloat64ToUint32(node);
561 20 : op = simplified()->ChangeUint32ToTagged();
562 141768 : } else if (output_type.Is(Type::Number()) ||
563 14 : (output_type.Is(Type::NumberOrOddball()) &&
564 : truncation.IsUsedAsFloat64())) {
565 70877 : op = simplified()->ChangeFloat64ToTagged(
566 70877 : output_type.Maybe(Type::MinusZero())
567 : ? CheckForMinusZeroMode::kCheckForMinusZero
568 70877 : : 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 118019 : 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 0 : } else if (output_rep == MachineRepresentation::kBit) {
656 : // TODO(v8:8977): specialize here and below
657 : node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
658 0 : use_node, use_info);
659 0 : op = machine()->ChangeTaggedPointerToCompressedPointer();
660 0 : } else if (IsWord(output_rep)) {
661 : node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
662 0 : use_node, use_info);
663 0 : op = machine()->ChangeTaggedPointerToCompressedPointer();
664 0 : } else if (output_rep == MachineRepresentation::kWord64) {
665 : node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
666 0 : use_node, use_info);
667 0 : op = machine()->ChangeTaggedPointerToCompressedPointer();
668 0 : } else if (output_rep == MachineRepresentation::kFloat32) {
669 : node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
670 0 : use_node, use_info);
671 0 : op = machine()->ChangeTaggedPointerToCompressedPointer();
672 0 : } else if (output_rep == MachineRepresentation::kFloat64) {
673 : node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
674 0 : use_node, use_info);
675 0 : op = machine()->ChangeTaggedPointerToCompressedPointer();
676 : } else {
677 : return TypeError(node, output_rep, output_type,
678 0 : MachineRepresentation::kCompressedPointer);
679 : }
680 5 : return InsertConversion(node, op, use_node);
681 : }
682 :
683 5 : Node* RepresentationChanger::GetCompressedRepresentationFor(
684 : Node* node, MachineRepresentation output_rep, Type output_type,
685 : Truncation truncation) {
686 5 : if (output_rep == MachineRepresentation::kCompressedSigned ||
687 : output_rep == MachineRepresentation::kCompressedPointer) {
688 : // this is a no-op.
689 : return node;
690 : }
691 : // Select the correct X -> Compressed operator.
692 : const Operator* op;
693 5 : if (output_type.Is(Type::None())) {
694 : // This is an impossible value; it should not be used at runtime.
695 0 : return jsgraph()->graph()->NewNode(
696 : jsgraph()->common()->DeadValue(MachineRepresentation::kCompressed),
697 0 : node);
698 5 : } else if (output_rep == MachineRepresentation::kBit) {
699 : // TODO(v8:8977): specialize here and below
700 : node =
701 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
702 0 : op = machine()->ChangeTaggedToCompressed();
703 5 : } else if (IsWord(output_rep)) {
704 : node =
705 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
706 0 : op = machine()->ChangeTaggedToCompressed();
707 5 : } else if (output_rep == MachineRepresentation::kWord64) {
708 : node =
709 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
710 0 : op = machine()->ChangeTaggedToCompressed();
711 5 : } else if (output_rep == MachineRepresentation::kFloat32) {
712 : node =
713 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
714 0 : op = machine()->ChangeTaggedToCompressed();
715 5 : } else if (output_rep == MachineRepresentation::kFloat64) {
716 : node =
717 0 : GetTaggedRepresentationFor(node, output_rep, output_type, truncation);
718 0 : op = machine()->ChangeTaggedToCompressed();
719 5 : } else if (IsAnyTagged(output_rep)) {
720 5 : op = machine()->ChangeTaggedToCompressed();
721 : } else {
722 : return TypeError(node, output_rep, output_type,
723 0 : MachineRepresentation::kCompressed);
724 : }
725 5 : return jsgraph()->graph()->NewNode(op, node);
726 : }
727 :
728 1402 : Node* RepresentationChanger::GetFloat32RepresentationFor(
729 : Node* node, MachineRepresentation output_rep, Type output_type,
730 : Truncation truncation) {
731 : // Eagerly fold representation changes for constants.
732 1402 : switch (node->opcode()) {
733 : case IrOpcode::kNumberConstant:
734 2308 : return jsgraph()->Float32Constant(
735 1154 : DoubleToFloat32(OpParameter<double>(node->op())));
736 : case IrOpcode::kInt32Constant:
737 : case IrOpcode::kFloat64Constant:
738 : case IrOpcode::kFloat32Constant:
739 0 : UNREACHABLE();
740 : break;
741 : default:
742 : break;
743 : }
744 : // Select the correct X -> Float32 operator.
745 : const Operator* op = nullptr;
746 248 : if (output_type.Is(Type::None())) {
747 : // This is an impossible value; it should not be used at runtime.
748 0 : return jsgraph()->graph()->NewNode(
749 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
750 248 : } else if (IsWord(output_rep)) {
751 31 : if (output_type.Is(Type::Signed32())) {
752 : // int32 -> float64 -> float32
753 26 : op = machine()->ChangeInt32ToFloat64();
754 : node = jsgraph()->graph()->NewNode(op, node);
755 26 : op = machine()->TruncateFloat64ToFloat32();
756 5 : } else if (output_type.Is(Type::Unsigned32()) ||
757 : truncation.IsUsedAsWord32()) {
758 : // Either the output is uint32 or the uses only care about the
759 : // low 32 bits (so we can pick uint32 safely).
760 :
761 : // uint32 -> float64 -> float32
762 5 : op = machine()->ChangeUint32ToFloat64();
763 : node = jsgraph()->graph()->NewNode(op, node);
764 5 : op = machine()->TruncateFloat64ToFloat32();
765 : }
766 217 : } else if (IsAnyTagged(output_rep)) {
767 5 : if (output_type.Is(Type::NumberOrOddball())) {
768 : // tagged -> float64 -> float32
769 5 : if (output_type.Is(Type::Number())) {
770 5 : op = simplified()->ChangeTaggedToFloat64();
771 : } else {
772 0 : op = simplified()->TruncateTaggedToFloat64();
773 : }
774 : node = jsgraph()->graph()->NewNode(op, node);
775 5 : op = machine()->TruncateFloat64ToFloat32();
776 : }
777 212 : } else if (output_rep == MachineRepresentation::kCompressed) {
778 : // TODO(v8:8977): Specialise here
779 0 : op = machine()->ChangeCompressedToTagged();
780 : node = jsgraph()->graph()->NewNode(op, node);
781 : return GetFloat32RepresentationFor(node, MachineRepresentation::kTagged,
782 0 : output_type, truncation);
783 212 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
784 : // TODO(v8:8977): Specialise here
785 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
786 : node = jsgraph()->graph()->NewNode(op, node);
787 : return GetFloat32RepresentationFor(
788 0 : node, MachineRepresentation::kTaggedSigned, output_type, truncation);
789 212 : } else if (output_rep == MachineRepresentation::kCompressedPointer) {
790 : // TODO(v8:8977): Specialise here
791 0 : op = machine()->ChangeCompressedPointerToTaggedPointer();
792 : node = jsgraph()->graph()->NewNode(op, node);
793 : return GetFloat32RepresentationFor(
794 0 : node, MachineRepresentation::kTaggedPointer, output_type, truncation);
795 212 : } else if (output_rep == MachineRepresentation::kFloat64) {
796 197 : op = machine()->TruncateFloat64ToFloat32();
797 15 : } else if (output_rep == MachineRepresentation::kWord64) {
798 10 : if (output_type.Is(cache_->kSafeInteger)) {
799 : // int64 -> float64 -> float32
800 5 : op = machine()->ChangeInt64ToFloat64();
801 : node = jsgraph()->graph()->NewNode(op, node);
802 5 : op = machine()->TruncateFloat64ToFloat32();
803 : }
804 : }
805 248 : if (op == nullptr) {
806 : return TypeError(node, output_rep, output_type,
807 10 : MachineRepresentation::kFloat32);
808 : }
809 238 : return jsgraph()->graph()->NewNode(op, node);
810 : }
811 :
812 252548 : Node* RepresentationChanger::GetFloat64RepresentationFor(
813 : Node* node, MachineRepresentation output_rep, Type output_type,
814 : Node* use_node, UseInfo use_info) {
815 : NumberMatcher m(node);
816 252548 : if (m.HasValue()) {
817 : switch (use_info.type_check()) {
818 : case TypeCheckKind::kNone:
819 : case TypeCheckKind::kNumber:
820 : case TypeCheckKind::kNumberOrOddball:
821 145744 : return jsgraph()->Float64Constant(m.Value());
822 : case TypeCheckKind::kHeapObject:
823 : case TypeCheckKind::kSigned32:
824 : case TypeCheckKind::kSigned64:
825 : case TypeCheckKind::kSignedSmall:
826 : break;
827 : }
828 : }
829 : // Select the correct X -> Float64 operator.
830 : const Operator* op = nullptr;
831 106803 : if (output_type.Is(Type::None())) {
832 : // This is an impossible value; it should not be used at runtime.
833 0 : return jsgraph()->graph()->NewNode(
834 0 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
835 106803 : } else if (IsWord(output_rep)) {
836 71541 : if (output_type.Is(Type::Signed32()) ||
837 12 : (output_type.Is(Type::Signed32OrMinusZero()) &&
838 : use_info.truncation().IdentifiesZeroAndMinusZero())) {
839 35640 : op = machine()->ChangeInt32ToFloat64();
840 83 : } else if (output_type.Is(Type::Unsigned32()) ||
841 : use_info.truncation().IsUsedAsWord32()) {
842 : // Either the output is uint32 or the uses only care about the
843 : // low 32 bits (so we can pick uint32 safely).
844 83 : op = machine()->ChangeUint32ToFloat64();
845 : }
846 71081 : } else if (output_rep == MachineRepresentation::kBit) {
847 0 : CHECK(output_type.Is(Type::Boolean()));
848 0 : if (use_info.truncation().IsUsedAsFloat64()) {
849 0 : op = machine()->ChangeUint32ToFloat64();
850 : } else {
851 0 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
852 : Node* unreachable =
853 0 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotAHeapNumber);
854 0 : return jsgraph()->graph()->NewNode(
855 : jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
856 0 : unreachable);
857 : }
858 142162 : } else if (output_rep == MachineRepresentation::kTagged ||
859 75440 : output_rep == MachineRepresentation::kTaggedSigned ||
860 : output_rep == MachineRepresentation::kTaggedPointer) {
861 68798 : if (output_type.Is(Type::Undefined())) {
862 244 : return jsgraph()->Float64Constant(
863 244 : std::numeric_limits<double>::quiet_NaN());
864 :
865 68554 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
866 1315 : node = InsertChangeTaggedSignedToInt32(node);
867 1315 : op = machine()->ChangeInt32ToFloat64();
868 67239 : } else if (output_type.Is(Type::Number())) {
869 11480 : op = simplified()->ChangeTaggedToFloat64();
870 55759 : } else if (output_type.Is(Type::NumberOrOddball())) {
871 : // TODO(jarin) Here we should check that truncation is Number.
872 1455 : op = simplified()->TruncateTaggedToFloat64();
873 108608 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
874 46469 : (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
875 46469 : !output_type.Maybe(Type::BooleanOrNullOrNumber()))) {
876 : op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber,
877 8302 : use_info.feedback());
878 46002 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
879 : op = simplified()->CheckedTaggedToFloat64(
880 46002 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
881 : }
882 2283 : } else if (output_rep == MachineRepresentation::kCompressed) {
883 : // TODO(v8:8977): Specialise here
884 0 : op = machine()->ChangeCompressedToTagged();
885 : node = jsgraph()->graph()->NewNode(op, node);
886 : return GetFloat64RepresentationFor(node, MachineRepresentation::kTagged,
887 0 : output_type, use_node, use_info);
888 2283 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
889 : // TODO(v8:8977): Specialise here
890 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
891 : node = jsgraph()->graph()->NewNode(op, node);
892 : return GetFloat64RepresentationFor(node,
893 : MachineRepresentation::kTaggedSigned,
894 0 : output_type, use_node, use_info);
895 2283 : } else if (output_rep == MachineRepresentation::kCompressedPointer) {
896 : // TODO(v8:8977): Specialise here
897 0 : op = machine()->ChangeCompressedPointerToTaggedPointer();
898 : node = jsgraph()->graph()->NewNode(op, node);
899 : return GetFloat64RepresentationFor(node,
900 : MachineRepresentation::kTaggedPointer,
901 0 : output_type, use_node, use_info);
902 2283 : } else if (output_rep == MachineRepresentation::kFloat32) {
903 2198 : op = machine()->ChangeFloat32ToFloat64();
904 85 : } else if (output_rep == MachineRepresentation::kWord64) {
905 170 : if (output_type.Is(cache_->kSafeInteger)) {
906 85 : op = machine()->ChangeInt64ToFloat64();
907 : }
908 : }
909 106560 : if (op == nullptr) {
910 : return TypeError(node, output_rep, output_type,
911 0 : MachineRepresentation::kFloat64);
912 : }
913 106560 : return InsertConversion(node, op, use_node);
914 : }
915 :
916 0 : Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
917 1036657 : return jsgraph()->Int32Constant(DoubleToInt32(value));
918 : }
919 :
920 7 : Node* RepresentationChanger::InsertUnconditionalDeopt(Node* node,
921 : DeoptimizeReason reason) {
922 7 : Node* effect = NodeProperties::GetEffectInput(node);
923 7 : Node* control = NodeProperties::GetControlInput(node);
924 : effect =
925 14 : jsgraph()->graph()->NewNode(simplified()->CheckIf(reason),
926 : jsgraph()->Int32Constant(0), effect, control);
927 7 : Node* unreachable = effect = jsgraph()->graph()->NewNode(
928 : jsgraph()->common()->Unreachable(), effect, control);
929 7 : NodeProperties::ReplaceEffectInput(node, effect);
930 7 : return unreachable;
931 : }
932 :
933 1351933 : Node* RepresentationChanger::GetWord32RepresentationFor(
934 : Node* node, MachineRepresentation output_rep, Type output_type,
935 : Node* use_node, UseInfo use_info) {
936 : // Eagerly fold representation changes for constants.
937 1351933 : switch (node->opcode()) {
938 : case IrOpcode::kInt32Constant:
939 : case IrOpcode::kInt64Constant:
940 : case IrOpcode::kFloat32Constant:
941 : case IrOpcode::kFloat64Constant:
942 0 : UNREACHABLE();
943 : break;
944 : case IrOpcode::kNumberConstant: {
945 1036789 : double const fv = OpParameter<double>(node->op());
946 2073578 : if (use_info.type_check() == TypeCheckKind::kNone ||
947 1001 : ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
948 950 : use_info.type_check() == TypeCheckKind::kSigned32 ||
949 270 : use_info.type_check() == TypeCheckKind::kNumber ||
950 85133 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) &&
951 : IsInt32Double(fv))) {
952 1036631 : return MakeTruncatedInt32Constant(fv);
953 : }
954 : break;
955 : }
956 : default:
957 : break;
958 : }
959 :
960 : // Select the correct X -> Word32 operator.
961 : const Operator* op = nullptr;
962 315259 : if (output_type.Is(Type::None())) {
963 : // This is an impossible value; it should not be used at runtime.
964 21 : return jsgraph()->graph()->NewNode(
965 21 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
966 315238 : } else if (output_rep == MachineRepresentation::kBit) {
967 59 : CHECK(output_type.Is(Type::Boolean()));
968 59 : if (use_info.truncation().IsUsedAsWord32()) {
969 : return node;
970 : } else {
971 0 : CHECK(Truncation::Any(kIdentifyZeros)
972 : .IsLessGeneralThan(use_info.truncation()));
973 0 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
974 : Node* unreachable =
975 0 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
976 0 : return jsgraph()->graph()->NewNode(
977 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord32),
978 0 : unreachable);
979 : }
980 315179 : } else if (output_rep == MachineRepresentation::kFloat64) {
981 8876 : if (output_type.Is(Type::Signed32())) {
982 804 : op = machine()->ChangeFloat64ToInt32();
983 8072 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
984 : use_info.type_check() == TypeCheckKind::kSigned32) {
985 2427 : op = simplified()->CheckedFloat64ToInt32(
986 2427 : output_type.Maybe(Type::MinusZero())
987 : ? use_info.minus_zero_check()
988 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
989 2427 : use_info.feedback());
990 5645 : } else if (output_type.Is(Type::Unsigned32())) {
991 6 : op = machine()->ChangeFloat64ToUint32();
992 5639 : } else if (use_info.truncation().IsUsedAsWord32()) {
993 5639 : op = machine()->TruncateFloat64ToWord32();
994 : } else {
995 : return TypeError(node, output_rep, output_type,
996 0 : MachineRepresentation::kWord32);
997 : }
998 306303 : } else if (output_rep == MachineRepresentation::kFloat32) {
999 15 : node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
1000 15 : if (output_type.Is(Type::Signed32())) {
1001 5 : op = machine()->ChangeFloat64ToInt32();
1002 10 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
1003 : use_info.type_check() == TypeCheckKind::kSigned32) {
1004 0 : op = simplified()->CheckedFloat64ToInt32(
1005 0 : output_type.Maybe(Type::MinusZero())
1006 : ? use_info.minus_zero_check()
1007 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1008 0 : use_info.feedback());
1009 10 : } else if (output_type.Is(Type::Unsigned32())) {
1010 5 : op = machine()->ChangeFloat64ToUint32();
1011 5 : } else if (use_info.truncation().IsUsedAsWord32()) {
1012 5 : op = machine()->TruncateFloat64ToWord32();
1013 : } else {
1014 : return TypeError(node, output_rep, output_type,
1015 0 : MachineRepresentation::kWord32);
1016 : }
1017 306288 : } else if (IsAnyTagged(output_rep)) {
1018 306161 : if (output_rep == MachineRepresentation::kTaggedSigned &&
1019 : output_type.Is(Type::SignedSmall())) {
1020 78017 : op = simplified()->ChangeTaggedSignedToInt32();
1021 150117 : } else if (output_type.Is(Type::Signed32())) {
1022 2357 : op = simplified()->ChangeTaggedToInt32();
1023 147760 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
1024 142775 : op = simplified()->CheckedTaggedSignedToInt32(use_info.feedback());
1025 4985 : } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
1026 2518 : op = simplified()->CheckedTaggedToInt32(
1027 2518 : output_type.Maybe(Type::MinusZero())
1028 : ? use_info.minus_zero_check()
1029 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1030 2518 : use_info.feedback());
1031 2467 : } else if (output_type.Is(Type::Unsigned32())) {
1032 518 : op = simplified()->ChangeTaggedToUint32();
1033 1949 : } else if (use_info.truncation().IsUsedAsWord32()) {
1034 1949 : if (output_type.Is(Type::NumberOrOddball())) {
1035 612 : op = simplified()->TruncateTaggedToWord32();
1036 1337 : } else if (use_info.type_check() == TypeCheckKind::kNumber) {
1037 : op = simplified()->CheckedTruncateTaggedToWord32(
1038 870 : CheckTaggedInputMode::kNumber, use_info.feedback());
1039 467 : } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
1040 : op = simplified()->CheckedTruncateTaggedToWord32(
1041 467 : CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
1042 : } else {
1043 : return TypeError(node, output_rep, output_type,
1044 0 : MachineRepresentation::kWord32);
1045 : }
1046 : } else {
1047 : return TypeError(node, output_rep, output_type,
1048 0 : MachineRepresentation::kWord32);
1049 : }
1050 78144 : } else if (output_rep == MachineRepresentation::kCompressed) {
1051 : // TODO(v8:8977): Specialise here
1052 0 : op = machine()->ChangeCompressedToTagged();
1053 : node = jsgraph()->graph()->NewNode(op, node);
1054 : return GetWord32RepresentationFor(node, MachineRepresentation::kTagged,
1055 0 : output_type, use_node, use_info);
1056 78144 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
1057 : // TODO(v8:8977): Specialise here
1058 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
1059 : node = jsgraph()->graph()->NewNode(op, node);
1060 : return GetWord32RepresentationFor(node,
1061 : MachineRepresentation::kTaggedSigned,
1062 0 : output_type, use_node, use_info);
1063 78144 : } else if (output_rep == MachineRepresentation::kCompressedPointer) {
1064 : // TODO(v8:8977): Specialise here
1065 0 : op = machine()->ChangeCompressedPointerToTaggedPointer();
1066 : node = jsgraph()->graph()->NewNode(op, node);
1067 : return GetWord32RepresentationFor(node,
1068 : MachineRepresentation::kTaggedPointer,
1069 0 : output_type, use_node, use_info);
1070 78144 : } else if (output_rep == MachineRepresentation::kWord32) {
1071 : // Only the checked case should get here, the non-checked case is
1072 : // handled in GetRepresentationFor.
1073 78075 : if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
1074 : use_info.type_check() == TypeCheckKind::kSigned32) {
1075 : bool indentify_zeros = use_info.truncation().IdentifiesZeroAndMinusZero();
1076 156078 : if (output_type.Is(Type::Signed32()) ||
1077 278 : (indentify_zeros && output_type.Is(Type::Signed32OrMinusZero()))) {
1078 : return node;
1079 838 : } else if (output_type.Is(Type::Unsigned32()) ||
1080 0 : (indentify_zeros &&
1081 : output_type.Is(Type::Unsigned32OrMinusZero()))) {
1082 419 : op = simplified()->CheckedUint32ToInt32(use_info.feedback());
1083 : } else {
1084 : return TypeError(node, output_rep, output_type,
1085 0 : MachineRepresentation::kWord32);
1086 : }
1087 36 : } else if (use_info.type_check() == TypeCheckKind::kNumber ||
1088 : use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
1089 : return node;
1090 : }
1091 69 : } else if (output_rep == MachineRepresentation::kWord8 ||
1092 : output_rep == MachineRepresentation::kWord16) {
1093 : DCHECK_EQ(MachineRepresentation::kWord32, use_info.representation());
1094 : DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall ||
1095 : use_info.type_check() == TypeCheckKind::kSigned32);
1096 : return node;
1097 69 : } else if (output_rep == MachineRepresentation::kWord64) {
1098 109 : if (output_type.Is(Type::Signed32()) ||
1099 : output_type.Is(Type::Unsigned32())) {
1100 40 : op = machine()->TruncateInt64ToInt32();
1101 82 : } else if (output_type.Is(cache_->kSafeInteger) &&
1102 : use_info.truncation().IsUsedAsWord32()) {
1103 5 : op = machine()->TruncateInt64ToInt32();
1104 24 : } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
1105 : use_info.type_check() == TypeCheckKind::kSigned32) {
1106 38 : if (output_type.Is(cache_->kPositiveSafeInteger)) {
1107 5 : op = simplified()->CheckedUint64ToInt32(use_info.feedback());
1108 28 : } else if (output_type.Is(cache_->kSafeInteger)) {
1109 14 : op = simplified()->CheckedInt64ToInt32(use_info.feedback());
1110 : } else {
1111 : return TypeError(node, output_rep, output_type,
1112 0 : MachineRepresentation::kWord32);
1113 : }
1114 : } else {
1115 : return TypeError(node, output_rep, output_type,
1116 5 : MachineRepresentation::kWord32);
1117 : }
1118 : }
1119 :
1120 237510 : if (op == nullptr) {
1121 : return TypeError(node, output_rep, output_type,
1122 0 : MachineRepresentation::kWord32);
1123 : }
1124 237510 : return InsertConversion(node, op, use_node);
1125 : }
1126 :
1127 483806 : Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
1128 : Node* use_node) {
1129 483806 : if (op->ControlInputCount() > 0) {
1130 : // If the operator can deoptimize (which means it has control
1131 : // input), we need to connect it to the effect and control chains.
1132 263257 : Node* effect = NodeProperties::GetEffectInput(use_node);
1133 263257 : Node* control = NodeProperties::GetControlInput(use_node);
1134 : Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
1135 263280 : NodeProperties::ReplaceEffectInput(use_node, conversion);
1136 263264 : return conversion;
1137 : }
1138 220549 : return jsgraph()->graph()->NewNode(op, node);
1139 : }
1140 :
1141 321724 : Node* RepresentationChanger::GetBitRepresentationFor(
1142 : Node* node, MachineRepresentation output_rep, Type output_type) {
1143 : // Eagerly fold representation changes for constants.
1144 321724 : switch (node->opcode()) {
1145 : case IrOpcode::kHeapConstant: {
1146 : HeapObjectMatcher m(node);
1147 132219 : if (m.Is(factory()->false_value())) {
1148 90773 : return jsgraph()->Int32Constant(0);
1149 41446 : } else if (m.Is(factory()->true_value())) {
1150 41446 : return jsgraph()->Int32Constant(1);
1151 : }
1152 : break;
1153 : }
1154 : default:
1155 : break;
1156 : }
1157 : // Select the correct X -> Bit operator.
1158 : const Operator* op;
1159 189505 : if (output_type.Is(Type::None())) {
1160 : // This is an impossible value; it should not be used at runtime.
1161 221 : return jsgraph()->graph()->NewNode(
1162 221 : jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
1163 189284 : } else if (output_rep == MachineRepresentation::kTagged ||
1164 : output_rep == MachineRepresentation::kTaggedPointer) {
1165 189270 : if (output_type.Is(Type::BooleanOrNullOrUndefined())) {
1166 : // true is the only trueish Oddball.
1167 140928 : op = simplified()->ChangeTaggedToBit();
1168 : } else {
1169 96316 : if (output_rep == MachineRepresentation::kTagged &&
1170 47974 : output_type.Maybe(Type::SignedSmall())) {
1171 47952 : op = simplified()->TruncateTaggedToBit();
1172 : } else {
1173 : // The {output_type} either doesn't include the Smi range,
1174 : // or the {output_rep} is known to be TaggedPointer.
1175 390 : op = simplified()->TruncateTaggedPointerToBit();
1176 : }
1177 : }
1178 14 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1179 0 : node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
1180 : jsgraph()->IntPtrConstant(0));
1181 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1182 0 : jsgraph()->Int32Constant(0));
1183 14 : } else if (output_rep == MachineRepresentation::kCompressed) {
1184 : // TODO(v8:8977): Specialise here
1185 0 : op = machine()->ChangeCompressedToTagged();
1186 : node = jsgraph()->graph()->NewNode(op, node);
1187 : return GetBitRepresentationFor(node, MachineRepresentation::kTagged,
1188 0 : output_type);
1189 14 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
1190 : // TODO(v8:8977): Specialise here
1191 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
1192 : node = jsgraph()->graph()->NewNode(op, node);
1193 : return GetBitRepresentationFor(node, MachineRepresentation::kTaggedSigned,
1194 0 : output_type);
1195 14 : } else if (output_rep == MachineRepresentation::kCompressedPointer) {
1196 : // TODO(v8:8977): Specialise here
1197 0 : op = machine()->ChangeCompressedPointerToTaggedPointer();
1198 : node = jsgraph()->graph()->NewNode(op, node);
1199 : return GetBitRepresentationFor(node, MachineRepresentation::kTaggedPointer,
1200 0 : output_type);
1201 14 : } else if (IsWord(output_rep)) {
1202 0 : node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1203 : jsgraph()->Int32Constant(0));
1204 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1205 0 : jsgraph()->Int32Constant(0));
1206 14 : } else if (output_rep == MachineRepresentation::kWord64) {
1207 0 : node = jsgraph()->graph()->NewNode(machine()->Word64Equal(), node,
1208 : jsgraph()->Int64Constant(0));
1209 0 : return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1210 0 : jsgraph()->Int32Constant(0));
1211 14 : } else if (output_rep == MachineRepresentation::kFloat32) {
1212 0 : node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
1213 0 : return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
1214 0 : jsgraph()->Float32Constant(0.0), node);
1215 14 : } else if (output_rep == MachineRepresentation::kFloat64) {
1216 14 : node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
1217 14 : return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
1218 14 : jsgraph()->Float64Constant(0.0), node);
1219 : } else {
1220 : return TypeError(node, output_rep, output_type,
1221 0 : MachineRepresentation::kBit);
1222 : }
1223 189270 : return jsgraph()->graph()->NewNode(op, node);
1224 : }
1225 :
1226 185521 : Node* RepresentationChanger::GetWord64RepresentationFor(
1227 : Node* node, MachineRepresentation output_rep, Type output_type,
1228 : Node* use_node, UseInfo use_info) {
1229 : // Eagerly fold representation changes for constants.
1230 185521 : switch (node->opcode()) {
1231 : case IrOpcode::kInt32Constant:
1232 : case IrOpcode::kInt64Constant:
1233 : case IrOpcode::kFloat32Constant:
1234 : case IrOpcode::kFloat64Constant:
1235 0 : UNREACHABLE();
1236 : break;
1237 : case IrOpcode::kNumberConstant: {
1238 149605 : double const fv = OpParameter<double>(node->op());
1239 : using limits = std::numeric_limits<int64_t>;
1240 149605 : if (fv <= limits::max() && fv >= limits::min()) {
1241 149598 : int64_t const iv = static_cast<int64_t>(fv);
1242 149598 : if (static_cast<double>(iv) == fv) {
1243 149598 : return jsgraph()->Int64Constant(iv);
1244 : }
1245 : }
1246 : break;
1247 : }
1248 : default:
1249 : break;
1250 : }
1251 :
1252 : // Select the correct X -> Word64 operator.
1253 : const Operator* op;
1254 35923 : if (output_type.Is(Type::None())) {
1255 : // This is an impossible value; it should not be used at runtime.
1256 89 : return jsgraph()->graph()->NewNode(
1257 89 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord64), node);
1258 35834 : } else if (output_rep == MachineRepresentation::kBit) {
1259 7 : CHECK(output_type.Is(Type::Boolean()));
1260 7 : CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
1261 : Node* unreachable =
1262 7 : InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
1263 7 : return jsgraph()->graph()->NewNode(
1264 : jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1265 7 : unreachable);
1266 35827 : } else if (IsWord(output_rep)) {
1267 35295 : if (output_type.Is(Type::Unsigned32())) {
1268 34489 : op = machine()->ChangeUint32ToUint64();
1269 806 : } else if (output_type.Is(Type::Signed32())) {
1270 801 : op = machine()->ChangeInt32ToInt64();
1271 : } else {
1272 : return TypeError(node, output_rep, output_type,
1273 5 : MachineRepresentation::kWord64);
1274 : }
1275 532 : } else if (output_rep == MachineRepresentation::kFloat32) {
1276 66 : if (output_type.Is(cache_->kInt64)) {
1277 : // float32 -> float64 -> int64
1278 15 : node = InsertChangeFloat32ToFloat64(node);
1279 15 : op = machine()->ChangeFloat64ToInt64();
1280 36 : } else if (output_type.Is(cache_->kUint64)) {
1281 : // float32 -> float64 -> uint64
1282 5 : node = InsertChangeFloat32ToFloat64(node);
1283 5 : op = machine()->ChangeFloat64ToUint64();
1284 13 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1285 : // float32 -> float64 -> int64
1286 13 : node = InsertChangeFloat32ToFloat64(node);
1287 13 : op = simplified()->CheckedFloat64ToInt64(
1288 13 : output_type.Maybe(Type::MinusZero())
1289 : ? use_info.minus_zero_check()
1290 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1291 13 : use_info.feedback());
1292 : } else {
1293 : return TypeError(node, output_rep, output_type,
1294 0 : MachineRepresentation::kWord64);
1295 : }
1296 499 : } else if (output_rep == MachineRepresentation::kFloat64) {
1297 118 : if (output_type.Is(cache_->kInt64)) {
1298 41 : op = machine()->ChangeFloat64ToInt64();
1299 36 : } else if (output_type.Is(cache_->kUint64)) {
1300 5 : op = machine()->ChangeFloat64ToUint64();
1301 13 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1302 13 : op = simplified()->CheckedFloat64ToInt64(
1303 13 : output_type.Maybe(Type::MinusZero())
1304 : ? use_info.minus_zero_check()
1305 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1306 13 : use_info.feedback());
1307 : } else {
1308 : return TypeError(node, output_rep, output_type,
1309 0 : MachineRepresentation::kWord64);
1310 : }
1311 440 : } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1312 310 : if (output_type.Is(Type::SignedSmall())) {
1313 310 : op = simplified()->ChangeTaggedSignedToInt64();
1314 : } else {
1315 : return TypeError(node, output_rep, output_type,
1316 0 : MachineRepresentation::kWord64);
1317 : }
1318 130 : } else if (CanBeTaggedPointer(output_rep)) {
1319 260 : if (output_type.Is(cache_->kInt64)) {
1320 23 : op = simplified()->ChangeTaggedToInt64();
1321 107 : } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1322 97 : op = simplified()->CheckedTaggedToInt64(
1323 97 : output_type.Maybe(Type::MinusZero())
1324 : ? use_info.minus_zero_check()
1325 : : CheckForMinusZeroMode::kDontCheckForMinusZero,
1326 97 : use_info.feedback());
1327 : } else {
1328 : return TypeError(node, output_rep, output_type,
1329 10 : MachineRepresentation::kWord64);
1330 : }
1331 0 : } else if (output_rep == MachineRepresentation::kCompressed) {
1332 : // TODO(v8:8977): Specialise here
1333 0 : op = machine()->ChangeCompressedToTagged();
1334 : node = jsgraph()->graph()->NewNode(op, node);
1335 : return GetWord64RepresentationFor(node, MachineRepresentation::kTagged,
1336 0 : output_type, use_node, use_info);
1337 0 : } else if (output_rep == MachineRepresentation::kCompressedSigned) {
1338 : // TODO(v8:8977): Specialise here
1339 0 : op = machine()->ChangeCompressedSignedToTaggedSigned();
1340 : node = jsgraph()->graph()->NewNode(op, node);
1341 : return GetWord64RepresentationFor(node,
1342 : MachineRepresentation::kTaggedSigned,
1343 0 : output_type, use_node, use_info);
1344 0 : } else if (output_rep == MachineRepresentation::kCompressedPointer) {
1345 : // TODO(v8:8977): Specialise here
1346 0 : op = machine()->ChangeCompressedPointerToTaggedPointer();
1347 : node = jsgraph()->graph()->NewNode(op, node);
1348 : return GetWord64RepresentationFor(node,
1349 : MachineRepresentation::kTaggedPointer,
1350 0 : output_type, use_node, use_info);
1351 : } else {
1352 : return TypeError(node, output_rep, output_type,
1353 0 : MachineRepresentation::kWord64);
1354 : }
1355 35812 : return InsertConversion(node, op, use_node);
1356 : }
1357 :
1358 213002 : const Operator* RepresentationChanger::Int32OperatorFor(
1359 : IrOpcode::Value opcode) {
1360 213002 : switch (opcode) {
1361 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1362 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1363 : case IrOpcode::kNumberAdd:
1364 102945 : return machine()->Int32Add();
1365 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1366 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1367 : case IrOpcode::kNumberSubtract:
1368 4731 : return machine()->Int32Sub();
1369 : case IrOpcode::kSpeculativeNumberMultiply:
1370 : case IrOpcode::kNumberMultiply:
1371 995 : return machine()->Int32Mul();
1372 : case IrOpcode::kSpeculativeNumberDivide:
1373 : case IrOpcode::kNumberDivide:
1374 0 : return machine()->Int32Div();
1375 : case IrOpcode::kSpeculativeNumberModulus:
1376 : case IrOpcode::kNumberModulus:
1377 0 : return machine()->Int32Mod();
1378 : case IrOpcode::kSpeculativeNumberBitwiseOr: // Fall through.
1379 : case IrOpcode::kNumberBitwiseOr:
1380 19040 : return machine()->Word32Or();
1381 : case IrOpcode::kSpeculativeNumberBitwiseXor: // Fall through.
1382 : case IrOpcode::kNumberBitwiseXor:
1383 1124 : return machine()->Word32Xor();
1384 : case IrOpcode::kSpeculativeNumberBitwiseAnd: // Fall through.
1385 : case IrOpcode::kNumberBitwiseAnd:
1386 8839 : return machine()->Word32And();
1387 : case IrOpcode::kNumberEqual:
1388 : case IrOpcode::kSpeculativeNumberEqual:
1389 9750 : return machine()->Word32Equal();
1390 : case IrOpcode::kNumberLessThan:
1391 : case IrOpcode::kSpeculativeNumberLessThan:
1392 64101 : return machine()->Int32LessThan();
1393 : case IrOpcode::kNumberLessThanOrEqual:
1394 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1395 1477 : return machine()->Int32LessThanOrEqual();
1396 : default:
1397 0 : UNREACHABLE();
1398 : }
1399 : }
1400 :
1401 151269 : const Operator* RepresentationChanger::Int32OverflowOperatorFor(
1402 : IrOpcode::Value opcode) {
1403 151269 : switch (opcode) {
1404 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1405 142224 : return simplified()->CheckedInt32Add();
1406 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1407 7710 : return simplified()->CheckedInt32Sub();
1408 : case IrOpcode::kSpeculativeNumberDivide:
1409 244 : return simplified()->CheckedInt32Div();
1410 : case IrOpcode::kSpeculativeNumberModulus:
1411 1091 : return simplified()->CheckedInt32Mod();
1412 : default:
1413 0 : UNREACHABLE();
1414 : }
1415 : }
1416 :
1417 481 : const Operator* RepresentationChanger::Int64OperatorFor(
1418 : IrOpcode::Value opcode) {
1419 : switch (opcode) {
1420 : case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1421 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1422 : case IrOpcode::kNumberAdd:
1423 260 : return machine()->Int64Add();
1424 : case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1425 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1426 : case IrOpcode::kNumberSubtract:
1427 221 : return machine()->Int64Sub();
1428 : default:
1429 0 : UNREACHABLE();
1430 : }
1431 : }
1432 :
1433 14412 : const Operator* RepresentationChanger::TaggedSignedOperatorFor(
1434 : IrOpcode::Value opcode) {
1435 14412 : switch (opcode) {
1436 : case IrOpcode::kSpeculativeNumberLessThan:
1437 : return machine()->Is32() ? machine()->Int32LessThan()
1438 5237 : : machine()->Int64LessThan();
1439 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1440 : return machine()->Is32() ? machine()->Int32LessThanOrEqual()
1441 239 : : machine()->Int64LessThanOrEqual();
1442 : case IrOpcode::kSpeculativeNumberEqual:
1443 : return machine()->Is32() ? machine()->Word32Equal()
1444 8936 : : machine()->Word64Equal();
1445 : default:
1446 0 : UNREACHABLE();
1447 : }
1448 : }
1449 :
1450 34266 : const Operator* RepresentationChanger::Uint32OperatorFor(
1451 : IrOpcode::Value opcode) {
1452 34266 : switch (opcode) {
1453 : case IrOpcode::kNumberAdd:
1454 0 : return machine()->Int32Add();
1455 : case IrOpcode::kNumberSubtract:
1456 0 : return machine()->Int32Sub();
1457 : case IrOpcode::kSpeculativeNumberMultiply:
1458 : case IrOpcode::kNumberMultiply:
1459 0 : return machine()->Int32Mul();
1460 : case IrOpcode::kSpeculativeNumberDivide:
1461 : case IrOpcode::kNumberDivide:
1462 0 : return machine()->Uint32Div();
1463 : case IrOpcode::kSpeculativeNumberModulus:
1464 : case IrOpcode::kNumberModulus:
1465 0 : return machine()->Uint32Mod();
1466 : case IrOpcode::kNumberEqual:
1467 : case IrOpcode::kSpeculativeNumberEqual:
1468 12972 : return machine()->Word32Equal();
1469 : case IrOpcode::kNumberLessThan:
1470 : case IrOpcode::kSpeculativeNumberLessThan:
1471 18814 : return machine()->Uint32LessThan();
1472 : case IrOpcode::kNumberLessThanOrEqual:
1473 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1474 1578 : return machine()->Uint32LessThanOrEqual();
1475 : case IrOpcode::kNumberClz32:
1476 30 : return machine()->Word32Clz();
1477 : case IrOpcode::kNumberImul:
1478 872 : return machine()->Int32Mul();
1479 : default:
1480 0 : UNREACHABLE();
1481 : }
1482 : }
1483 :
1484 113 : const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
1485 : IrOpcode::Value opcode) {
1486 113 : switch (opcode) {
1487 : case IrOpcode::kSpeculativeNumberDivide:
1488 69 : return simplified()->CheckedUint32Div();
1489 : case IrOpcode::kSpeculativeNumberModulus:
1490 44 : return simplified()->CheckedUint32Mod();
1491 : default:
1492 0 : UNREACHABLE();
1493 : }
1494 : }
1495 :
1496 168306 : const Operator* RepresentationChanger::Float64OperatorFor(
1497 : IrOpcode::Value opcode) {
1498 168306 : switch (opcode) {
1499 : case IrOpcode::kSpeculativeNumberAdd:
1500 : case IrOpcode::kSpeculativeSafeIntegerAdd:
1501 : case IrOpcode::kNumberAdd:
1502 73515 : return machine()->Float64Add();
1503 : case IrOpcode::kSpeculativeNumberSubtract:
1504 : case IrOpcode::kSpeculativeSafeIntegerSubtract:
1505 : case IrOpcode::kNumberSubtract:
1506 1195 : return machine()->Float64Sub();
1507 : case IrOpcode::kSpeculativeNumberMultiply:
1508 : case IrOpcode::kNumberMultiply:
1509 11596 : return machine()->Float64Mul();
1510 : case IrOpcode::kSpeculativeNumberDivide:
1511 : case IrOpcode::kNumberDivide:
1512 15295 : return machine()->Float64Div();
1513 : case IrOpcode::kSpeculativeNumberModulus:
1514 : case IrOpcode::kNumberModulus:
1515 562 : return machine()->Float64Mod();
1516 : case IrOpcode::kNumberEqual:
1517 : case IrOpcode::kSpeculativeNumberEqual:
1518 16986 : return machine()->Float64Equal();
1519 : case IrOpcode::kNumberLessThan:
1520 : case IrOpcode::kSpeculativeNumberLessThan:
1521 3762 : return machine()->Float64LessThan();
1522 : case IrOpcode::kNumberLessThanOrEqual:
1523 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1524 266 : return machine()->Float64LessThanOrEqual();
1525 : case IrOpcode::kNumberAbs:
1526 190 : return machine()->Float64Abs();
1527 : case IrOpcode::kNumberAcos:
1528 0 : return machine()->Float64Acos();
1529 : case IrOpcode::kNumberAcosh:
1530 0 : return machine()->Float64Acosh();
1531 : case IrOpcode::kNumberAsin:
1532 7 : return machine()->Float64Asin();
1533 : case IrOpcode::kNumberAsinh:
1534 0 : return machine()->Float64Asinh();
1535 : case IrOpcode::kNumberAtan:
1536 0 : return machine()->Float64Atan();
1537 : case IrOpcode::kNumberAtanh:
1538 0 : return machine()->Float64Atanh();
1539 : case IrOpcode::kNumberAtan2:
1540 0 : return machine()->Float64Atan2();
1541 : case IrOpcode::kNumberCbrt:
1542 0 : return machine()->Float64Cbrt();
1543 : case IrOpcode::kNumberCeil:
1544 6675 : return machine()->Float64RoundUp().placeholder();
1545 : case IrOpcode::kNumberCos:
1546 14 : return machine()->Float64Cos();
1547 : case IrOpcode::kNumberCosh:
1548 7 : return machine()->Float64Cosh();
1549 : case IrOpcode::kNumberExp:
1550 32 : return machine()->Float64Exp();
1551 : case IrOpcode::kNumberExpm1:
1552 14 : return machine()->Float64Expm1();
1553 : case IrOpcode::kNumberFloor:
1554 27873 : return machine()->Float64RoundDown().placeholder();
1555 : case IrOpcode::kNumberFround:
1556 1287 : return machine()->TruncateFloat64ToFloat32();
1557 : case IrOpcode::kNumberLog:
1558 131 : return machine()->Float64Log();
1559 : case IrOpcode::kNumberLog1p:
1560 0 : return machine()->Float64Log1p();
1561 : case IrOpcode::kNumberLog2:
1562 0 : return machine()->Float64Log2();
1563 : case IrOpcode::kNumberLog10:
1564 0 : return machine()->Float64Log10();
1565 : case IrOpcode::kNumberMax:
1566 72 : return machine()->Float64Max();
1567 : case IrOpcode::kNumberMin:
1568 148 : return machine()->Float64Min();
1569 : case IrOpcode::kNumberPow:
1570 909 : return machine()->Float64Pow();
1571 : case IrOpcode::kNumberSin:
1572 31 : return machine()->Float64Sin();
1573 : case IrOpcode::kNumberSinh:
1574 7 : return machine()->Float64Sinh();
1575 : case IrOpcode::kNumberSqrt:
1576 51 : return machine()->Float64Sqrt();
1577 : case IrOpcode::kNumberTan:
1578 28 : return machine()->Float64Tan();
1579 : case IrOpcode::kNumberTanh:
1580 7 : return machine()->Float64Tanh();
1581 : case IrOpcode::kNumberTrunc:
1582 6914 : return machine()->Float64RoundTruncate().placeholder();
1583 : case IrOpcode::kNumberSilenceNaN:
1584 732 : return machine()->Float64SilenceNaN();
1585 : default:
1586 0 : UNREACHABLE();
1587 : }
1588 : }
1589 :
1590 35 : Node* RepresentationChanger::TypeError(Node* node,
1591 : MachineRepresentation output_rep,
1592 : Type output_type,
1593 : MachineRepresentation use) {
1594 35 : type_error_ = true;
1595 35 : if (!testing_type_errors_) {
1596 0 : std::ostringstream out_str;
1597 0 : out_str << output_rep << " (";
1598 0 : output_type.PrintTo(out_str);
1599 0 : out_str << ")";
1600 :
1601 0 : std::ostringstream use_str;
1602 0 : use_str << use;
1603 :
1604 : FATAL(
1605 : "RepresentationChangerError: node #%d:%s of "
1606 : "%s cannot be changed to %s",
1607 : node->id(), node->op()->mnemonic(), out_str.str().c_str(),
1608 0 : use_str.str().c_str());
1609 : }
1610 35 : return node;
1611 : }
1612 :
1613 0 : Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
1614 0 : return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
1615 : }
1616 :
1617 430 : Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
1618 860 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
1619 : }
1620 :
1621 20 : Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
1622 40 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
1623 : }
1624 :
1625 807 : Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
1626 1614 : return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
1627 : }
1628 :
1629 14 : Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) {
1630 28 : return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
1631 : }
1632 :
1633 1315 : Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
1634 1315 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
1635 1315 : node);
1636 : }
1637 :
1638 0 : Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
1639 0 : return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
1640 0 : node);
1641 : }
1642 :
1643 0 : Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) {
1644 0 : return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
1645 : }
1646 :
1647 32 : Node* RepresentationChanger::InsertTruncateInt64ToInt32(Node* node) {
1648 64 : return jsgraph()->graph()->NewNode(machine()->TruncateInt64ToInt32(), node);
1649 : }
1650 :
1651 : } // namespace compiler
1652 : } // namespace internal
1653 122036 : } // namespace v8
|