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 | 7 |
8 namespace v8 { | 8 namespace v8 { |
9 namespace internal { | 9 namespace internal { |
10 namespace compiler { | 10 namespace compiler { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 }; | 55 }; |
56 | 56 |
57 | 57 |
58 void InstructionSelector::VisitLoad(Node* node) { | 58 void InstructionSelector::VisitLoad(Node* node) { |
59 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 59 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
60 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 60 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
61 X64OperandGenerator g(this); | 61 X64OperandGenerator g(this); |
62 Node* base = node->InputAt(0); | 62 Node* base = node->InputAt(0); |
63 Node* index = node->InputAt(1); | 63 Node* index = node->InputAt(1); |
64 | 64 |
65 InstructionOperand* output = (rep == kRepFloat32 || rep == kRepFloat64) | |
66 ? g.DefineAsDoubleRegister(node) | |
67 : g.DefineAsRegister(node); | |
68 ArchOpcode opcode; | 65 ArchOpcode opcode; |
69 // TODO(titzer): signed/unsigned small loads | 66 // TODO(titzer): signed/unsigned small loads |
70 switch (rep) { | 67 switch (rep) { |
71 case kRepFloat32: | 68 case kRepFloat32: |
72 opcode = kX64Movss; | 69 opcode = kX64Movss; |
73 break; | 70 break; |
74 case kRepFloat64: | 71 case kRepFloat64: |
75 opcode = kX64Movsd; | 72 opcode = kX64Movsd; |
76 break; | 73 break; |
77 case kRepBit: // Fall through. | 74 case kRepBit: // Fall through. |
78 case kRepWord8: | 75 case kRepWord8: |
79 opcode = typ == kTypeInt32 ? kX64Movsxbl : kX64Movzxbl; | 76 opcode = typ == kTypeInt32 ? kX64Movsxbl : kX64Movzxbl; |
80 break; | 77 break; |
81 case kRepWord16: | 78 case kRepWord16: |
82 opcode = typ == kTypeInt32 ? kX64Movsxwl : kX64Movzxwl; | 79 opcode = typ == kTypeInt32 ? kX64Movsxwl : kX64Movzxwl; |
83 break; | 80 break; |
84 case kRepWord32: | 81 case kRepWord32: |
85 opcode = kX64Movl; | 82 opcode = kX64Movl; |
86 break; | 83 break; |
87 case kRepTagged: // Fall through. | 84 case kRepTagged: // Fall through. |
88 case kRepWord64: | 85 case kRepWord64: |
89 opcode = kX64Movq; | 86 opcode = kX64Movq; |
90 break; | 87 break; |
91 default: | 88 default: |
92 UNREACHABLE(); | 89 UNREACHABLE(); |
93 return; | 90 return; |
94 } | 91 } |
95 if (g.CanBeImmediate(base)) { | 92 if (g.CanBeImmediate(base)) { |
96 // load [#base + %index] | 93 // load [#base + %index] |
97 Emit(opcode | AddressingModeField::encode(kMode_MRI), output, | 94 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
98 g.UseRegister(index), g.UseImmediate(base)); | 95 g.DefineAsRegister(node), g.UseRegister(index), g.UseImmediate(base)); |
99 } else if (g.CanBeImmediate(index)) { // load [%base + #index] | 96 } else if (g.CanBeImmediate(index)) { // load [%base + #index] |
100 Emit(opcode | AddressingModeField::encode(kMode_MRI), output, | 97 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
101 g.UseRegister(base), g.UseImmediate(index)); | 98 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
102 } else { // load [%base + %index + K] | 99 } else { // load [%base + %index + K] |
103 Emit(opcode | AddressingModeField::encode(kMode_MR1I), output, | 100 Emit(opcode | AddressingModeField::encode(kMode_MR1I), |
104 g.UseRegister(base), g.UseRegister(index)); | 101 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); |
105 } | 102 } |
106 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] | 103 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] |
107 } | 104 } |
108 | 105 |
109 | 106 |
110 void InstructionSelector::VisitStore(Node* node) { | 107 void InstructionSelector::VisitStore(Node* node) { |
111 X64OperandGenerator g(this); | 108 X64OperandGenerator g(this); |
112 Node* base = node->InputAt(0); | 109 Node* base = node->InputAt(0); |
113 Node* index = node->InputAt(1); | 110 Node* index = node->InputAt(1); |
114 Node* value = node->InputAt(2); | 111 Node* value = node->InputAt(2); |
115 | 112 |
116 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 113 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
117 MachineType rep = RepresentationOf(store_rep.machine_type); | 114 MachineType rep = RepresentationOf(store_rep.machine_type); |
118 if (store_rep.write_barrier_kind == kFullWriteBarrier) { | 115 if (store_rep.write_barrier_kind == kFullWriteBarrier) { |
119 DCHECK(rep == kRepTagged); | 116 DCHECK(rep == kRepTagged); |
120 // TODO(dcarney): refactor RecordWrite function to take temp registers | 117 // TODO(dcarney): refactor RecordWrite function to take temp registers |
121 // and pass them here instead of using fixed regs | 118 // and pass them here instead of using fixed regs |
122 // TODO(dcarney): handle immediate indices. | 119 // TODO(dcarney): handle immediate indices. |
123 InstructionOperand* temps[] = {g.TempRegister(rcx), g.TempRegister(rdx)}; | 120 InstructionOperand* temps[] = {g.TempRegister(rcx), g.TempRegister(rdx)}; |
124 Emit(kX64StoreWriteBarrier, NULL, g.UseFixed(base, rbx), | 121 Emit(kX64StoreWriteBarrier, NULL, g.UseFixed(base, rbx), |
125 g.UseFixed(index, rcx), g.UseFixed(value, rdx), ARRAY_SIZE(temps), | 122 g.UseFixed(index, rcx), g.UseFixed(value, rdx), ARRAY_SIZE(temps), |
126 temps); | 123 temps); |
127 return; | 124 return; |
128 } | 125 } |
129 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind); | 126 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind); |
130 InstructionOperand* val; | 127 InstructionOperand* val; |
131 if (rep == kRepFloat32 || rep == kRepFloat64) { | 128 if (g.CanBeImmediate(value)) { |
132 val = g.UseDoubleRegister(value); | 129 val = g.UseImmediate(value); |
| 130 } else if (rep == kRepWord8 || rep == kRepBit) { |
| 131 val = g.UseByteRegister(value); |
133 } else { | 132 } else { |
134 if (g.CanBeImmediate(value)) { | 133 val = g.UseRegister(value); |
135 val = g.UseImmediate(value); | |
136 } else if (rep == kRepWord8 || rep == kRepBit) { | |
137 val = g.UseByteRegister(value); | |
138 } else { | |
139 val = g.UseRegister(value); | |
140 } | |
141 } | 134 } |
142 ArchOpcode opcode; | 135 ArchOpcode opcode; |
143 switch (rep) { | 136 switch (rep) { |
144 case kRepFloat32: | 137 case kRepFloat32: |
145 opcode = kX64Movss; | 138 opcode = kX64Movss; |
146 break; | 139 break; |
147 case kRepFloat64: | 140 case kRepFloat64: |
148 opcode = kX64Movsd; | 141 opcode = kX64Movsd; |
149 break; | 142 break; |
150 case kRepBit: // Fall through. | 143 case kRepBit: // Fall through. |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 } | 477 } |
485 | 478 |
486 | 479 |
487 void InstructionSelector::VisitInt64UMod(Node* node) { | 480 void InstructionSelector::VisitInt64UMod(Node* node) { |
488 VisitMod(this, node, kX64Udiv); | 481 VisitMod(this, node, kX64Udiv); |
489 } | 482 } |
490 | 483 |
491 | 484 |
492 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { | 485 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { |
493 X64OperandGenerator g(this); | 486 X64OperandGenerator g(this); |
494 Emit(kSSEInt32ToFloat64, g.DefineAsDoubleRegister(node), | 487 Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
495 g.Use(node->InputAt(0))); | |
496 } | 488 } |
497 | 489 |
498 | 490 |
499 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { | 491 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { |
500 X64OperandGenerator g(this); | 492 X64OperandGenerator g(this); |
501 // TODO(turbofan): X64 SSE cvtqsi2sd should support operands. | 493 // TODO(turbofan): X64 SSE cvtqsi2sd should support operands. |
502 Emit(kSSEUint32ToFloat64, g.DefineAsDoubleRegister(node), | 494 Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), |
503 g.UseRegister(node->InputAt(0))); | 495 g.UseRegister(node->InputAt(0))); |
504 } | 496 } |
505 | 497 |
506 | 498 |
507 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { | 499 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { |
508 X64OperandGenerator g(this); | 500 X64OperandGenerator g(this); |
509 Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 501 Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
510 } | 502 } |
511 | 503 |
512 | 504 |
513 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { | 505 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { |
514 X64OperandGenerator g(this); | 506 X64OperandGenerator g(this); |
515 // TODO(turbofan): X64 SSE cvttsd2siq should support operands. | 507 // TODO(turbofan): X64 SSE cvttsd2siq should support operands. |
516 Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), | 508 Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), |
517 g.UseDoubleRegister(node->InputAt(0))); | 509 g.UseRegister(node->InputAt(0))); |
518 } | 510 } |
519 | 511 |
520 | 512 |
521 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { | 513 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
522 X64OperandGenerator g(this); | 514 X64OperandGenerator g(this); |
523 Emit(kX64Movsxlq, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 515 Emit(kX64Movsxlq, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
524 } | 516 } |
525 | 517 |
526 | 518 |
527 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { | 519 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { |
528 X64OperandGenerator g(this); | 520 X64OperandGenerator g(this); |
529 Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 521 Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
530 } | 522 } |
531 | 523 |
532 | 524 |
533 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { | 525 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { |
534 X64OperandGenerator g(this); | 526 X64OperandGenerator g(this); |
535 Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 527 Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
536 } | 528 } |
537 | 529 |
538 | 530 |
539 void InstructionSelector::VisitFloat64Add(Node* node) { | 531 void InstructionSelector::VisitFloat64Add(Node* node) { |
540 X64OperandGenerator g(this); | 532 X64OperandGenerator g(this); |
541 Emit(kSSEFloat64Add, g.DefineSameAsFirst(node), | 533 Emit(kSSEFloat64Add, g.DefineSameAsFirst(node), |
542 g.UseDoubleRegister(node->InputAt(0)), | 534 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
543 g.UseDoubleRegister(node->InputAt(1))); | |
544 } | 535 } |
545 | 536 |
546 | 537 |
547 void InstructionSelector::VisitFloat64Sub(Node* node) { | 538 void InstructionSelector::VisitFloat64Sub(Node* node) { |
548 X64OperandGenerator g(this); | 539 X64OperandGenerator g(this); |
549 Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node), | 540 Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node), |
550 g.UseDoubleRegister(node->InputAt(0)), | 541 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
551 g.UseDoubleRegister(node->InputAt(1))); | |
552 } | 542 } |
553 | 543 |
554 | 544 |
555 void InstructionSelector::VisitFloat64Mul(Node* node) { | 545 void InstructionSelector::VisitFloat64Mul(Node* node) { |
556 X64OperandGenerator g(this); | 546 X64OperandGenerator g(this); |
557 Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node), | 547 Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node), |
558 g.UseDoubleRegister(node->InputAt(0)), | 548 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
559 g.UseDoubleRegister(node->InputAt(1))); | |
560 } | 549 } |
561 | 550 |
562 | 551 |
563 void InstructionSelector::VisitFloat64Div(Node* node) { | 552 void InstructionSelector::VisitFloat64Div(Node* node) { |
564 X64OperandGenerator g(this); | 553 X64OperandGenerator g(this); |
565 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), | 554 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), |
566 g.UseDoubleRegister(node->InputAt(0)), | 555 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
567 g.UseDoubleRegister(node->InputAt(1))); | |
568 } | 556 } |
569 | 557 |
570 | 558 |
571 void InstructionSelector::VisitFloat64Mod(Node* node) { | 559 void InstructionSelector::VisitFloat64Mod(Node* node) { |
572 X64OperandGenerator g(this); | 560 X64OperandGenerator g(this); |
573 InstructionOperand* temps[] = {g.TempRegister(rax)}; | 561 InstructionOperand* temps[] = {g.TempRegister(rax)}; |
574 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), | 562 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), |
575 g.UseDoubleRegister(node->InputAt(0)), | 563 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1, |
576 g.UseDoubleRegister(node->InputAt(1)), 1, temps); | 564 temps); |
577 } | 565 } |
578 | 566 |
579 | 567 |
580 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, | 568 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, |
581 FlagsContinuation* cont) { | 569 FlagsContinuation* cont) { |
582 VisitBinop(this, node, kX64Add32, cont); | 570 VisitBinop(this, node, kX64Add32, cont); |
583 } | 571 } |
584 | 572 |
585 | 573 |
586 void InstructionSelector::VisitInt32SubWithOverflow(Node* node, | 574 void InstructionSelector::VisitInt32SubWithOverflow(Node* node, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 FlagsContinuation* cont) { | 653 FlagsContinuation* cont) { |
666 VisitWordCompare(this, node, kX64Cmp, cont, false); | 654 VisitWordCompare(this, node, kX64Cmp, cont, false); |
667 } | 655 } |
668 | 656 |
669 | 657 |
670 void InstructionSelector::VisitFloat64Compare(Node* node, | 658 void InstructionSelector::VisitFloat64Compare(Node* node, |
671 FlagsContinuation* cont) { | 659 FlagsContinuation* cont) { |
672 X64OperandGenerator g(this); | 660 X64OperandGenerator g(this); |
673 Node* left = node->InputAt(0); | 661 Node* left = node->InputAt(0); |
674 Node* right = node->InputAt(1); | 662 Node* right = node->InputAt(1); |
675 VisitCompare(this, kSSEFloat64Cmp, g.UseDoubleRegister(left), g.Use(right), | 663 VisitCompare(this, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), cont); |
676 cont); | |
677 } | 664 } |
678 | 665 |
679 | 666 |
680 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, | 667 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
681 BasicBlock* deoptimization) { | 668 BasicBlock* deoptimization) { |
682 X64OperandGenerator g(this); | 669 X64OperandGenerator g(this); |
683 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); | 670 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); |
684 | 671 |
685 FrameStateDescriptor* frame_state_descriptor = NULL; | 672 FrameStateDescriptor* frame_state_descriptor = NULL; |
686 if (descriptor->NeedsFrameState()) { | 673 if (descriptor->NeedsFrameState()) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 DCHECK(deoptimization == NULL && continuation == NULL); | 729 DCHECK(deoptimization == NULL && continuation == NULL); |
743 Emit(kPopStack | | 730 Emit(kPopStack | |
744 MiscField::encode(static_cast<int>(buffer.pushed_nodes.size())), | 731 MiscField::encode(static_cast<int>(buffer.pushed_nodes.size())), |
745 NULL); | 732 NULL); |
746 } | 733 } |
747 } | 734 } |
748 | 735 |
749 } // namespace compiler | 736 } // namespace compiler |
750 } // namespace internal | 737 } // namespace internal |
751 } // namespace v8 | 738 } // namespace v8 |
OLD | NEW |