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 |