| 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/base/bits.h" | 5 #include "src/base/bits.h" |
| 6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 private: | 113 private: |
| 114 bool ImmediateFitsAddrMode1Instruction(int32_t imm) const { | 114 bool ImmediateFitsAddrMode1Instruction(int32_t imm) const { |
| 115 return Assembler::ImmediateFitsAddrMode1Instruction(imm); | 115 return Assembler::ImmediateFitsAddrMode1Instruction(imm); |
| 116 } | 116 } |
| 117 }; | 117 }; |
| 118 | 118 |
| 119 | 119 |
| 120 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 120 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, |
| 121 Node* node) { | 121 Node* node) { |
| 122 ArmOperandGenerator g(selector); | 122 ArmOperandGenerator g(selector); |
| 123 selector->Emit(opcode, g.DefineAsDoubleRegister(node), | 123 selector->Emit(opcode, g.DefineAsRegister(node), |
| 124 g.UseDoubleRegister(node->InputAt(0)), | 124 g.UseRegister(node->InputAt(0)), |
| 125 g.UseDoubleRegister(node->InputAt(1))); | 125 g.UseRegister(node->InputAt(1))); |
| 126 } | 126 } |
| 127 | 127 |
| 128 | 128 |
| 129 static bool TryMatchROR(InstructionSelector* selector, | 129 static bool TryMatchROR(InstructionSelector* selector, |
| 130 InstructionCode* opcode_return, Node* node, | 130 InstructionCode* opcode_return, Node* node, |
| 131 InstructionOperand** value_return, | 131 InstructionOperand** value_return, |
| 132 InstructionOperand** shift_return) { | 132 InstructionOperand** shift_return) { |
| 133 ArmOperandGenerator g(selector); | 133 ArmOperandGenerator g(selector); |
| 134 if (node->opcode() != IrOpcode::kWord32Ror) return false; | 134 if (node->opcode() != IrOpcode::kWord32Ror) return false; |
| 135 Int32BinopMatcher m(node); | 135 Int32BinopMatcher m(node); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 } | 289 } |
| 290 | 290 |
| 291 | 291 |
| 292 void InstructionSelector::VisitLoad(Node* node) { | 292 void InstructionSelector::VisitLoad(Node* node) { |
| 293 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 293 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
| 294 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 294 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
| 295 ArmOperandGenerator g(this); | 295 ArmOperandGenerator g(this); |
| 296 Node* base = node->InputAt(0); | 296 Node* base = node->InputAt(0); |
| 297 Node* index = node->InputAt(1); | 297 Node* index = node->InputAt(1); |
| 298 | 298 |
| 299 InstructionOperand* result = (rep == kRepFloat32 || rep == kRepFloat64) | |
| 300 ? g.DefineAsDoubleRegister(node) | |
| 301 : g.DefineAsRegister(node); | |
| 302 | |
| 303 ArchOpcode opcode; | 299 ArchOpcode opcode; |
| 304 switch (rep) { | 300 switch (rep) { |
| 305 case kRepFloat32: | 301 case kRepFloat32: |
| 306 opcode = kArmVldr32; | 302 opcode = kArmVldr32; |
| 307 break; | 303 break; |
| 308 case kRepFloat64: | 304 case kRepFloat64: |
| 309 opcode = kArmVldr64; | 305 opcode = kArmVldr64; |
| 310 break; | 306 break; |
| 311 case kRepBit: // Fall through. | 307 case kRepBit: // Fall through. |
| 312 case kRepWord8: | 308 case kRepWord8: |
| 313 opcode = typ == kTypeUint32 ? kArmLdrb : kArmLdrsb; | 309 opcode = typ == kTypeUint32 ? kArmLdrb : kArmLdrsb; |
| 314 break; | 310 break; |
| 315 case kRepWord16: | 311 case kRepWord16: |
| 316 opcode = typ == kTypeUint32 ? kArmLdrh : kArmLdrsh; | 312 opcode = typ == kTypeUint32 ? kArmLdrh : kArmLdrsh; |
| 317 break; | 313 break; |
| 318 case kRepTagged: // Fall through. | 314 case kRepTagged: // Fall through. |
| 319 case kRepWord32: | 315 case kRepWord32: |
| 320 opcode = kArmLdr; | 316 opcode = kArmLdr; |
| 321 break; | 317 break; |
| 322 default: | 318 default: |
| 323 UNREACHABLE(); | 319 UNREACHABLE(); |
| 324 return; | 320 return; |
| 325 } | 321 } |
| 326 | 322 |
| 327 if (g.CanBeImmediate(index, opcode)) { | 323 if (g.CanBeImmediate(index, opcode)) { |
| 328 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), result, | 324 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), |
| 329 g.UseRegister(base), g.UseImmediate(index)); | 325 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
| 330 } else { | 326 } else { |
| 331 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), result, | 327 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), |
| 332 g.UseRegister(base), g.UseRegister(index)); | 328 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); |
| 333 } | 329 } |
| 334 } | 330 } |
| 335 | 331 |
| 336 | 332 |
| 337 void InstructionSelector::VisitStore(Node* node) { | 333 void InstructionSelector::VisitStore(Node* node) { |
| 338 ArmOperandGenerator g(this); | 334 ArmOperandGenerator g(this); |
| 339 Node* base = node->InputAt(0); | 335 Node* base = node->InputAt(0); |
| 340 Node* index = node->InputAt(1); | 336 Node* index = node->InputAt(1); |
| 341 Node* value = node->InputAt(2); | 337 Node* value = node->InputAt(2); |
| 342 | 338 |
| 343 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 339 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
| 344 MachineType rep = RepresentationOf(store_rep.machine_type); | 340 MachineType rep = RepresentationOf(store_rep.machine_type); |
| 345 if (store_rep.write_barrier_kind == kFullWriteBarrier) { | 341 if (store_rep.write_barrier_kind == kFullWriteBarrier) { |
| 346 DCHECK(rep == kRepTagged); | 342 DCHECK(rep == kRepTagged); |
| 347 // TODO(dcarney): refactor RecordWrite function to take temp registers | 343 // TODO(dcarney): refactor RecordWrite function to take temp registers |
| 348 // and pass them here instead of using fixed regs | 344 // and pass them here instead of using fixed regs |
| 349 // TODO(dcarney): handle immediate indices. | 345 // TODO(dcarney): handle immediate indices. |
| 350 InstructionOperand* temps[] = {g.TempRegister(r5), g.TempRegister(r6)}; | 346 InstructionOperand* temps[] = {g.TempRegister(r5), g.TempRegister(r6)}; |
| 351 Emit(kArmStoreWriteBarrier, NULL, g.UseFixed(base, r4), | 347 Emit(kArmStoreWriteBarrier, NULL, g.UseFixed(base, r4), |
| 352 g.UseFixed(index, r5), g.UseFixed(value, r6), ARRAY_SIZE(temps), | 348 g.UseFixed(index, r5), g.UseFixed(value, r6), ARRAY_SIZE(temps), |
| 353 temps); | 349 temps); |
| 354 return; | 350 return; |
| 355 } | 351 } |
| 356 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind); | 352 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind); |
| 357 InstructionOperand* val = (rep == kRepFloat32 || rep == kRepFloat64) | |
| 358 ? g.UseDoubleRegister(value) | |
| 359 : g.UseRegister(value); | |
| 360 | 353 |
| 361 ArchOpcode opcode; | 354 ArchOpcode opcode; |
| 362 switch (rep) { | 355 switch (rep) { |
| 363 case kRepFloat32: | 356 case kRepFloat32: |
| 364 opcode = kArmVstr32; | 357 opcode = kArmVstr32; |
| 365 break; | 358 break; |
| 366 case kRepFloat64: | 359 case kRepFloat64: |
| 367 opcode = kArmVstr64; | 360 opcode = kArmVstr64; |
| 368 break; | 361 break; |
| 369 case kRepBit: // Fall through. | 362 case kRepBit: // Fall through. |
| 370 case kRepWord8: | 363 case kRepWord8: |
| 371 opcode = kArmStrb; | 364 opcode = kArmStrb; |
| 372 break; | 365 break; |
| 373 case kRepWord16: | 366 case kRepWord16: |
| 374 opcode = kArmStrh; | 367 opcode = kArmStrh; |
| 375 break; | 368 break; |
| 376 case kRepTagged: // Fall through. | 369 case kRepTagged: // Fall through. |
| 377 case kRepWord32: | 370 case kRepWord32: |
| 378 opcode = kArmStr; | 371 opcode = kArmStr; |
| 379 break; | 372 break; |
| 380 default: | 373 default: |
| 381 UNREACHABLE(); | 374 UNREACHABLE(); |
| 382 return; | 375 return; |
| 383 } | 376 } |
| 384 | 377 |
| 385 if (g.CanBeImmediate(index, opcode)) { | 378 if (g.CanBeImmediate(index, opcode)) { |
| 386 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL, | 379 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL, |
| 387 g.UseRegister(base), g.UseImmediate(index), val); | 380 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
| 388 } else { | 381 } else { |
| 389 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL, | 382 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL, |
| 390 g.UseRegister(base), g.UseRegister(index), val); | 383 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); |
| 391 } | 384 } |
| 392 } | 385 } |
| 393 | 386 |
| 394 | 387 |
| 395 static inline void EmitBic(InstructionSelector* selector, Node* node, | 388 static inline void EmitBic(InstructionSelector* selector, Node* node, |
| 396 Node* left, Node* right) { | 389 Node* left, Node* right) { |
| 397 ArmOperandGenerator g(selector); | 390 ArmOperandGenerator g(selector); |
| 398 InstructionCode opcode = kArmBic; | 391 InstructionCode opcode = kArmBic; |
| 399 InstructionOperand* value_operand; | 392 InstructionOperand* value_operand; |
| 400 InstructionOperand* shift_operand; | 393 InstructionOperand* shift_operand; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 } | 686 } |
| 694 | 687 |
| 695 | 688 |
| 696 void InstructionSelector::VisitInt32UMod(Node* node) { | 689 void InstructionSelector::VisitInt32UMod(Node* node) { |
| 697 VisitMod(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64); | 690 VisitMod(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64); |
| 698 } | 691 } |
| 699 | 692 |
| 700 | 693 |
| 701 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { | 694 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { |
| 702 ArmOperandGenerator g(this); | 695 ArmOperandGenerator g(this); |
| 703 Emit(kArmVcvtF64S32, g.DefineAsDoubleRegister(node), | 696 Emit(kArmVcvtF64S32, g.DefineAsRegister(node), |
| 704 g.UseRegister(node->InputAt(0))); | 697 g.UseRegister(node->InputAt(0))); |
| 705 } | 698 } |
| 706 | 699 |
| 707 | 700 |
| 708 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { | 701 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { |
| 709 ArmOperandGenerator g(this); | 702 ArmOperandGenerator g(this); |
| 710 Emit(kArmVcvtF64U32, g.DefineAsDoubleRegister(node), | 703 Emit(kArmVcvtF64U32, g.DefineAsRegister(node), |
| 711 g.UseRegister(node->InputAt(0))); | 704 g.UseRegister(node->InputAt(0))); |
| 712 } | 705 } |
| 713 | 706 |
| 714 | 707 |
| 715 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { | 708 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { |
| 716 ArmOperandGenerator g(this); | 709 ArmOperandGenerator g(this); |
| 717 Emit(kArmVcvtS32F64, g.DefineAsRegister(node), | 710 Emit(kArmVcvtS32F64, g.DefineAsRegister(node), |
| 718 g.UseDoubleRegister(node->InputAt(0))); | 711 g.UseRegister(node->InputAt(0))); |
| 719 } | 712 } |
| 720 | 713 |
| 721 | 714 |
| 722 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { | 715 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { |
| 723 ArmOperandGenerator g(this); | 716 ArmOperandGenerator g(this); |
| 724 Emit(kArmVcvtU32F64, g.DefineAsRegister(node), | 717 Emit(kArmVcvtU32F64, g.DefineAsRegister(node), |
| 725 g.UseDoubleRegister(node->InputAt(0))); | 718 g.UseRegister(node->InputAt(0))); |
| 726 } | 719 } |
| 727 | 720 |
| 728 | 721 |
| 729 void InstructionSelector::VisitFloat64Add(Node* node) { | 722 void InstructionSelector::VisitFloat64Add(Node* node) { |
| 730 ArmOperandGenerator g(this); | 723 ArmOperandGenerator g(this); |
| 731 Int32BinopMatcher m(node); | 724 Int32BinopMatcher m(node); |
| 732 if (m.left().IsFloat64Mul() && CanCover(node, m.left().node())) { | 725 if (m.left().IsFloat64Mul() && CanCover(node, m.left().node())) { |
| 733 Int32BinopMatcher mleft(m.left().node()); | 726 Int32BinopMatcher mleft(m.left().node()); |
| 734 Emit(kArmVmlaF64, g.DefineSameAsFirst(node), | 727 Emit(kArmVmlaF64, g.DefineSameAsFirst(node), |
| 735 g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()), | 728 g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 758 return; | 751 return; |
| 759 } | 752 } |
| 760 VisitRRRFloat64(this, kArmVsubF64, node); | 753 VisitRRRFloat64(this, kArmVsubF64, node); |
| 761 } | 754 } |
| 762 | 755 |
| 763 | 756 |
| 764 void InstructionSelector::VisitFloat64Mul(Node* node) { | 757 void InstructionSelector::VisitFloat64Mul(Node* node) { |
| 765 ArmOperandGenerator g(this); | 758 ArmOperandGenerator g(this); |
| 766 Float64BinopMatcher m(node); | 759 Float64BinopMatcher m(node); |
| 767 if (m.right().Is(-1.0)) { | 760 if (m.right().Is(-1.0)) { |
| 768 Emit(kArmVnegF64, g.DefineAsRegister(node), | 761 Emit(kArmVnegF64, g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
| 769 g.UseDoubleRegister(m.left().node())); | |
| 770 } else { | 762 } else { |
| 771 VisitRRRFloat64(this, kArmVmulF64, node); | 763 VisitRRRFloat64(this, kArmVmulF64, node); |
| 772 } | 764 } |
| 773 } | 765 } |
| 774 | 766 |
| 775 | 767 |
| 776 void InstructionSelector::VisitFloat64Div(Node* node) { | 768 void InstructionSelector::VisitFloat64Div(Node* node) { |
| 777 VisitRRRFloat64(this, kArmVdivF64, node); | 769 VisitRRRFloat64(this, kArmVdivF64, node); |
| 778 } | 770 } |
| 779 | 771 |
| 780 | 772 |
| 781 void InstructionSelector::VisitFloat64Mod(Node* node) { | 773 void InstructionSelector::VisitFloat64Mod(Node* node) { |
| 782 ArmOperandGenerator g(this); | 774 ArmOperandGenerator g(this); |
| 783 Emit(kArmVmodF64, g.DefineAsFixedDouble(node, d0), | 775 Emit(kArmVmodF64, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0), |
| 784 g.UseFixedDouble(node->InputAt(0), d0), | 776 g.UseFixed(node->InputAt(1), d1))->MarkAsCall(); |
| 785 g.UseFixedDouble(node->InputAt(1), d1))->MarkAsCall(); | |
| 786 } | 777 } |
| 787 | 778 |
| 788 | 779 |
| 789 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, | 780 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
| 790 BasicBlock* deoptimization) { | 781 BasicBlock* deoptimization) { |
| 791 ArmOperandGenerator g(this); | 782 ArmOperandGenerator g(this); |
| 792 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); | 783 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); |
| 793 | 784 |
| 794 FrameStateDescriptor* frame_state_descriptor = NULL; | 785 FrameStateDescriptor* frame_state_descriptor = NULL; |
| 795 if (descriptor->NeedsFrameState()) { | 786 if (descriptor->NeedsFrameState()) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 FlagsContinuation* cont) { | 941 FlagsContinuation* cont) { |
| 951 VisitWordCompare(this, node, kArmCmp, cont, false); | 942 VisitWordCompare(this, node, kArmCmp, cont, false); |
| 952 } | 943 } |
| 953 | 944 |
| 954 | 945 |
| 955 void InstructionSelector::VisitFloat64Compare(Node* node, | 946 void InstructionSelector::VisitFloat64Compare(Node* node, |
| 956 FlagsContinuation* cont) { | 947 FlagsContinuation* cont) { |
| 957 ArmOperandGenerator g(this); | 948 ArmOperandGenerator g(this); |
| 958 Float64BinopMatcher m(node); | 949 Float64BinopMatcher m(node); |
| 959 if (cont->IsBranch()) { | 950 if (cont->IsBranch()) { |
| 960 Emit(cont->Encode(kArmVcmpF64), NULL, g.UseDoubleRegister(m.left().node()), | 951 Emit(cont->Encode(kArmVcmpF64), NULL, g.UseRegister(m.left().node()), |
| 961 g.UseDoubleRegister(m.right().node()), g.Label(cont->true_block()), | 952 g.UseRegister(m.right().node()), g.Label(cont->true_block()), |
| 962 g.Label(cont->false_block()))->MarkAsControl(); | 953 g.Label(cont->false_block()))->MarkAsControl(); |
| 963 } else { | 954 } else { |
| 964 DCHECK(cont->IsSet()); | 955 DCHECK(cont->IsSet()); |
| 965 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), | 956 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), |
| 966 g.UseDoubleRegister(m.left().node()), | 957 g.UseRegister(m.left().node()), g.UseRegister(m.right().node())); |
| 967 g.UseDoubleRegister(m.right().node())); | |
| 968 } | 958 } |
| 969 } | 959 } |
| 970 | 960 |
| 971 } // namespace compiler | 961 } // namespace compiler |
| 972 } // namespace internal | 962 } // namespace internal |
| 973 } // namespace v8 | 963 } // namespace v8 |
| OLD | NEW |