representation-change.cc 59.6 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/representation-change.h"

#include <sstream>

#include "src/base/bits.h"
10
#include "src/codegen/code-factory.h"
11
#include "src/compiler/js-heap-broker.h"
12
#include "src/compiler/machine-operator.h"
13
#include "src/compiler/node-matchers.h"
14
#include "src/compiler/type-cache.h"
15
#include "src/heap/factory-inl.h"
16 17 18 19 20 21 22 23 24 25 26 27 28

namespace v8 {
namespace internal {
namespace compiler {

const char* Truncation::description() const {
  switch (kind()) {
    case TruncationKind::kNone:
      return "no-value-use";
    case TruncationKind::kBool:
      return "truncate-to-bool";
    case TruncationKind::kWord32:
      return "truncate-to-word32";
29 30
    case TruncationKind::kWord64:
      return "truncate-to-word64";
31
    case TruncationKind::kOddballAndBigIntToNumber:
32 33
      switch (identify_zeros()) {
        case kIdentifyZeros:
34
          return "truncate-oddball&bigint-to-number (identify zeros)";
35
        case kDistinguishZeros:
36
          return "truncate-oddball&bigint-to-number (distinguish zeros)";
37
      }
38
    case TruncationKind::kAny:
39 40 41 42 43 44
      switch (identify_zeros()) {
        case kIdentifyZeros:
          return "no-truncation (but identify zeros)";
        case kDistinguishZeros:
          return "no-truncation (but distinguish zeros)";
      }
45 46 47 48 49 50
  }
  UNREACHABLE();
}

// Partial order for truncations:
//
51 52 53 54 55 56
//               kAny <-------+
//                 ^          |
//                 |          |
//  kOddballAndBigIntToNumber |
//               ^            |
//               /            |
57 58 59
//        kWord64             |
//             ^              |
//             |              |
60 61 62 63 64 65 66 67
//        kWord32           kBool
//              ^            ^
//              \            /
//               \          /
//                \        /
//                 \      /
//                  \    /
//                  kNone
68
//
69
// TODO(jarin) We might consider making kBool < kOddballAndBigIntToNumber.
70 71 72 73 74 75 76

// static
Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
                                                  TruncationKind rep2) {
  if (LessGeneral(rep1, rep2)) return rep2;
  if (LessGeneral(rep2, rep1)) return rep1;
  // Handle the generalization of float64-representable values.
77 78 79
  if (LessGeneral(rep1, TruncationKind::kOddballAndBigIntToNumber) &&
      LessGeneral(rep2, TruncationKind::kOddballAndBigIntToNumber)) {
    return TruncationKind::kOddballAndBigIntToNumber;
80
  }
81 82 83 84 85
  // Handle the generalization of any-representable values.
  if (LessGeneral(rep1, TruncationKind::kAny) &&
      LessGeneral(rep2, TruncationKind::kAny)) {
    return TruncationKind::kAny;
  }
86
  // All other combinations are illegal.
87
  FATAL("Tried to combine incompatible truncations");
88 89 90
  return TruncationKind::kNone;
}

91 92 93 94 95 96 97 98 99
// static
IdentifyZeros Truncation::GeneralizeIdentifyZeros(IdentifyZeros i1,
                                                  IdentifyZeros i2) {
  if (i1 == i2) {
    return i1;
  } else {
    return kDistinguishZeros;
  }
}
100 101 102 103 104 105 106 107 108 109

// static
bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
  switch (rep1) {
    case TruncationKind::kNone:
      return true;
    case TruncationKind::kBool:
      return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
    case TruncationKind::kWord32:
      return rep2 == TruncationKind::kWord32 ||
110 111 112 113 114
             rep2 == TruncationKind::kWord64 ||
             rep2 == TruncationKind::kOddballAndBigIntToNumber ||
             rep2 == TruncationKind::kAny;
    case TruncationKind::kWord64:
      return rep2 == TruncationKind::kWord64 ||
115 116 117 118 119
             rep2 == TruncationKind::kOddballAndBigIntToNumber ||
             rep2 == TruncationKind::kAny;
    case TruncationKind::kOddballAndBigIntToNumber:
      return rep2 == TruncationKind::kOddballAndBigIntToNumber ||
             rep2 == TruncationKind::kAny;
120 121 122 123 124 125
    case TruncationKind::kAny:
      return rep2 == TruncationKind::kAny;
  }
  UNREACHABLE();
}

126 127 128 129
// static
bool Truncation::LessGeneralIdentifyZeros(IdentifyZeros i1, IdentifyZeros i2) {
  return i1 == i2 || i1 == kIdentifyZeros;
}
130 131 132

namespace {

133 134 135 136
bool IsWord(MachineRepresentation rep) {
  return rep == MachineRepresentation::kWord8 ||
         rep == MachineRepresentation::kWord16 ||
         rep == MachineRepresentation::kWord32;
137 138 139 140
}

}  // namespace

141 142
RepresentationChanger::RepresentationChanger(JSGraph* jsgraph,
                                             JSHeapBroker* broker)
143 144
    : cache_(TypeCache::Get()),
      jsgraph_(jsgraph),
145
      broker_(broker),
146 147 148
      testing_type_errors_(false),
      type_error_(false) {}

149
// Changes representation from {output_rep} to {use_rep}. The {truncation}
150 151 152
// parameter is only used for sanity checking - if the changer cannot figure
// out signedness for the word32->float64 conversion, then we check that the
// uses truncate to word32 (so they do not care about signedness).
153
Node* RepresentationChanger::GetRepresentationFor(
154
    Node* node, MachineRepresentation output_rep, Type output_type,
155
    Node* use_node, UseInfo use_info) {
156
  if (output_rep == MachineRepresentation::kNone && !output_type.IsNone()) {
157 158
    // The output representation should be set if the type is inhabited (i.e.,
    // if the value is possible).
159
    return TypeError(node, output_rep, output_type, use_info.representation());
160
  }
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175

  // Handle the no-op shortcuts when no checking is necessary.
  if (use_info.type_check() == TypeCheckKind::kNone ||
      output_rep != MachineRepresentation::kWord32) {
    if (use_info.representation() == output_rep) {
      // Representations are the same. That's a no-op.
      return node;
    }
    if (IsWord(use_info.representation()) && IsWord(output_rep)) {
      // Both are words less than or equal to 32-bits.
      // Since loads of integers from memory implicitly sign or zero extend the
      // value to the full machine word size and stores implicitly truncate,
      // no representation change is necessary.
      return node;
    }
176
  }
177 178

  switch (use_info.representation()) {
179
    case MachineRepresentation::kTaggedSigned:
180 181 182 183
      DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
             use_info.type_check() == TypeCheckKind::kSignedSmall);
      return GetTaggedSignedRepresentationFor(node, output_rep, output_type,
                                              use_node, use_info);
184
    case MachineRepresentation::kTaggedPointer:
185
      DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
186 187
             use_info.type_check() == TypeCheckKind::kHeapObject ||
             use_info.type_check() == TypeCheckKind::kBigInt);
188 189
      return GetTaggedPointerRepresentationFor(node, output_rep, output_type,
                                               use_node, use_info);
190
    case MachineRepresentation::kTagged:
191
      DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
192 193
      return GetTaggedRepresentationFor(node, output_rep, output_type,
                                        use_info.truncation());
194
    case MachineRepresentation::kFloat32:
195
      DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
196
      return GetFloat32RepresentationFor(node, output_rep, output_type,
197
                                         use_info.truncation());
198
    case MachineRepresentation::kFloat64:
199
      return GetFloat64RepresentationFor(node, output_rep, output_type,
200
                                         use_node, use_info);
201
    case MachineRepresentation::kBit:
202
      DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
203
      return GetBitRepresentationFor(node, output_rep, output_type);
204 205 206
    case MachineRepresentation::kWord8:
    case MachineRepresentation::kWord16:
    case MachineRepresentation::kWord32:
207 208
      return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
                                        use_info);
209
    case MachineRepresentation::kWord64:
210
      DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
211
             use_info.type_check() == TypeCheckKind::kSigned64 ||
212 213
             use_info.type_check() == TypeCheckKind::kBigInt ||
             use_info.type_check() == TypeCheckKind::kArrayIndex);
214 215
      return GetWord64RepresentationFor(node, output_rep, output_type, use_node,
                                        use_info);
216
    case MachineRepresentation::kSimd128:
217
    case MachineRepresentation::kNone:
218
      return node;
219 220 221
    case MachineRepresentation::kCompressed:
    case MachineRepresentation::kCompressedPointer:
      UNREACHABLE();
222
  }
223
  UNREACHABLE();
224 225
}

226
Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
227
    Node* node, MachineRepresentation output_rep, Type output_type,
228
    Node* use_node, UseInfo use_info) {
229 230
  // Eagerly fold representation changes for constants.
  switch (node->opcode()) {
231
    case IrOpcode::kNumberConstant:
232
      if (output_type.Is(Type::SignedSmall())) {
233
        return node;
234
      }
235
      break;
236 237 238 239 240
    default:
      break;
  }
  // Select the correct X -> Tagged operator.
  const Operator* op;
241
  if (output_type.Is(Type::None())) {
242
    // This is an impossible value; it should not be used at runtime.
243 244 245
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedSigned),
        node);
246
  } else if (IsWord(output_rep)) {
247
    if (output_type.Is(Type::Signed31())) {
248
      op = simplified()->ChangeInt31ToTaggedSigned();
249
    } else if (output_type.Is(Type::Signed32())) {
250 251 252
      if (SmiValuesAre32Bits()) {
        op = simplified()->ChangeInt32ToTagged();
      } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
253
        op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
254 255 256 257
      } else {
        return TypeError(node, output_rep, output_type,
                         MachineRepresentation::kTaggedSigned);
      }
258
    } else if (output_type.Is(Type::Unsigned32()) &&
259
               use_info.type_check() == TypeCheckKind::kSignedSmall) {
260
      op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
261 262 263 264
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedSigned);
    }
265 266 267 268 269 270 271 272 273 274
  } else if (output_rep == MachineRepresentation::kWord64) {
    if (output_type.Is(Type::Signed31())) {
      // int64 -> int32 -> tagged signed
      node = InsertTruncateInt64ToInt32(node);
      op = simplified()->ChangeInt31ToTaggedSigned();
    } else if (output_type.Is(Type::Signed32()) && SmiValuesAre32Bits()) {
      // int64 -> int32 -> tagged signed
      node = InsertTruncateInt64ToInt32(node);
      op = simplified()->ChangeInt32ToTagged();
    } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
275
      if (output_type.Is(cache_->kPositiveSafeInteger)) {
276
        op = simplified()->CheckedUint64ToTaggedSigned(use_info.feedback());
277
      } else if (output_type.Is(cache_->kSafeInteger)) {
278 279 280 281 282 283 284 285 286
        op = simplified()->CheckedInt64ToTaggedSigned(use_info.feedback());
      } else {
        return TypeError(node, output_rep, output_type,
                         MachineRepresentation::kTaggedSigned);
      }
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedSigned);
    }
287
  } else if (output_rep == MachineRepresentation::kFloat64) {
288
    if (output_type.Is(Type::Signed31())) {
289 290 291
      // float64 -> int32 -> tagged signed
      node = InsertChangeFloat64ToInt32(node);
      op = simplified()->ChangeInt31ToTaggedSigned();
292
    } else if (output_type.Is(Type::Signed32())) {
293 294 295 296 297
      // float64 -> int32 -> tagged signed
      node = InsertChangeFloat64ToInt32(node);
      if (SmiValuesAre32Bits()) {
        op = simplified()->ChangeInt32ToTagged();
      } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
298
        op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
299 300 301 302
      } else {
        return TypeError(node, output_rep, output_type,
                         MachineRepresentation::kTaggedSigned);
      }
303
    } else if (output_type.Is(Type::Unsigned32()) &&
304 305 306
               use_info.type_check() == TypeCheckKind::kSignedSmall) {
      // float64 -> uint32 -> tagged signed
      node = InsertChangeFloat64ToUint32(node);
307
      op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
308
    } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
309 310
      node = InsertCheckedFloat64ToInt32(
          node,
311
          output_type.Maybe(Type::MinusZero())
312
              ? CheckForMinusZeroMode::kCheckForMinusZero
313
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
314
          use_info.feedback(), use_node);
315 316 317
      if (SmiValuesAre32Bits()) {
        op = simplified()->ChangeInt32ToTagged();
      } else {
318
        op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
319
      }
320 321 322 323
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedSigned);
    }
324 325
  } else if (output_rep == MachineRepresentation::kFloat32) {
    if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
326 327 328
      node = InsertChangeFloat32ToFloat64(node);
      node = InsertCheckedFloat64ToInt32(
          node,
329
          output_type.Maybe(Type::MinusZero())
330
              ? CheckForMinusZeroMode::kCheckForMinusZero
331
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
332
          use_info.feedback(), use_node);
333 334 335
      if (SmiValuesAre32Bits()) {
        op = simplified()->ChangeInt32ToTagged();
      } else {
336
        op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
337 338 339 340 341
      }
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedSigned);
    }
342 343
  } else if (CanBeTaggedPointer(output_rep)) {
    if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
344
      op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
345
    } else if (output_type.Is(Type::SignedSmall())) {
346 347 348 349 350
      op = simplified()->ChangeTaggedToTaggedSigned();
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedSigned);
    }
351 352 353 354 355
  } else if (output_rep == MachineRepresentation::kBit) {
    if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
      // TODO(turbofan): Consider adding a Bailout operator that just deopts.
      // Also use that for MachineRepresentation::kPointer case above.
      node = InsertChangeBitToTagged(node);
356
      op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
357 358 359 360
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedSigned);
    }
361 362 363 364
  } else {
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kTaggedSigned);
  }
365
  return InsertConversion(node, op, use_node);
366 367 368
}

Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
369
    Node* node, MachineRepresentation output_rep, Type output_type,
370
    Node* use_node, UseInfo use_info) {
371 372 373
  // Eagerly fold representation changes for constants.
  switch (node->opcode()) {
    case IrOpcode::kHeapConstant:
374
    case IrOpcode::kDelayedStringConstant:
375 376 377 378
      return node;  // No change necessary.
    case IrOpcode::kInt32Constant:
    case IrOpcode::kFloat64Constant:
    case IrOpcode::kFloat32Constant:
379
      UNREACHABLE();
380 381 382
    default:
      break;
  }
383 384
  // Select the correct X -> TaggedPointer operator.
  Operator const* op;
385
  if (output_type.Is(Type::None())) {
386
    // This is an impossible value; it should not be used at runtime.
387 388 389
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
        node);
390
  } else if (output_rep == MachineRepresentation::kBit) {
391
    if (output_type.Is(Type::Boolean())) {
392 393 394 395 396
      op = simplified()->ChangeBitToTagged();
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTagged);
    }
397
  } else if (IsWord(output_rep)) {
398
    if (output_type.Is(Type::Unsigned32())) {
399 400
      // uint32 -> float64 -> tagged
      node = InsertChangeUint32ToFloat64(node);
401
    } else if (output_type.Is(Type::Signed32())) {
402 403 404 405 406 407 408
      // int32 -> float64 -> tagged
      node = InsertChangeInt32ToFloat64(node);
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedPointer);
    }
    op = simplified()->ChangeFloat64ToTaggedPointer();
409
  } else if (output_rep == MachineRepresentation::kWord64) {
410
    if (output_type.Is(cache_->kSafeInteger)) {
411 412 413 414
      // int64 -> float64 -> tagged pointer
      op = machine()->ChangeInt64ToFloat64();
      node = jsgraph()->graph()->NewNode(op, node);
      op = simplified()->ChangeFloat64ToTaggedPointer();
415 416
    } else if (output_type.Is(Type::BigInt())) {
      op = simplified()->ChangeUint64ToBigInt();
417 418 419 420
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedPointer);
    }
421
  } else if (output_rep == MachineRepresentation::kFloat32) {
422
    if (output_type.Is(Type::Number())) {
423 424 425 426 427 428 429
      // float32 -> float64 -> tagged
      node = InsertChangeFloat32ToFloat64(node);
      op = simplified()->ChangeFloat64ToTaggedPointer();
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedPointer);
    }
430
  } else if (output_rep == MachineRepresentation::kFloat64) {
431
    if (output_type.Is(Type::Number())) {
432 433 434 435 436 437
      // float64 -> tagged
      op = simplified()->ChangeFloat64ToTaggedPointer();
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTaggedPointer);
    }
438 439
  } else if (CanBeTaggedSigned(output_rep) &&
             use_info.type_check() == TypeCheckKind::kHeapObject) {
440
    if (!output_type.Maybe(Type::SignedSmall())) {
441 442 443 444
      return node;
    }
    // TODO(turbofan): Consider adding a Bailout operator that just deopts
    // for TaggedSigned output representation.
445
    op = simplified()->CheckedTaggedToTaggedPointer(use_info.feedback());
446 447 448 449 450
  } else if (IsAnyTagged(output_rep) &&
             (use_info.type_check() == TypeCheckKind::kBigInt ||
              output_type.Is(Type::BigInt()))) {
    if (output_type.Is(Type::BigInt())) {
      return node;
451
    }
452
    op = simplified()->CheckBigInt(use_info.feedback());
453 454 455
  } else {
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kTaggedPointer);
456
  }
457
  return InsertConversion(node, op, use_node);
458 459
}

460
Node* RepresentationChanger::GetTaggedRepresentationFor(
461
    Node* node, MachineRepresentation output_rep, Type output_type,
462
    Truncation truncation) {
463 464 465 466
  // Eagerly fold representation changes for constants.
  switch (node->opcode()) {
    case IrOpcode::kNumberConstant:
    case IrOpcode::kHeapConstant:
467
    case IrOpcode::kDelayedStringConstant:
468 469 470 471
      return node;  // No change necessary.
    case IrOpcode::kInt32Constant:
    case IrOpcode::kFloat64Constant:
    case IrOpcode::kFloat32Constant:
472
      UNREACHABLE();
473 474 475
    default:
      break;
  }
476 477 478 479 480
  if (output_rep == MachineRepresentation::kTaggedSigned ||
      output_rep == MachineRepresentation::kTaggedPointer) {
    // this is a no-op.
    return node;
  }
481 482
  // Select the correct X -> Tagged operator.
  const Operator* op;
483
  if (output_type.Is(Type::None())) {
484
    // This is an impossible value; it should not be used at runtime.
485 486
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
487
  } else if (output_rep == MachineRepresentation::kBit) {
488
    if (output_type.Is(Type::Boolean())) {
489 490 491 492 493
      op = simplified()->ChangeBitToTagged();
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTagged);
    }
494
  } else if (IsWord(output_rep)) {
495
    if (output_type.Is(Type::Signed31())) {
496
      op = simplified()->ChangeInt31ToTaggedSigned();
497 498 499
    } else if (output_type.Is(Type::Signed32()) ||
               (output_type.Is(Type::Signed32OrMinusZero()) &&
                truncation.IdentifiesZeroAndMinusZero())) {
500
      op = simplified()->ChangeInt32ToTagged();
501
    } else if (output_type.Is(Type::Unsigned32()) ||
502 503
               (output_type.Is(Type::Unsigned32OrMinusZero()) &&
                truncation.IdentifiesZeroAndMinusZero()) ||
504 505 506
               truncation.IsUsedAsWord32()) {
      // Either the output is uint32 or the uses only care about the
      // low 32 bits (so we can pick uint32 safely).
507
      op = simplified()->ChangeUint32ToTagged();
508
    } else {
509 510
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTagged);
511
    }
512 513 514 515 516 517 518 519 520 521 522 523 524
  } else if (output_rep == MachineRepresentation::kWord64) {
    if (output_type.Is(Type::Signed31())) {
      // int64 -> int32 -> tagged signed
      node = InsertTruncateInt64ToInt32(node);
      op = simplified()->ChangeInt31ToTaggedSigned();
    } else if (output_type.Is(Type::Signed32())) {
      // int64 -> int32 -> tagged
      node = InsertTruncateInt64ToInt32(node);
      op = simplified()->ChangeInt32ToTagged();
    } else if (output_type.Is(Type::Unsigned32())) {
      // int64 -> uint32 -> tagged
      node = InsertTruncateInt64ToInt32(node);
      op = simplified()->ChangeUint32ToTagged();
525
    } else if (output_type.Is(cache_->kPositiveSafeInteger)) {
526 527
      // uint64 -> tagged
      op = simplified()->ChangeUint64ToTagged();
528
    } else if (output_type.Is(cache_->kSafeInteger)) {
529 530
      // int64 -> tagged
      op = simplified()->ChangeInt64ToTagged();
531 532 533
    } else if (output_type.Is(Type::BigInt())) {
      // uint64 -> BigInt
      op = simplified()->ChangeUint64ToBigInt();
534 535 536 537
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTagged);
    }
538
  } else if (output_rep ==
539
             MachineRepresentation::kFloat32) {  // float32 -> float64 -> tagged
540
    node = InsertChangeFloat32ToFloat64(node);
541
    op = simplified()->ChangeFloat64ToTagged(
542
        output_type.Maybe(Type::MinusZero())
543 544
            ? CheckForMinusZeroMode::kCheckForMinusZero
            : CheckForMinusZeroMode::kDontCheckForMinusZero);
545
  } else if (output_rep == MachineRepresentation::kFloat64) {
546
    if (output_type.Is(Type::Signed31())) {  // float64 -> int32 -> tagged
547
      node = InsertChangeFloat64ToInt32(node);
548
      op = simplified()->ChangeInt31ToTaggedSigned();
549
    } else if (output_type.Is(
550 551 552
                   Type::Signed32())) {  // float64 -> int32 -> tagged
      node = InsertChangeFloat64ToInt32(node);
      op = simplified()->ChangeInt32ToTagged();
553
    } else if (output_type.Is(
554 555 556
                   Type::Unsigned32())) {  // float64 -> uint32 -> tagged
      node = InsertChangeFloat64ToUint32(node);
      op = simplified()->ChangeUint32ToTagged();
557 558
    } else if (output_type.Is(Type::Number()) ||
               (output_type.Is(Type::NumberOrOddball()) &&
559
                truncation.TruncatesOddballAndBigIntToNumber())) {
560
      op = simplified()->ChangeFloat64ToTagged(
561
          output_type.Maybe(Type::MinusZero())
562 563
              ? CheckForMinusZeroMode::kCheckForMinusZero
              : CheckForMinusZeroMode::kDontCheckForMinusZero);
564 565 566
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kTagged);
567
    }
568
  } else {
569 570
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kTagged);
571 572 573 574 575
  }
  return jsgraph()->graph()->NewNode(op, node);
}

Node* RepresentationChanger::GetFloat32RepresentationFor(
576
    Node* node, MachineRepresentation output_rep, Type output_type,
577
    Truncation truncation) {
578 579 580 581
  // Eagerly fold representation changes for constants.
  switch (node->opcode()) {
    case IrOpcode::kNumberConstant:
      return jsgraph()->Float32Constant(
582
          DoubleToFloat32(OpParameter<double>(node->op())));
583
    case IrOpcode::kInt32Constant:
584
    case IrOpcode::kFloat64Constant:
585
    case IrOpcode::kFloat32Constant:
586
      UNREACHABLE();
587 588 589 590
    default:
      break;
  }
  // Select the correct X -> Float32 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 595
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
596
  } else if (IsWord(output_rep)) {
597
    if (output_type.Is(Type::Signed32())) {
598
      // int32 -> float64 -> float32
599
      op = machine()->ChangeInt32ToFloat64();
600 601
      node = jsgraph()->graph()->NewNode(op, node);
      op = machine()->TruncateFloat64ToFloat32();
602
    } else if (output_type.Is(Type::Unsigned32()) ||
603
               truncation.IsUsedAsWord32()) {
604 605 606 607
      // Either the output is uint32 or the uses only care about the
      // low 32 bits (so we can pick uint32 safely).

      // uint32 -> float64 -> float32
608
      op = machine()->ChangeUint32ToFloat64();
609 610
      node = jsgraph()->graph()->NewNode(op, node);
      op = machine()->TruncateFloat64ToFloat32();
611
    }
612
  } else if (IsAnyTagged(output_rep)) {
613
    if (output_type.Is(Type::NumberOrOddball())) {
614
      // tagged -> float64 -> float32
615
      if (output_type.Is(Type::Number())) {
616 617 618 619
        op = simplified()->ChangeTaggedToFloat64();
      } else {
        op = simplified()->TruncateTaggedToFloat64();
      }
620 621 622
      node = jsgraph()->graph()->NewNode(op, node);
      op = machine()->TruncateFloat64ToFloat32();
    }
623
  } else if (output_rep == MachineRepresentation::kFloat64) {
624
    op = machine()->TruncateFloat64ToFloat32();
625
  } else if (output_rep == MachineRepresentation::kWord64) {
626
    if (output_type.Is(cache_->kSafeInteger)) {
627 628 629 630 631
      // int64 -> float64 -> float32
      op = machine()->ChangeInt64ToFloat64();
      node = jsgraph()->graph()->NewNode(op, node);
      op = machine()->TruncateFloat64ToFloat32();
    }
632 633
  }
  if (op == nullptr) {
634 635
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kFloat32);
636 637 638 639 640
  }
  return jsgraph()->graph()->NewNode(op, node);
}

Node* RepresentationChanger::GetFloat64RepresentationFor(
641
    Node* node, MachineRepresentation output_rep, Type output_type,
642
    Node* use_node, UseInfo use_info) {
643 644
  NumberMatcher m(node);
  if (m.HasValue()) {
645 646
    // BigInts are not used as number constants.
    DCHECK(use_info.type_check() != TypeCheckKind::kBigInt);
647 648 649 650 651
    switch (use_info.type_check()) {
      case TypeCheckKind::kNone:
      case TypeCheckKind::kNumber:
      case TypeCheckKind::kNumberOrOddball:
        return jsgraph()->Float64Constant(m.Value());
652
      case TypeCheckKind::kBigInt:
653 654 655 656
      case TypeCheckKind::kHeapObject:
      case TypeCheckKind::kSigned32:
      case TypeCheckKind::kSigned64:
      case TypeCheckKind::kSignedSmall:
657
      case TypeCheckKind::kArrayIndex:
658 659
        break;
    }
660 661
  }
  // Select the correct X -> Float64 operator.
662
  const Operator* op = nullptr;
663
  if (output_type.Is(Type::None())) {
664
    // This is an impossible value; it should not be used at runtime.
665 666
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
667
  } else if (IsWord(output_rep)) {
668 669 670
    if (output_type.Is(Type::Signed32()) ||
        (output_type.Is(Type::Signed32OrMinusZero()) &&
         use_info.truncation().IdentifiesZeroAndMinusZero())) {
671
      op = machine()->ChangeInt32ToFloat64();
672
    } else if (output_type.Is(Type::Unsigned32()) ||
673 674
               (output_type.Is(Type::Unsigned32OrMinusZero()) &&
                use_info.truncation().IdentifiesZeroAndMinusZero()) ||
675
               use_info.truncation().IsUsedAsWord32()) {
676 677
      // Either the output is uint32 or the uses only care about the
      // low 32 bits (so we can pick uint32 safely).
678
      op = machine()->ChangeUint32ToFloat64();
679
    }
680
  } else if (output_rep == MachineRepresentation::kBit) {
681
    CHECK(output_type.Is(Type::Boolean()));
682
    if (use_info.truncation().TruncatesOddballAndBigIntToNumber() ||
683
        use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
684 685 686 687 688 689 690 691 692
      op = machine()->ChangeUint32ToFloat64();
    } else {
      CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
      Node* unreachable =
          InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotAHeapNumber);
      return jsgraph()->graph()->NewNode(
          jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
          unreachable);
    }
693
  } else if (IsAnyTagged(output_rep)) {
694
    if (output_type.Is(Type::Undefined())) {
695 696
      return jsgraph()->Float64Constant(
          std::numeric_limits<double>::quiet_NaN());
697 698

    } else if (output_rep == MachineRepresentation::kTaggedSigned) {
699 700
      node = InsertChangeTaggedSignedToInt32(node);
      op = machine()->ChangeInt32ToFloat64();
701
    } else if (output_type.Is(Type::Number())) {
702
      op = simplified()->ChangeTaggedToFloat64();
703
    } else if ((output_type.Is(Type::NumberOrOddball()) &&
704
                use_info.truncation().TruncatesOddballAndBigIntToNumber()) ||
705 706 707 708 709 710 711 712 713
               output_type.Is(Type::NumberOrHole())) {
      // JavaScript 'null' is an Oddball that results in +0 when truncated to
      // Number. In a context like -0 == null, which must evaluate to false,
      // this truncation must not happen. For this reason we restrict this case
      // to when either the user explicitly requested a float (and thus wants
      // +0 if null is the input) or we know from the types that the input can
      // only be Number | Hole. The latter is necessary to handle the operator
      // CheckFloat64Hole. We did not put in the type (Number | Oddball \ Null)
      // to discover more bugs related to this conversion via crashes.
714
      op = simplified()->TruncateTaggedToFloat64();
715 716
    } else if (use_info.type_check() == TypeCheckKind::kNumber ||
               (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
717
                !output_type.Maybe(Type::BooleanOrNullOrNumber()))) {
718 719
      op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber,
                                                use_info.feedback());
720
    } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
721
      op = simplified()->CheckedTaggedToFloat64(
722
          CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
723
    }
724
  } else if (output_rep == MachineRepresentation::kFloat32) {
725
    op = machine()->ChangeFloat32ToFloat64();
726
  } else if (output_rep == MachineRepresentation::kWord64) {
727
    if (output_type.Is(cache_->kSafeInteger)) {
728 729
      op = machine()->ChangeInt64ToFloat64();
    }
730 731
  }
  if (op == nullptr) {
732 733
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kFloat64);
734
  }
735
  return InsertConversion(node, op, use_node);
736 737 738 739 740 741
}

Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
  return jsgraph()->Int32Constant(DoubleToInt32(value));
}

742 743
Node* RepresentationChanger::InsertUnconditionalDeopt(Node* node,
                                                      DeoptimizeReason reason) {
744 745
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
746
  effect =
747 748
      jsgraph()->graph()->NewNode(simplified()->CheckIf(reason),
                                  jsgraph()->Int32Constant(0), effect, control);
749 750 751 752
  Node* unreachable = effect = jsgraph()->graph()->NewNode(
      jsgraph()->common()->Unreachable(), effect, control);
  NodeProperties::ReplaceEffectInput(node, effect);
  return unreachable;
753 754
}

755
Node* RepresentationChanger::GetWord32RepresentationFor(
756
    Node* node, MachineRepresentation output_rep, Type output_type,
757
    Node* use_node, UseInfo use_info) {
758
  // Eagerly fold representation changes for constants.
759 760
  switch (node->opcode()) {
    case IrOpcode::kInt32Constant:
761
    case IrOpcode::kInt64Constant:
762 763 764 765
    case IrOpcode::kFloat32Constant:
    case IrOpcode::kFloat64Constant:
      UNREACHABLE();
    case IrOpcode::kNumberConstant: {
766
      double const fv = OpParameter<double>(node->op());
767
      if (use_info.type_check() == TypeCheckKind::kNone ||
768
          ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
769 770
            use_info.type_check() == TypeCheckKind::kSigned32 ||
            use_info.type_check() == TypeCheckKind::kNumber ||
771 772
            use_info.type_check() == TypeCheckKind::kNumberOrOddball ||
            use_info.type_check() == TypeCheckKind::kArrayIndex) &&
773 774 775 776 777 778 779
           IsInt32Double(fv))) {
        return MakeTruncatedInt32Constant(fv);
      }
      break;
    }
    default:
      break;
780
  }
781

782
  // Select the correct X -> Word32 operator.
783
  const Operator* op = nullptr;
784
  if (output_type.Is(Type::None())) {
785
    // This is an impossible value; it should not be used at runtime.
786 787
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
788
  } else if (output_rep == MachineRepresentation::kBit) {
789 790 791 792 793 794 795
    CHECK(output_type.Is(Type::Boolean()));
    if (use_info.truncation().IsUsedAsWord32()) {
      return node;
    } else {
      CHECK(Truncation::Any(kIdentifyZeros)
                .IsLessGeneralThan(use_info.truncation()));
      CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
796
      CHECK_NE(use_info.type_check(), TypeCheckKind::kNumberOrOddball);
797 798
      Node* unreachable =
          InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
799
      return jsgraph()->graph()->NewNode(
800 801
          jsgraph()->common()->DeadValue(MachineRepresentation::kWord32),
          unreachable);
802
    }
803
  } else if (output_rep == MachineRepresentation::kFloat64) {
804
    if (output_type.Is(Type::Signed32())) {
805
      op = machine()->ChangeFloat64ToInt32();
806
    } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
807 808
               use_info.type_check() == TypeCheckKind::kSigned32 ||
               use_info.type_check() == TypeCheckKind::kArrayIndex) {
809
      op = simplified()->CheckedFloat64ToInt32(
810
          output_type.Maybe(Type::MinusZero())
811
              ? use_info.minus_zero_check()
812 813
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
          use_info.feedback());
814
    } else if (output_type.Is(Type::Unsigned32())) {
815 816 817
      op = machine()->ChangeFloat64ToUint32();
    } else if (use_info.truncation().IsUsedAsWord32()) {
      op = machine()->TruncateFloat64ToWord32();
818 819 820
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord32);
821
    }
822
  } else if (output_rep == MachineRepresentation::kFloat32) {
823
    node = InsertChangeFloat32ToFloat64(node);  // float32 -> float64 -> int32
824
    if (output_type.Is(Type::Signed32())) {
825
      op = machine()->ChangeFloat64ToInt32();
826
    } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
827 828
               use_info.type_check() == TypeCheckKind::kSigned32 ||
               use_info.type_check() == TypeCheckKind::kArrayIndex) {
829
      op = simplified()->CheckedFloat64ToInt32(
830
          output_type.Maybe(Type::MinusZero())
831
              ? use_info.minus_zero_check()
832 833
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
          use_info.feedback());
834
    } else if (output_type.Is(Type::Unsigned32())) {
835 836 837
      op = machine()->ChangeFloat64ToUint32();
    } else if (use_info.truncation().IsUsedAsWord32()) {
      op = machine()->TruncateFloat64ToWord32();
838 839 840
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord32);
841
    }
842 843
  } else if (IsAnyTagged(output_rep)) {
    if (output_rep == MachineRepresentation::kTaggedSigned &&
844
        output_type.Is(Type::SignedSmall())) {
845
      op = simplified()->ChangeTaggedSignedToInt32();
846
    } else if (output_type.Is(Type::Signed32())) {
847
      op = simplified()->ChangeTaggedToInt32();
848
    } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
849
      op = simplified()->CheckedTaggedSignedToInt32(use_info.feedback());
850
    } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
851
      op = simplified()->CheckedTaggedToInt32(
852
          output_type.Maybe(Type::MinusZero())
853
              ? use_info.minus_zero_check()
854 855
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
          use_info.feedback());
856 857
    } else if (use_info.type_check() == TypeCheckKind::kArrayIndex) {
      op = simplified()->CheckedTaggedToArrayIndex(use_info.feedback());
858
    } else if (output_type.Is(Type::Unsigned32())) {
859 860
      op = simplified()->ChangeTaggedToUint32();
    } else if (use_info.truncation().IsUsedAsWord32()) {
861
      if (output_type.Is(Type::NumberOrOddball())) {
862
        op = simplified()->TruncateTaggedToWord32();
863 864
      } else if (use_info.type_check() == TypeCheckKind::kNumber) {
        op = simplified()->CheckedTruncateTaggedToWord32(
865
            CheckTaggedInputMode::kNumber, use_info.feedback());
866 867
      } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
        op = simplified()->CheckedTruncateTaggedToWord32(
868
            CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
869 870 871
      } else {
        return TypeError(node, output_rep, output_type,
                         MachineRepresentation::kWord32);
872
      }
873 874 875
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord32);
876
    }
877 878 879
  } else if (output_rep == MachineRepresentation::kWord32) {
    // Only the checked case should get here, the non-checked case is
    // handled in GetRepresentationFor.
880
    if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
881 882
        use_info.type_check() == TypeCheckKind::kSigned32 ||
        use_info.type_check() == TypeCheckKind::kArrayIndex) {
883 884 885
      bool indentify_zeros = use_info.truncation().IdentifiesZeroAndMinusZero();
      if (output_type.Is(Type::Signed32()) ||
          (indentify_zeros && output_type.Is(Type::Signed32OrMinusZero()))) {
886
        return node;
887 888 889
      } else if (output_type.Is(Type::Unsigned32()) ||
                 (indentify_zeros &&
                  output_type.Is(Type::Unsigned32OrMinusZero()))) {
890
        op = simplified()->CheckedUint32ToInt32(use_info.feedback());
891 892 893
      } else {
        return TypeError(node, output_rep, output_type,
                         MachineRepresentation::kWord32);
894
      }
895 896
    } else if (use_info.type_check() == TypeCheckKind::kNumber ||
               use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
897 898 899 900
      return node;
    }
  } else if (output_rep == MachineRepresentation::kWord8 ||
             output_rep == MachineRepresentation::kWord16) {
901
    DCHECK_EQ(MachineRepresentation::kWord32, use_info.representation());
902 903
    DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall ||
           use_info.type_check() == TypeCheckKind::kSigned32);
904
    return node;
905 906 907 908
  } else if (output_rep == MachineRepresentation::kWord64) {
    if (output_type.Is(Type::Signed32()) ||
        output_type.Is(Type::Unsigned32())) {
      op = machine()->TruncateInt64ToInt32();
909
    } else if (output_type.Is(cache_->kSafeInteger) &&
910 911 912
               use_info.truncation().IsUsedAsWord32()) {
      op = machine()->TruncateInt64ToInt32();
    } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
913 914
               use_info.type_check() == TypeCheckKind::kSigned32 ||
               use_info.type_check() == TypeCheckKind::kArrayIndex) {
915
      if (output_type.Is(cache_->kPositiveSafeInteger)) {
916
        op = simplified()->CheckedUint64ToInt32(use_info.feedback());
917
      } else if (output_type.Is(cache_->kSafeInteger)) {
918 919 920 921 922 923 924 925 926
        op = simplified()->CheckedInt64ToInt32(use_info.feedback());
      } else {
        return TypeError(node, output_rep, output_type,
                         MachineRepresentation::kWord32);
      }
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord32);
    }
927
  }
928

929
  if (op == nullptr) {
930 931
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kWord32);
932
  }
933 934 935 936 937 938 939
  return InsertConversion(node, op, use_node);
}

Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
                                              Node* use_node) {
  if (op->ControlInputCount() > 0) {
    // If the operator can deoptimize (which means it has control
940
    // input), we need to connect it to the effect and control chains.
941 942
    Node* effect = NodeProperties::GetEffectInput(use_node);
    Node* control = NodeProperties::GetControlInput(use_node);
943
    Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
944
    NodeProperties::ReplaceEffectInput(use_node, conversion);
945 946
    return conversion;
  }
947 948 949
  return jsgraph()->graph()->NewNode(op, node);
}

950
Node* RepresentationChanger::GetBitRepresentationFor(
951
    Node* node, MachineRepresentation output_rep, Type output_type) {
952 953 954
  // Eagerly fold representation changes for constants.
  switch (node->opcode()) {
    case IrOpcode::kHeapConstant: {
955 956 957 958 959 960
      HeapObjectMatcher m(node);
      if (m.Is(factory()->false_value())) {
        return jsgraph()->Int32Constant(0);
      } else if (m.Is(factory()->true_value())) {
        return jsgraph()->Int32Constant(1);
      }
961
      break;
962 963 964 965 966 967
    }
    default:
      break;
  }
  // Select the correct X -> Bit operator.
  const Operator* op;
968
  if (output_type.Is(Type::None())) {
969
    // This is an impossible value; it should not be used at runtime.
970 971
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
972 973
  } else if (output_rep == MachineRepresentation::kTagged ||
             output_rep == MachineRepresentation::kTaggedPointer) {
974
    if (output_type.Is(Type::BooleanOrNullOrUndefined())) {
975 976 977
      // true is the only trueish Oddball.
      op = simplified()->ChangeTaggedToBit();
    } else {
978
      if (output_rep == MachineRepresentation::kTagged &&
979
          output_type.Maybe(Type::SignedSmall())) {
980 981 982 983 984 985
        op = simplified()->TruncateTaggedToBit();
      } else {
        // The {output_type} either doesn't include the Smi range,
        // or the {output_rep} is known to be TaggedPointer.
        op = simplified()->TruncateTaggedPointerToBit();
      }
986 987
    }
  } else if (output_rep == MachineRepresentation::kTaggedSigned) {
988
    if (COMPRESS_POINTERS_BOOL) {
989 990 991 992 993 994
      node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
                                         jsgraph()->Int32Constant(0));
    } else {
      node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
                                         jsgraph()->IntPtrConstant(0));
    }
995 996 997 998 999 1000 1001
    return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
                                       jsgraph()->Int32Constant(0));
  } else if (IsWord(output_rep)) {
    node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
                                       jsgraph()->Int32Constant(0));
    return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
                                       jsgraph()->Int32Constant(0));
1002 1003 1004 1005 1006
  } else if (output_rep == MachineRepresentation::kWord64) {
    node = jsgraph()->graph()->NewNode(machine()->Word64Equal(), node,
                                       jsgraph()->Int64Constant(0));
    return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
                                       jsgraph()->Int32Constant(0));
1007 1008 1009 1010 1011 1012 1013 1014
  } else if (output_rep == MachineRepresentation::kFloat32) {
    node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
    return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
                                       jsgraph()->Float32Constant(0.0), node);
  } else if (output_rep == MachineRepresentation::kFloat64) {
    node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
    return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
                                       jsgraph()->Float64Constant(0.0), node);
1015
  } else {
1016 1017
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kBit);
1018 1019 1020 1021 1022
  }
  return jsgraph()->graph()->NewNode(op, node);
}

Node* RepresentationChanger::GetWord64RepresentationFor(
1023 1024
    Node* node, MachineRepresentation output_rep, Type output_type,
    Node* use_node, UseInfo use_info) {
1025 1026 1027 1028 1029 1030 1031 1032 1033
  // Eagerly fold representation changes for constants.
  switch (node->opcode()) {
    case IrOpcode::kInt32Constant:
    case IrOpcode::kInt64Constant:
    case IrOpcode::kFloat32Constant:
    case IrOpcode::kFloat64Constant:
      UNREACHABLE();
    case IrOpcode::kNumberConstant: {
      double const fv = OpParameter<double>(node->op());
1034 1035 1036 1037 1038 1039
      using limits = std::numeric_limits<int64_t>;
      if (fv <= limits::max() && fv >= limits::min()) {
        int64_t const iv = static_cast<int64_t>(fv);
        if (static_cast<double>(iv) == fv) {
          return jsgraph()->Int64Constant(iv);
        }
1040 1041 1042
      }
      break;
    }
1043 1044 1045 1046 1047 1048 1049 1050 1051
    case IrOpcode::kHeapConstant: {
      HeapObjectMatcher m(node);
      if (m.HasValue() && m.Ref(broker_).IsBigInt()) {
        auto bigint = m.Ref(broker_).AsBigInt();
        return jsgraph()->Int64Constant(
            static_cast<int64_t>(bigint.AsUint64()));
      }
      break;
    }
1052 1053 1054 1055 1056 1057
    default:
      break;
  }

  // Select the correct X -> Word64 operator.
  const Operator* op;
1058
  if (output_type.Is(Type::None())) {
1059
    // This is an impossible value; it should not be used at runtime.
1060
    return jsgraph()->graph()->NewNode(
1061
        jsgraph()->common()->DeadValue(MachineRepresentation::kWord64), node);
1062
  } else if (output_rep == MachineRepresentation::kBit) {
1063 1064
    CHECK(output_type.Is(Type::Boolean()));
    CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
1065
    CHECK_NE(use_info.type_check(), TypeCheckKind::kNumberOrOddball);
1066 1067 1068 1069 1070
    Node* unreachable =
        InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
    return jsgraph()->graph()->NewNode(
        jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
        unreachable);
1071
  } else if (IsWord(output_rep)) {
1072 1073 1074 1075
    if (output_type.Is(Type::Unsigned32OrMinusZero())) {
      // uint32 -> uint64
      CHECK_IMPLIES(output_type.Maybe(Type::MinusZero()),
                    use_info.truncation().IdentifiesZeroAndMinusZero());
1076
      op = machine()->ChangeUint32ToUint64();
1077 1078 1079 1080
    } else if (output_type.Is(Type::Signed32OrMinusZero())) {
      // int32 -> int64
      CHECK_IMPLIES(output_type.Maybe(Type::MinusZero()),
                    use_info.truncation().IdentifiesZeroAndMinusZero());
1081 1082 1083 1084 1085 1086
      op = machine()->ChangeInt32ToInt64();
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord64);
    }
  } else if (output_rep == MachineRepresentation::kFloat32) {
1087
    if (output_type.Is(cache_->kInt64)) {
1088 1089 1090
      // float32 -> float64 -> int64
      node = InsertChangeFloat32ToFloat64(node);
      op = machine()->ChangeFloat64ToInt64();
1091
    } else if (output_type.Is(cache_->kUint64)) {
1092 1093 1094
      // float32 -> float64 -> uint64
      node = InsertChangeFloat32ToFloat64(node);
      op = machine()->ChangeFloat64ToUint64();
1095 1096
    } else if (use_info.type_check() == TypeCheckKind::kSigned64 ||
               use_info.type_check() == TypeCheckKind::kArrayIndex) {
1097 1098 1099 1100 1101 1102 1103
      // float32 -> float64 -> int64
      node = InsertChangeFloat32ToFloat64(node);
      op = simplified()->CheckedFloat64ToInt64(
          output_type.Maybe(Type::MinusZero())
              ? use_info.minus_zero_check()
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
          use_info.feedback());
1104 1105 1106 1107 1108
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord64);
    }
  } else if (output_rep == MachineRepresentation::kFloat64) {
1109
    if (output_type.Is(cache_->kInt64)) {
1110
      op = machine()->ChangeFloat64ToInt64();
1111
    } else if (output_type.Is(cache_->kUint64)) {
1112
      op = machine()->ChangeFloat64ToUint64();
1113 1114
    } else if (use_info.type_check() == TypeCheckKind::kSigned64 ||
               use_info.type_check() == TypeCheckKind::kArrayIndex) {
1115 1116 1117 1118 1119
      op = simplified()->CheckedFloat64ToInt64(
          output_type.Maybe(Type::MinusZero())
              ? use_info.minus_zero_check()
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
          use_info.feedback());
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord64);
    }
  } else if (output_rep == MachineRepresentation::kTaggedSigned) {
    if (output_type.Is(Type::SignedSmall())) {
      op = simplified()->ChangeTaggedSignedToInt64();
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord64);
    }
1131 1132 1133 1134 1135 1136
  } else if (IsAnyTagged(output_rep) &&
             use_info.truncation().IsUsedAsWord64() &&
             (use_info.type_check() == TypeCheckKind::kBigInt ||
              output_type.Is(Type::BigInt()))) {
    node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
                                             use_node, use_info);
1137
    op = simplified()->TruncateBigIntToUint64();
1138
  } else if (CanBeTaggedPointer(output_rep)) {
1139
    if (output_type.Is(cache_->kInt64)) {
1140
      op = simplified()->ChangeTaggedToInt64();
1141 1142
    } else if (use_info.type_check() == TypeCheckKind::kSigned64 ||
               use_info.type_check() == TypeCheckKind::kArrayIndex) {
1143 1144 1145 1146 1147
      op = simplified()->CheckedTaggedToInt64(
          output_type.Maybe(Type::MinusZero())
              ? use_info.minus_zero_check()
              : CheckForMinusZeroMode::kDontCheckForMinusZero,
          use_info.feedback());
1148 1149 1150 1151 1152 1153 1154
    } else {
      return TypeError(node, output_rep, output_type,
                       MachineRepresentation::kWord64);
    }
  } else {
    return TypeError(node, output_rep, output_type,
                     MachineRepresentation::kWord64);
1155
  }
1156
  return InsertConversion(node, op, use_node);
1157 1158 1159 1160 1161
}

const Operator* RepresentationChanger::Int32OperatorFor(
    IrOpcode::Value opcode) {
  switch (opcode) {
1162
    case IrOpcode::kSpeculativeNumberAdd:  // Fall through.
1163
    case IrOpcode::kSpeculativeSafeIntegerAdd:
1164 1165
    case IrOpcode::kNumberAdd:
      return machine()->Int32Add();
1166
    case IrOpcode::kSpeculativeNumberSubtract:  // Fall through.
1167
    case IrOpcode::kSpeculativeSafeIntegerSubtract:
1168 1169
    case IrOpcode::kNumberSubtract:
      return machine()->Int32Sub();
1170
    case IrOpcode::kSpeculativeNumberMultiply:
1171 1172
    case IrOpcode::kNumberMultiply:
      return machine()->Int32Mul();
1173
    case IrOpcode::kSpeculativeNumberDivide:
1174 1175
    case IrOpcode::kNumberDivide:
      return machine()->Int32Div();
1176
    case IrOpcode::kSpeculativeNumberModulus:
1177 1178
    case IrOpcode::kNumberModulus:
      return machine()->Int32Mod();
1179
    case IrOpcode::kSpeculativeNumberBitwiseOr:  // Fall through.
1180 1181
    case IrOpcode::kNumberBitwiseOr:
      return machine()->Word32Or();
1182
    case IrOpcode::kSpeculativeNumberBitwiseXor:  // Fall through.
1183 1184
    case IrOpcode::kNumberBitwiseXor:
      return machine()->Word32Xor();
1185
    case IrOpcode::kSpeculativeNumberBitwiseAnd:  // Fall through.
1186 1187 1188
    case IrOpcode::kNumberBitwiseAnd:
      return machine()->Word32And();
    case IrOpcode::kNumberEqual:
1189
    case IrOpcode::kSpeculativeNumberEqual:
1190 1191
      return machine()->Word32Equal();
    case IrOpcode::kNumberLessThan:
1192
    case IrOpcode::kSpeculativeNumberLessThan:
1193 1194
      return machine()->Int32LessThan();
    case IrOpcode::kNumberLessThanOrEqual:
1195
    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1196 1197 1198 1199 1200 1201
      return machine()->Int32LessThanOrEqual();
    default:
      UNREACHABLE();
  }
}

1202 1203 1204
const Operator* RepresentationChanger::Int32OverflowOperatorFor(
    IrOpcode::Value opcode) {
  switch (opcode) {
1205
    case IrOpcode::kSpeculativeSafeIntegerAdd:
1206
      return simplified()->CheckedInt32Add();
1207
    case IrOpcode::kSpeculativeSafeIntegerSubtract:
1208
      return simplified()->CheckedInt32Sub();
1209 1210 1211 1212
    case IrOpcode::kSpeculativeNumberDivide:
      return simplified()->CheckedInt32Div();
    case IrOpcode::kSpeculativeNumberModulus:
      return simplified()->CheckedInt32Mod();
1213 1214 1215 1216
    default:
      UNREACHABLE();
  }
}
1217

1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
const Operator* RepresentationChanger::Int64OperatorFor(
    IrOpcode::Value opcode) {
  switch (opcode) {
    case IrOpcode::kSpeculativeNumberAdd:  // Fall through.
    case IrOpcode::kSpeculativeSafeIntegerAdd:
    case IrOpcode::kNumberAdd:
      return machine()->Int64Add();
    case IrOpcode::kSpeculativeNumberSubtract:  // Fall through.
    case IrOpcode::kSpeculativeSafeIntegerSubtract:
    case IrOpcode::kNumberSubtract:
      return machine()->Int64Sub();
    default:
      UNREACHABLE();
  }
}

1234 1235 1236 1237
const Operator* RepresentationChanger::TaggedSignedOperatorFor(
    IrOpcode::Value opcode) {
  switch (opcode) {
    case IrOpcode::kSpeculativeNumberLessThan:
1238 1239 1240
      return (COMPRESS_POINTERS_BOOL || machine()->Is32())
                 ? machine()->Int32LessThan()
                 : machine()->Int64LessThan();
1241
    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1242 1243 1244
      return (COMPRESS_POINTERS_BOOL || machine()->Is32())
                 ? machine()->Int32LessThanOrEqual()
                 : machine()->Int64LessThanOrEqual();
1245
    case IrOpcode::kSpeculativeNumberEqual:
1246 1247 1248
      return (COMPRESS_POINTERS_BOOL || machine()->Is32())
                 ? machine()->Word32Equal()
                 : machine()->Word64Equal();
1249 1250 1251 1252 1253
    default:
      UNREACHABLE();
  }
}

1254 1255 1256 1257 1258 1259 1260
const Operator* RepresentationChanger::Uint32OperatorFor(
    IrOpcode::Value opcode) {
  switch (opcode) {
    case IrOpcode::kNumberAdd:
      return machine()->Int32Add();
    case IrOpcode::kNumberSubtract:
      return machine()->Int32Sub();
1261
    case IrOpcode::kSpeculativeNumberMultiply:
1262 1263
    case IrOpcode::kNumberMultiply:
      return machine()->Int32Mul();
1264
    case IrOpcode::kSpeculativeNumberDivide:
1265 1266
    case IrOpcode::kNumberDivide:
      return machine()->Uint32Div();
1267
    case IrOpcode::kSpeculativeNumberModulus:
1268 1269 1270
    case IrOpcode::kNumberModulus:
      return machine()->Uint32Mod();
    case IrOpcode::kNumberEqual:
1271
    case IrOpcode::kSpeculativeNumberEqual:
1272 1273
      return machine()->Word32Equal();
    case IrOpcode::kNumberLessThan:
1274
    case IrOpcode::kSpeculativeNumberLessThan:
1275 1276
      return machine()->Uint32LessThan();
    case IrOpcode::kNumberLessThanOrEqual:
1277
    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1278
      return machine()->Uint32LessThanOrEqual();
1279 1280
    case IrOpcode::kNumberClz32:
      return machine()->Word32Clz();
1281 1282
    case IrOpcode::kNumberImul:
      return machine()->Int32Mul();
1283 1284 1285 1286 1287
    default:
      UNREACHABLE();
  }
}

1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
    IrOpcode::Value opcode) {
  switch (opcode) {
    case IrOpcode::kSpeculativeNumberDivide:
      return simplified()->CheckedUint32Div();
    case IrOpcode::kSpeculativeNumberModulus:
      return simplified()->CheckedUint32Mod();
    default:
      UNREACHABLE();
  }
}
1299 1300 1301 1302

const Operator* RepresentationChanger::Float64OperatorFor(
    IrOpcode::Value opcode) {
  switch (opcode) {
1303
    case IrOpcode::kSpeculativeNumberAdd:
1304
    case IrOpcode::kSpeculativeSafeIntegerAdd:
1305 1306
    case IrOpcode::kNumberAdd:
      return machine()->Float64Add();
1307
    case IrOpcode::kSpeculativeNumberSubtract:
1308
    case IrOpcode::kSpeculativeSafeIntegerSubtract:
1309 1310
    case IrOpcode::kNumberSubtract:
      return machine()->Float64Sub();
1311
    case IrOpcode::kSpeculativeNumberMultiply:
1312 1313
    case IrOpcode::kNumberMultiply:
      return machine()->Float64Mul();
1314
    case IrOpcode::kSpeculativeNumberDivide:
1315 1316
    case IrOpcode::kNumberDivide:
      return machine()->Float64Div();
1317
    case IrOpcode::kSpeculativeNumberModulus:
1318 1319 1320
    case IrOpcode::kNumberModulus:
      return machine()->Float64Mod();
    case IrOpcode::kNumberEqual:
1321
    case IrOpcode::kSpeculativeNumberEqual:
1322 1323
      return machine()->Float64Equal();
    case IrOpcode::kNumberLessThan:
1324
    case IrOpcode::kSpeculativeNumberLessThan:
1325 1326
      return machine()->Float64LessThan();
    case IrOpcode::kNumberLessThanOrEqual:
1327
    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1328
      return machine()->Float64LessThanOrEqual();
1329 1330
    case IrOpcode::kNumberAbs:
      return machine()->Float64Abs();
1331 1332 1333 1334 1335 1336 1337 1338
    case IrOpcode::kNumberAcos:
      return machine()->Float64Acos();
    case IrOpcode::kNumberAcosh:
      return machine()->Float64Acosh();
    case IrOpcode::kNumberAsin:
      return machine()->Float64Asin();
    case IrOpcode::kNumberAsinh:
      return machine()->Float64Asinh();
1339 1340
    case IrOpcode::kNumberAtan:
      return machine()->Float64Atan();
1341 1342
    case IrOpcode::kNumberAtanh:
      return machine()->Float64Atanh();
1343 1344
    case IrOpcode::kNumberAtan2:
      return machine()->Float64Atan2();
1345 1346
    case IrOpcode::kNumberCbrt:
      return machine()->Float64Cbrt();
1347 1348
    case IrOpcode::kNumberCeil:
      return machine()->Float64RoundUp().placeholder();
1349 1350
    case IrOpcode::kNumberCos:
      return machine()->Float64Cos();
1351 1352
    case IrOpcode::kNumberCosh:
      return machine()->Float64Cosh();
1353 1354
    case IrOpcode::kNumberExp:
      return machine()->Float64Exp();
1355 1356
    case IrOpcode::kNumberExpm1:
      return machine()->Float64Expm1();
1357 1358
    case IrOpcode::kNumberFloor:
      return machine()->Float64RoundDown().placeholder();
1359 1360
    case IrOpcode::kNumberFround:
      return machine()->TruncateFloat64ToFloat32();
1361 1362
    case IrOpcode::kNumberLog:
      return machine()->Float64Log();
1363 1364
    case IrOpcode::kNumberLog1p:
      return machine()->Float64Log1p();
1365 1366 1367 1368
    case IrOpcode::kNumberLog2:
      return machine()->Float64Log2();
    case IrOpcode::kNumberLog10:
      return machine()->Float64Log10();
1369 1370 1371 1372
    case IrOpcode::kNumberMax:
      return machine()->Float64Max();
    case IrOpcode::kNumberMin:
      return machine()->Float64Min();
1373 1374
    case IrOpcode::kNumberPow:
      return machine()->Float64Pow();
1375 1376
    case IrOpcode::kNumberSin:
      return machine()->Float64Sin();
1377 1378
    case IrOpcode::kNumberSinh:
      return machine()->Float64Sinh();
1379 1380
    case IrOpcode::kNumberSqrt:
      return machine()->Float64Sqrt();
1381 1382
    case IrOpcode::kNumberTan:
      return machine()->Float64Tan();
1383 1384
    case IrOpcode::kNumberTanh:
      return machine()->Float64Tanh();
1385 1386
    case IrOpcode::kNumberTrunc:
      return machine()->Float64RoundTruncate().placeholder();
1387 1388
    case IrOpcode::kNumberSilenceNaN:
      return machine()->Float64SilenceNaN();
1389 1390 1391 1392 1393
    default:
      UNREACHABLE();
  }
}

1394 1395
Node* RepresentationChanger::TypeError(Node* node,
                                       MachineRepresentation output_rep,
1396
                                       Type output_type,
1397
                                       MachineRepresentation use) {
1398 1399 1400
  type_error_ = true;
  if (!testing_type_errors_) {
    std::ostringstream out_str;
1401
    out_str << output_rep << " (";
1402
    output_type.PrintTo(out_str);
1403
    out_str << ")";
1404 1405

    std::ostringstream use_str;
1406
    use_str << use;
1407

1408 1409 1410 1411 1412
    FATAL(
        "RepresentationChangerError: node #%d:%s of "
        "%s cannot be changed to %s",
        node->id(), node->op()->mnemonic(), out_str.str().c_str(),
        use_str.str().c_str());
1413 1414 1415 1416
  }
  return node;
}

1417 1418 1419
Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
  return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
}
1420 1421 1422 1423 1424

Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
  return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
}

1425 1426 1427 1428 1429 1430 1431
Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
  return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
}

Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
  return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
}
1432

1433 1434 1435 1436
Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) {
  return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
}

1437 1438 1439 1440 1441
Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
  return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
                                     node);
}

1442 1443 1444 1445 1446
Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
  return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
                                     node);
}

1447 1448 1449 1450
Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) {
  return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
}

1451 1452 1453 1454
Node* RepresentationChanger::InsertTruncateInt64ToInt32(Node* node) {
  return jsgraph()->graph()->NewNode(machine()->TruncateInt64ToInt32(), node);
}

1455
Node* RepresentationChanger::InsertCheckedFloat64ToInt32(
1456
    Node* node, CheckForMinusZeroMode check, const FeedbackSource& feedback,
1457 1458 1459 1460 1461
    Node* use_node) {
  return InsertConversion(
      node, simplified()->CheckedFloat64ToInt32(check, feedback), use_node);
}

1462 1463
Isolate* RepresentationChanger::isolate() const { return broker_->isolate(); }

1464 1465 1466
}  // namespace compiler
}  // namespace internal
}  // namespace v8