| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
| 6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
| 7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 return WhichPowerOf2_64(value_minus_one); | 331 return WhichPowerOf2_64(value_minus_one); |
| 332 } | 332 } |
| 333 } | 333 } |
| 334 return 0; | 334 return 0; |
| 335 } | 335 } |
| 336 | 336 |
| 337 } // namespace | 337 } // namespace |
| 338 | 338 |
| 339 | 339 |
| 340 void InstructionSelector::VisitLoad(Node* node) { | 340 void InstructionSelector::VisitLoad(Node* node) { |
| 341 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 341 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 342 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | |
| 343 Arm64OperandGenerator g(this); | 342 Arm64OperandGenerator g(this); |
| 344 Node* base = node->InputAt(0); | 343 Node* base = node->InputAt(0); |
| 345 Node* index = node->InputAt(1); | 344 Node* index = node->InputAt(1); |
| 346 ArchOpcode opcode; | 345 ArchOpcode opcode; |
| 347 ImmediateMode immediate_mode = kNoImmediate; | 346 ImmediateMode immediate_mode = kNoImmediate; |
| 348 switch (rep) { | 347 switch (load_rep.representation()) { |
| 349 case kRepFloat32: | 348 case MachineRepresentation::kFloat32: |
| 350 opcode = kArm64LdrS; | 349 opcode = kArm64LdrS; |
| 351 immediate_mode = kLoadStoreImm32; | 350 immediate_mode = kLoadStoreImm32; |
| 352 break; | 351 break; |
| 353 case kRepFloat64: | 352 case MachineRepresentation::kFloat64: |
| 354 opcode = kArm64LdrD; | 353 opcode = kArm64LdrD; |
| 355 immediate_mode = kLoadStoreImm64; | 354 immediate_mode = kLoadStoreImm64; |
| 356 break; | 355 break; |
| 357 case kRepBit: // Fall through. | 356 case MachineRepresentation::kBit: // Fall through. |
| 358 case kRepWord8: | 357 case MachineRepresentation::kWord8: |
| 359 opcode = typ == kTypeInt32 ? kArm64Ldrsb : kArm64Ldrb; | 358 opcode = load_rep.IsSigned() ? kArm64Ldrsb : kArm64Ldrb; |
| 360 immediate_mode = kLoadStoreImm8; | 359 immediate_mode = kLoadStoreImm8; |
| 361 break; | 360 break; |
| 362 case kRepWord16: | 361 case MachineRepresentation::kWord16: |
| 363 opcode = typ == kTypeInt32 ? kArm64Ldrsh : kArm64Ldrh; | 362 opcode = load_rep.IsSigned() ? kArm64Ldrsh : kArm64Ldrh; |
| 364 immediate_mode = kLoadStoreImm16; | 363 immediate_mode = kLoadStoreImm16; |
| 365 break; | 364 break; |
| 366 case kRepWord32: | 365 case MachineRepresentation::kWord32: |
| 367 opcode = kArm64LdrW; | 366 opcode = kArm64LdrW; |
| 368 immediate_mode = kLoadStoreImm32; | 367 immediate_mode = kLoadStoreImm32; |
| 369 break; | 368 break; |
| 370 case kRepTagged: // Fall through. | 369 case MachineRepresentation::kTagged: // Fall through. |
| 371 case kRepWord64: | 370 case MachineRepresentation::kWord64: |
| 372 opcode = kArm64Ldr; | 371 opcode = kArm64Ldr; |
| 373 immediate_mode = kLoadStoreImm64; | 372 immediate_mode = kLoadStoreImm64; |
| 374 break; | 373 break; |
| 375 default: | 374 default: |
| 376 UNREACHABLE(); | 375 UNREACHABLE(); |
| 377 return; | 376 return; |
| 378 } | 377 } |
| 379 if (g.CanBeImmediate(index, immediate_mode)) { | 378 if (g.CanBeImmediate(index, immediate_mode)) { |
| 380 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 379 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 381 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | 380 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
| 382 } else { | 381 } else { |
| 383 Emit(opcode | AddressingModeField::encode(kMode_MRR), | 382 Emit(opcode | AddressingModeField::encode(kMode_MRR), |
| 384 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); | 383 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); |
| 385 } | 384 } |
| 386 } | 385 } |
| 387 | 386 |
| 388 | 387 |
| 389 void InstructionSelector::VisitStore(Node* node) { | 388 void InstructionSelector::VisitStore(Node* node) { |
| 390 Arm64OperandGenerator g(this); | 389 Arm64OperandGenerator g(this); |
| 391 Node* base = node->InputAt(0); | 390 Node* base = node->InputAt(0); |
| 392 Node* index = node->InputAt(1); | 391 Node* index = node->InputAt(1); |
| 393 Node* value = node->InputAt(2); | 392 Node* value = node->InputAt(2); |
| 394 | 393 |
| 395 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 394 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
| 396 WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind(); | 395 WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind(); |
| 397 MachineType rep = RepresentationOf(store_rep.machine_type()); | 396 MachineRepresentation rep = store_rep.machine_type().representation(); |
| 398 | 397 |
| 399 // TODO(arm64): I guess this could be done in a better way. | 398 // TODO(arm64): I guess this could be done in a better way. |
| 400 if (write_barrier_kind != kNoWriteBarrier) { | 399 if (write_barrier_kind != kNoWriteBarrier) { |
| 401 DCHECK_EQ(kRepTagged, rep); | 400 DCHECK_EQ(MachineRepresentation::kTagged, rep); |
| 402 InstructionOperand inputs[3]; | 401 InstructionOperand inputs[3]; |
| 403 size_t input_count = 0; | 402 size_t input_count = 0; |
| 404 inputs[input_count++] = g.UseUniqueRegister(base); | 403 inputs[input_count++] = g.UseUniqueRegister(base); |
| 405 inputs[input_count++] = g.UseUniqueRegister(index); | 404 inputs[input_count++] = g.UseUniqueRegister(index); |
| 406 inputs[input_count++] = (write_barrier_kind == kMapWriteBarrier) | 405 inputs[input_count++] = (write_barrier_kind == kMapWriteBarrier) |
| 407 ? g.UseRegister(value) | 406 ? g.UseRegister(value) |
| 408 : g.UseUniqueRegister(value); | 407 : g.UseUniqueRegister(value); |
| 409 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; | 408 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; |
| 410 switch (write_barrier_kind) { | 409 switch (write_barrier_kind) { |
| 411 case kNoWriteBarrier: | 410 case kNoWriteBarrier: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 423 } | 422 } |
| 424 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; | 423 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; |
| 425 size_t const temp_count = arraysize(temps); | 424 size_t const temp_count = arraysize(temps); |
| 426 InstructionCode code = kArchStoreWithWriteBarrier; | 425 InstructionCode code = kArchStoreWithWriteBarrier; |
| 427 code |= MiscField::encode(static_cast<int>(record_write_mode)); | 426 code |= MiscField::encode(static_cast<int>(record_write_mode)); |
| 428 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); | 427 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); |
| 429 } else { | 428 } else { |
| 430 ArchOpcode opcode; | 429 ArchOpcode opcode; |
| 431 ImmediateMode immediate_mode = kNoImmediate; | 430 ImmediateMode immediate_mode = kNoImmediate; |
| 432 switch (rep) { | 431 switch (rep) { |
| 433 case kRepFloat32: | 432 case MachineRepresentation::kFloat32: |
| 434 opcode = kArm64StrS; | 433 opcode = kArm64StrS; |
| 435 immediate_mode = kLoadStoreImm32; | 434 immediate_mode = kLoadStoreImm32; |
| 436 break; | 435 break; |
| 437 case kRepFloat64: | 436 case MachineRepresentation::kFloat64: |
| 438 opcode = kArm64StrD; | 437 opcode = kArm64StrD; |
| 439 immediate_mode = kLoadStoreImm64; | 438 immediate_mode = kLoadStoreImm64; |
| 440 break; | 439 break; |
| 441 case kRepBit: // Fall through. | 440 case MachineRepresentation::kBit: // Fall through. |
| 442 case kRepWord8: | 441 case MachineRepresentation::kWord8: |
| 443 opcode = kArm64Strb; | 442 opcode = kArm64Strb; |
| 444 immediate_mode = kLoadStoreImm8; | 443 immediate_mode = kLoadStoreImm8; |
| 445 break; | 444 break; |
| 446 case kRepWord16: | 445 case MachineRepresentation::kWord16: |
| 447 opcode = kArm64Strh; | 446 opcode = kArm64Strh; |
| 448 immediate_mode = kLoadStoreImm16; | 447 immediate_mode = kLoadStoreImm16; |
| 449 break; | 448 break; |
| 450 case kRepWord32: | 449 case MachineRepresentation::kWord32: |
| 451 opcode = kArm64StrW; | 450 opcode = kArm64StrW; |
| 452 immediate_mode = kLoadStoreImm32; | 451 immediate_mode = kLoadStoreImm32; |
| 453 break; | 452 break; |
| 454 case kRepTagged: // Fall through. | 453 case MachineRepresentation::kTagged: // Fall through. |
| 455 case kRepWord64: | 454 case MachineRepresentation::kWord64: |
| 456 opcode = kArm64Str; | 455 opcode = kArm64Str; |
| 457 immediate_mode = kLoadStoreImm64; | 456 immediate_mode = kLoadStoreImm64; |
| 458 break; | 457 break; |
| 459 default: | 458 default: |
| 460 UNREACHABLE(); | 459 UNREACHABLE(); |
| 461 return; | 460 return; |
| 462 } | 461 } |
| 463 if (g.CanBeImmediate(index, immediate_mode)) { | 462 if (g.CanBeImmediate(index, immediate_mode)) { |
| 464 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 463 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
| 465 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 464 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
| 466 } else { | 465 } else { |
| 467 Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(), | 466 Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(), |
| 468 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); | 467 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); |
| 469 } | 468 } |
| 470 } | 469 } |
| 471 } | 470 } |
| 472 | 471 |
| 473 | 472 |
| 474 void InstructionSelector::VisitCheckedLoad(Node* node) { | 473 void InstructionSelector::VisitCheckedLoad(Node* node) { |
| 475 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 474 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); |
| 476 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | |
| 477 Arm64OperandGenerator g(this); | 475 Arm64OperandGenerator g(this); |
| 478 Node* const buffer = node->InputAt(0); | 476 Node* const buffer = node->InputAt(0); |
| 479 Node* const offset = node->InputAt(1); | 477 Node* const offset = node->InputAt(1); |
| 480 Node* const length = node->InputAt(2); | 478 Node* const length = node->InputAt(2); |
| 481 ArchOpcode opcode; | 479 ArchOpcode opcode; |
| 482 switch (rep) { | 480 switch (load_rep.representation()) { |
| 483 case kRepWord8: | 481 case MachineRepresentation::kWord8: |
| 484 opcode = typ == kTypeInt32 ? kCheckedLoadInt8 : kCheckedLoadUint8; | 482 opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8; |
| 485 break; | 483 break; |
| 486 case kRepWord16: | 484 case MachineRepresentation::kWord16: |
| 487 opcode = typ == kTypeInt32 ? kCheckedLoadInt16 : kCheckedLoadUint16; | 485 opcode = load_rep.IsSigned() ? kCheckedLoadInt16 : kCheckedLoadUint16; |
| 488 break; | 486 break; |
| 489 case kRepWord32: | 487 case MachineRepresentation::kWord32: |
| 490 opcode = kCheckedLoadWord32; | 488 opcode = kCheckedLoadWord32; |
| 491 break; | 489 break; |
| 492 case kRepWord64: | 490 case MachineRepresentation::kWord64: |
| 493 opcode = kCheckedLoadWord64; | 491 opcode = kCheckedLoadWord64; |
| 494 break; | 492 break; |
| 495 case kRepFloat32: | 493 case MachineRepresentation::kFloat32: |
| 496 opcode = kCheckedLoadFloat32; | 494 opcode = kCheckedLoadFloat32; |
| 497 break; | 495 break; |
| 498 case kRepFloat64: | 496 case MachineRepresentation::kFloat64: |
| 499 opcode = kCheckedLoadFloat64; | 497 opcode = kCheckedLoadFloat64; |
| 500 break; | 498 break; |
| 501 default: | 499 default: |
| 502 UNREACHABLE(); | 500 UNREACHABLE(); |
| 503 return; | 501 return; |
| 504 } | 502 } |
| 505 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer), | 503 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer), |
| 506 g.UseRegister(offset), g.UseOperand(length, kArithmeticImm)); | 504 g.UseRegister(offset), g.UseOperand(length, kArithmeticImm)); |
| 507 } | 505 } |
| 508 | 506 |
| 509 | 507 |
| 510 void InstructionSelector::VisitCheckedStore(Node* node) { | 508 void InstructionSelector::VisitCheckedStore(Node* node) { |
| 511 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 509 MachineRepresentation rep = |
| 510 CheckedStoreRepresentationOf(node->op()).representation(); |
| 512 Arm64OperandGenerator g(this); | 511 Arm64OperandGenerator g(this); |
| 513 Node* const buffer = node->InputAt(0); | 512 Node* const buffer = node->InputAt(0); |
| 514 Node* const offset = node->InputAt(1); | 513 Node* const offset = node->InputAt(1); |
| 515 Node* const length = node->InputAt(2); | 514 Node* const length = node->InputAt(2); |
| 516 Node* const value = node->InputAt(3); | 515 Node* const value = node->InputAt(3); |
| 517 ArchOpcode opcode; | 516 ArchOpcode opcode; |
| 518 switch (rep) { | 517 switch (rep) { |
| 519 case kRepWord8: | 518 case MachineRepresentation::kWord8: |
| 520 opcode = kCheckedStoreWord8; | 519 opcode = kCheckedStoreWord8; |
| 521 break; | 520 break; |
| 522 case kRepWord16: | 521 case MachineRepresentation::kWord16: |
| 523 opcode = kCheckedStoreWord16; | 522 opcode = kCheckedStoreWord16; |
| 524 break; | 523 break; |
| 525 case kRepWord32: | 524 case MachineRepresentation::kWord32: |
| 526 opcode = kCheckedStoreWord32; | 525 opcode = kCheckedStoreWord32; |
| 527 break; | 526 break; |
| 528 case kRepWord64: | 527 case MachineRepresentation::kWord64: |
| 529 opcode = kCheckedStoreWord64; | 528 opcode = kCheckedStoreWord64; |
| 530 break; | 529 break; |
| 531 case kRepFloat32: | 530 case MachineRepresentation::kFloat32: |
| 532 opcode = kCheckedStoreFloat32; | 531 opcode = kCheckedStoreFloat32; |
| 533 break; | 532 break; |
| 534 case kRepFloat64: | 533 case MachineRepresentation::kFloat64: |
| 535 opcode = kCheckedStoreFloat64; | 534 opcode = kCheckedStoreFloat64; |
| 536 break; | 535 break; |
| 537 default: | 536 default: |
| 538 UNREACHABLE(); | 537 UNREACHABLE(); |
| 539 return; | 538 return; |
| 540 } | 539 } |
| 541 Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset), | 540 Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset), |
| 542 g.UseOperand(length, kArithmeticImm), g.UseRegister(value)); | 541 g.UseOperand(length, kArithmeticImm), g.UseRegister(value)); |
| 543 } | 542 } |
| 544 | 543 |
| (...skipping 1601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2146 MachineOperatorBuilder::kFloat32RoundTiesEven | | 2145 MachineOperatorBuilder::kFloat32RoundTiesEven | |
| 2147 MachineOperatorBuilder::kFloat64RoundTiesEven | | 2146 MachineOperatorBuilder::kFloat64RoundTiesEven | |
| 2148 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2147 MachineOperatorBuilder::kWord32ShiftIsSafe | |
| 2149 MachineOperatorBuilder::kInt32DivIsSafe | | 2148 MachineOperatorBuilder::kInt32DivIsSafe | |
| 2150 MachineOperatorBuilder::kUint32DivIsSafe; | 2149 MachineOperatorBuilder::kUint32DivIsSafe; |
| 2151 } | 2150 } |
| 2152 | 2151 |
| 2153 } // namespace compiler | 2152 } // namespace compiler |
| 2154 } // namespace internal | 2153 } // namespace internal |
| 2155 } // namespace v8 | 2154 } // namespace v8 |
| OLD | NEW |