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 <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "src/base/adapters.h" | 7 #include "src/base/adapters.h" |
8 #include "src/compiler/instruction-selector-impl.h" | 8 #include "src/compiler/instruction-selector-impl.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 } | 30 } |
31 case IrOpcode::kNumberConstant: { | 31 case IrOpcode::kNumberConstant: { |
32 const double value = OpParameter<double>(node); | 32 const double value = OpParameter<double>(node); |
33 return bit_cast<int64_t>(value) == 0; | 33 return bit_cast<int64_t>(value) == 0; |
34 } | 34 } |
35 default: | 35 default: |
36 return false; | 36 return false; |
37 } | 37 } |
38 } | 38 } |
39 | 39 |
| 40 int32_t GetImmediateIntegerValue(Node* node) { |
| 41 DCHECK(CanBeImmediate(node)); |
| 42 if (node->opcode() == IrOpcode::kInt32Constant) { |
| 43 return OpParameter<int32_t>(node); |
| 44 } |
| 45 DCHECK_EQ(IrOpcode::kInt64Constant, node->opcode()); |
| 46 return static_cast<int32_t>(OpParameter<int64_t>(node)); |
| 47 } |
| 48 |
40 bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input, | 49 bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input, |
41 int effect_level) { | 50 int effect_level) { |
42 if (input->opcode() != IrOpcode::kLoad || | 51 if (input->opcode() != IrOpcode::kLoad || |
43 !selector()->CanCover(node, input)) { | 52 !selector()->CanCover(node, input)) { |
44 return false; | 53 return false; |
45 } | 54 } |
46 if (effect_level != selector()->GetEffectLevel(input)) { | 55 if (effect_level != selector()->GetEffectLevel(input)) { |
47 return false; | 56 return false; |
48 } | 57 } |
49 MachineRepresentation rep = | 58 MachineRepresentation rep = |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 } | 633 } |
625 } | 634 } |
626 VisitWord64Shift(this, node, kX64Shl); | 635 VisitWord64Shift(this, node, kX64Shl); |
627 } | 636 } |
628 | 637 |
629 | 638 |
630 void InstructionSelector::VisitWord32Shr(Node* node) { | 639 void InstructionSelector::VisitWord32Shr(Node* node) { |
631 VisitWord32Shift(this, node, kX64Shr32); | 640 VisitWord32Shift(this, node, kX64Shr32); |
632 } | 641 } |
633 | 642 |
634 | 643 namespace { |
635 void InstructionSelector::VisitWord64Shr(Node* node) { | 644 bool TryMatchLoadWord64AndShiftRight(InstructionSelector* selector, Node* node, |
636 VisitWord64Shift(this, node, kX64Shr); | 645 InstructionCode opcode) { |
637 } | 646 DCHECK(IrOpcode::kWord64Sar == node->opcode() || |
638 | 647 IrOpcode::kWord64Shr == node->opcode()); |
639 | 648 X64OperandGenerator g(selector); |
640 void InstructionSelector::VisitWord32Sar(Node* node) { | |
641 X64OperandGenerator g(this); | |
642 Int32BinopMatcher m(node); | |
643 if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) { | |
644 Int32BinopMatcher mleft(m.left().node()); | |
645 if (mleft.right().Is(16) && m.right().Is(16)) { | |
646 Emit(kX64Movsxwl, g.DefineAsRegister(node), g.Use(mleft.left().node())); | |
647 return; | |
648 } else if (mleft.right().Is(24) && m.right().Is(24)) { | |
649 Emit(kX64Movsxbl, g.DefineAsRegister(node), g.Use(mleft.left().node())); | |
650 return; | |
651 } | |
652 } | |
653 VisitWord32Shift(this, node, kX64Sar32); | |
654 } | |
655 | |
656 | |
657 void InstructionSelector::VisitWord64Sar(Node* node) { | |
658 X64OperandGenerator g(this); | |
659 Int64BinopMatcher m(node); | 649 Int64BinopMatcher m(node); |
660 if (CanCover(m.node(), m.left().node()) && m.left().IsLoad() && | 650 if (selector->CanCover(m.node(), m.left().node()) && m.left().IsLoad() && |
661 m.right().Is(32)) { | 651 m.right().Is(32)) { |
662 // Just load and sign-extend the interesting 4 bytes instead. This happens, | 652 // Just load and sign-extend the interesting 4 bytes instead. This happens, |
663 // for example, when we're loading and untagging SMIs. | 653 // for example, when we're loading and untagging SMIs. |
664 BaseWithIndexAndDisplacement64Matcher mleft(m.left().node(), | 654 BaseWithIndexAndDisplacement64Matcher mleft(m.left().node(), |
665 AddressOption::kAllowAll); | 655 AddressOption::kAllowAll); |
666 if (mleft.matches() && (mleft.displacement() == nullptr || | 656 if (mleft.matches() && (mleft.displacement() == nullptr || |
667 g.CanBeImmediate(mleft.displacement()))) { | 657 g.CanBeImmediate(mleft.displacement()))) { |
668 size_t input_count = 0; | 658 size_t input_count = 0; |
669 InstructionOperand inputs[3]; | 659 InstructionOperand inputs[3]; |
670 AddressingMode mode = g.GetEffectiveAddressMemoryOperand( | 660 AddressingMode mode = g.GetEffectiveAddressMemoryOperand( |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 case kMode_MR4I: | 698 case kMode_MR4I: |
709 case kMode_MR8I: | 699 case kMode_MR8I: |
710 case kMode_M1I: | 700 case kMode_M1I: |
711 case kMode_M2I: | 701 case kMode_M2I: |
712 case kMode_M4I: | 702 case kMode_M4I: |
713 case kMode_M8I: | 703 case kMode_M8I: |
714 UNREACHABLE(); | 704 UNREACHABLE(); |
715 } | 705 } |
716 inputs[input_count++] = ImmediateOperand(ImmediateOperand::INLINE, 4); | 706 inputs[input_count++] = ImmediateOperand(ImmediateOperand::INLINE, 4); |
717 } else { | 707 } else { |
718 ImmediateOperand* op = ImmediateOperand::cast(&inputs[input_count - 1]); | 708 int32_t displacement = g.GetImmediateIntegerValue(mleft.displacement()); |
719 int32_t displacement = sequence()->GetImmediate(op).ToInt32(); | 709 inputs[input_count - 1] = |
720 *op = ImmediateOperand(ImmediateOperand::INLINE, displacement + 4); | 710 ImmediateOperand(ImmediateOperand::INLINE, displacement + 4); |
721 } | 711 } |
722 InstructionOperand outputs[] = {g.DefineAsRegister(node)}; | 712 InstructionOperand outputs[] = {g.DefineAsRegister(node)}; |
723 InstructionCode code = kX64Movsxlq | AddressingModeField::encode(mode); | 713 InstructionCode code = opcode | AddressingModeField::encode(mode); |
724 Emit(code, 1, outputs, input_count, inputs); | 714 selector->Emit(code, 1, outputs, input_count, inputs); |
| 715 return true; |
| 716 } |
| 717 } |
| 718 return false; |
| 719 } |
| 720 } // namespace |
| 721 |
| 722 void InstructionSelector::VisitWord64Shr(Node* node) { |
| 723 if (TryMatchLoadWord64AndShiftRight(this, node, kX64Movl)) return; |
| 724 VisitWord64Shift(this, node, kX64Shr); |
| 725 } |
| 726 |
| 727 void InstructionSelector::VisitWord32Sar(Node* node) { |
| 728 X64OperandGenerator g(this); |
| 729 Int32BinopMatcher m(node); |
| 730 if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) { |
| 731 Int32BinopMatcher mleft(m.left().node()); |
| 732 if (mleft.right().Is(16) && m.right().Is(16)) { |
| 733 Emit(kX64Movsxwl, g.DefineAsRegister(node), g.Use(mleft.left().node())); |
| 734 return; |
| 735 } else if (mleft.right().Is(24) && m.right().Is(24)) { |
| 736 Emit(kX64Movsxbl, g.DefineAsRegister(node), g.Use(mleft.left().node())); |
725 return; | 737 return; |
726 } | 738 } |
727 } | 739 } |
| 740 VisitWord32Shift(this, node, kX64Sar32); |
| 741 } |
| 742 |
| 743 void InstructionSelector::VisitWord64Sar(Node* node) { |
| 744 if (TryMatchLoadWord64AndShiftRight(this, node, kX64Movsxlq)) return; |
728 VisitWord64Shift(this, node, kX64Sar); | 745 VisitWord64Shift(this, node, kX64Sar); |
729 } | 746 } |
730 | 747 |
731 | 748 |
732 void InstructionSelector::VisitWord32Ror(Node* node) { | 749 void InstructionSelector::VisitWord32Ror(Node* node) { |
733 VisitWord32Shift(this, node, kX64Ror32); | 750 VisitWord32Shift(this, node, kX64Ror32); |
734 } | 751 } |
735 | 752 |
736 | 753 |
737 void InstructionSelector::VisitWord64Ror(Node* node) { | 754 void InstructionSelector::VisitWord64Ror(Node* node) { |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1251 | 1268 |
1252 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { | 1269 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { |
1253 X64OperandGenerator g(this); | 1270 X64OperandGenerator g(this); |
1254 Node* value = node->InputAt(0); | 1271 Node* value = node->InputAt(0); |
1255 if (CanCover(node, value)) { | 1272 if (CanCover(node, value)) { |
1256 switch (value->opcode()) { | 1273 switch (value->opcode()) { |
1257 case IrOpcode::kWord64Sar: | 1274 case IrOpcode::kWord64Sar: |
1258 case IrOpcode::kWord64Shr: { | 1275 case IrOpcode::kWord64Shr: { |
1259 Int64BinopMatcher m(value); | 1276 Int64BinopMatcher m(value); |
1260 if (m.right().Is(32)) { | 1277 if (m.right().Is(32)) { |
| 1278 if (TryMatchLoadWord64AndShiftRight(this, value, kX64Movl)) { |
| 1279 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); |
| 1280 return; |
| 1281 } |
1261 Emit(kX64Shr, g.DefineSameAsFirst(node), | 1282 Emit(kX64Shr, g.DefineSameAsFirst(node), |
1262 g.UseRegister(m.left().node()), g.TempImmediate(32)); | 1283 g.UseRegister(m.left().node()), g.TempImmediate(32)); |
1263 return; | 1284 return; |
1264 } | 1285 } |
1265 break; | 1286 break; |
1266 } | 1287 } |
1267 default: | 1288 default: |
1268 break; | 1289 break; |
1269 } | 1290 } |
1270 } | 1291 } |
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2211 // static | 2232 // static |
2212 MachineOperatorBuilder::AlignmentRequirements | 2233 MachineOperatorBuilder::AlignmentRequirements |
2213 InstructionSelector::AlignmentRequirements() { | 2234 InstructionSelector::AlignmentRequirements() { |
2214 return MachineOperatorBuilder::AlignmentRequirements:: | 2235 return MachineOperatorBuilder::AlignmentRequirements:: |
2215 FullUnalignedAccessSupport(); | 2236 FullUnalignedAccessSupport(); |
2216 } | 2237 } |
2217 | 2238 |
2218 } // namespace compiler | 2239 } // namespace compiler |
2219 } // namespace internal | 2240 } // namespace internal |
2220 } // namespace v8 | 2241 } // namespace v8 |
OLD | NEW |