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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 154 |
155 | 155 |
156 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, | 156 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, |
157 ImmediateMode operand_mode) { | 157 ImmediateMode operand_mode) { |
158 Arm64OperandGenerator g(selector); | 158 Arm64OperandGenerator g(selector); |
159 selector->Emit(opcode, g.DefineAsRegister(node), | 159 selector->Emit(opcode, g.DefineAsRegister(node), |
160 g.UseRegister(node->InputAt(0)), | 160 g.UseRegister(node->InputAt(0)), |
161 g.UseOperand(node->InputAt(1), operand_mode)); | 161 g.UseOperand(node->InputAt(1), operand_mode)); |
162 } | 162 } |
163 | 163 |
164 | |
165 bool TryMatchAnyShift(InstructionSelector* selector, Node* node, | 164 bool TryMatchAnyShift(InstructionSelector* selector, Node* node, |
166 Node* input_node, InstructionCode* opcode, bool try_ror) { | 165 Node* input_node, InstructionCode* opcode, bool try_ror) { |
167 Arm64OperandGenerator g(selector); | 166 Arm64OperandGenerator g(selector); |
168 | 167 |
169 if (!selector->CanCover(node, input_node)) return false; | 168 if (!selector->CanCover(node, input_node)) return false; |
170 if (input_node->InputCount() != 2) return false; | 169 if (input_node->InputCount() != 2) return false; |
171 if (!g.IsIntegerConstant(input_node->InputAt(1))) return false; | 170 if (!g.IsIntegerConstant(input_node->InputAt(1))) return false; |
172 | 171 |
173 switch (input_node->opcode()) { | 172 switch (input_node->opcode()) { |
174 case IrOpcode::kWord32Shl: | 173 case IrOpcode::kWord32Shl: |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 uint64_t value_minus_one = m->right().Value() - 1; | 450 uint64_t value_minus_one = m->right().Value() - 1; |
452 if (base::bits::IsPowerOfTwo64(value_minus_one)) { | 451 if (base::bits::IsPowerOfTwo64(value_minus_one)) { |
453 return WhichPowerOf2_64(value_minus_one); | 452 return WhichPowerOf2_64(value_minus_one); |
454 } | 453 } |
455 } | 454 } |
456 return 0; | 455 return 0; |
457 } | 456 } |
458 | 457 |
459 } // namespace | 458 } // namespace |
460 | 459 |
461 | 460 void EmitLoad(InstructionSelector* selector, Node* node, InstructionCode opcode, |
462 void InstructionSelector::VisitLoad(Node* node) { | 461 ImmediateMode immediate_mode, MachineRepresentation rep, |
463 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | 462 Node* output = nullptr) { |
464 MachineRepresentation rep = load_rep.representation(); | 463 Arm64OperandGenerator g(selector); |
465 Arm64OperandGenerator g(this); | |
466 Node* base = node->InputAt(0); | 464 Node* base = node->InputAt(0); |
467 Node* index = node->InputAt(1); | 465 Node* index = node->InputAt(1); |
468 InstructionCode opcode = kArchNop; | |
469 ImmediateMode immediate_mode = kNoImmediate; | |
470 InstructionOperand inputs[3]; | 466 InstructionOperand inputs[3]; |
471 size_t input_count = 0; | 467 size_t input_count = 0; |
472 InstructionOperand outputs[1]; | 468 InstructionOperand outputs[1]; |
| 469 |
| 470 // If output is not nullptr, use that as the output register. This |
| 471 // is used when we merge a conversion into the load. |
| 472 outputs[0] = g.DefineAsRegister(output == nullptr ? node : output); |
| 473 inputs[0] = g.UseRegister(base); |
| 474 |
| 475 if (g.CanBeImmediate(index, immediate_mode)) { |
| 476 input_count = 2; |
| 477 inputs[1] = g.UseImmediate(index); |
| 478 opcode |= AddressingModeField::encode(kMode_MRI); |
| 479 } else if (TryMatchLoadStoreShift(&g, selector, rep, node, index, &inputs[1], |
| 480 &inputs[2])) { |
| 481 input_count = 3; |
| 482 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I); |
| 483 } else { |
| 484 input_count = 2; |
| 485 inputs[1] = g.UseRegister(index); |
| 486 opcode |= AddressingModeField::encode(kMode_MRR); |
| 487 } |
| 488 |
| 489 selector->Emit(opcode, arraysize(outputs), outputs, input_count, inputs); |
| 490 } |
| 491 |
| 492 void InstructionSelector::VisitLoad(Node* node) { |
| 493 InstructionCode opcode = kArchNop; |
| 494 ImmediateMode immediate_mode = kNoImmediate; |
| 495 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 496 MachineRepresentation rep = load_rep.representation(); |
473 switch (rep) { | 497 switch (rep) { |
474 case MachineRepresentation::kFloat32: | 498 case MachineRepresentation::kFloat32: |
475 opcode = kArm64LdrS; | 499 opcode = kArm64LdrS; |
476 immediate_mode = kLoadStoreImm32; | 500 immediate_mode = kLoadStoreImm32; |
477 break; | 501 break; |
478 case MachineRepresentation::kFloat64: | 502 case MachineRepresentation::kFloat64: |
479 opcode = kArm64LdrD; | 503 opcode = kArm64LdrD; |
480 immediate_mode = kLoadStoreImm64; | 504 immediate_mode = kLoadStoreImm64; |
481 break; | 505 break; |
482 case MachineRepresentation::kBit: // Fall through. | 506 case MachineRepresentation::kBit: // Fall through. |
(...skipping 12 matching lines...) Expand all Loading... |
495 case MachineRepresentation::kTagged: // Fall through. | 519 case MachineRepresentation::kTagged: // Fall through. |
496 case MachineRepresentation::kWord64: | 520 case MachineRepresentation::kWord64: |
497 opcode = kArm64Ldr; | 521 opcode = kArm64Ldr; |
498 immediate_mode = kLoadStoreImm64; | 522 immediate_mode = kLoadStoreImm64; |
499 break; | 523 break; |
500 case MachineRepresentation::kSimd128: // Fall through. | 524 case MachineRepresentation::kSimd128: // Fall through. |
501 case MachineRepresentation::kNone: | 525 case MachineRepresentation::kNone: |
502 UNREACHABLE(); | 526 UNREACHABLE(); |
503 return; | 527 return; |
504 } | 528 } |
505 | 529 EmitLoad(this, node, opcode, immediate_mode, rep); |
506 outputs[0] = g.DefineAsRegister(node); | |
507 inputs[0] = g.UseRegister(base); | |
508 | |
509 if (g.CanBeImmediate(index, immediate_mode)) { | |
510 input_count = 2; | |
511 inputs[1] = g.UseImmediate(index); | |
512 opcode |= AddressingModeField::encode(kMode_MRI); | |
513 } else if (TryMatchLoadStoreShift(&g, this, rep, node, index, &inputs[1], | |
514 &inputs[2])) { | |
515 input_count = 3; | |
516 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I); | |
517 } else { | |
518 input_count = 2; | |
519 inputs[1] = g.UseRegister(index); | |
520 opcode |= AddressingModeField::encode(kMode_MRR); | |
521 } | |
522 | |
523 Emit(opcode, arraysize(outputs), outputs, input_count, inputs); | |
524 } | 530 } |
525 | 531 |
526 | 532 |
527 void InstructionSelector::VisitStore(Node* node) { | 533 void InstructionSelector::VisitStore(Node* node) { |
528 Arm64OperandGenerator g(this); | 534 Arm64OperandGenerator g(this); |
529 Node* base = node->InputAt(0); | 535 Node* base = node->InputAt(0); |
530 Node* index = node->InputAt(1); | 536 Node* index = node->InputAt(1); |
531 Node* value = node->InputAt(2); | 537 Node* value = node->InputAt(2); |
532 | 538 |
533 StoreRepresentation store_rep = StoreRepresentationOf(node->op()); | 539 StoreRepresentation store_rep = StoreRepresentationOf(node->op()); |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 } | 958 } |
953 } | 959 } |
954 VisitRRO(this, kArm64Lsl32, node, kShift32Imm); | 960 VisitRRO(this, kArm64Lsl32, node, kShift32Imm); |
955 } | 961 } |
956 | 962 |
957 | 963 |
958 void InstructionSelector::VisitWord64Shl(Node* node) { | 964 void InstructionSelector::VisitWord64Shl(Node* node) { |
959 Arm64OperandGenerator g(this); | 965 Arm64OperandGenerator g(this); |
960 Int64BinopMatcher m(node); | 966 Int64BinopMatcher m(node); |
961 if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) && | 967 if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) && |
962 m.right().IsInRange(32, 63)) { | 968 m.right().IsInRange(32, 63) && CanCover(node, m.left().node())) { |
963 // There's no need to sign/zero-extend to 64-bit if we shift out the upper | 969 // There's no need to sign/zero-extend to 64-bit if we shift out the upper |
964 // 32 bits anyway. | 970 // 32 bits anyway. |
965 Emit(kArm64Lsl, g.DefineAsRegister(node), | 971 Emit(kArm64Lsl, g.DefineAsRegister(node), |
966 g.UseRegister(m.left().node()->InputAt(0)), | 972 g.UseRegister(m.left().node()->InputAt(0)), |
967 g.UseImmediate(m.right().node())); | 973 g.UseImmediate(m.right().node())); |
968 return; | 974 return; |
969 } | 975 } |
970 VisitRRO(this, kArm64Lsl, node, kShift64Imm); | 976 VisitRRO(this, kArm64Lsl, node, kShift64Imm); |
971 } | 977 } |
972 | 978 |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1556 Node* success_output = NodeProperties::FindProjection(node, 1); | 1562 Node* success_output = NodeProperties::FindProjection(node, 1); |
1557 if (success_output) { | 1563 if (success_output) { |
1558 outputs[output_count++] = g.DefineAsRegister(success_output); | 1564 outputs[output_count++] = g.DefineAsRegister(success_output); |
1559 } | 1565 } |
1560 | 1566 |
1561 Emit(kArm64Float64ToUint64, output_count, outputs, 1, inputs); | 1567 Emit(kArm64Float64ToUint64, output_count, outputs, 1, inputs); |
1562 } | 1568 } |
1563 | 1569 |
1564 | 1570 |
1565 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { | 1571 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
1566 VisitRR(this, kArm64Sxtw, node); | 1572 Node* value = node->InputAt(0); |
| 1573 if (value->opcode() == IrOpcode::kLoad && CanCover(node, value)) { |
| 1574 // Generate sign-extending load. |
| 1575 LoadRepresentation load_rep = LoadRepresentationOf(value->op()); |
| 1576 MachineRepresentation rep = load_rep.representation(); |
| 1577 InstructionCode opcode = kArchNop; |
| 1578 ImmediateMode immediate_mode = kNoImmediate; |
| 1579 switch (rep) { |
| 1580 case MachineRepresentation::kBit: // Fall through. |
| 1581 case MachineRepresentation::kWord8: |
| 1582 opcode = load_rep.IsSigned() ? kArm64Ldrsb : kArm64Ldrb; |
| 1583 immediate_mode = kLoadStoreImm8; |
| 1584 break; |
| 1585 case MachineRepresentation::kWord16: |
| 1586 opcode = load_rep.IsSigned() ? kArm64Ldrsh : kArm64Ldrh; |
| 1587 immediate_mode = kLoadStoreImm16; |
| 1588 break; |
| 1589 case MachineRepresentation::kWord32: |
| 1590 opcode = kArm64Ldrsw; |
| 1591 immediate_mode = kLoadStoreImm32; |
| 1592 break; |
| 1593 default: |
| 1594 UNREACHABLE(); |
| 1595 return; |
| 1596 } |
| 1597 EmitLoad(this, value, opcode, immediate_mode, rep, node); |
| 1598 } else { |
| 1599 VisitRR(this, kArm64Sxtw, node); |
| 1600 } |
1567 } | 1601 } |
1568 | 1602 |
1569 | 1603 |
1570 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { | 1604 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { |
1571 Arm64OperandGenerator g(this); | 1605 Arm64OperandGenerator g(this); |
1572 Node* value = node->InputAt(0); | 1606 Node* value = node->InputAt(0); |
1573 switch (value->opcode()) { | 1607 switch (value->opcode()) { |
1574 case IrOpcode::kWord32And: | 1608 case IrOpcode::kWord32And: |
1575 case IrOpcode::kWord32Or: | 1609 case IrOpcode::kWord32Or: |
1576 case IrOpcode::kWord32Xor: | 1610 case IrOpcode::kWord32Xor: |
(...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2717 // static | 2751 // static |
2718 MachineOperatorBuilder::AlignmentRequirements | 2752 MachineOperatorBuilder::AlignmentRequirements |
2719 InstructionSelector::AlignmentRequirements() { | 2753 InstructionSelector::AlignmentRequirements() { |
2720 return MachineOperatorBuilder::AlignmentRequirements:: | 2754 return MachineOperatorBuilder::AlignmentRequirements:: |
2721 FullUnalignedAccessSupport(); | 2755 FullUnalignedAccessSupport(); |
2722 } | 2756 } |
2723 | 2757 |
2724 } // namespace compiler | 2758 } // namespace compiler |
2725 } // namespace internal | 2759 } // namespace internal |
2726 } // namespace v8 | 2760 } // namespace v8 |
OLD | NEW |