1 // Copyright 2014 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 <limits> 6 7 #include "test/cctest/cctest.h" 8 #include "test/cctest/compiler/codegen-tester.h" 9 #include "test/cctest/compiler/graph-builder-tester.h" 10 #include "test/cctest/compiler/value-helper.h" 11 12 #include "src/compiler/node-matchers.h" 13 #include "src/compiler/representation-change.h" 14 15 namespace v8 { 16 namespace internal { 17 namespace compiler { 18 19 class RepresentationChangerTester : public HandleAndZoneScope, 20 public GraphAndBuilders { 21 public: 22 explicit RepresentationChangerTester(int num_parameters = 0) 23 : GraphAndBuilders(main_zone()), 24 javascript_(main_zone()), 25 jsgraph_(main_isolate(), main_graph_, &main_common_, &javascript_, 26 &main_simplified_, &main_machine_), 27 changer_(&jsgraph_, main_isolate()) { 28 Node* s = graph()->NewNode(common()->Start(num_parameters)); 29 graph()->SetStart(s); 30 } 31 32 JSOperatorBuilder javascript_; 33 JSGraph jsgraph_; 34 RepresentationChanger changer_; 35 36 Isolate* isolate() { return main_isolate(); } 37 Graph* graph() { return main_graph_; } 38 CommonOperatorBuilder* common() { return &main_common_; } 39 JSGraph* jsgraph() { return &jsgraph_; } 40 RepresentationChanger* changer() { return &changer_; } 41 42 // TODO(titzer): use ValueChecker / ValueUtil 43 void CheckInt32Constant(Node* n, int32_t expected) { 44 Int32Matcher m(n); 45 CHECK(m.HasValue()); 46 CHECK_EQ(expected, m.Value()); 47 } 48 49 void CheckUint32Constant(Node* n, uint32_t expected) { 50 Uint32Matcher m(n); 51 CHECK(m.HasValue()); 52 CHECK_EQ(static_cast<int>(expected), static_cast<int>(m.Value())); 53 } 54 55 void CheckFloat64Constant(Node* n, double expected) { 56 Float64Matcher m(n); 57 CHECK(m.HasValue()); 58 CHECK_DOUBLE_EQ(expected, m.Value()); 59 } 60 61 void CheckFloat32Constant(Node* n, float expected) { 62 CHECK_EQ(IrOpcode::kFloat32Constant, n->opcode()); 63 float fval = OpParameter<float>(n->op()); 64 CHECK_FLOAT_EQ(expected, fval); 65 } 66 67 void CheckHeapConstant(Node* n, HeapObject* expected) { 68 HeapObjectMatcher m(n); 69 CHECK(m.HasValue()); 70 CHECK_EQ(expected, *m.Value()); 71 } 72 73 void CheckNumberConstant(Node* n, double expected) { 74 NumberMatcher m(n); 75 CHECK_EQ(IrOpcode::kNumberConstant, n->opcode()); 76 CHECK(m.HasValue()); 77 CHECK_DOUBLE_EQ(expected, m.Value()); 78 } 79 80 Node* Parameter(int index = 0) { 81 Node* n = graph()->NewNode(common()->Parameter(index), graph()->start()); 82 NodeProperties::SetType(n, Type::Any()); 83 return n; 84 } 85 86 Node* Return(Node* input) { 87 Node* n = graph()->NewNode(common()->Return(), input, graph()->start(), 88 graph()->start()); 89 return n; 90 } 91 92 void CheckTypeError(MachineRepresentation from, Type* from_type, 93 MachineRepresentation to) { 94 changer()->testing_type_errors_ = true; 95 changer()->type_error_ = false; 96 Node* n = Parameter(0); 97 Node* use = Return(n); 98 Node* c = changer()->GetRepresentationFor(n, from, from_type, use, 99 UseInfo(to, Truncation::None())); 100 CHECK(changer()->type_error_); 101 CHECK_EQ(n, c); 102 } 103 104 void CheckNop(MachineRepresentation from, Type* from_type, 105 MachineRepresentation to) { 106 Node* n = Parameter(0); 107 Node* use = Return(n); 108 Node* c = changer()->GetRepresentationFor(n, from, from_type, use, 109 UseInfo(to, Truncation::None())); 110 CHECK_EQ(n, c); 111 } 112 }; 113 114 115 const MachineType kMachineTypes[] = { 116 MachineType::Float32(), MachineType::Float64(), MachineType::Int8(), 117 MachineType::Uint8(), MachineType::Int16(), MachineType::Uint16(), 118 MachineType::Int32(), MachineType::Uint32(), MachineType::Int64(), 119 MachineType::Uint64(), MachineType::AnyTagged()}; 120 121 122 TEST(BoolToBit_constant) { 123 RepresentationChangerTester r; 124 125 Node* true_node = r.jsgraph()->TrueConstant(); 126 Node* true_use = r.Return(true_node); 127 Node* true_bit = r.changer()->GetRepresentationFor( 128 true_node, MachineRepresentation::kTagged, Type::None(), true_use, 129 UseInfo(MachineRepresentation::kBit, Truncation::None())); 130 r.CheckInt32Constant(true_bit, 1); 131 132 Node* false_node = r.jsgraph()->FalseConstant(); 133 Node* false_use = r.Return(false_node); 134 Node* false_bit = r.changer()->GetRepresentationFor( 135 false_node, MachineRepresentation::kTagged, Type::None(), false_use, 136 UseInfo(MachineRepresentation::kBit, Truncation::None())); 137 r.CheckInt32Constant(false_bit, 0); 138 } 139 140 141 TEST(BitToBool_constant) { 142 RepresentationChangerTester r; 143 144 for (int i = -5; i < 5; i++) { 145 Node* node = r.jsgraph()->Int32Constant(i); 146 Node* use = r.Return(node); 147 Node* val = r.changer()->GetRepresentationFor( 148 node, MachineRepresentation::kBit, Type::Boolean(), use, 149 UseInfo(MachineRepresentation::kTagged, Truncation::None())); 150 r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value() 151 : r.isolate()->heap()->true_value()); 152 } 153 } 154 155 156 TEST(ToTagged_constant) { 157 RepresentationChangerTester r; 158 159 { 160 FOR_FLOAT64_INPUTS(i) { 161 Node* n = r.jsgraph()->Float64Constant(*i); 162 Node* use = r.Return(n); 163 Node* c = r.changer()->GetRepresentationFor( 164 n, MachineRepresentation::kFloat64, Type::None(), use, 165 UseInfo(MachineRepresentation::kTagged, Truncation::None())); 166 r.CheckNumberConstant(c, *i); 167 } 168 } 169 170 { 171 FOR_FLOAT64_INPUTS(i) { 172 Node* n = r.jsgraph()->Constant(*i); 173 Node* use = r.Return(n); 174 Node* c = r.changer()->GetRepresentationFor( 175 n, MachineRepresentation::kFloat64, Type::None(), use, 176 UseInfo(MachineRepresentation::kTagged, Truncation::None())); 177 r.CheckNumberConstant(c, *i); 178 } 179 } 180 181 { 182 FOR_FLOAT32_INPUTS(i) { 183 Node* n = r.jsgraph()->Float32Constant(*i); 184 Node* use = r.Return(n); 185 Node* c = r.changer()->GetRepresentationFor( 186 n, MachineRepresentation::kFloat32, Type::None(), use, 187 UseInfo(MachineRepresentation::kTagged, Truncation::None())); 188 r.CheckNumberConstant(c, *i); 189 } 190 } 191 192 { 193 FOR_INT32_INPUTS(i) { 194 Node* n = r.jsgraph()->Int32Constant(*i); 195 Node* use = r.Return(n); 196 Node* c = r.changer()->GetRepresentationFor( 197 n, MachineRepresentation::kWord32, Type::Signed32(), use, 198 UseInfo(MachineRepresentation::kTagged, Truncation::None())); 199 r.CheckNumberConstant(c, *i); 200 } 201 } 202 203 { 204 FOR_UINT32_INPUTS(i) { 205 Node* n = r.jsgraph()->Int32Constant(*i); 206 Node* use = r.Return(n); 207 Node* c = r.changer()->GetRepresentationFor( 208 n, MachineRepresentation::kWord32, Type::Unsigned32(), use, 209 UseInfo(MachineRepresentation::kTagged, Truncation::None())); 210 r.CheckNumberConstant(c, *i); 211 } 212 } 213 } 214 215 216 TEST(ToFloat64_constant) { 217 RepresentationChangerTester r; 218 219 { 220 FOR_FLOAT64_INPUTS(i) { 221 Node* n = r.jsgraph()->Float64Constant(*i); 222 Node* use = r.Return(n); 223 Node* c = r.changer()->GetRepresentationFor( 224 n, MachineRepresentation::kFloat64, Type::None(), use, 225 UseInfo(MachineRepresentation::kFloat64, Truncation::None())); 226 CHECK_EQ(n, c); 227 } 228 } 229 230 { 231 FOR_FLOAT64_INPUTS(i) { 232 Node* n = r.jsgraph()->Constant(*i); 233 Node* use = r.Return(n); 234 Node* c = r.changer()->GetRepresentationFor( 235 n, MachineRepresentation::kTagged, Type::None(), use, 236 UseInfo(MachineRepresentation::kFloat64, Truncation::None())); 237 r.CheckFloat64Constant(c, *i); 238 } 239 } 240 241 { 242 FOR_FLOAT32_INPUTS(i) { 243 Node* n = r.jsgraph()->Float32Constant(*i); 244 Node* use = r.Return(n); 245 Node* c = r.changer()->GetRepresentationFor( 246 n, MachineRepresentation::kFloat32, Type::None(), use, 247 UseInfo(MachineRepresentation::kFloat64, Truncation::None())); 248 r.CheckFloat64Constant(c, *i); 249 } 250 } 251 252 { 253 FOR_INT32_INPUTS(i) { 254 Node* n = r.jsgraph()->Int32Constant(*i); 255 Node* use = r.Return(n); 256 Node* c = r.changer()->GetRepresentationFor( 257 n, MachineRepresentation::kWord32, Type::Signed32(), use, 258 UseInfo(MachineRepresentation::kFloat64, Truncation::None())); 259 r.CheckFloat64Constant(c, *i); 260 } 261 } 262 263 { 264 FOR_UINT32_INPUTS(i) { 265 Node* n = r.jsgraph()->Int32Constant(*i); 266 Node* use = r.Return(n); 267 Node* c = r.changer()->GetRepresentationFor( 268 n, MachineRepresentation::kWord32, Type::Unsigned32(), use, 269 UseInfo(MachineRepresentation::kFloat64, Truncation::None())); 270 r.CheckFloat64Constant(c, *i); 271 } 272 } 273 } 274 275 276 static bool IsFloat32Int32(int32_t val) { 277 return val >= -(1 << 23) && val <= (1 << 23); 278 } 279 280 281 static bool IsFloat32Uint32(uint32_t val) { return val <= (1 << 23); } 282 283 284 TEST(ToFloat32_constant) { 285 RepresentationChangerTester r; 286 287 { 288 FOR_FLOAT32_INPUTS(i) { 289 Node* n = r.jsgraph()->Float32Constant(*i); 290 Node* use = r.Return(n); 291 Node* c = r.changer()->GetRepresentationFor( 292 n, MachineRepresentation::kFloat32, Type::None(), use, 293 UseInfo(MachineRepresentation::kFloat32, Truncation::None())); 294 CHECK_EQ(n, c); 295 } 296 } 297 298 { 299 FOR_FLOAT32_INPUTS(i) { 300 Node* n = r.jsgraph()->Constant(*i); 301 Node* use = r.Return(n); 302 Node* c = r.changer()->GetRepresentationFor( 303 n, MachineRepresentation::kTagged, Type::None(), use, 304 UseInfo(MachineRepresentation::kFloat32, Truncation::None())); 305 r.CheckFloat32Constant(c, *i); 306 } 307 } 308 309 { 310 FOR_FLOAT32_INPUTS(i) { 311 Node* n = r.jsgraph()->Float64Constant(*i); 312 Node* use = r.Return(n); 313 Node* c = r.changer()->GetRepresentationFor( 314 n, MachineRepresentation::kFloat64, Type::None(), use, 315 UseInfo(MachineRepresentation::kFloat32, Truncation::None())); 316 r.CheckFloat32Constant(c, *i); 317 } 318 } 319 320 { 321 FOR_INT32_INPUTS(i) { 322 if (!IsFloat32Int32(*i)) continue; 323 Node* n = r.jsgraph()->Int32Constant(*i); 324 Node* use = r.Return(n); 325 Node* c = r.changer()->GetRepresentationFor( 326 n, MachineRepresentation::kWord32, Type::Signed32(), use, 327 UseInfo(MachineRepresentation::kFloat32, Truncation::None())); 328 r.CheckFloat32Constant(c, static_cast<float>(*i)); 329 } 330 } 331 332 { 333 FOR_UINT32_INPUTS(i) { 334 if (!IsFloat32Uint32(*i)) continue; 335 Node* n = r.jsgraph()->Int32Constant(*i); 336 Node* use = r.Return(n); 337 Node* c = r.changer()->GetRepresentationFor( 338 n, MachineRepresentation::kWord32, Type::Unsigned32(), use, 339 UseInfo(MachineRepresentation::kFloat32, Truncation::None())); 340 r.CheckFloat32Constant(c, static_cast<float>(*i)); 341 } 342 } 343 } 344 345 346 TEST(ToInt32_constant) { 347 RepresentationChangerTester r; 348 349 { 350 FOR_INT32_INPUTS(i) { 351 Node* n = r.jsgraph()->Int32Constant(*i); 352 Node* use = r.Return(n); 353 Node* c = r.changer()->GetRepresentationFor( 354 n, MachineRepresentation::kWord32, Type::Signed32(), use, 355 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 356 r.CheckInt32Constant(c, *i); 357 } 358 } 359 360 { 361 FOR_INT32_INPUTS(i) { 362 if (!IsFloat32Int32(*i)) continue; 363 Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i)); 364 Node* use = r.Return(n); 365 Node* c = r.changer()->GetRepresentationFor( 366 n, MachineRepresentation::kFloat32, Type::Signed32(), use, 367 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 368 r.CheckInt32Constant(c, *i); 369 } 370 } 371 372 { 373 FOR_INT32_INPUTS(i) { 374 Node* n = r.jsgraph()->Float64Constant(*i); 375 Node* use = r.Return(n); 376 Node* c = r.changer()->GetRepresentationFor( 377 n, MachineRepresentation::kFloat64, Type::Signed32(), use, 378 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 379 r.CheckInt32Constant(c, *i); 380 } 381 } 382 383 { 384 FOR_INT32_INPUTS(i) { 385 Node* n = r.jsgraph()->Constant(*i); 386 Node* use = r.Return(n); 387 Node* c = r.changer()->GetRepresentationFor( 388 n, MachineRepresentation::kTagged, Type::Signed32(), use, 389 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 390 r.CheckInt32Constant(c, *i); 391 } 392 } 393 } 394 395 396 TEST(ToUint32_constant) { 397 RepresentationChangerTester r; 398 399 { 400 FOR_UINT32_INPUTS(i) { 401 Node* n = r.jsgraph()->Int32Constant(*i); 402 Node* use = r.Return(n); 403 Node* c = r.changer()->GetRepresentationFor( 404 n, MachineRepresentation::kWord32, Type::Unsigned32(), use, 405 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 406 r.CheckUint32Constant(c, *i); 407 } 408 } 409 410 { 411 FOR_UINT32_INPUTS(i) { 412 if (!IsFloat32Uint32(*i)) continue; 413 Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i)); 414 Node* use = r.Return(n); 415 Node* c = r.changer()->GetRepresentationFor( 416 n, MachineRepresentation::kFloat32, Type::Unsigned32(), use, 417 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 418 r.CheckUint32Constant(c, *i); 419 } 420 } 421 422 { 423 FOR_UINT32_INPUTS(i) { 424 Node* n = r.jsgraph()->Float64Constant(*i); 425 Node* use = r.Return(n); 426 Node* c = r.changer()->GetRepresentationFor( 427 n, MachineRepresentation::kFloat64, Type::Unsigned32(), use, 428 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 429 r.CheckUint32Constant(c, *i); 430 } 431 } 432 433 { 434 FOR_UINT32_INPUTS(i) { 435 Node* n = r.jsgraph()->Constant(static_cast<double>(*i)); 436 Node* use = r.Return(n); 437 Node* c = r.changer()->GetRepresentationFor( 438 n, MachineRepresentation::kTagged, Type::Unsigned32(), use, 439 UseInfo(MachineRepresentation::kWord32, Truncation::None())); 440 r.CheckUint32Constant(c, *i); 441 } 442 } 443 } 444 445 446 static void CheckChange(IrOpcode::Value expected, MachineRepresentation from, 447 Type* from_type, MachineRepresentation to) { 448 RepresentationChangerTester r; 449 450 Node* n = r.Parameter(); 451 Node* use = r.Return(n); 452 Node* c = r.changer()->GetRepresentationFor(n, from, from_type, use, 453 UseInfo(to, Truncation::None())); 454 455 CHECK_NE(c, n); 456 CHECK_EQ(expected, c->opcode()); 457 CHECK_EQ(n, c->InputAt(0)); 458 } 459 460 461 static void CheckTwoChanges(IrOpcode::Value expected2, 462 IrOpcode::Value expected1, 463 MachineRepresentation from, Type* from_type, 464 MachineRepresentation to) { 465 RepresentationChangerTester r; 466 467 Node* n = r.Parameter(); 468 Node* use = r.Return(n); 469 Node* c1 = r.changer()->GetRepresentationFor(n, from, from_type, use, 470 UseInfo(to, Truncation::None())); 471 472 CHECK_NE(c1, n); 473 CHECK_EQ(expected1, c1->opcode()); 474 Node* c2 = c1->InputAt(0); 475 CHECK_NE(c2, n); 476 CHECK_EQ(expected2, c2->opcode()); 477 CHECK_EQ(n, c2->InputAt(0)); 478 } 479 480 481 TEST(SingleChanges) { 482 CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged, 483 Type::None(), MachineRepresentation::kBit); 484 CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit, 485 Type::None(), MachineRepresentation::kTagged); 486 487 CheckChange(IrOpcode::kChangeInt31ToTaggedSigned, 488 MachineRepresentation::kWord32, Type::Signed31(), 489 MachineRepresentation::kTagged); 490 CheckChange(IrOpcode::kChangeInt32ToTagged, MachineRepresentation::kWord32, 491 Type::Signed32(), MachineRepresentation::kTagged); 492 CheckChange(IrOpcode::kChangeUint32ToTagged, MachineRepresentation::kWord32, 493 Type::Unsigned32(), MachineRepresentation::kTagged); 494 CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineRepresentation::kFloat64, 495 Type::Number(), MachineRepresentation::kTagged); 496 CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32, 497 IrOpcode::kChangeInt31ToTaggedSigned, 498 MachineRepresentation::kFloat64, Type::Signed31(), 499 MachineRepresentation::kTagged); 500 CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32, 501 IrOpcode::kChangeInt32ToTagged, 502 MachineRepresentation::kFloat64, Type::Signed32(), 503 MachineRepresentation::kTagged); 504 CheckTwoChanges(IrOpcode::kChangeFloat64ToUint32, 505 IrOpcode::kChangeUint32ToTagged, 506 MachineRepresentation::kFloat64, Type::Unsigned32(), 507 MachineRepresentation::kTagged); 508 509 CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged, 510 Type::Signed32(), MachineRepresentation::kWord32); 511 CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged, 512 Type::Unsigned32(), MachineRepresentation::kWord32); 513 CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged, 514 Type::Number(), MachineRepresentation::kFloat64); 515 CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged, 516 Type::Number(), MachineRepresentation::kFloat64); 517 CheckChange(IrOpcode::kTruncateTaggedToFloat64, 518 MachineRepresentation::kTagged, Type::NumberOrUndefined(), 519 MachineRepresentation::kFloat64); 520 CheckTwoChanges(IrOpcode::kChangeTaggedSignedToInt32, 521 IrOpcode::kChangeInt32ToFloat64, 522 MachineRepresentation::kTagged, Type::TaggedSigned(), 523 MachineRepresentation::kFloat64); 524 525 // Int32,Uint32 <-> Float64 are actually machine conversions. 526 CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32, 527 Type::Signed32(), MachineRepresentation::kFloat64); 528 CheckChange(IrOpcode::kChangeUint32ToFloat64, MachineRepresentation::kWord32, 529 Type::Unsigned32(), MachineRepresentation::kFloat64); 530 CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64, 531 Type::Signed32(), MachineRepresentation::kWord32); 532 CheckChange(IrOpcode::kChangeFloat64ToUint32, MachineRepresentation::kFloat64, 533 Type::Unsigned32(), MachineRepresentation::kWord32); 534 535 CheckChange(IrOpcode::kTruncateFloat64ToFloat32, 536 MachineRepresentation::kFloat64, Type::None(), 537 MachineRepresentation::kFloat32); 538 539 // Int32,Uint32 <-> Float32 require two changes. 540 CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64, 541 IrOpcode::kTruncateFloat64ToFloat32, 542 MachineRepresentation::kWord32, Type::Signed32(), 543 MachineRepresentation::kFloat32); 544 CheckTwoChanges(IrOpcode::kChangeUint32ToFloat64, 545 IrOpcode::kTruncateFloat64ToFloat32, 546 MachineRepresentation::kWord32, Type::Unsigned32(), 547 MachineRepresentation::kFloat32); 548 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, 549 IrOpcode::kChangeFloat64ToInt32, 550 MachineRepresentation::kFloat32, Type::Signed32(), 551 MachineRepresentation::kWord32); 552 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, 553 IrOpcode::kChangeFloat64ToUint32, 554 MachineRepresentation::kFloat32, Type::Unsigned32(), 555 MachineRepresentation::kWord32); 556 557 // Float32 <-> Tagged require two changes. 558 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, 559 IrOpcode::kChangeFloat64ToTagged, 560 MachineRepresentation::kFloat32, Type::None(), 561 MachineRepresentation::kTagged); 562 CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64, 563 IrOpcode::kTruncateFloat64ToFloat32, 564 MachineRepresentation::kTagged, Type::None(), 565 MachineRepresentation::kFloat32); 566 } 567 568 569 TEST(SignednessInWord32) { 570 RepresentationChangerTester r; 571 572 CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged, 573 Type::Signed32(), MachineRepresentation::kWord32); 574 CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged, 575 Type::Unsigned32(), MachineRepresentation::kWord32); 576 CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32, 577 Type::None(), MachineRepresentation::kFloat64); 578 CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64, 579 Type::Signed32(), MachineRepresentation::kWord32); 580 CheckChange(IrOpcode::kTruncateFloat64ToWord32, 581 MachineRepresentation::kFloat64, Type::Number(), 582 MachineRepresentation::kWord32); 583 584 CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64, 585 IrOpcode::kTruncateFloat64ToFloat32, 586 MachineRepresentation::kWord32, Type::None(), 587 MachineRepresentation::kFloat32); 588 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, 589 IrOpcode::kTruncateFloat64ToWord32, 590 MachineRepresentation::kFloat32, Type::Number(), 591 MachineRepresentation::kWord32); 592 } 593 594 595 TEST(Nops) { 596 RepresentationChangerTester r; 597 598 // X -> X is always a nop for any single representation X. 599 for (size_t i = 0; i < arraysize(kMachineTypes); i++) { 600 r.CheckNop(kMachineTypes[i].representation(), Type::None(), 601 kMachineTypes[i].representation()); 602 } 603 604 // 32-bit floats. 605 r.CheckNop(MachineRepresentation::kFloat32, Type::None(), 606 MachineRepresentation::kFloat32); 607 r.CheckNop(MachineRepresentation::kFloat32, Type::Number(), 608 MachineRepresentation::kFloat32); 609 610 // 32-bit words can be used as smaller word sizes and vice versa, because 611 // loads from memory implicitly sign or zero extend the value to the 612 // full machine word size, and stores implicitly truncate. 613 r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(), 614 MachineRepresentation::kWord8); 615 r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(), 616 MachineRepresentation::kWord16); 617 r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(), 618 MachineRepresentation::kWord32); 619 r.CheckNop(MachineRepresentation::kWord8, Type::Signed32(), 620 MachineRepresentation::kWord32); 621 r.CheckNop(MachineRepresentation::kWord16, Type::Signed32(), 622 MachineRepresentation::kWord32); 623 624 // kRepBit (result of comparison) is implicitly a wordish thing. 625 r.CheckNop(MachineRepresentation::kBit, Type::None(), 626 MachineRepresentation::kWord8); 627 r.CheckNop(MachineRepresentation::kBit, Type::None(), 628 MachineRepresentation::kWord16); 629 r.CheckNop(MachineRepresentation::kBit, Type::None(), 630 MachineRepresentation::kWord32); 631 r.CheckNop(MachineRepresentation::kBit, Type::None(), 632 MachineRepresentation::kWord64); 633 r.CheckNop(MachineRepresentation::kBit, Type::Boolean(), 634 MachineRepresentation::kWord8); 635 r.CheckNop(MachineRepresentation::kBit, Type::Boolean(), 636 MachineRepresentation::kWord16); 637 r.CheckNop(MachineRepresentation::kBit, Type::Boolean(), 638 MachineRepresentation::kWord32); 639 r.CheckNop(MachineRepresentation::kBit, Type::Boolean(), 640 MachineRepresentation::kWord64); 641 } 642 643 644 TEST(TypeErrors) { 645 RepresentationChangerTester r; 646 647 // Wordish cannot be implicitly converted to/from comparison conditions. 648 r.CheckTypeError(MachineRepresentation::kWord8, Type::None(), 649 MachineRepresentation::kBit); 650 r.CheckTypeError(MachineRepresentation::kWord16, Type::None(), 651 MachineRepresentation::kBit); 652 r.CheckTypeError(MachineRepresentation::kWord32, Type::None(), 653 MachineRepresentation::kBit); 654 r.CheckTypeError(MachineRepresentation::kWord64, Type::None(), 655 MachineRepresentation::kBit); 656 657 // Floats cannot be implicitly converted to/from comparison conditions. 658 r.CheckTypeError(MachineRepresentation::kFloat64, Type::None(), 659 MachineRepresentation::kBit); 660 r.CheckTypeError(MachineRepresentation::kBit, Type::None(), 661 MachineRepresentation::kFloat64); 662 r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(), 663 MachineRepresentation::kFloat64); 664 665 // Floats cannot be implicitly converted to/from comparison conditions. 666 r.CheckTypeError(MachineRepresentation::kFloat32, Type::None(), 667 MachineRepresentation::kBit); 668 r.CheckTypeError(MachineRepresentation::kBit, Type::None(), 669 MachineRepresentation::kFloat32); 670 r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(), 671 MachineRepresentation::kFloat32); 672 673 // Word64 is internal and shouldn't be implicitly converted. 674 r.CheckTypeError(MachineRepresentation::kWord64, Type::None(), 675 MachineRepresentation::kTagged); 676 r.CheckTypeError(MachineRepresentation::kTagged, Type::None(), 677 MachineRepresentation::kWord64); 678 r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(), 679 MachineRepresentation::kWord64); 680 681 // Word64 / Word32 shouldn't be implicitly converted. 682 r.CheckTypeError(MachineRepresentation::kWord64, Type::None(), 683 MachineRepresentation::kWord32); 684 r.CheckTypeError(MachineRepresentation::kWord32, Type::None(), 685 MachineRepresentation::kWord64); 686 r.CheckTypeError(MachineRepresentation::kWord32, Type::Signed32(), 687 MachineRepresentation::kWord64); 688 r.CheckTypeError(MachineRepresentation::kWord32, Type::Unsigned32(), 689 MachineRepresentation::kWord64); 690 } 691 692 } // namespace compiler 693 } // namespace internal 694 } // namespace v8 695