• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/objects-inl.h"
14 
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18 
description() const19 const char* Truncation::description() const {
20   switch (kind()) {
21     case TruncationKind::kNone:
22       return "no-value-use";
23     case TruncationKind::kBool:
24       return "truncate-to-bool";
25     case TruncationKind::kWord32:
26       return "truncate-to-word32";
27     case TruncationKind::kWord64:
28       return "truncate-to-word64";
29     case TruncationKind::kFloat64:
30       return "truncate-to-float64";
31     case TruncationKind::kAny:
32       return "no-truncation";
33   }
34   UNREACHABLE();
35   return nullptr;
36 }
37 
38 
39 // Partial order for truncations:
40 //
41 //  kWord64       kAny
42 //     ^            ^
43 //     \            |
44 //      \         kFloat64  <--+
45 //       \        ^            |
46 //        \       /            |
47 //         kWord32           kBool
48 //               ^            ^
49 //               \            /
50 //                \          /
51 //                 \        /
52 //                  \      /
53 //                   \    /
54 //                   kNone
55 
56 // static
Generalize(TruncationKind rep1,TruncationKind rep2)57 Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
58                                                   TruncationKind rep2) {
59   if (LessGeneral(rep1, rep2)) return rep2;
60   if (LessGeneral(rep2, rep1)) return rep1;
61   // Handle the generalization of float64-representable values.
62   if (LessGeneral(rep1, TruncationKind::kFloat64) &&
63       LessGeneral(rep2, TruncationKind::kFloat64)) {
64     return TruncationKind::kFloat64;
65   }
66   // Handle the generalization of any-representable values.
67   if (LessGeneral(rep1, TruncationKind::kAny) &&
68       LessGeneral(rep2, TruncationKind::kAny)) {
69     return TruncationKind::kAny;
70   }
71   // All other combinations are illegal.
72   FATAL("Tried to combine incompatible truncations");
73   return TruncationKind::kNone;
74 }
75 
76 
77 // static
LessGeneral(TruncationKind rep1,TruncationKind rep2)78 bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
79   switch (rep1) {
80     case TruncationKind::kNone:
81       return true;
82     case TruncationKind::kBool:
83       return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
84     case TruncationKind::kWord32:
85       return rep2 == TruncationKind::kWord32 ||
86              rep2 == TruncationKind::kWord64 ||
87              rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
88     case TruncationKind::kWord64:
89       return rep2 == TruncationKind::kWord64;
90     case TruncationKind::kFloat64:
91       return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
92     case TruncationKind::kAny:
93       return rep2 == TruncationKind::kAny;
94   }
95   UNREACHABLE();
96   return false;
97 }
98 
99 
100 namespace {
101 
IsWord(MachineRepresentation rep)102 bool IsWord(MachineRepresentation rep) {
103   return rep == MachineRepresentation::kWord8 ||
104          rep == MachineRepresentation::kWord16 ||
105          rep == MachineRepresentation::kWord32;
106 }
107 
108 }  // namespace
109 
110 // Changes representation from {output_rep} to {use_rep}. The {truncation}
111 // parameter is only used for sanity checking - if the changer cannot figure
112 // out signedness for the word32->float64 conversion, then we check that the
113 // uses truncate to word32 (so they do not care about signedness).
GetRepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type,Node * use_node,UseInfo use_info)114 Node* RepresentationChanger::GetRepresentationFor(
115     Node* node, MachineRepresentation output_rep, Type* output_type,
116     Node* use_node, UseInfo use_info) {
117   if (output_rep == MachineRepresentation::kNone &&
118       output_type->IsInhabited()) {
119     // The output representation should be set if the type is inhabited (i.e.,
120     // if the value is possible).
121     return TypeError(node, output_rep, output_type, use_info.representation());
122   }
123 
124   // Handle the no-op shortcuts when no checking is necessary.
125   if (use_info.type_check() == TypeCheckKind::kNone ||
126       output_rep != MachineRepresentation::kWord32) {
127     if (use_info.representation() == output_rep) {
128       // Representations are the same. That's a no-op.
129       return node;
130     }
131     if (IsWord(use_info.representation()) && IsWord(output_rep)) {
132       // Both are words less than or equal to 32-bits.
133       // Since loads of integers from memory implicitly sign or zero extend the
134       // value to the full machine word size and stores implicitly truncate,
135       // no representation change is necessary.
136       return node;
137     }
138   }
139 
140   switch (use_info.representation()) {
141     case MachineRepresentation::kTaggedSigned:
142       DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
143              use_info.type_check() == TypeCheckKind::kSignedSmall);
144       return GetTaggedSignedRepresentationFor(node, output_rep, output_type,
145                                               use_node, use_info);
146     case MachineRepresentation::kTaggedPointer:
147       DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
148              use_info.type_check() == TypeCheckKind::kHeapObject);
149       return GetTaggedPointerRepresentationFor(node, output_rep, output_type,
150                                                use_node, use_info);
151     case MachineRepresentation::kTagged:
152       DCHECK(use_info.type_check() == TypeCheckKind::kNone);
153       return GetTaggedRepresentationFor(node, output_rep, output_type,
154                                         use_info.truncation());
155     case MachineRepresentation::kFloat32:
156       DCHECK(use_info.type_check() == TypeCheckKind::kNone);
157       return GetFloat32RepresentationFor(node, output_rep, output_type,
158                                          use_info.truncation());
159     case MachineRepresentation::kFloat64:
160       return GetFloat64RepresentationFor(node, output_rep, output_type,
161                                          use_node, use_info);
162     case MachineRepresentation::kBit:
163       DCHECK(use_info.type_check() == TypeCheckKind::kNone);
164       return GetBitRepresentationFor(node, output_rep, output_type);
165     case MachineRepresentation::kWord8:
166     case MachineRepresentation::kWord16:
167     case MachineRepresentation::kWord32:
168       return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
169                                         use_info);
170     case MachineRepresentation::kWord64:
171       DCHECK(use_info.type_check() == TypeCheckKind::kNone);
172       return GetWord64RepresentationFor(node, output_rep, output_type);
173     case MachineRepresentation::kSimd128:
174     case MachineRepresentation::kSimd1x4:
175     case MachineRepresentation::kSimd1x8:
176     case MachineRepresentation::kSimd1x16:
177     case MachineRepresentation::kNone:
178       return node;
179   }
180   UNREACHABLE();
181   return nullptr;
182 }
183 
GetTaggedSignedRepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type,Node * use_node,UseInfo use_info)184 Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
185     Node* node, MachineRepresentation output_rep, Type* output_type,
186     Node* use_node, UseInfo use_info) {
187   // Eagerly fold representation changes for constants.
188   switch (node->opcode()) {
189     case IrOpcode::kNumberConstant:
190       if (output_type->Is(Type::SignedSmall())) {
191         return node;
192       }
193       break;
194     default:
195       break;
196   }
197   // Select the correct X -> Tagged operator.
198   const Operator* op;
199   if (output_type->Is(Type::None())) {
200     // This is an impossible value; it should not be used at runtime.
201     // We just provide a dummy value here.
202     return jsgraph()->Constant(0);
203   } else if (IsWord(output_rep)) {
204     if (output_type->Is(Type::Signed31())) {
205       op = simplified()->ChangeInt31ToTaggedSigned();
206     } else if (output_type->Is(Type::Signed32())) {
207       if (SmiValuesAre32Bits()) {
208         op = simplified()->ChangeInt32ToTagged();
209       } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
210         op = simplified()->CheckedInt32ToTaggedSigned();
211       } else {
212         return TypeError(node, output_rep, output_type,
213                          MachineRepresentation::kTaggedSigned);
214       }
215     } else if (output_type->Is(Type::Unsigned32()) &&
216                use_info.type_check() == TypeCheckKind::kSignedSmall) {
217       op = simplified()->CheckedUint32ToTaggedSigned();
218     } else {
219       return TypeError(node, output_rep, output_type,
220                        MachineRepresentation::kTaggedSigned);
221     }
222   } else if (output_rep == MachineRepresentation::kFloat64) {
223     if (output_type->Is(Type::Signed31())) {
224       // float64 -> int32 -> tagged signed
225       node = InsertChangeFloat64ToInt32(node);
226       op = simplified()->ChangeInt31ToTaggedSigned();
227     } else if (output_type->Is(Type::Signed32())) {
228       // float64 -> int32 -> tagged signed
229       node = InsertChangeFloat64ToInt32(node);
230       if (SmiValuesAre32Bits()) {
231         op = simplified()->ChangeInt32ToTagged();
232       } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
233         op = simplified()->CheckedInt32ToTaggedSigned();
234       } else {
235         return TypeError(node, output_rep, output_type,
236                          MachineRepresentation::kTaggedSigned);
237       }
238     } else if (output_type->Is(Type::Unsigned32()) &&
239                use_info.type_check() == TypeCheckKind::kSignedSmall) {
240       // float64 -> uint32 -> tagged signed
241       node = InsertChangeFloat64ToUint32(node);
242       op = simplified()->CheckedUint32ToTaggedSigned();
243     } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
244       op = simplified()->CheckedFloat64ToInt32(
245           output_type->Maybe(Type::MinusZero())
246               ? CheckForMinusZeroMode::kCheckForMinusZero
247               : CheckForMinusZeroMode::kDontCheckForMinusZero);
248       node = InsertConversion(node, op, use_node);
249       if (SmiValuesAre32Bits()) {
250         op = simplified()->ChangeInt32ToTagged();
251       } else {
252         op = simplified()->CheckedInt32ToTaggedSigned();
253       }
254     } else {
255       return TypeError(node, output_rep, output_type,
256                        MachineRepresentation::kTaggedSigned);
257     }
258   } else if (output_rep == MachineRepresentation::kFloat32) {
259     if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
260       op = machine()->ChangeFloat32ToFloat64();
261       node = InsertConversion(node, op, use_node);
262       op = simplified()->CheckedFloat64ToInt32(
263           output_type->Maybe(Type::MinusZero())
264               ? CheckForMinusZeroMode::kCheckForMinusZero
265               : CheckForMinusZeroMode::kDontCheckForMinusZero);
266       node = InsertConversion(node, op, use_node);
267       if (SmiValuesAre32Bits()) {
268         op = simplified()->ChangeInt32ToTagged();
269       } else {
270         op = simplified()->CheckedInt32ToTaggedSigned();
271       }
272     } else {
273       return TypeError(node, output_rep, output_type,
274                        MachineRepresentation::kTaggedSigned);
275     }
276   } else if (CanBeTaggedPointer(output_rep)) {
277     if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
278       op = simplified()->CheckedTaggedToTaggedSigned();
279     } else if (output_type->Is(Type::SignedSmall())) {
280       op = simplified()->ChangeTaggedToTaggedSigned();
281     } else {
282       return TypeError(node, output_rep, output_type,
283                        MachineRepresentation::kTaggedSigned);
284     }
285   } else if (output_rep == MachineRepresentation::kBit &&
286              use_info.type_check() == TypeCheckKind::kSignedSmall) {
287     // TODO(turbofan): Consider adding a Bailout operator that just deopts.
288     // Also use that for MachineRepresentation::kPointer case above.
289     node = InsertChangeBitToTagged(node);
290     op = simplified()->CheckedTaggedToTaggedSigned();
291   } else {
292     return TypeError(node, output_rep, output_type,
293                      MachineRepresentation::kTaggedSigned);
294   }
295   return InsertConversion(node, op, use_node);
296 }
297 
GetTaggedPointerRepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type,Node * use_node,UseInfo use_info)298 Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
299     Node* node, MachineRepresentation output_rep, Type* output_type,
300     Node* use_node, UseInfo use_info) {
301   // Eagerly fold representation changes for constants.
302   switch (node->opcode()) {
303     case IrOpcode::kHeapConstant:
304       return node;  // No change necessary.
305     case IrOpcode::kInt32Constant:
306     case IrOpcode::kFloat64Constant:
307     case IrOpcode::kFloat32Constant:
308       UNREACHABLE();
309     default:
310       break;
311   }
312   // Select the correct X -> TaggedPointer operator.
313   Operator const* op;
314   if (output_type->Is(Type::None())) {
315     // This is an impossible value; it should not be used at runtime.
316     // We just provide a dummy value here.
317     return jsgraph()->TheHoleConstant();
318   } else if (output_rep == MachineRepresentation::kBit) {
319     if (output_type->Is(Type::Boolean())) {
320       op = simplified()->ChangeBitToTagged();
321     } else {
322       return TypeError(node, output_rep, output_type,
323                        MachineRepresentation::kTagged);
324     }
325   } else if (IsWord(output_rep)) {
326     if (output_type->Is(Type::Unsigned32())) {
327       // uint32 -> float64 -> tagged
328       node = InsertChangeUint32ToFloat64(node);
329     } else if (output_type->Is(Type::Signed32())) {
330       // int32 -> float64 -> tagged
331       node = InsertChangeInt32ToFloat64(node);
332     } else {
333       return TypeError(node, output_rep, output_type,
334                        MachineRepresentation::kTaggedPointer);
335     }
336     op = simplified()->ChangeFloat64ToTaggedPointer();
337   } else if (output_rep == MachineRepresentation::kFloat32) {
338     // float32 -> float64 -> tagged
339     node = InsertChangeFloat32ToFloat64(node);
340     op = simplified()->ChangeFloat64ToTaggedPointer();
341   } else if (output_rep == MachineRepresentation::kFloat64) {
342     // float64 -> tagged
343     op = simplified()->ChangeFloat64ToTaggedPointer();
344   } else if (CanBeTaggedSigned(output_rep) &&
345              use_info.type_check() == TypeCheckKind::kHeapObject) {
346     if (!output_type->Maybe(Type::SignedSmall())) {
347       return node;
348     }
349     // TODO(turbofan): Consider adding a Bailout operator that just deopts
350     // for TaggedSigned output representation.
351     op = simplified()->CheckedTaggedToTaggedPointer();
352   } else {
353     return TypeError(node, output_rep, output_type,
354                      MachineRepresentation::kTaggedPointer);
355   }
356   return InsertConversion(node, op, use_node);
357 }
358 
GetTaggedRepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type,Truncation truncation)359 Node* RepresentationChanger::GetTaggedRepresentationFor(
360     Node* node, MachineRepresentation output_rep, Type* output_type,
361     Truncation truncation) {
362   // Eagerly fold representation changes for constants.
363   switch (node->opcode()) {
364     case IrOpcode::kNumberConstant:
365     case IrOpcode::kHeapConstant:
366       return node;  // No change necessary.
367     case IrOpcode::kInt32Constant:
368     case IrOpcode::kFloat64Constant:
369     case IrOpcode::kFloat32Constant:
370       UNREACHABLE();
371       break;
372     default:
373       break;
374   }
375   if (output_rep == MachineRepresentation::kTaggedSigned ||
376       output_rep == MachineRepresentation::kTaggedPointer) {
377     // this is a no-op.
378     return node;
379   }
380   // Select the correct X -> Tagged operator.
381   const Operator* op;
382   if (output_type->Is(Type::None())) {
383     // This is an impossible value; it should not be used at runtime.
384     // We just provide a dummy value here.
385     return jsgraph()->TheHoleConstant();
386   } else if (output_rep == MachineRepresentation::kBit) {
387     if (output_type->Is(Type::Boolean())) {
388       op = simplified()->ChangeBitToTagged();
389     } else {
390       return TypeError(node, output_rep, output_type,
391                        MachineRepresentation::kTagged);
392     }
393   } else if (IsWord(output_rep)) {
394     if (output_type->Is(Type::Signed31())) {
395       op = simplified()->ChangeInt31ToTaggedSigned();
396     } else if (output_type->Is(Type::Signed32())) {
397       op = simplified()->ChangeInt32ToTagged();
398     } else if (output_type->Is(Type::Unsigned32()) ||
399                truncation.IsUsedAsWord32()) {
400       // Either the output is uint32 or the uses only care about the
401       // low 32 bits (so we can pick uint32 safely).
402       op = simplified()->ChangeUint32ToTagged();
403     } else {
404       return TypeError(node, output_rep, output_type,
405                        MachineRepresentation::kTagged);
406     }
407   } else if (output_rep ==
408              MachineRepresentation::kFloat32) {  // float32 -> float64 -> tagged
409     node = InsertChangeFloat32ToFloat64(node);
410     op = simplified()->ChangeFloat64ToTagged();
411   } else if (output_rep == MachineRepresentation::kFloat64) {
412     if (output_type->Is(Type::Signed31())) {  // float64 -> int32 -> tagged
413       node = InsertChangeFloat64ToInt32(node);
414       op = simplified()->ChangeInt31ToTaggedSigned();
415     } else if (output_type->Is(
416                    Type::Signed32())) {  // float64 -> int32 -> tagged
417       node = InsertChangeFloat64ToInt32(node);
418       op = simplified()->ChangeInt32ToTagged();
419     } else if (output_type->Is(
420                    Type::Unsigned32())) {  // float64 -> uint32 -> tagged
421       node = InsertChangeFloat64ToUint32(node);
422       op = simplified()->ChangeUint32ToTagged();
423     } else {
424       op = simplified()->ChangeFloat64ToTagged();
425     }
426   } else {
427     return TypeError(node, output_rep, output_type,
428                      MachineRepresentation::kTagged);
429   }
430   return jsgraph()->graph()->NewNode(op, node);
431 }
432 
433 
GetFloat32RepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type,Truncation truncation)434 Node* RepresentationChanger::GetFloat32RepresentationFor(
435     Node* node, MachineRepresentation output_rep, Type* output_type,
436     Truncation truncation) {
437   // Eagerly fold representation changes for constants.
438   switch (node->opcode()) {
439     case IrOpcode::kNumberConstant:
440       return jsgraph()->Float32Constant(
441           DoubleToFloat32(OpParameter<double>(node)));
442     case IrOpcode::kInt32Constant:
443     case IrOpcode::kFloat64Constant:
444     case IrOpcode::kFloat32Constant:
445       UNREACHABLE();
446       break;
447     default:
448       break;
449   }
450   // Select the correct X -> Float32 operator.
451   const Operator* op = nullptr;
452   if (output_type->Is(Type::None())) {
453     // This is an impossible value; it should not be used at runtime.
454     // We just provide a dummy value here.
455     return jsgraph()->Float32Constant(0.0f);
456   } else if (IsWord(output_rep)) {
457     if (output_type->Is(Type::Signed32())) {
458       // int32 -> float64 -> float32
459       op = machine()->ChangeInt32ToFloat64();
460       node = jsgraph()->graph()->NewNode(op, node);
461       op = machine()->TruncateFloat64ToFloat32();
462     } else if (output_type->Is(Type::Unsigned32()) ||
463                truncation.IsUsedAsWord32()) {
464       // Either the output is uint32 or the uses only care about the
465       // low 32 bits (so we can pick uint32 safely).
466 
467       // uint32 -> float64 -> float32
468       op = machine()->ChangeUint32ToFloat64();
469       node = jsgraph()->graph()->NewNode(op, node);
470       op = machine()->TruncateFloat64ToFloat32();
471     }
472   } else if (output_rep == MachineRepresentation::kTagged ||
473              output_rep == MachineRepresentation::kTaggedPointer) {
474     if (output_type->Is(Type::NumberOrOddball())) {
475       // tagged -> float64 -> float32
476       if (output_type->Is(Type::Number())) {
477         op = simplified()->ChangeTaggedToFloat64();
478       } else {
479         op = simplified()->TruncateTaggedToFloat64();
480       }
481       node = jsgraph()->graph()->NewNode(op, node);
482       op = machine()->TruncateFloat64ToFloat32();
483     }
484   } else if (output_rep == MachineRepresentation::kFloat64) {
485     op = machine()->TruncateFloat64ToFloat32();
486   }
487   if (op == nullptr) {
488     return TypeError(node, output_rep, output_type,
489                      MachineRepresentation::kFloat32);
490   }
491   return jsgraph()->graph()->NewNode(op, node);
492 }
493 
GetFloat64RepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type,Node * use_node,UseInfo use_info)494 Node* RepresentationChanger::GetFloat64RepresentationFor(
495     Node* node, MachineRepresentation output_rep, Type* output_type,
496     Node* use_node, UseInfo use_info) {
497   // Eagerly fold representation changes for constants.
498   if ((use_info.type_check() == TypeCheckKind::kNone)) {
499     // TODO(jarin) Handle checked constant conversions.
500     switch (node->opcode()) {
501       case IrOpcode::kNumberConstant:
502         return jsgraph()->Float64Constant(OpParameter<double>(node));
503       case IrOpcode::kInt32Constant:
504       case IrOpcode::kFloat64Constant:
505       case IrOpcode::kFloat32Constant:
506         UNREACHABLE();
507         break;
508       default:
509         break;
510     }
511   }
512   // Select the correct X -> Float64 operator.
513   const Operator* op = nullptr;
514   if (output_type->Is(Type::None())) {
515     // This is an impossible value; it should not be used at runtime.
516     // We just provide a dummy value here.
517     return jsgraph()->Float64Constant(0.0);
518   } else if (IsWord(output_rep)) {
519     if (output_type->Is(Type::Signed32())) {
520       op = machine()->ChangeInt32ToFloat64();
521     } else if (output_type->Is(Type::Unsigned32()) ||
522                use_info.truncation().IsUsedAsWord32()) {
523       // Either the output is uint32 or the uses only care about the
524       // low 32 bits (so we can pick uint32 safely).
525       op = machine()->ChangeUint32ToFloat64();
526     }
527   } else if (output_rep == MachineRepresentation::kBit) {
528     op = machine()->ChangeUint32ToFloat64();
529   } else if (output_rep == MachineRepresentation::kTagged ||
530              output_rep == MachineRepresentation::kTaggedSigned ||
531              output_rep == MachineRepresentation::kTaggedPointer) {
532     if (output_type->Is(Type::Undefined())) {
533       return jsgraph()->Float64Constant(
534           std::numeric_limits<double>::quiet_NaN());
535 
536     } else if (output_rep == MachineRepresentation::kTaggedSigned) {
537       node = InsertChangeTaggedSignedToInt32(node);
538       op = machine()->ChangeInt32ToFloat64();
539     } else if (output_type->Is(Type::Number())) {
540       op = simplified()->ChangeTaggedToFloat64();
541     } else if (output_type->Is(Type::NumberOrOddball())) {
542       // TODO(jarin) Here we should check that truncation is Number.
543       op = simplified()->TruncateTaggedToFloat64();
544     } else if (use_info.type_check() == TypeCheckKind::kNumber ||
545                (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
546                 !output_type->Maybe(Type::BooleanOrNullOrNumber()))) {
547       op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber);
548     } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
549       op = simplified()->CheckedTaggedToFloat64(
550           CheckTaggedInputMode::kNumberOrOddball);
551     }
552   } else if (output_rep == MachineRepresentation::kFloat32) {
553     op = machine()->ChangeFloat32ToFloat64();
554   }
555   if (op == nullptr) {
556     return TypeError(node, output_rep, output_type,
557                      MachineRepresentation::kFloat64);
558   }
559   return InsertConversion(node, op, use_node);
560 }
561 
MakeTruncatedInt32Constant(double value)562 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
563   return jsgraph()->Int32Constant(DoubleToInt32(value));
564 }
565 
GetWord32RepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type,Node * use_node,UseInfo use_info)566 Node* RepresentationChanger::GetWord32RepresentationFor(
567     Node* node, MachineRepresentation output_rep, Type* output_type,
568     Node* use_node, UseInfo use_info) {
569   // Eagerly fold representation changes for constants.
570   switch (node->opcode()) {
571     case IrOpcode::kInt32Constant:
572     case IrOpcode::kFloat32Constant:
573     case IrOpcode::kFloat64Constant:
574       UNREACHABLE();
575       break;
576     case IrOpcode::kNumberConstant: {
577       double const fv = OpParameter<double>(node);
578       if (use_info.type_check() == TypeCheckKind::kNone ||
579           ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
580             use_info.type_check() == TypeCheckKind::kSigned32) &&
581            IsInt32Double(fv))) {
582         return MakeTruncatedInt32Constant(fv);
583       }
584       break;
585     }
586     default:
587       break;
588   }
589 
590   // Select the correct X -> Word32 operator.
591   const Operator* op = nullptr;
592   if (output_type->Is(Type::None())) {
593     // This is an impossible value; it should not be used at runtime.
594     // We just provide a dummy value here.
595     return jsgraph()->Int32Constant(0);
596   } else if (output_rep == MachineRepresentation::kBit) {
597     return node;  // Sloppy comparison -> word32
598   } else if (output_rep == MachineRepresentation::kFloat64) {
599     if (output_type->Is(Type::Signed32())) {
600       op = machine()->ChangeFloat64ToInt32();
601     } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
602                use_info.type_check() == TypeCheckKind::kSigned32) {
603       op = simplified()->CheckedFloat64ToInt32(
604           output_type->Maybe(Type::MinusZero())
605               ? use_info.minus_zero_check()
606               : CheckForMinusZeroMode::kDontCheckForMinusZero);
607     } else if (output_type->Is(Type::Unsigned32())) {
608       op = machine()->ChangeFloat64ToUint32();
609     } else if (use_info.truncation().IsUsedAsWord32()) {
610       op = machine()->TruncateFloat64ToWord32();
611     }
612   } else if (output_rep == MachineRepresentation::kFloat32) {
613     node = InsertChangeFloat32ToFloat64(node);  // float32 -> float64 -> int32
614     if (output_type->Is(Type::Signed32())) {
615       op = machine()->ChangeFloat64ToInt32();
616     } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
617                use_info.type_check() == TypeCheckKind::kSigned32) {
618       op = simplified()->CheckedFloat64ToInt32(
619           output_type->Maybe(Type::MinusZero())
620               ? CheckForMinusZeroMode::kCheckForMinusZero
621               : CheckForMinusZeroMode::kDontCheckForMinusZero);
622     } else if (output_type->Is(Type::Unsigned32())) {
623       op = machine()->ChangeFloat64ToUint32();
624     } else if (use_info.truncation().IsUsedAsWord32()) {
625       op = machine()->TruncateFloat64ToWord32();
626     }
627   } else if (output_rep == MachineRepresentation::kTaggedSigned) {
628     if (output_type->Is(Type::Signed32())) {
629       op = simplified()->ChangeTaggedSignedToInt32();
630     } else if (use_info.truncation().IsUsedAsWord32()) {
631       if (use_info.type_check() != TypeCheckKind::kNone) {
632         op = simplified()->CheckedTruncateTaggedToWord32();
633       } else {
634         op = simplified()->TruncateTaggedToWord32();
635       }
636     }
637   } else if (output_rep == MachineRepresentation::kTagged ||
638              output_rep == MachineRepresentation::kTaggedPointer) {
639     if (output_type->Is(Type::Signed32())) {
640       op = simplified()->ChangeTaggedToInt32();
641     } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
642       op = simplified()->CheckedTaggedSignedToInt32();
643     } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
644       op = simplified()->CheckedTaggedToInt32(
645           output_type->Maybe(Type::MinusZero())
646               ? CheckForMinusZeroMode::kCheckForMinusZero
647               : CheckForMinusZeroMode::kDontCheckForMinusZero);
648     } else if (output_type->Is(Type::Unsigned32())) {
649       op = simplified()->ChangeTaggedToUint32();
650     } else if (use_info.truncation().IsUsedAsWord32()) {
651       if (output_type->Is(Type::NumberOrOddball())) {
652         op = simplified()->TruncateTaggedToWord32();
653       } else if (use_info.type_check() != TypeCheckKind::kNone) {
654         op = simplified()->CheckedTruncateTaggedToWord32();
655       }
656     }
657   } else if (output_rep == MachineRepresentation::kWord32) {
658     // Only the checked case should get here, the non-checked case is
659     // handled in GetRepresentationFor.
660     if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
661         use_info.type_check() == TypeCheckKind::kSigned32) {
662       if (output_type->Is(Type::Signed32())) {
663         return node;
664       } else if (output_type->Is(Type::Unsigned32())) {
665         op = simplified()->CheckedUint32ToInt32();
666       }
667     } else {
668       DCHECK_EQ(TypeCheckKind::kNumberOrOddball, use_info.type_check());
669       return node;
670     }
671   } else if (output_rep == MachineRepresentation::kWord8 ||
672              output_rep == MachineRepresentation::kWord16) {
673     DCHECK(use_info.representation() == MachineRepresentation::kWord32);
674     DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall ||
675            use_info.type_check() == TypeCheckKind::kSigned32);
676     return node;
677   }
678 
679   if (op == nullptr) {
680     return TypeError(node, output_rep, output_type,
681                      MachineRepresentation::kWord32);
682   }
683   return InsertConversion(node, op, use_node);
684 }
685 
InsertConversion(Node * node,const Operator * op,Node * use_node)686 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
687                                               Node* use_node) {
688   if (op->ControlInputCount() > 0) {
689     // If the operator can deoptimize (which means it has control
690     // input), we need to connect it to the effect and control chains.
691     Node* effect = NodeProperties::GetEffectInput(use_node);
692     Node* control = NodeProperties::GetControlInput(use_node);
693     Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
694     NodeProperties::ReplaceEffectInput(use_node, conversion);
695     return conversion;
696   }
697   return jsgraph()->graph()->NewNode(op, node);
698 }
699 
700 
GetBitRepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type)701 Node* RepresentationChanger::GetBitRepresentationFor(
702     Node* node, MachineRepresentation output_rep, Type* output_type) {
703   // Eagerly fold representation changes for constants.
704   switch (node->opcode()) {
705     case IrOpcode::kHeapConstant: {
706       HeapObjectMatcher m(node);
707       if (m.Is(factory()->false_value())) {
708         return jsgraph()->Int32Constant(0);
709       } else if (m.Is(factory()->true_value())) {
710         return jsgraph()->Int32Constant(1);
711       }
712     }
713     default:
714       break;
715   }
716   // Select the correct X -> Bit operator.
717   const Operator* op;
718   if (output_type->Is(Type::None())) {
719     // This is an impossible value; it should not be used at runtime.
720     // We just provide a dummy value here.
721     return jsgraph()->Int32Constant(0);
722   } else if (output_rep == MachineRepresentation::kTagged ||
723              output_rep == MachineRepresentation::kTaggedPointer) {
724     if (output_type->Is(Type::BooleanOrNullOrUndefined())) {
725       // true is the only trueish Oddball.
726       op = simplified()->ChangeTaggedToBit();
727     } else {
728       op = simplified()->TruncateTaggedToBit();
729     }
730   } else if (output_rep == MachineRepresentation::kTaggedSigned) {
731     node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
732                                        jsgraph()->IntPtrConstant(0));
733     return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
734                                        jsgraph()->Int32Constant(0));
735   } else if (IsWord(output_rep)) {
736     node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
737                                        jsgraph()->Int32Constant(0));
738     return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
739                                        jsgraph()->Int32Constant(0));
740   } else if (output_rep == MachineRepresentation::kFloat32) {
741     node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
742     return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
743                                        jsgraph()->Float32Constant(0.0), node);
744   } else if (output_rep == MachineRepresentation::kFloat64) {
745     node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
746     return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
747                                        jsgraph()->Float64Constant(0.0), node);
748   } else {
749     return TypeError(node, output_rep, output_type,
750                      MachineRepresentation::kBit);
751   }
752   return jsgraph()->graph()->NewNode(op, node);
753 }
754 
GetWord64RepresentationFor(Node * node,MachineRepresentation output_rep,Type * output_type)755 Node* RepresentationChanger::GetWord64RepresentationFor(
756     Node* node, MachineRepresentation output_rep, Type* output_type) {
757   if (output_type->Is(Type::None())) {
758     // This is an impossible value; it should not be used at runtime.
759     // We just provide a dummy value here.
760     return jsgraph()->Int64Constant(0);
761   } else if (output_rep == MachineRepresentation::kBit) {
762     return node;  // Sloppy comparison -> word64
763   }
764   // Can't really convert Word64 to anything else. Purported to be internal.
765   return TypeError(node, output_rep, output_type,
766                    MachineRepresentation::kWord64);
767 }
768 
Int32OperatorFor(IrOpcode::Value opcode)769 const Operator* RepresentationChanger::Int32OperatorFor(
770     IrOpcode::Value opcode) {
771   switch (opcode) {
772     case IrOpcode::kSpeculativeNumberAdd:  // Fall through.
773     case IrOpcode::kNumberAdd:
774       return machine()->Int32Add();
775     case IrOpcode::kSpeculativeNumberSubtract:  // Fall through.
776     case IrOpcode::kNumberSubtract:
777       return machine()->Int32Sub();
778     case IrOpcode::kSpeculativeNumberMultiply:
779     case IrOpcode::kNumberMultiply:
780       return machine()->Int32Mul();
781     case IrOpcode::kSpeculativeNumberDivide:
782     case IrOpcode::kNumberDivide:
783       return machine()->Int32Div();
784     case IrOpcode::kSpeculativeNumberModulus:
785     case IrOpcode::kNumberModulus:
786       return machine()->Int32Mod();
787     case IrOpcode::kSpeculativeNumberBitwiseOr:  // Fall through.
788     case IrOpcode::kNumberBitwiseOr:
789       return machine()->Word32Or();
790     case IrOpcode::kSpeculativeNumberBitwiseXor:  // Fall through.
791     case IrOpcode::kNumberBitwiseXor:
792       return machine()->Word32Xor();
793     case IrOpcode::kSpeculativeNumberBitwiseAnd:  // Fall through.
794     case IrOpcode::kNumberBitwiseAnd:
795       return machine()->Word32And();
796     case IrOpcode::kNumberEqual:
797     case IrOpcode::kSpeculativeNumberEqual:
798       return machine()->Word32Equal();
799     case IrOpcode::kNumberLessThan:
800     case IrOpcode::kSpeculativeNumberLessThan:
801       return machine()->Int32LessThan();
802     case IrOpcode::kNumberLessThanOrEqual:
803     case IrOpcode::kSpeculativeNumberLessThanOrEqual:
804       return machine()->Int32LessThanOrEqual();
805     default:
806       UNREACHABLE();
807       return nullptr;
808   }
809 }
810 
Int32OverflowOperatorFor(IrOpcode::Value opcode)811 const Operator* RepresentationChanger::Int32OverflowOperatorFor(
812     IrOpcode::Value opcode) {
813   switch (opcode) {
814     case IrOpcode::kSpeculativeNumberAdd:
815       return simplified()->CheckedInt32Add();
816     case IrOpcode::kSpeculativeNumberSubtract:
817       return simplified()->CheckedInt32Sub();
818     case IrOpcode::kSpeculativeNumberDivide:
819       return simplified()->CheckedInt32Div();
820     case IrOpcode::kSpeculativeNumberModulus:
821       return simplified()->CheckedInt32Mod();
822     default:
823       UNREACHABLE();
824       return nullptr;
825   }
826 }
827 
TaggedSignedOperatorFor(IrOpcode::Value opcode)828 const Operator* RepresentationChanger::TaggedSignedOperatorFor(
829     IrOpcode::Value opcode) {
830   switch (opcode) {
831     case IrOpcode::kSpeculativeNumberLessThan:
832       return machine()->Is32() ? machine()->Int32LessThan()
833                                : machine()->Int64LessThan();
834     case IrOpcode::kSpeculativeNumberLessThanOrEqual:
835       return machine()->Is32() ? machine()->Int32LessThanOrEqual()
836                                : machine()->Int64LessThanOrEqual();
837     case IrOpcode::kSpeculativeNumberEqual:
838       return machine()->Is32() ? machine()->Word32Equal()
839                                : machine()->Word64Equal();
840     default:
841       UNREACHABLE();
842       return nullptr;
843   }
844 }
845 
Uint32OperatorFor(IrOpcode::Value opcode)846 const Operator* RepresentationChanger::Uint32OperatorFor(
847     IrOpcode::Value opcode) {
848   switch (opcode) {
849     case IrOpcode::kNumberAdd:
850       return machine()->Int32Add();
851     case IrOpcode::kNumberSubtract:
852       return machine()->Int32Sub();
853     case IrOpcode::kSpeculativeNumberMultiply:
854     case IrOpcode::kNumberMultiply:
855       return machine()->Int32Mul();
856     case IrOpcode::kSpeculativeNumberDivide:
857     case IrOpcode::kNumberDivide:
858       return machine()->Uint32Div();
859     case IrOpcode::kSpeculativeNumberModulus:
860     case IrOpcode::kNumberModulus:
861       return machine()->Uint32Mod();
862     case IrOpcode::kNumberEqual:
863     case IrOpcode::kSpeculativeNumberEqual:
864       return machine()->Word32Equal();
865     case IrOpcode::kNumberLessThan:
866     case IrOpcode::kSpeculativeNumberLessThan:
867       return machine()->Uint32LessThan();
868     case IrOpcode::kNumberLessThanOrEqual:
869     case IrOpcode::kSpeculativeNumberLessThanOrEqual:
870       return machine()->Uint32LessThanOrEqual();
871     case IrOpcode::kNumberClz32:
872       return machine()->Word32Clz();
873     case IrOpcode::kNumberImul:
874       return machine()->Int32Mul();
875     default:
876       UNREACHABLE();
877       return nullptr;
878   }
879 }
880 
Uint32OverflowOperatorFor(IrOpcode::Value opcode)881 const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
882     IrOpcode::Value opcode) {
883   switch (opcode) {
884     case IrOpcode::kSpeculativeNumberDivide:
885       return simplified()->CheckedUint32Div();
886     case IrOpcode::kSpeculativeNumberModulus:
887       return simplified()->CheckedUint32Mod();
888     default:
889       UNREACHABLE();
890       return nullptr;
891   }
892 }
893 
Float64OperatorFor(IrOpcode::Value opcode)894 const Operator* RepresentationChanger::Float64OperatorFor(
895     IrOpcode::Value opcode) {
896   switch (opcode) {
897     case IrOpcode::kSpeculativeNumberAdd:
898     case IrOpcode::kNumberAdd:
899       return machine()->Float64Add();
900     case IrOpcode::kSpeculativeNumberSubtract:
901     case IrOpcode::kNumberSubtract:
902       return machine()->Float64Sub();
903     case IrOpcode::kSpeculativeNumberMultiply:
904     case IrOpcode::kNumberMultiply:
905       return machine()->Float64Mul();
906     case IrOpcode::kSpeculativeNumberDivide:
907     case IrOpcode::kNumberDivide:
908       return machine()->Float64Div();
909     case IrOpcode::kSpeculativeNumberModulus:
910     case IrOpcode::kNumberModulus:
911       return machine()->Float64Mod();
912     case IrOpcode::kNumberEqual:
913     case IrOpcode::kSpeculativeNumberEqual:
914       return machine()->Float64Equal();
915     case IrOpcode::kNumberLessThan:
916     case IrOpcode::kSpeculativeNumberLessThan:
917       return machine()->Float64LessThan();
918     case IrOpcode::kNumberLessThanOrEqual:
919     case IrOpcode::kSpeculativeNumberLessThanOrEqual:
920       return machine()->Float64LessThanOrEqual();
921     case IrOpcode::kNumberAbs:
922       return machine()->Float64Abs();
923     case IrOpcode::kNumberAcos:
924       return machine()->Float64Acos();
925     case IrOpcode::kNumberAcosh:
926       return machine()->Float64Acosh();
927     case IrOpcode::kNumberAsin:
928       return machine()->Float64Asin();
929     case IrOpcode::kNumberAsinh:
930       return machine()->Float64Asinh();
931     case IrOpcode::kNumberAtan:
932       return machine()->Float64Atan();
933     case IrOpcode::kNumberAtanh:
934       return machine()->Float64Atanh();
935     case IrOpcode::kNumberAtan2:
936       return machine()->Float64Atan2();
937     case IrOpcode::kNumberCbrt:
938       return machine()->Float64Cbrt();
939     case IrOpcode::kNumberCeil:
940       return machine()->Float64RoundUp().placeholder();
941     case IrOpcode::kNumberCos:
942       return machine()->Float64Cos();
943     case IrOpcode::kNumberCosh:
944       return machine()->Float64Cosh();
945     case IrOpcode::kNumberExp:
946       return machine()->Float64Exp();
947     case IrOpcode::kNumberExpm1:
948       return machine()->Float64Expm1();
949     case IrOpcode::kNumberFloor:
950       return machine()->Float64RoundDown().placeholder();
951     case IrOpcode::kNumberFround:
952       return machine()->TruncateFloat64ToFloat32();
953     case IrOpcode::kNumberLog:
954       return machine()->Float64Log();
955     case IrOpcode::kNumberLog1p:
956       return machine()->Float64Log1p();
957     case IrOpcode::kNumberLog2:
958       return machine()->Float64Log2();
959     case IrOpcode::kNumberLog10:
960       return machine()->Float64Log10();
961     case IrOpcode::kNumberMax:
962       return machine()->Float64Max();
963     case IrOpcode::kNumberMin:
964       return machine()->Float64Min();
965     case IrOpcode::kNumberPow:
966       return machine()->Float64Pow();
967     case IrOpcode::kNumberSin:
968       return machine()->Float64Sin();
969     case IrOpcode::kNumberSinh:
970       return machine()->Float64Sinh();
971     case IrOpcode::kNumberSqrt:
972       return machine()->Float64Sqrt();
973     case IrOpcode::kNumberTan:
974       return machine()->Float64Tan();
975     case IrOpcode::kNumberTanh:
976       return machine()->Float64Tanh();
977     case IrOpcode::kNumberTrunc:
978       return machine()->Float64RoundTruncate().placeholder();
979     case IrOpcode::kNumberSilenceNaN:
980       return machine()->Float64SilenceNaN();
981     default:
982       UNREACHABLE();
983       return nullptr;
984   }
985 }
986 
987 
TypeError(Node * node,MachineRepresentation output_rep,Type * output_type,MachineRepresentation use)988 Node* RepresentationChanger::TypeError(Node* node,
989                                        MachineRepresentation output_rep,
990                                        Type* output_type,
991                                        MachineRepresentation use) {
992   type_error_ = true;
993   if (!testing_type_errors_) {
994     std::ostringstream out_str;
995     out_str << output_rep << " (";
996     output_type->PrintTo(out_str);
997     out_str << ")";
998 
999     std::ostringstream use_str;
1000     use_str << use;
1001 
1002     V8_Fatal(__FILE__, __LINE__,
1003              "RepresentationChangerError: node #%d:%s of "
1004              "%s cannot be changed to %s",
1005              node->id(), node->op()->mnemonic(), out_str.str().c_str(),
1006              use_str.str().c_str());
1007   }
1008   return node;
1009 }
1010 
InsertChangeBitToTagged(Node * node)1011 Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
1012   return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
1013 }
1014 
InsertChangeFloat32ToFloat64(Node * node)1015 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
1016   return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
1017 }
1018 
InsertChangeFloat64ToUint32(Node * node)1019 Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
1020   return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
1021 }
1022 
InsertChangeFloat64ToInt32(Node * node)1023 Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
1024   return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
1025 }
1026 
InsertChangeInt32ToFloat64(Node * node)1027 Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) {
1028   return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
1029 }
1030 
InsertChangeTaggedSignedToInt32(Node * node)1031 Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
1032   return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
1033                                      node);
1034 }
1035 
InsertChangeTaggedToFloat64(Node * node)1036 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
1037   return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
1038                                      node);
1039 }
1040 
InsertChangeUint32ToFloat64(Node * node)1041 Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) {
1042   return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
1043 }
1044 
1045 }  // namespace compiler
1046 }  // namespace internal
1047 }  // namespace v8
1048