v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
representation-change.cc
Go to the documentation of this file.
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
6
7#include <sstream>
8
18
19namespace v8 {
20namespace internal {
21namespace compiler {
22
23const char* Truncation::description() const {
24 switch (kind()) {
26 return "no-value-use";
28 return "truncate-to-bool";
30 return "truncate-to-word32";
32 return "truncate-to-word64";
34 switch (identify_zeros()) {
35 case kIdentifyZeros:
36 return "truncate-oddball&bigint-to-number (identify zeros)";
38 return "truncate-oddball&bigint-to-number (distinguish zeros)";
39 }
41 switch (identify_zeros()) {
42 case kIdentifyZeros:
43 return "no-truncation (but identify zeros)";
45 return "no-truncation (but distinguish zeros)";
46 }
47 }
49}
50
51// Partial order for truncations:
52//
53// kAny <-------+
54// ^ |
55// | |
56// kOddballAndBigIntToNumber |
57// ^ |
58// / |
59// kWord64 |
60// ^ |
61// | |
62// kWord32 kBool
63// ^ ^
64// \ /
65// \ /
66// \ /
67// \ /
68// \ /
69// kNone
70//
71// TODO(jarin) We might consider making kBool < kOddballAndBigIntToNumber.
72
73// static
75 TruncationKind rep2) {
76 if (LessGeneral(rep1, rep2)) return rep2;
77 if (LessGeneral(rep2, rep1)) return rep1;
78 // Handle the generalization of float64-representable values.
82 }
83 // Handle the generalization of any-representable values.
87 }
88 // All other combinations are illegal.
89 FATAL("Tried to combine incompatible truncations");
90}
91
92// static
94 IdentifyZeros i2) {
95 if (i1 == i2) {
96 return i1;
97 } else {
98 return kDistinguishZeros;
99 }
100}
101
102// static
104 switch (rep1) {
106 return true;
108 return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
110 return rep2 == TruncationKind::kWord32 ||
111 rep2 == TruncationKind::kWord64 ||
113 rep2 == TruncationKind::kAny;
115 return rep2 == TruncationKind::kWord64 ||
117 rep2 == TruncationKind::kAny;
120 rep2 == TruncationKind::kAny;
122 return rep2 == TruncationKind::kAny;
123 }
124 UNREACHABLE();
125}
126
127// static
129 return i1 == i2 || i1 == kIdentifyZeros;
130}
131
132namespace {
133
135 return rep == MachineRepresentation::kWord8 ||
138}
139
140bool TypeCheckIsBigInt(TypeCheckKind type_check) {
141 return type_check == TypeCheckKind::kBigInt ||
142 type_check == TypeCheckKind::kBigInt64;
143}
144
145constexpr bool SupportsFpParamsInCLinkage() {
146#ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
147 return Is64();
148#else
149 return false;
150#endif
151}
152
153} // namespace
154
158 : cache_(TypeCache::Get()),
159 jsgraph_(jsgraph),
161 verifier_(verifier),
162 testing_type_errors_(false),
163 type_error_(false) {}
164
165// Changes representation from {output_rep} to {use_rep}. The {truncation}
166// parameter is only used for checking - if the changer cannot figure
167// out signedness for the word32->float64 conversion, then we check that the
168// uses truncate to word32 (so they do not care about signedness).
170 Node* node, MachineRepresentation output_rep, Type output_type,
171 Node* use_node, UseInfo use_info) {
172 // We are currently not inserting conversions in machine graphs.
173 // We might add that, though.
174 DCHECK_IMPLIES(!output_type.IsNone(), !output_type.Is(Type::Machine()));
175 if (output_rep == MachineRepresentation::kNone && !output_type.IsNone()) {
176 // The output representation should be set if the type is inhabited (i.e.,
177 // if the value is possible).
178 return TypeError(node, output_rep, output_type, use_info.representation());
179 }
180
181 if (output_type.Is(Type::BigInt()) &&
182 output_rep == MachineRepresentation::kWord64 &&
183 !TypeCheckIsBigInt(use_info.type_check())) {
184 // Rematerialize any truncated BigInt if user is not expecting a BigInt.
185 if (output_type.Is(Type::UnsignedBigInt64())) {
186 node = InsertConversion(node, simplified()->ChangeUint64ToBigInt(),
187 use_node);
188 } else {
189 node =
190 InsertConversion(node, simplified()->ChangeInt64ToBigInt(), use_node);
191 }
193 } else if (output_rep == MachineRepresentation::kFloat16RawBits) {
194 // Float16Array elements are loaded as raw bits in a word16 then converted
195 // to float64, since architectures have spotty support for fp16.
196 DCHECK(output_type.Is(Type::Number()));
197 if (machine()->ChangeFloat16RawBitsToFloat64().IsSupported()) {
198 node = jsgraph()->graph()->NewNode(
199 machine()->ChangeFloat16RawBitsToFloat64().op(), node);
200 } else {
202 }
204 }
205
206 // Handle the no-op shortcuts when no checking is necessary.
207 if (use_info.type_check() == TypeCheckKind::kNone ||
208 // TODO(nicohartmann@, chromium:1077804): Ignoring {use_info.type_check()}
209 // in case the representation already matches is not correct. For now,
210 // this behavior is disabled only for TypeCheckKind::kBigInt, but should
211 // be fixed for all other type checks.
212 (output_rep != MachineRepresentation::kWord32 &&
213 !TypeCheckIsBigInt(use_info.type_check()))) {
214 if (use_info.representation() == output_rep) {
215 // Representations are the same. That's a no-op.
216 return node;
217 }
218 if (IsWord(use_info.representation()) && IsWord(output_rep)) {
219 // Both are words less than or equal to 32-bits.
220 // Since loads of integers from memory implicitly sign or zero extend the
221 // value to the full machine word size and stores implicitly truncate,
222 // no representation change is necessary.
223 return node;
224 }
225 }
226
227 switch (use_info.representation()) {
229 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
231 return GetTaggedSignedRepresentationFor(node, output_rep, output_type,
232 use_node, use_info);
234 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
236 use_info.type_check() == TypeCheckKind::kBigInt);
237 return GetTaggedPointerRepresentationFor(node, output_rep, output_type,
238 use_node, use_info);
241 return GetTaggedRepresentationFor(node, output_rep, output_type,
242 use_info.truncation());
245 return GetFloat16RawBitsRepresentationFor(node, output_rep, output_type,
246 use_node, use_info);
249 return GetFloat32RepresentationFor(node, output_rep, output_type,
250 use_info.truncation());
252 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
253 use_info.type_check() == TypeCheckKind::kNumber ||
256 return GetFloat64RepresentationFor(node, output_rep, output_type,
257 use_node, use_info);
260 return GetBitRepresentationFor(node, output_rep, output_type);
264 return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
265 use_info);
267 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
268 use_info.type_check() == TypeCheckKind::kSigned64 ||
270 TypeCheckIsBigInt(use_info.type_check()) ||
272 return GetWord64RepresentationFor(node, output_rep, output_type, use_node,
273 use_info);
277 return node;
285 UNREACHABLE();
286 }
287 UNREACHABLE();
288}
289
291 Node* node, MachineRepresentation output_rep, Type output_type,
292 Node* use_node, UseInfo use_info) {
293 // Eagerly fold representation changes for constants.
294 switch (node->opcode()) {
295 case IrOpcode::kNumberConstant:
296 if (output_type.Is(Type::SignedSmall())) {
297 return node;
298 }
299 break;
300 default:
301 break;
302 }
303 // Select the correct X -> Tagged operator.
304 const Operator* op;
305 if (output_type.Is(Type::None())) {
306 // This is an impossible value; it should not be used at runtime.
307 return jsgraph()->graph()->NewNode(
308 jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedSigned),
309 node);
310 } else if (IsWord(output_rep)) {
311 if (output_type.Is(Type::Signed31())) {
313 } else if (output_type.Is(Type::Signed32())) {
314 if (SmiValuesAre32Bits()) {
316 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
318 } else {
319 return TypeError(node, output_rep, output_type,
321 }
322 } else if (output_type.Is(Type::Unsigned32()) &&
325 } else {
326 return TypeError(node, output_rep, output_type,
328 }
329 } else if (output_rep == MachineRepresentation::kWord64) {
330 if (output_type.Is(Type::Signed31())) {
331 // int64 -> int32 -> tagged signed
332 node = InsertTruncateInt64ToInt32(node);
334 } else if (output_type.Is(Type::Signed32()) && SmiValuesAre32Bits()) {
335 // int64 -> int32 -> tagged signed
336 node = InsertTruncateInt64ToInt32(node);
338 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
339 if (output_type.Is(cache_->kPositiveSafeInteger)) {
341 } else if (output_type.Is(cache_->kSafeInteger)) {
343 } else {
344 return TypeError(node, output_rep, output_type,
346 }
347 } else {
348 return TypeError(node, output_rep, output_type,
350 }
351 } else if (output_rep == MachineRepresentation::kFloat64) {
352 if (output_type.Is(Type::Signed31())) {
353 // float64 -> int32 -> tagged signed
354 node = InsertChangeFloat64ToInt32(node);
356 } else if (output_type.Is(Type::Signed32())) {
357 // float64 -> int32 -> tagged signed
358 node = InsertChangeFloat64ToInt32(node);
359 if (SmiValuesAre32Bits()) {
361 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
363 } else {
364 return TypeError(node, output_rep, output_type,
366 }
367 } else if (output_type.Is(Type::Unsigned32()) &&
369 // float64 -> uint32 -> tagged signed
370 node = InsertChangeFloat64ToUint32(node);
372 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
374 node,
375 output_type.Maybe(Type::MinusZero())
378 use_info.feedback(), use_node);
379 if (SmiValuesAre32Bits()) {
381 } else {
383 }
384 } else {
385 return TypeError(node, output_rep, output_type,
387 }
388 } else if (output_rep == MachineRepresentation::kFloat32) {
389 if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
390 node = InsertChangeFloat32ToFloat64(node);
392 node,
393 output_type.Maybe(Type::MinusZero())
396 use_info.feedback(), use_node);
397 if (SmiValuesAre32Bits()) {
399 } else {
401 }
402 } else {
403 return TypeError(node, output_rep, output_type,
405 }
406 } else if (CanBeTaggedPointer(output_rep)) {
407 if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
409 } else if (output_type.Is(Type::SignedSmall())) {
411 } else {
412 return TypeError(node, output_rep, output_type,
414 }
415 } else if (output_rep == MachineRepresentation::kBit) {
416 if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
417 // TODO(turbofan): Consider adding a Bailout operator that just deopts.
418 // Also use that for MachineRepresentation::kPointer case above.
419 node = InsertChangeBitToTagged(node);
421 } else {
422 return TypeError(node, output_rep, output_type,
424 }
425 } else {
426 return TypeError(node, output_rep, output_type,
428 }
429 return InsertConversion(node, op, use_node);
430}
431
433 Node* node, MachineRepresentation output_rep, Type output_type,
434 Node* use_node, UseInfo use_info) {
435 // Eagerly fold representation changes for constants.
436 switch (node->opcode()) {
437 case IrOpcode::kHeapConstant:
438 if (TypeCheckIsBigInt(use_info.type_check())) break;
439 return node; // No change necessary.
440 case IrOpcode::kInt32Constant:
441 case IrOpcode::kFloat64Constant:
442 case IrOpcode::kFloat32Constant:
443 UNREACHABLE();
444 default:
445 break;
446 }
447 // Select the correct X -> TaggedPointer operator.
448 Operator const* op;
449 if (output_type.Is(Type::None())) {
450 // This is an impossible value; it should not be used at runtime.
451 return jsgraph()->graph()->NewNode(
452 jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
453 node);
454 }
455
456 if (TypeCheckIsBigInt(use_info.type_check()) &&
457 !output_type.Is(Type::BigInt())) {
458 // BigInt checks can only be performed on tagged representations. Note that
459 // a corresponding check is inserted down below.
460 if (!CanBeTaggedPointer(output_rep)) {
461 Node* unreachable =
462 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotABigInt);
463 return jsgraph()->graph()->NewNode(
464 jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
465 unreachable);
466 }
467 }
468
469 if (output_rep == MachineRepresentation::kBit) {
470 if (output_type.Is(Type::Boolean())) {
472 } else {
473 return TypeError(node, output_rep, output_type,
475 }
476 } else if (IsWord(output_rep)) {
477 if (output_type.Is(Type::Unsigned32())) {
478 // uint32 -> float64 -> tagged
479 node = InsertChangeUint32ToFloat64(node);
480 } else if (output_type.Is(Type::Signed32())) {
481 // int32 -> float64 -> tagged
482 node = InsertChangeInt32ToFloat64(node);
483 } else {
484 return TypeError(node, output_rep, output_type,
486 }
488 } else if (output_rep == MachineRepresentation::kWord64) {
489 if (output_type.Is(cache_->kSafeInteger)) {
490 // int64 -> float64 -> tagged pointer
492 node = jsgraph()->graph()->NewNode(op, node);
494 } else if (output_type.Is(Type::SignedBigInt64()) &&
495 use_info.type_check() == TypeCheckKind::kBigInt) {
497 } else if (output_type.Is(Type::UnsignedBigInt64()) &&
498 use_info.type_check() == TypeCheckKind::kBigInt) {
500 } else {
501 return TypeError(node, output_rep, output_type,
503 }
504 } else if (output_rep == MachineRepresentation::kFloat32) {
505 if (output_type.Is(Type::Number())) {
506 // float32 -> float64 -> tagged
507 node = InsertChangeFloat32ToFloat64(node);
509 } else {
510 return TypeError(node, output_rep, output_type,
512 }
513 } else if (output_rep == MachineRepresentation::kFloat64) {
514 if (output_type.Is(Type::Number())) {
515 // float64 -> tagged
517 } else {
518 return TypeError(node, output_rep, output_type,
520 }
521 } else if (IsAnyTagged(output_rep)) {
522 if (use_info.type_check() == TypeCheckKind::kBigInt) {
523 if (output_type.Is(Type::BigInt())) {
525 return node;
526 }
527 op = simplified()->CheckBigInt(use_info.feedback());
528 } else if (use_info.type_check() == TypeCheckKind::kBigInt64) {
529 if (output_type.Is(Type::SignedBigInt64())) {
531 return node;
532 }
533 if (!output_type.Is(Type::BigInt())) {
534 node = InsertConversion(
535 node, simplified()->CheckBigInt(use_info.feedback()), use_node);
536 }
537 op = simplified()->CheckedBigIntToBigInt64(use_info.feedback());
538 } else if (output_rep == MachineRepresentation::kTaggedPointer ||
539 !output_type.Maybe(Type::SignedSmall())) {
541 return node;
542 } else {
544 }
545 } else {
546 return TypeError(node, output_rep, output_type,
548 }
549 return InsertConversion(node, op, use_node);
550}
551
553 Node* node, MachineRepresentation output_rep, Type output_type,
554 Truncation truncation) {
555 // Eagerly fold representation changes for constants.
556 switch (node->opcode()) {
557 case IrOpcode::kNumberConstant:
558 case IrOpcode::kHeapConstant:
559 return node; // No change necessary.
560 case IrOpcode::kInt32Constant:
561 case IrOpcode::kFloat64Constant:
562 case IrOpcode::kFloat32Constant:
563 UNREACHABLE();
564 default:
565 break;
566 }
567 if (output_rep == MachineRepresentation::kTaggedSigned ||
569 output_rep == MachineRepresentation::kMapWord) {
570 // this is a no-op.
571 return node;
572 }
573 // Select the correct X -> Tagged operator.
574 const Operator* op;
575 if (output_type.Is(Type::None())) {
576 // This is an impossible value; it should not be used at runtime.
577 return jsgraph()->graph()->NewNode(
578 jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
579 } else if (output_rep == MachineRepresentation::kBit) {
580 if (output_type.Is(Type::Boolean())) {
582 } else {
583 return TypeError(node, output_rep, output_type,
585 }
586 } else if (IsWord(output_rep)) {
587 if (output_type.Is(Type::Signed31())) {
589 } else if (output_type.Is(Type::Signed32()) ||
590 (output_type.Is(Type::Signed32OrMinusZero()) &&
591 truncation.IdentifiesZeroAndMinusZero())) {
593 } else if (output_type.Is(Type::Unsigned32()) ||
594 (output_type.Is(Type::Unsigned32OrMinusZero()) &&
595 truncation.IdentifiesZeroAndMinusZero()) ||
596 truncation.IsUsedAsWord32()) {
597 // Either the output is uint32 or the uses only care about the
598 // low 32 bits (so we can pick uint32 safely).
600 } else {
601 return TypeError(node, output_rep, output_type,
603 }
604 } else if (output_rep == MachineRepresentation::kWord64) {
605 if (output_type.Is(Type::Signed31())) {
606 // int64 -> int32 -> tagged signed
607 node = InsertTruncateInt64ToInt32(node);
609 } else if (output_type.Is(Type::Signed32())) {
610 // int64 -> int32 -> tagged
611 node = InsertTruncateInt64ToInt32(node);
613 } else if (output_type.Is(Type::Unsigned32())) {
614 // int64 -> uint32 -> tagged
615 node = InsertTruncateInt64ToInt32(node);
617 } else if (output_type.Is(cache_->kPositiveSafeInteger)) {
618 // uint64 -> tagged
620 } else if (output_type.Is(cache_->kSafeInteger)) {
621 // int64 -> tagged
623 } else if (output_type.Is(Type::SignedBigInt64())) {
624 // int64 -> BigInt
626 } else if (output_type.Is(Type::UnsignedBigInt64())) {
627 // uint64 -> BigInt
629 } else {
630 return TypeError(node, output_rep, output_type,
632 }
633 } else if (output_rep ==
634 MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
635 node = InsertChangeFloat32ToFloat64(node);
637 output_type.Maybe(Type::MinusZero())
640 } else if (output_rep == MachineRepresentation::kFloat64) {
641 if (output_type.Is(Type::Signed31())) { // float64 -> int32 -> tagged
642 node = InsertChangeFloat64ToInt32(node);
644 } else if (output_type.Is(
645 Type::Signed32())) { // float64 -> int32 -> tagged
646 node = InsertChangeFloat64ToInt32(node);
648 } else if (output_type.Is(
649 Type::Unsigned32())) { // float64 -> uint32 -> tagged
650 node = InsertChangeFloat64ToUint32(node);
652 } else if (output_type.Is(Type::Number()) ||
653 (output_type.Is(Type::NumberOrOddball()) &&
654 truncation.TruncatesOddballAndBigIntToNumber())) {
656 output_type.Maybe(Type::MinusZero())
659 } else {
660 return TypeError(node, output_rep, output_type,
662 }
663 } else {
664 return TypeError(node, output_rep, output_type,
666 }
667 return jsgraph()->graph()->NewNode(op, node);
668}
669
671 Node* node, MachineRepresentation output_rep, Type output_type,
672 Node* use_node, UseInfo use_info) {
673 if (output_rep != MachineRepresentation::kFloat64) {
674 node = GetFloat64RepresentationFor(node, output_rep, output_type, use_node,
675 use_info);
676 }
677
678 // Eagerly fold representation changes for constants.
679 switch (node->opcode()) {
680 case IrOpcode::kFloat64Constant:
681 return jsgraph()->Uint32Constant(
683 case IrOpcode::kNumberConstant:
684 case IrOpcode::kInt32Constant:
685 case IrOpcode::kFloat32Constant:
686 UNREACHABLE();
687 default:
688 break;
689 }
690
691 // This is an impossible value; it should not be used at runtime.
692 if (output_type.Is(Type::None())) {
693 return jsgraph()->graph()->NewNode(
694 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat16RawBits),
695 node);
696 }
697
698 // Insert a float64 -> float16 node.
699 if (machine()->TruncateFloat64ToFloat16RawBits().IsSupported()) {
700 return jsgraph()->graph()->NewNode(
701 machine()->TruncateFloat64ToFloat16RawBits().op(), node);
702 } else {
704 }
705}
706
708 Node* node, MachineRepresentation output_rep, Type output_type,
709 Truncation truncation) {
710 // Eagerly fold representation changes for constants.
711 switch (node->opcode()) {
712 case IrOpcode::kNumberConstant:
713 return jsgraph()->Float32Constant(
715 case IrOpcode::kInt32Constant:
716 case IrOpcode::kFloat64Constant:
717 case IrOpcode::kFloat32Constant:
718 UNREACHABLE();
719 default:
720 break;
721 }
722 // Select the correct X -> Float32 operator.
723 const Operator* op = nullptr;
724 if (output_type.Is(Type::None())) {
725 // This is an impossible value; it should not be used at runtime.
726 return jsgraph()->graph()->NewNode(
727 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
728 } else if (IsWord(output_rep)) {
729 if (output_type.Is(Type::Signed32())) {
730 // int32 -> float64 -> float32
732 node = jsgraph()->graph()->NewNode(op, node);
734 } else if (output_type.Is(Type::Unsigned32()) ||
735 truncation.IsUsedAsWord32()) {
736 // Either the output is uint32 or the uses only care about the
737 // low 32 bits (so we can pick uint32 safely).
738
739 // uint32 -> float64 -> float32
741 node = jsgraph()->graph()->NewNode(op, node);
743 }
744 } else if (IsAnyTagged(output_rep)) {
745 if (output_type.Is(Type::NumberOrOddball())) {
746 // tagged -> float64 -> float32
747 if (output_type.Is(Type::Number())) {
749 } else {
751 }
752 node = jsgraph()->graph()->NewNode(op, node);
754 }
755 } else if (output_rep == MachineRepresentation::kFloat64) {
757 } else if (output_rep == MachineRepresentation::kWord64) {
758 if (output_type.Is(cache_->kSafeInteger)) {
759 // int64 -> float64 -> float32
761 node = jsgraph()->graph()->NewNode(op, node);
763 }
764 }
765 if (op == nullptr) {
766 return TypeError(node, output_rep, output_type,
768 }
769 return jsgraph()->graph()->NewNode(op, node);
770}
771
773 Node* node, MachineRepresentation output_rep, Type output_type,
774 Node* use_node, UseInfo use_info) {
775 NumberMatcher m(node);
776 if (m.HasResolvedValue()) {
777 // BigInts are not used as number constants.
778 DCHECK(!TypeCheckIsBigInt(use_info.type_check()));
779 switch (use_info.type_check()) {
784 return jsgraph()->Float64Constant(m.ResolvedValue());
793 break;
794 }
795 }
796
797 // Select the correct X -> Float64 operator.
798 const Operator* op = nullptr;
799 if (output_type.Is(Type::None())) {
800 // This is an impossible value; it should not be used at runtime.
801 return jsgraph()->graph()->NewNode(
802 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
803 } else if (IsWord(output_rep)) {
804 if (output_type.Is(Type::Signed32()) ||
805 (output_type.Is(Type::Signed32OrMinusZero()) &&
808 } else if (output_type.Is(Type::Unsigned32()) ||
809 (output_type.Is(Type::Unsigned32OrMinusZero()) &&
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).
815 }
816 } else if (output_rep == MachineRepresentation::kBit) {
817 CHECK(output_type.Is(Type::Boolean()));
822 } else {
824 Node* unreachable =
825 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotAHeapNumber);
826 return jsgraph()->graph()->NewNode(
827 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
828 unreachable);
829 }
830 } else if (IsAnyTagged(output_rep)) {
831 if (output_type.Is(Type::Undefined())) {
833 (use_info.type_check() == TypeCheckKind::kNone &&
835 return jsgraph()->Float64Constant(
836 std::numeric_limits<double>::quiet_NaN());
837 } else {
838 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
839 use_info.type_check() == TypeCheckKind::kNumber ||
841 Node* unreachable = InsertUnconditionalDeopt(
842 use_node, use_info.type_check() == TypeCheckKind::kNumber
843 ? DeoptimizeReason::kNotANumber
844 : DeoptimizeReason::kNotANumberOrBoolean);
845 return jsgraph()->graph()->NewNode(
846 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
847 unreachable);
848 }
849 } else if (output_rep == MachineRepresentation::kTaggedSigned) {
852 } else if (output_type.Is(Type::Number())) {
854 } else if ((output_type.Is(Type::NumberOrOddball()) &&
856 output_type.Is(Type::NumberOrHole())) {
857 // JavaScript 'null' is an Oddball that results in +0 when truncated to
858 // Number. In a context like -0 == null, which must evaluate to false,
859 // this truncation must not happen. For this reason we restrict this
860 // case to when either the user explicitly requested a float (and thus
861 // wants +0 if null is the input) or we know from the types that the
862 // input can only be Number | Hole. The latter is necessary to handle
863 // the operator CheckFloat64Hole. We did not put in the type (Number |
864 // Oddball \ Null) to discover more bugs related to this conversion via
865 // crashes.
867 } else if (use_info.type_check() == TypeCheckKind::kNumber ||
869 !output_type.Maybe(Type::BooleanOrNullOrNumber()))) {
871 use_info.feedback());
872 } else if (use_info.type_check() == TypeCheckKind::kNumberOrBoolean) {
875 } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
878 }
879 } else if (output_rep == MachineRepresentation::kFloat32) {
881 } else if (output_rep == MachineRepresentation::kWord64) {
882 if (output_type.Is(cache_->kSafeInteger)) {
884 }
885 }
886 if (op == nullptr) {
887 return TypeError(node, output_rep, output_type,
889 }
890 return InsertConversion(node, op, use_node);
891}
892
896
898 Node* node, DeoptimizeReason reason, const FeedbackSource& feedback) {
899 Node* effect = NodeProperties::GetEffectInput(node);
900 Node* control = NodeProperties::GetControlInput(node);
901 effect =
902 jsgraph()->graph()->NewNode(simplified()->CheckIf(reason, feedback),
903 jsgraph()->Int32Constant(0), effect, control);
904 Node* unreachable = effect = jsgraph()->graph()->NewNode(
905 jsgraph()->common()->Unreachable(), effect, control);
907 return unreachable;
908}
909
911 Node* node, MachineRepresentation output_rep, Type output_type,
912 Node* use_node, UseInfo use_info) {
913 // Eagerly fold representation changes for constants.
914 switch (node->opcode()) {
915 case IrOpcode::kInt32Constant:
916 case IrOpcode::kInt64Constant:
917 case IrOpcode::kFloat32Constant:
918 case IrOpcode::kFloat64Constant:
919 UNREACHABLE();
920 case IrOpcode::kNumberConstant: {
921 double const fv = OpParameter<double>(node->op());
922 if (use_info.type_check() == TypeCheckKind::kNone ||
923 ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
924 use_info.type_check() == TypeCheckKind::kSigned32 ||
926 use_info.type_check() == TypeCheckKind::kNumber ||
928 use_info.type_check() == TypeCheckKind::kArrayIndex) &&
929 IsInt32Double(fv))) {
932 }
933 break;
934 }
935 default:
936 break;
937 }
938
939 // Select the correct X -> Word32 operator.
940 const Operator* op = nullptr;
941 if (output_type.Is(Type::None())) {
942 // This is an impossible value; it should not be used at runtime.
943 return jsgraph()->graph()->NewNode(
944 jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
945 } else if (output_rep == MachineRepresentation::kBit) {
946 CHECK(output_type.Is(Type::Boolean()));
947 if (use_info.truncation().IsUsedAsWord32()) {
948 return node;
949 } else {
951 .IsLessGeneralThan(use_info.truncation()));
954 Node* unreachable =
955 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
956 return jsgraph()->graph()->NewNode(
957 jsgraph()->common()->DeadValue(MachineRepresentation::kWord32),
958 unreachable);
959 }
960 } else if (output_rep == MachineRepresentation::kFloat64) {
961 if (output_type.Is(Type::Signed32())) {
963 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
964 use_info.type_check() == TypeCheckKind::kSigned32 ||
967 output_type.Maybe(Type::MinusZero())
968 ? use_info.minus_zero_check()
970 use_info.feedback());
971 } else if (output_type.Is(Type::Unsigned32())) {
973 } else if (use_info.truncation().IsUsedAsWord32()) {
976 output_type.Maybe(Type::MinusZero())
977 ? use_info.minus_zero_check()
979 use_info.feedback());
980 node = InsertConversion(node, op, use_node);
982 } else {
984 }
985 } else {
986 return TypeError(node, output_rep, output_type,
988 }
989 } else if (output_rep == MachineRepresentation::kFloat32) {
990 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
991 if (output_type.Is(Type::Signed32())) {
993 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
994 use_info.type_check() == TypeCheckKind::kSigned32 ||
997 output_type.Maybe(Type::MinusZero())
998 ? use_info.minus_zero_check()
1000 use_info.feedback());
1001 } else if (output_type.Is(Type::Unsigned32())) {
1003 } else if (use_info.truncation().IsUsedAsWord32()) {
1006 output_type.Maybe(Type::MinusZero())
1007 ? use_info.minus_zero_check()
1009 use_info.feedback());
1010 node = InsertConversion(node, op, use_node);
1011 op = machine()->TruncateInt64ToInt32();
1012 } else {
1014 }
1015 } else {
1016 return TypeError(node, output_rep, output_type,
1018 }
1019 } else if (IsAnyTagged(output_rep)) {
1020 if (output_rep == MachineRepresentation::kTaggedSigned &&
1021 output_type.Is(Type::SignedSmall())) {
1023 } else if (output_type.Is(Type::Signed32())) {
1025 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
1027 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
1029 output_type.Maybe(Type::MinusZero())
1030 ? use_info.minus_zero_check()
1032 use_info.feedback());
1033 } else if (use_info.type_check() == TypeCheckKind::kArrayIndex) {
1034 op = simplified()->CheckedTaggedToArrayIndex(use_info.feedback());
1035 } else if (output_type.Is(Type::Unsigned32())) {
1037 } else if (use_info.truncation().IsUsedAsWord32()) {
1041 } else if (output_type.Is(Type::NumberOrOddballOrHole())) {
1043 } else if (use_info.type_check() == TypeCheckKind::kNumber) {
1046 } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
1049 } else {
1050 return TypeError(node, output_rep, output_type,
1052 }
1053 } else {
1054 return TypeError(node, output_rep, output_type,
1056 }
1057 } else if (output_rep == MachineRepresentation::kWord32) {
1058 // Only the checked case should get here, the non-checked case is
1059 // handled in GetRepresentationFor.
1060 if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
1061 use_info.type_check() == TypeCheckKind::kSigned32 ||
1062 use_info.type_check() == TypeCheckKind::kArrayIndex) {
1063 bool identify_zeros = use_info.truncation().IdentifiesZeroAndMinusZero();
1064 if (output_type.Is(Type::Signed32()) ||
1065 (identify_zeros && output_type.Is(Type::Signed32OrMinusZero()))) {
1066 return node;
1067 } else if (output_type.Is(Type::Unsigned32()) ||
1068 (identify_zeros &&
1069 output_type.Is(Type::Unsigned32OrMinusZero()))) {
1070 op = simplified()->CheckedUint32ToInt32(use_info.feedback());
1071 } else {
1072 return TypeError(node, output_rep, output_type,
1074 }
1075 } else if (use_info.type_check() == TypeCheckKind::kAdditiveSafeInteger ||
1076 use_info.type_check() == TypeCheckKind::kNumber ||
1078 return node;
1079 }
1080 } else if (output_rep == MachineRepresentation::kWord8 ||
1081 output_rep == MachineRepresentation::kWord16) {
1084 use_info.type_check() == TypeCheckKind::kSigned32);
1085 return node;
1086 } else if (output_rep == MachineRepresentation::kWord64) {
1087 if (output_type.Is(Type::Signed32()) ||
1088 (output_type.Is(Type::Unsigned32()) &&
1089 use_info.type_check() == TypeCheckKind::kNone) ||
1090 (output_type.Is(cache_->kSafeInteger) &&
1091 use_info.truncation().IsUsedAsWord32())) {
1092 op = machine()->TruncateInt64ToInt32();
1093 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
1094 use_info.type_check() == TypeCheckKind::kSigned32 ||
1095 use_info.type_check() == TypeCheckKind::kArrayIndex) {
1096 if (output_type.Is(cache_->kPositiveSafeInteger)) {
1097 op = simplified()->CheckedUint64ToInt32(use_info.feedback());
1098 } else if (output_type.Is(cache_->kSafeInteger)) {
1099 op = simplified()->CheckedInt64ToInt32(use_info.feedback());
1100 } else {
1101 return TypeError(node, output_rep, output_type,
1103 }
1104 } else {
1105 return TypeError(node, output_rep, output_type,
1107 }
1108 }
1109
1110 if (op == nullptr) {
1111 return TypeError(node, output_rep, output_type,
1113 }
1114 return InsertConversion(node, op, use_node);
1115}
1116
1118 Node* use_node) {
1119 if (op->ControlInputCount() > 0) {
1120 // If the operator can deoptimize (which means it has control
1121 // input), we need to connect it to the effect and control chains.
1122 Node* effect = NodeProperties::GetEffectInput(use_node);
1123 Node* control = NodeProperties::GetControlInput(use_node);
1124 Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
1125 NodeProperties::ReplaceEffectInput(use_node, conversion);
1126 return conversion;
1127 }
1128 return jsgraph()->graph()->NewNode(op, node);
1129}
1130
1132 Node* node, MachineRepresentation output_rep, Type output_type) {
1133 // Eagerly fold representation changes for constants.
1134 switch (node->opcode()) {
1135 case IrOpcode::kHeapConstant: {
1136 HeapObjectMatcher m(node);
1137 if (m.Is(factory()->false_value())) {
1139 Type::Constant(broker_, broker_->false_value(), jsgraph()->zone()),
1140 jsgraph()->Int32Constant(0));
1141 } else if (m.Is(factory()->true_value())) {
1143 Type::Constant(broker_, broker_->true_value(), jsgraph()->zone()),
1144 jsgraph()->Int32Constant(1));
1145 }
1146 break;
1147 }
1148 default:
1149 break;
1150 }
1151 // Select the correct X -> Bit operator.
1152 const Operator* op;
1153 if (output_type.Is(Type::None())) {
1154 // This is an impossible value; it should not be used at runtime.
1155 return jsgraph()->graph()->NewNode(
1156 jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
1157 } else if (output_rep == MachineRepresentation::kTagged ||
1159 if (output_type.Is(Type::BooleanOrNullOrUndefined())) {
1160 // true is the only trueish Oddball.
1161 op = simplified()->ChangeTaggedToBit();
1162 } else {
1163 if (output_rep == MachineRepresentation::kTagged &&
1164 output_type.Maybe(Type::SignedSmall())) {
1166 } else {
1167 // The {output_type} either doesn't include the Smi range,
1168 // or the {output_rep} is known to be TaggedPointer.
1170 }
1171 }
1172 } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1174 node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1175 jsgraph()->Int32Constant(0));
1176 } else {
1177 node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
1178 jsgraph()->IntPtrConstant(0));
1179 }
1180 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1181 jsgraph()->Int32Constant(0));
1182 } else if (IsWord(output_rep)) {
1183 node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1184 jsgraph()->Int32Constant(0));
1185 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1186 jsgraph()->Int32Constant(0));
1187 } else if (output_rep == MachineRepresentation::kWord64) {
1188 node = jsgraph()->graph()->NewNode(machine()->Word64Equal(), node,
1189 jsgraph()->Int64Constant(0));
1190 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1191 jsgraph()->Int32Constant(0));
1192 } else if (output_rep == MachineRepresentation::kFloat32) {
1193 node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
1194 return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
1195 jsgraph()->Float32Constant(0.0), node);
1196 } else if (output_rep == MachineRepresentation::kFloat64) {
1197 node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
1198 return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
1199 jsgraph()->Float64Constant(0.0), node);
1200 } else {
1201 return TypeError(node, output_rep, output_type,
1203 }
1204 return jsgraph()->graph()->NewNode(op, node);
1205}
1206
1208 Node* node, MachineRepresentation output_rep, Type output_type,
1209 Node* use_node, UseInfo use_info) {
1210 // Eagerly fold representation changes for constants.
1211 switch (node->opcode()) {
1212 case IrOpcode::kInt32Constant:
1213 case IrOpcode::kInt64Constant:
1214 case IrOpcode::kFloat32Constant:
1215 case IrOpcode::kFloat64Constant:
1216 UNREACHABLE();
1217 case IrOpcode::kNumberConstant: {
1218 if (!TypeCheckIsBigInt(use_info.type_check())) {
1219 double const fv = OpParameter<double>(node->op());
1220 if (base::IsValueInRangeForNumericType<int64_t>(fv)) {
1221 int64_t const iv = static_cast<int64_t>(fv);
1222 if (static_cast<double>(iv) == fv) {
1224 jsgraph()->Int64Constant(iv));
1225 }
1226 }
1227 }
1228 break;
1229 }
1230 case IrOpcode::kHeapConstant: {
1231 HeapObjectMatcher m(node);
1232 if (m.HasResolvedValue() && m.Ref(broker_).IsBigInt() &&
1233 (Is64() && use_info.truncation().IsUsedAsWord64())) {
1234 BigIntRef bigint = m.Ref(broker_).AsBigInt();
1237 jsgraph()->Int64Constant(static_cast<int64_t>(bigint.AsUint64())));
1238 }
1239 break;
1240 }
1241 default:
1242 break;
1243 }
1244
1245 if (TypeCheckIsBigInt(use_info.type_check())) {
1246 // BigInts are only represented as tagged pointer and word64.
1247 if (!CanBeTaggedPointer(output_rep) &&
1248 output_rep != MachineRepresentation::kWord64) {
1249 DCHECK(!output_type.Equals(Type::BigInt()));
1250 Node* unreachable = InsertUnconditionalDeopt(
1251 use_node, DeoptimizeReason::kNotABigInt, use_info.feedback());
1252 return jsgraph()->graph()->NewNode(
1253 jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1254 unreachable);
1255 }
1256 }
1257
1258 // Select the correct X -> Word64 operator.
1259 const Operator* op;
1260 if (output_type.Is(Type::None())) {
1261 // This is an impossible value; it should not be used at runtime.
1262 return jsgraph()->graph()->NewNode(
1263 jsgraph()->common()->DeadValue(MachineRepresentation::kWord64), node);
1264 } else if (output_rep == MachineRepresentation::kBit) {
1265 CHECK(output_type.Is(Type::Boolean()));
1270 Node* unreachable =
1271 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
1272 return jsgraph()->graph()->NewNode(
1273 jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1274 unreachable);
1275 } else if (IsWord(output_rep)) {
1276 if (output_type.Is(Type::Unsigned32OrMinusZero())) {
1277 // uint32 -> uint64
1278 CHECK_IMPLIES(output_type.Maybe(Type::MinusZero()),
1280 op = machine()->ChangeUint32ToUint64();
1281 } else if (output_type.Is(Type::Signed32OrMinusZero())) {
1282 // int32 -> int64
1283 CHECK_IMPLIES(output_type.Maybe(Type::MinusZero()),
1285 op = machine()->ChangeInt32ToInt64();
1286 } else {
1287 return TypeError(node, output_rep, output_type,
1289 }
1290 } else if (output_rep == MachineRepresentation::kFloat32) {
1291 if (output_type.Is(cache_->kDoubleRepresentableInt64) ||
1293 use_info.truncation().IdentifiesZeroAndMinusZero())) {
1294 // float32 -> float64 -> int64
1295 node = InsertChangeFloat32ToFloat64(node);
1296 op = machine()->ChangeFloat64ToInt64();
1297 } else if (output_type.Is(cache_->kDoubleRepresentableUint64)) {
1298 // float32 -> float64 -> uint64
1299 node = InsertChangeFloat32ToFloat64(node);
1301 } else if (use_info.type_check() == TypeCheckKind::kSigned64 ||
1302 use_info.type_check() == TypeCheckKind::kArrayIndex) {
1303 // float32 -> float64 -> int64
1304 node = InsertChangeFloat32ToFloat64(node);
1306 output_type.Maybe(Type::MinusZero())
1307 ? use_info.minus_zero_check()
1309 use_info.feedback());
1310 } else if (use_info.type_check() == TypeCheckKind::kAdditiveSafeInteger) {
1311 node = InsertChangeFloat32ToFloat64(node);
1313 output_type.Maybe(Type::MinusZero())
1314 ? use_info.minus_zero_check()
1316 use_info.feedback());
1317 } else {
1318 return TypeError(node, output_rep, output_type,
1320 }
1321 } else if (output_rep == MachineRepresentation::kFloat64) {
1322 if (output_type.Is(cache_->kDoubleRepresentableInt64) ||
1324 use_info.truncation().IdentifiesZeroAndMinusZero())) {
1325 op = machine()->ChangeFloat64ToInt64();
1326 } else if (output_type.Is(cache_->kDoubleRepresentableUint64)) {
1328 } else if (use_info.type_check() == TypeCheckKind::kSigned64 ||
1329 use_info.type_check() == TypeCheckKind::kArrayIndex) {
1331 output_type.Maybe(Type::MinusZero())
1332 ? use_info.minus_zero_check()
1334 use_info.feedback());
1335 } else if (use_info.type_check() == TypeCheckKind::kAdditiveSafeInteger) {
1337 output_type.Maybe(Type::MinusZero())
1338 ? use_info.minus_zero_check()
1340 use_info.feedback());
1341 } else {
1342 return TypeError(node, output_rep, output_type,
1344 }
1345 } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1346 if (output_type.Is(Type::SignedSmall())) {
1348 } else {
1349 return TypeError(node, output_rep, output_type,
1351 }
1352 } else if (IsAnyTagged(output_rep) &&
1353 ((Is64() && use_info.truncation().IsUsedAsWord64() &&
1354 (use_info.type_check() == TypeCheckKind::kBigInt ||
1355 output_type.Is(Type::BigInt()))) ||
1356 use_info.type_check() == TypeCheckKind::kBigInt64)) {
1357 node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
1358 use_node, use_info);
1360 } else if (CanBeTaggedPointer(output_rep)) {
1361 if (output_type.Is(cache_->kDoubleRepresentableInt64) ||
1363 use_info.truncation().IdentifiesZeroAndMinusZero())) {
1365 } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1367 output_type.Maybe(Type::MinusZero())
1368 ? use_info.minus_zero_check()
1370 use_info.feedback());
1371 } else if (use_info.type_check() == TypeCheckKind::kArrayIndex) {
1372 op = simplified()->CheckedTaggedToArrayIndex(use_info.feedback());
1373 } else if (use_info.type_check() == TypeCheckKind::kAdditiveSafeInteger) {
1375 output_type.Maybe(Type::MinusZero())
1376 ? use_info.minus_zero_check()
1378 use_info.feedback());
1379 } else {
1380 return TypeError(node, output_rep, output_type,
1382 }
1383 } else if (output_rep == MachineRepresentation::kWord64) {
1384 DCHECK(TypeCheckIsBigInt(use_info.type_check()));
1385 if (output_type.Is(Type::UnsignedBigInt64()) &&
1386 use_info.type_check() == TypeCheckKind::kBigInt64) {
1387 op = simplified()->CheckedUint64ToInt64(use_info.feedback());
1388 } else if ((output_type.Is(Type::BigInt()) &&
1389 use_info.type_check() == TypeCheckKind::kBigInt) ||
1390 (output_type.Is(Type::SignedBigInt64()) &&
1391 use_info.type_check() == TypeCheckKind::kBigInt64)) {
1392 return node;
1393 } else {
1394 DCHECK(output_type != Type::BigInt() ||
1395 use_info.type_check() != TypeCheckKind::kBigInt64);
1396 Node* unreachable = InsertUnconditionalDeopt(
1397 use_node, DeoptimizeReason::kNotABigInt, use_info.feedback());
1398 return jsgraph()->graph()->NewNode(
1399 jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1400 unreachable);
1401 }
1402 } else if (output_rep == MachineRepresentation::kSandboxedPointer) {
1403 if (output_type.Is(Type::SandboxedPointer())) {
1404 return node;
1405 } else {
1406 return TypeError(node, output_rep, output_type,
1408 }
1409 } else {
1410 return TypeError(node, output_rep, output_type,
1412 }
1413 return InsertConversion(node, op, use_node);
1414}
1415
1417 IrOpcode::Value opcode) {
1418 switch (opcode) {
1419 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1420 case IrOpcode::kSpeculativeAdditiveSafeIntegerAdd:
1421 case IrOpcode::kSpeculativeSmallIntegerAdd:
1422 case IrOpcode::kNumberAdd:
1423 return machine()->Int32Add();
1424 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1425 case IrOpcode::kSpeculativeAdditiveSafeIntegerSubtract:
1426 case IrOpcode::kSpeculativeSmallIntegerSubtract:
1427 case IrOpcode::kNumberSubtract:
1428 return machine()->Int32Sub();
1429 case IrOpcode::kSpeculativeNumberMultiply:
1430 case IrOpcode::kNumberMultiply:
1431 return machine()->Int32Mul();
1432 case IrOpcode::kSpeculativeNumberDivide:
1433 case IrOpcode::kNumberDivide:
1434 return machine()->Int32Div();
1435 case IrOpcode::kSpeculativeNumberModulus:
1436 case IrOpcode::kNumberModulus:
1437 return machine()->Int32Mod();
1438 case IrOpcode::kSpeculativeNumberBitwiseOr: // Fall through.
1439 case IrOpcode::kNumberBitwiseOr:
1440 return machine()->Word32Or();
1441 case IrOpcode::kSpeculativeNumberBitwiseXor: // Fall through.
1442 case IrOpcode::kNumberBitwiseXor:
1443 return machine()->Word32Xor();
1444 case IrOpcode::kSpeculativeNumberBitwiseAnd: // Fall through.
1445 case IrOpcode::kNumberBitwiseAnd:
1446 return machine()->Word32And();
1447 case IrOpcode::kNumberEqual:
1448 case IrOpcode::kSpeculativeNumberEqual:
1449 return machine()->Word32Equal();
1450 case IrOpcode::kNumberLessThan:
1451 case IrOpcode::kSpeculativeNumberLessThan:
1452 return machine()->Int32LessThan();
1453 case IrOpcode::kNumberLessThanOrEqual:
1454 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1455 return machine()->Int32LessThanOrEqual();
1456 default:
1457 UNREACHABLE();
1458 }
1459}
1460
1462 IrOpcode::Value opcode) {
1463 switch (opcode) {
1464 case IrOpcode::kSpeculativeSmallIntegerAdd:
1465 return simplified()->CheckedInt32Add();
1466 case IrOpcode::kSpeculativeSmallIntegerSubtract:
1467 return simplified()->CheckedInt32Sub();
1468 case IrOpcode::kSpeculativeNumberDivide:
1469 return simplified()->CheckedInt32Div();
1470 case IrOpcode::kSpeculativeNumberModulus:
1471 return simplified()->CheckedInt32Mod();
1472 default:
1473 UNREACHABLE();
1474 }
1475}
1476
1478 IrOpcode::Value opcode) {
1479 switch (opcode) {
1480 case IrOpcode::kSpeculativeAdditiveSafeIntegerAdd:
1482 case IrOpcode::kSpeculativeAdditiveSafeIntegerSubtract:
1484 default:
1485 UNREACHABLE();
1486 }
1487}
1488
1490 IrOpcode::Value opcode) {
1491 switch (opcode) {
1492 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1493 case IrOpcode::kSpeculativeSmallIntegerAdd:
1494 case IrOpcode::kNumberAdd:
1495 case IrOpcode::kSpeculativeBigIntAdd:
1496 return machine()->Int64Add();
1497 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1498 case IrOpcode::kSpeculativeSmallIntegerSubtract:
1499 case IrOpcode::kNumberSubtract:
1500 case IrOpcode::kSpeculativeBigIntSubtract:
1501 return machine()->Int64Sub();
1502 case IrOpcode::kSpeculativeBigIntMultiply:
1503 return machine()->Int64Mul();
1504 case IrOpcode::kSpeculativeBigIntBitwiseAnd:
1505 return machine()->Word64And();
1506 case IrOpcode::kSpeculativeBigIntBitwiseOr:
1507 return machine()->Word64Or();
1508 case IrOpcode::kSpeculativeBigIntBitwiseXor:
1509 return machine()->Word64Xor();
1510 case IrOpcode::kSpeculativeBigIntEqual:
1511 return machine()->Word64Equal();
1512 case IrOpcode::kSpeculativeBigIntLessThan:
1513 return machine()->Int64LessThan();
1514 case IrOpcode::kSpeculativeBigIntLessThanOrEqual:
1515 return machine()->Int64LessThanOrEqual();
1516 default:
1517 UNREACHABLE();
1518 }
1519}
1520
1522 IrOpcode::Value opcode) {
1523 switch (opcode) {
1524 case IrOpcode::kSpeculativeBigIntAdd:
1525 return simplified()->CheckedInt64Add();
1526 case IrOpcode::kSpeculativeBigIntSubtract:
1527 return simplified()->CheckedInt64Sub();
1528 case IrOpcode::kSpeculativeBigIntMultiply:
1529 return simplified()->CheckedInt64Mul();
1530 case IrOpcode::kSpeculativeBigIntDivide:
1531 return simplified()->CheckedInt64Div();
1532 case IrOpcode::kSpeculativeBigIntModulus:
1533 return simplified()->CheckedInt64Mod();
1534 default:
1535 UNREACHABLE();
1536 }
1537}
1538
1540 IrOpcode::Value opcode) {
1541 switch (opcode) {
1542 case IrOpcode::kSpeculativeBigIntAdd:
1543 return simplified()->BigIntAdd();
1544 case IrOpcode::kSpeculativeBigIntSubtract:
1545 return simplified()->BigIntSubtract();
1546 case IrOpcode::kSpeculativeBigIntMultiply:
1547 return simplified()->BigIntMultiply();
1548 case IrOpcode::kSpeculativeBigIntDivide:
1549 return simplified()->BigIntDivide();
1550 case IrOpcode::kSpeculativeBigIntModulus:
1551 return simplified()->BigIntModulus();
1552 case IrOpcode::kSpeculativeBigIntBitwiseAnd:
1553 return simplified()->BigIntBitwiseAnd();
1554 case IrOpcode::kSpeculativeBigIntBitwiseOr:
1555 return simplified()->BigIntBitwiseOr();
1556 case IrOpcode::kSpeculativeBigIntBitwiseXor:
1557 return simplified()->BigIntBitwiseXor();
1558 case IrOpcode::kSpeculativeBigIntShiftLeft:
1559 return simplified()->BigIntShiftLeft();
1560 case IrOpcode::kSpeculativeBigIntShiftRight:
1561 return simplified()->BigIntShiftRight();
1562 case IrOpcode::kSpeculativeBigIntEqual:
1563 return simplified()->BigIntEqual();
1564 case IrOpcode::kSpeculativeBigIntLessThan:
1565 return simplified()->BigIntLessThan();
1566 case IrOpcode::kSpeculativeBigIntLessThanOrEqual:
1568 default:
1569 UNREACHABLE();
1570 }
1571}
1572
1574 IrOpcode::Value opcode) {
1575 switch (opcode) {
1576 case IrOpcode::kSpeculativeNumberLessThan:
1577 return (COMPRESS_POINTERS_BOOL || machine()->Is32())
1578 ? machine()->Int32LessThan()
1579 : machine()->Int64LessThan();
1580 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1581 return (COMPRESS_POINTERS_BOOL || machine()->Is32())
1584 case IrOpcode::kSpeculativeNumberEqual:
1585 return (COMPRESS_POINTERS_BOOL || machine()->Is32())
1586 ? machine()->Word32Equal()
1587 : machine()->Word64Equal();
1588 default:
1589 UNREACHABLE();
1590 }
1591}
1592
1594 IrOpcode::Value opcode) {
1595 switch (opcode) {
1596 case IrOpcode::kNumberAdd:
1597 return machine()->Int32Add();
1598 case IrOpcode::kNumberSubtract:
1599 return machine()->Int32Sub();
1600 case IrOpcode::kSpeculativeNumberMultiply:
1601 case IrOpcode::kNumberMultiply:
1602 return machine()->Int32Mul();
1603 case IrOpcode::kSpeculativeNumberDivide:
1604 case IrOpcode::kNumberDivide:
1605 return machine()->Uint32Div();
1606 case IrOpcode::kSpeculativeNumberModulus:
1607 case IrOpcode::kNumberModulus:
1608 return machine()->Uint32Mod();
1609 case IrOpcode::kNumberEqual:
1610 case IrOpcode::kSpeculativeNumberEqual:
1611 return machine()->Word32Equal();
1612 case IrOpcode::kNumberLessThan:
1613 case IrOpcode::kSpeculativeNumberLessThan:
1614 return machine()->Uint32LessThan();
1615 case IrOpcode::kNumberLessThanOrEqual:
1616 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1617 return machine()->Uint32LessThanOrEqual();
1618 case IrOpcode::kNumberClz32:
1619 return machine()->Word32Clz();
1620 case IrOpcode::kNumberImul:
1621 return machine()->Int32Mul();
1622 default:
1623 UNREACHABLE();
1624 }
1625}
1626
1628 IrOpcode::Value opcode) {
1629 switch (opcode) {
1630 case IrOpcode::kSpeculativeNumberDivide:
1631 return simplified()->CheckedUint32Div();
1632 case IrOpcode::kSpeculativeNumberModulus:
1633 return simplified()->CheckedUint32Mod();
1634 default:
1635 UNREACHABLE();
1636 }
1637}
1638
1640 IrOpcode::Value opcode) {
1641 switch (opcode) {
1642 case IrOpcode::kSpeculativeNumberAdd:
1643 case IrOpcode::kSpeculativeAdditiveSafeIntegerAdd:
1644 case IrOpcode::kSpeculativeSmallIntegerAdd:
1645 case IrOpcode::kNumberAdd:
1646 return machine()->Float64Add();
1647 case IrOpcode::kSpeculativeNumberSubtract:
1648 case IrOpcode::kSpeculativeAdditiveSafeIntegerSubtract:
1649 case IrOpcode::kSpeculativeSmallIntegerSubtract:
1650 case IrOpcode::kNumberSubtract:
1651 return machine()->Float64Sub();
1652 case IrOpcode::kSpeculativeNumberMultiply:
1653 case IrOpcode::kNumberMultiply:
1654 return machine()->Float64Mul();
1655 case IrOpcode::kSpeculativeNumberDivide:
1656 case IrOpcode::kNumberDivide:
1657 return machine()->Float64Div();
1658 case IrOpcode::kSpeculativeNumberModulus:
1659 case IrOpcode::kNumberModulus:
1660 return machine()->Float64Mod();
1661 case IrOpcode::kNumberEqual:
1662 case IrOpcode::kSpeculativeNumberEqual:
1663 return machine()->Float64Equal();
1664 case IrOpcode::kNumberLessThan:
1665 case IrOpcode::kSpeculativeNumberLessThan:
1666 return machine()->Float64LessThan();
1667 case IrOpcode::kNumberLessThanOrEqual:
1668 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1669 return machine()->Float64LessThanOrEqual();
1670 case IrOpcode::kNumberAbs:
1671 return machine()->Float64Abs();
1672 case IrOpcode::kNumberAcos:
1673 return machine()->Float64Acos();
1674 case IrOpcode::kNumberAcosh:
1675 return machine()->Float64Acosh();
1676 case IrOpcode::kNumberAsin:
1677 return machine()->Float64Asin();
1678 case IrOpcode::kNumberAsinh:
1679 return machine()->Float64Asinh();
1680 case IrOpcode::kNumberAtan:
1681 return machine()->Float64Atan();
1682 case IrOpcode::kNumberAtanh:
1683 return machine()->Float64Atanh();
1684 case IrOpcode::kNumberAtan2:
1685 return machine()->Float64Atan2();
1686 case IrOpcode::kNumberCbrt:
1687 return machine()->Float64Cbrt();
1688 case IrOpcode::kNumberCeil:
1689 return machine()->Float64RoundUp().placeholder();
1690 case IrOpcode::kNumberCos:
1691 return machine()->Float64Cos();
1692 case IrOpcode::kNumberCosh:
1693 return machine()->Float64Cosh();
1694 case IrOpcode::kNumberExp:
1695 return machine()->Float64Exp();
1696 case IrOpcode::kNumberExpm1:
1697 return machine()->Float64Expm1();
1698 case IrOpcode::kNumberFloor:
1699 return machine()->Float64RoundDown().placeholder();
1700 case IrOpcode::kNumberFround:
1702 case IrOpcode::kNumberLog:
1703 return machine()->Float64Log();
1704 case IrOpcode::kNumberLog1p:
1705 return machine()->Float64Log1p();
1706 case IrOpcode::kNumberLog2:
1707 return machine()->Float64Log2();
1708 case IrOpcode::kNumberLog10:
1709 return machine()->Float64Log10();
1710 case IrOpcode::kNumberMax:
1711 return machine()->Float64Max();
1712 case IrOpcode::kNumberMin:
1713 return machine()->Float64Min();
1714 case IrOpcode::kSpeculativeNumberPow:
1715 case IrOpcode::kNumberPow:
1716 return machine()->Float64Pow();
1717 case IrOpcode::kNumberSin:
1718 return machine()->Float64Sin();
1719 case IrOpcode::kNumberSinh:
1720 return machine()->Float64Sinh();
1721 case IrOpcode::kNumberSqrt:
1722 return machine()->Float64Sqrt();
1723 case IrOpcode::kNumberTan:
1724 return machine()->Float64Tan();
1725 case IrOpcode::kNumberTanh:
1726 return machine()->Float64Tanh();
1727 case IrOpcode::kNumberTrunc:
1728 return machine()->Float64RoundTruncate().placeholder();
1729 case IrOpcode::kNumberSilenceNaN:
1730 return machine()->Float64SilenceNaN();
1731 default:
1732 UNREACHABLE();
1733 }
1734}
1735
1737 MachineRepresentation output_rep,
1738 Type output_type,
1740 type_error_ = true;
1741 if (!testing_type_errors_) {
1742 std::ostringstream out_str;
1743 out_str << output_rep << " (";
1744 output_type.PrintTo(out_str);
1745 out_str << ")";
1746
1747 std::ostringstream use_str;
1748 use_str << use;
1749
1750 FATAL(
1751 "RepresentationChangerError: node #%d:%s of "
1752 "%s cannot be changed to %s",
1753 node->id(), node->op()->mnemonic(), out_str.str().c_str(),
1754 use_str.str().c_str());
1755 }
1756 return node;
1757}
1758
1760 return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
1761}
1762
1764 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
1765}
1766
1768 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
1769}
1770
1772 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
1773}
1774
1776 return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
1777}
1778
1780 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
1781 node);
1782}
1783
1785 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
1786 node);
1787}
1788
1790 return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
1791}
1792
1794 return jsgraph()->graph()->NewNode(machine()->TruncateInt64ToInt32(), node);
1795}
1796
1798 Node* node, CheckForMinusZeroMode check, const FeedbackSource& feedback,
1799 Node* use_node) {
1800 return InsertConversion(
1801 node, simplified()->CheckedFloat64ToInt32(check, feedback), use_node);
1802}
1803
1807 jsgraph()->ExternalConstant(
1808 ExternalReference::ieee754_fp16_raw_bits_to_fp32_raw_bits()));
1809 }
1811}
1812
1815 if constexpr (SupportsFpParamsInCLinkage()) {
1816 ieee754_fp64_to_fp16_raw_bits_code_.set(jsgraph()->ExternalConstant(
1817 ExternalReference::ieee754_fp64_to_fp16_raw_bits()));
1818 } else {
1819 ieee754_fp64_to_fp16_raw_bits_code_.set(jsgraph()->ExternalConstant(
1821 ieee754_fp64_raw_bits_to_fp16_raw_bits_for_32bit_arch()));
1822 }
1823 }
1825}
1826
1827Operator const*
1841
1844 Zone* graph_zone = jsgraph()->zone();
1845 CallDescriptor* desc;
1846 if constexpr (SupportsFpParamsInCLinkage()) {
1848 builder.AddReturn(MachineType::Uint32());
1849 builder.AddParam(MachineType::Float64());
1852 } else {
1854 builder.AddReturn(MachineType::Uint32());
1855 builder.AddParam(MachineType::Uint32());
1856 builder.AddParam(MachineType::Uint32());
1859 }
1861 jsgraph()->common()->Call(desc));
1862 }
1864}
1865
1867 Node* node) {
1868 // Replace the op directly if the underlying architecture has support.
1869 DCHECK(!machine()->ChangeFloat16RawBitsToFloat64().IsSupported());
1870 DCHECK_EQ(0, Ieee754Fp16RawBitsToFp32RawBitsOperator()->ControlInputCount());
1871 // On architectures that don't have fp16 support, Float16Array elements are
1872 // loaded as raw bits in a word16, converted to float32 in software, then
1873 // converted to float64.
1874 Node* float32_raw_bits =
1877 return InsertChangeFloat32ToFloat64(jsgraph()->graph()->NewNode(
1878 machine()->BitcastInt32ToFloat32(), float32_raw_bits));
1879}
1880
1882 Node* node) {
1883 // Use the op directly if the underlying architecture has support.
1884 DCHECK(!machine()->TruncateFloat64ToFloat16RawBits().IsSupported());
1885 DCHECK_EQ(0, Ieee754Fp64ToFp16RawBitsOperator()->ControlInputCount());
1886 // On architectures that don't have fp16 support, the input to be stored in
1887 // Float16Array elements are converted from float64 to float16 in software.
1888 if constexpr (SupportsFpParamsInCLinkage()) {
1891 } else {
1892 Node* hi = jsgraph()->graph()->NewNode(
1893 machine()->Float64ExtractHighWord32(), node);
1894 Node* lo =
1895 jsgraph()->graph()->NewNode(machine()->Float64ExtractLowWord32(), node);
1898 }
1899}
1900
1902 Node* node) {
1903 if (verification_enabled()) {
1904 DCHECK(!type.IsInvalid());
1905 node = jsgraph()->graph()->NewNode(
1906 jsgraph()->common()->SLVerifierHint(nullptr, type), node);
1907 verifier_->RecordHint(node);
1908 }
1909 return node;
1910}
1911
1913
1914} // namespace compiler
1915} // namespace internal
1916} // namespace v8
TFGraph * graph
JSGraph * jsgraph
static constexpr MachineType Float64()
static constexpr MachineType Uint32()
static CallDescriptor * GetSimplifiedCDescriptor(Zone *zone, const MachineSignature *sig, CallDescriptor::Flags flags=CallDescriptor::kNoFlags, Operator::Properties properties=Operator::kNoThrow)
Definition c-linkage.cc:269
Node * Uint32Constant(uint32_t value)
static void ReplaceEffectInput(Node *node, Node *effect, int index=0)
static Type GetType(const Node *node)
static Node * GetEffectInput(Node *node, int index=0)
static Node * GetControlInput(Node *node, int index=0)
SetOncePointer< Operator const > ieee754_fp64_to_fp16_raw_bits_operator_
Node * GetBitRepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type)
const Operator * Int32OperatorFor(IrOpcode::Value opcode)
const Operator * Int32OverflowOperatorFor(IrOpcode::Value opcode)
SetOncePointer< Node > ieee754_fp16_raw_bits_to_fp32_raw_bits_code_
const Operator * AdditiveSafeIntegerOverflowOperatorFor(IrOpcode::Value opcode)
const Operator * Uint32OperatorFor(IrOpcode::Value opcode)
Node * GetFloat16RawBitsRepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Node *use_node, UseInfo use_info)
Node * GetTaggedRepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Truncation truncation)
Node * GetTaggedPointerRepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Node *use_node, UseInfo use_info)
Node * InsertTypeOverrideForVerifier(const Type &type, Node *node)
const Operator * Uint32OverflowOperatorFor(IrOpcode::Value opcode)
Node * InsertConversion(Node *node, const Operator *op, Node *use_node)
RepresentationChanger(JSGraph *jsgraph, JSHeapBroker *broker, SimplifiedLoweringVerifier *verifier)
Node * GetTaggedSignedRepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Node *use_node, UseInfo use_info)
Node * InsertCheckedFloat64ToInt32(Node *node, CheckForMinusZeroMode check, const FeedbackSource &feedback, Node *use_node)
Node * InsertUnconditionalDeopt(Node *node, DeoptimizeReason reason, const FeedbackSource &feedback={})
SetOncePointer< Operator const > ieee754_fp16_raw_bits_to_fp32_raw_bits_operator_
Node * GetRepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Node *use_node, UseInfo use_info)
const Operator * TaggedSignedOperatorFor(IrOpcode::Value opcode)
Node * GetWord32RepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Node *use_node, UseInfo use_info)
Node * GetWord64RepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Node *use_node, UseInfo use_info)
Node * GetFloat32RepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Truncation truncation)
const Operator * Int64OverflowOperatorFor(IrOpcode::Value opcode)
const Operator * BigIntOperatorFor(IrOpcode::Value opcode)
Node * GetFloat64RepresentationFor(Node *node, MachineRepresentation output_rep, Type output_type, Node *use_node, UseInfo use_info)
Node * TypeError(Node *node, MachineRepresentation output_rep, Type output_type, MachineRepresentation use)
const Operator * Int64OperatorFor(IrOpcode::Value opcode)
const Operator * Float64OperatorFor(IrOpcode::Value opcode)
const Operator * CheckedInt64ToInt32(const FeedbackSource &feedback)
const Operator * CheckedUint32ToInt32(const FeedbackSource &feedback)
const Operator * CheckedTaggedToAdditiveSafeInteger(CheckForMinusZeroMode, const FeedbackSource &feedback)
const Operator * CheckedTaggedToTaggedPointer(const FeedbackSource &feedback)
const Operator * CheckBigInt(const FeedbackSource &feedback)
const Operator * CheckedTruncateTaggedToWord32(CheckTaggedInputMode, const FeedbackSource &feedback)
const Operator * ChangeFloat64ToTagged(CheckForMinusZeroMode)
const Operator * CheckedFloat64ToAdditiveSafeInteger(CheckForMinusZeroMode, const FeedbackSource &feedback)
const Operator * CheckedTaggedToInt64(CheckForMinusZeroMode, const FeedbackSource &feedback)
const Operator * CheckedInt32ToTaggedSigned(const FeedbackSource &feedback)
const Operator * CheckedUint64ToTaggedSigned(const FeedbackSource &feedback)
const Operator * CheckedUint64ToInt32(const FeedbackSource &feedback)
const Operator * CheckedTaggedToArrayIndex(const FeedbackSource &feedback)
const Operator * CheckedTaggedToInt32(CheckForMinusZeroMode, const FeedbackSource &feedback)
const Operator * CheckedUint32ToTaggedSigned(const FeedbackSource &feedback)
const Operator * CheckedInt64ToTaggedSigned(const FeedbackSource &feedback)
const Operator * CheckedTaggedToFloat64(CheckTaggedInputMode, const FeedbackSource &feedback)
const Operator * CheckedFloat64ToInt64(CheckForMinusZeroMode, const FeedbackSource &feedback)
const Operator * CheckedBigIntToBigInt64(const FeedbackSource &feedback)
const Operator * CheckedFloat64ToInt32(CheckForMinusZeroMode, const FeedbackSource &feedback)
const Operator * CheckedTaggedSignedToInt32(const FeedbackSource &feedback)
const Operator * CheckedTaggedToTaggedSigned(const FeedbackSource &feedback)
const Operator * CheckedUint64ToInt64(const FeedbackSource &feedback)
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
static Truncation Any(IdentifyZeros identify_zeros=kDistinguishZeros)
Definition use-info.h:46
bool TruncatesOddballAndBigIntToNumber() const
Definition use-info.h:68
TruncationKind kind() const
Definition use-info.h:107
static bool LessGeneral(TruncationKind rep1, TruncationKind rep2)
static bool LessGeneralIdentifyZeros(IdentifyZeros u1, IdentifyZeros u2)
IdentifyZeros identify_zeros() const
Definition use-info.h:92
bool IdentifiesZeroAndMinusZero() const
Definition use-info.h:75
static Truncation Generalize(Truncation t1, Truncation t2)
Definition use-info.h:50
static IdentifyZeros GeneralizeIdentifyZeros(IdentifyZeros i1, IdentifyZeros i2)
Type const kDoubleRepresentableInt64OrMinusZero
Definition type-cache.h:41
bool Maybe(Type that) const
void PrintTo(std::ostream &os) const
static Type Constant(JSHeapBroker *broker, Handle< i::Object > value, Zone *zone)
bool Equals(Type that) const
bool Is(Type that) const
Truncation truncation() const
Definition use-info.h:354
const FeedbackSource & feedback() const
Definition use-info.h:361
TypeCheckKind type_check() const
Definition use-info.h:355
CheckForMinusZeroMode minus_zero_check() const
Definition use-info.h:356
MachineRepresentation representation() const
Definition use-info.h:353
#define COMPRESS_POINTERS_BOOL
Definition globals.h:99
JSHeapBroker *const broker_
Zone * graph_zone
JSHeapBroker * broker
Node * node
int m
Definition mul-fft.cc:294
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
T const & OpParameter(const Operator *op)
Definition operator.h:214
static const Operator * IntPtrConstant(CommonOperatorBuilder *common, intptr_t value)
bool IsInt32Double(double value)
constexpr bool IsAnyTagged(MachineRepresentation rep)
constexpr bool CanBeTaggedPointer(MachineRepresentation rep)
int32_t DoubleToInt32(double x)
other heap size generate builtins concurrently on separate threads in mksnapshot track concurrent recompilation artificial compilation delay in ms max number of threads that concurrent Turbofan can use(0 for unbounded)") DEFINE_BOOL( stress_concurrent_inlining
constexpr bool SmiValuesAre32Bits()
float DoubleToFloat32(double x)
uint16_t DoubleToFloat16(double value)
constexpr bool Is64()
SimplifiedLoweringVerifier * verifier_
#define FATAL(...)
Definition logging.h:47
#define CHECK_IMPLIES(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_NE(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485