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