Chromium Code Reviews| 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 static bool TryMatchLoadWord64AndShiftRight(InstructionSelector* selector, |
|
Jarin
2016/08/18 10:38:16
anonymous namespace?
epertoso
2016/08/18 10:51:11
Done.
| |
| 635 void InstructionSelector::VisitWord64Shr(Node* node) { | 644 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 | |
| 721 void InstructionSelector::VisitWord64Shr(Node* node) { | |
| 722 if (TryMatchLoadWord64AndShiftRight(this, node, kX64Movl)) return; | |
| 723 VisitWord64Shift(this, node, kX64Shr); | |
| 724 } | |
| 725 | |
| 726 void InstructionSelector::VisitWord32Sar(Node* node) { | |
| 727 X64OperandGenerator g(this); | |
| 728 Int32BinopMatcher m(node); | |
| 729 if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) { | |
| 730 Int32BinopMatcher mleft(m.left().node()); | |
| 731 if (mleft.right().Is(16) && m.right().Is(16)) { | |
| 732 Emit(kX64Movsxwl, g.DefineAsRegister(node), g.Use(mleft.left().node())); | |
| 733 return; | |
| 734 } else if (mleft.right().Is(24) && m.right().Is(24)) { | |
| 735 Emit(kX64Movsxbl, g.DefineAsRegister(node), g.Use(mleft.left().node())); | |
| 725 return; | 736 return; |
| 726 } | 737 } |
| 727 } | 738 } |
| 739 VisitWord32Shift(this, node, kX64Sar32); | |
| 740 } | |
| 741 | |
| 742 void InstructionSelector::VisitWord64Sar(Node* node) { | |
| 743 if (TryMatchLoadWord64AndShiftRight(this, node, kX64Movsxlq)) return; | |
| 728 VisitWord64Shift(this, node, kX64Sar); | 744 VisitWord64Shift(this, node, kX64Sar); |
| 729 } | 745 } |
| 730 | 746 |
| 731 | 747 |
| 732 void InstructionSelector::VisitWord32Ror(Node* node) { | 748 void InstructionSelector::VisitWord32Ror(Node* node) { |
| 733 VisitWord32Shift(this, node, kX64Ror32); | 749 VisitWord32Shift(this, node, kX64Ror32); |
| 734 } | 750 } |
| 735 | 751 |
| 736 | 752 |
| 737 void InstructionSelector::VisitWord64Ror(Node* node) { | 753 void InstructionSelector::VisitWord64Ror(Node* node) { |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1251 | 1267 |
| 1252 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { | 1268 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { |
| 1253 X64OperandGenerator g(this); | 1269 X64OperandGenerator g(this); |
| 1254 Node* value = node->InputAt(0); | 1270 Node* value = node->InputAt(0); |
| 1255 if (CanCover(node, value)) { | 1271 if (CanCover(node, value)) { |
| 1256 switch (value->opcode()) { | 1272 switch (value->opcode()) { |
| 1257 case IrOpcode::kWord64Sar: | 1273 case IrOpcode::kWord64Sar: |
| 1258 case IrOpcode::kWord64Shr: { | 1274 case IrOpcode::kWord64Shr: { |
| 1259 Int64BinopMatcher m(value); | 1275 Int64BinopMatcher m(value); |
| 1260 if (m.right().Is(32)) { | 1276 if (m.right().Is(32)) { |
| 1277 if (TryMatchLoadWord64AndShiftRight(this, value, kX64Movl)) { | |
| 1278 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); | |
| 1279 return; | |
| 1280 } | |
| 1261 Emit(kX64Shr, g.DefineSameAsFirst(node), | 1281 Emit(kX64Shr, g.DefineSameAsFirst(node), |
| 1262 g.UseRegister(m.left().node()), g.TempImmediate(32)); | 1282 g.UseRegister(m.left().node()), g.TempImmediate(32)); |
| 1263 return; | 1283 return; |
| 1264 } | 1284 } |
| 1265 break; | 1285 break; |
| 1266 } | 1286 } |
| 1267 default: | 1287 default: |
| 1268 break; | 1288 break; |
| 1269 } | 1289 } |
| 1270 } | 1290 } |
| (...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2211 // static | 2231 // static |
| 2212 MachineOperatorBuilder::AlignmentRequirements | 2232 MachineOperatorBuilder::AlignmentRequirements |
| 2213 InstructionSelector::AlignmentRequirements() { | 2233 InstructionSelector::AlignmentRequirements() { |
| 2214 return MachineOperatorBuilder::AlignmentRequirements:: | 2234 return MachineOperatorBuilder::AlignmentRequirements:: |
| 2215 FullUnalignedAccessSupport(); | 2235 FullUnalignedAccessSupport(); |
| 2216 } | 2236 } |
| 2217 | 2237 |
| 2218 } // namespace compiler | 2238 } // namespace compiler |
| 2219 } // namespace internal | 2239 } // namespace internal |
| 2220 } // namespace v8 | 2240 } // namespace v8 |
| OLD | NEW |