| 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 |