| 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 #include "src/compiler/node-properties-inl.h" | 7 #include "src/compiler/node-properties-inl.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 | 42 |
| 43 void InstructionSelector::VisitLoad(Node* node) { | 43 void InstructionSelector::VisitLoad(Node* node) { |
| 44 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 44 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
| 45 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 45 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
| 46 IA32OperandGenerator g(this); | 46 IA32OperandGenerator g(this); |
| 47 Node* base = node->InputAt(0); | 47 Node* base = node->InputAt(0); |
| 48 Node* index = node->InputAt(1); | 48 Node* index = node->InputAt(1); |
| 49 | 49 |
| 50 InstructionOperand* output = (rep == kRepFloat32 || rep == kRepFloat64) | |
| 51 ? g.DefineAsDoubleRegister(node) | |
| 52 : g.DefineAsRegister(node); | |
| 53 ArchOpcode opcode; | 50 ArchOpcode opcode; |
| 54 // TODO(titzer): signed/unsigned small loads | 51 // TODO(titzer): signed/unsigned small loads |
| 55 switch (rep) { | 52 switch (rep) { |
| 56 case kRepFloat32: | 53 case kRepFloat32: |
| 57 opcode = kIA32Movss; | 54 opcode = kIA32Movss; |
| 58 break; | 55 break; |
| 59 case kRepFloat64: | 56 case kRepFloat64: |
| 60 opcode = kIA32Movsd; | 57 opcode = kIA32Movsd; |
| 61 break; | 58 break; |
| 62 case kRepBit: // Fall through. | 59 case kRepBit: // Fall through. |
| 63 case kRepWord8: | 60 case kRepWord8: |
| 64 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; | 61 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; |
| 65 break; | 62 break; |
| 66 case kRepWord16: | 63 case kRepWord16: |
| 67 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; | 64 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; |
| 68 break; | 65 break; |
| 69 case kRepTagged: // Fall through. | 66 case kRepTagged: // Fall through. |
| 70 case kRepWord32: | 67 case kRepWord32: |
| 71 opcode = kIA32Movl; | 68 opcode = kIA32Movl; |
| 72 break; | 69 break; |
| 73 default: | 70 default: |
| 74 UNREACHABLE(); | 71 UNREACHABLE(); |
| 75 return; | 72 return; |
| 76 } | 73 } |
| 77 if (g.CanBeImmediate(base)) { | 74 if (g.CanBeImmediate(base)) { |
| 78 if (Int32Matcher(index).Is(0)) { // load [#base + #0] | 75 if (Int32Matcher(index).Is(0)) { // load [#base + #0] |
| 79 Emit(opcode | AddressingModeField::encode(kMode_MI), output, | 76 Emit(opcode | AddressingModeField::encode(kMode_MI), |
| 77 g.DefineAsRegister(node), g.UseImmediate(base)); |
| 78 } else { // load [#base + %index] |
| 79 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 80 g.DefineAsRegister(node), g.UseRegister(index), |
| 80 g.UseImmediate(base)); | 81 g.UseImmediate(base)); |
| 81 } else { // load [#base + %index] | |
| 82 Emit(opcode | AddressingModeField::encode(kMode_MRI), output, | |
| 83 g.UseRegister(index), g.UseImmediate(base)); | |
| 84 } | 82 } |
| 85 } else if (g.CanBeImmediate(index)) { // load [%base + #index] | 83 } else if (g.CanBeImmediate(index)) { // load [%base + #index] |
| 86 Emit(opcode | AddressingModeField::encode(kMode_MRI), output, | 84 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 87 g.UseRegister(base), g.UseImmediate(index)); | 85 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
| 88 } else { // load [%base + %index + K] | 86 } else { // load [%base + %index + K] |
| 89 Emit(opcode | AddressingModeField::encode(kMode_MR1I), output, | 87 Emit(opcode | AddressingModeField::encode(kMode_MR1I), |
| 90 g.UseRegister(base), g.UseRegister(index)); | 88 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); |
| 91 } | 89 } |
| 92 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] | 90 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] |
| 93 } | 91 } |
| 94 | 92 |
| 95 | 93 |
| 96 void InstructionSelector::VisitStore(Node* node) { | 94 void InstructionSelector::VisitStore(Node* node) { |
| 97 IA32OperandGenerator g(this); | 95 IA32OperandGenerator g(this); |
| 98 Node* base = node->InputAt(0); | 96 Node* base = node->InputAt(0); |
| 99 Node* index = node->InputAt(1); | 97 Node* index = node->InputAt(1); |
| 100 Node* value = node->InputAt(2); | 98 Node* value = node->InputAt(2); |
| 101 | 99 |
| 102 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 100 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
| 103 MachineType rep = RepresentationOf(store_rep.machine_type); | 101 MachineType rep = RepresentationOf(store_rep.machine_type); |
| 104 if (store_rep.write_barrier_kind == kFullWriteBarrier) { | 102 if (store_rep.write_barrier_kind == kFullWriteBarrier) { |
| 105 DCHECK_EQ(kRepTagged, rep); | 103 DCHECK_EQ(kRepTagged, rep); |
| 106 // TODO(dcarney): refactor RecordWrite function to take temp registers | 104 // TODO(dcarney): refactor RecordWrite function to take temp registers |
| 107 // and pass them here instead of using fixed regs | 105 // and pass them here instead of using fixed regs |
| 108 // TODO(dcarney): handle immediate indices. | 106 // TODO(dcarney): handle immediate indices. |
| 109 InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)}; | 107 InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)}; |
| 110 Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx), | 108 Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx), |
| 111 g.UseFixed(index, ecx), g.UseFixed(value, edx), ARRAY_SIZE(temps), | 109 g.UseFixed(index, ecx), g.UseFixed(value, edx), ARRAY_SIZE(temps), |
| 112 temps); | 110 temps); |
| 113 return; | 111 return; |
| 114 } | 112 } |
| 115 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind); | 113 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind); |
| 116 InstructionOperand* val; | 114 InstructionOperand* val; |
| 117 if (rep == kRepFloat32 || rep == kRepFloat64) { | 115 if (g.CanBeImmediate(value)) { |
| 118 val = g.UseDoubleRegister(value); | 116 val = g.UseImmediate(value); |
| 117 } else if (rep == kRepWord8 || rep == kRepBit) { |
| 118 val = g.UseByteRegister(value); |
| 119 } else { | 119 } else { |
| 120 if (g.CanBeImmediate(value)) { | 120 val = g.UseRegister(value); |
| 121 val = g.UseImmediate(value); | |
| 122 } else if (rep == kRepWord8 || rep == kRepBit) { | |
| 123 val = g.UseByteRegister(value); | |
| 124 } else { | |
| 125 val = g.UseRegister(value); | |
| 126 } | |
| 127 } | 121 } |
| 128 ArchOpcode opcode; | 122 ArchOpcode opcode; |
| 129 switch (rep) { | 123 switch (rep) { |
| 130 case kRepFloat32: | 124 case kRepFloat32: |
| 131 opcode = kIA32Movss; | 125 opcode = kIA32Movss; |
| 132 break; | 126 break; |
| 133 case kRepFloat64: | 127 case kRepFloat64: |
| 134 opcode = kIA32Movsd; | 128 opcode = kIA32Movsd; |
| 135 break; | 129 break; |
| 136 case kRepBit: // Fall through. | 130 case kRepBit: // Fall through. |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 } | 349 } |
| 356 | 350 |
| 357 | 351 |
| 358 void InstructionSelector::VisitInt32UMod(Node* node) { | 352 void InstructionSelector::VisitInt32UMod(Node* node) { |
| 359 VisitMod(this, node, kIA32Udiv); | 353 VisitMod(this, node, kIA32Udiv); |
| 360 } | 354 } |
| 361 | 355 |
| 362 | 356 |
| 363 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { | 357 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { |
| 364 IA32OperandGenerator g(this); | 358 IA32OperandGenerator g(this); |
| 365 Emit(kSSEInt32ToFloat64, g.DefineAsDoubleRegister(node), | 359 Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
| 366 g.Use(node->InputAt(0))); | |
| 367 } | 360 } |
| 368 | 361 |
| 369 | 362 |
| 370 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { | 363 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { |
| 371 IA32OperandGenerator g(this); | 364 IA32OperandGenerator g(this); |
| 372 // TODO(turbofan): IA32 SSE LoadUint32() should take an operand. | 365 // TODO(turbofan): IA32 SSE LoadUint32() should take an operand. |
| 373 Emit(kSSEUint32ToFloat64, g.DefineAsDoubleRegister(node), | 366 Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), |
| 374 g.UseRegister(node->InputAt(0))); | 367 g.UseRegister(node->InputAt(0))); |
| 375 } | 368 } |
| 376 | 369 |
| 377 | 370 |
| 378 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { | 371 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { |
| 379 IA32OperandGenerator g(this); | 372 IA32OperandGenerator g(this); |
| 380 Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 373 Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
| 381 } | 374 } |
| 382 | 375 |
| 383 | 376 |
| 384 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { | 377 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { |
| 385 IA32OperandGenerator g(this); | 378 IA32OperandGenerator g(this); |
| 386 // TODO(turbofan): IA32 SSE subsd() should take an operand. | 379 // TODO(turbofan): IA32 SSE subsd() should take an operand. |
| 387 Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), | 380 Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), |
| 388 g.UseDoubleRegister(node->InputAt(0))); | 381 g.UseRegister(node->InputAt(0))); |
| 389 } | 382 } |
| 390 | 383 |
| 391 | 384 |
| 392 void InstructionSelector::VisitFloat64Add(Node* node) { | 385 void InstructionSelector::VisitFloat64Add(Node* node) { |
| 393 IA32OperandGenerator g(this); | 386 IA32OperandGenerator g(this); |
| 394 Emit(kSSEFloat64Add, g.DefineSameAsFirst(node), | 387 Emit(kSSEFloat64Add, g.DefineSameAsFirst(node), |
| 395 g.UseDoubleRegister(node->InputAt(0)), | 388 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
| 396 g.UseDoubleRegister(node->InputAt(1))); | |
| 397 } | 389 } |
| 398 | 390 |
| 399 | 391 |
| 400 void InstructionSelector::VisitFloat64Sub(Node* node) { | 392 void InstructionSelector::VisitFloat64Sub(Node* node) { |
| 401 IA32OperandGenerator g(this); | 393 IA32OperandGenerator g(this); |
| 402 Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node), | 394 Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node), |
| 403 g.UseDoubleRegister(node->InputAt(0)), | 395 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
| 404 g.UseDoubleRegister(node->InputAt(1))); | |
| 405 } | 396 } |
| 406 | 397 |
| 407 | 398 |
| 408 void InstructionSelector::VisitFloat64Mul(Node* node) { | 399 void InstructionSelector::VisitFloat64Mul(Node* node) { |
| 409 IA32OperandGenerator g(this); | 400 IA32OperandGenerator g(this); |
| 410 Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node), | 401 Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node), |
| 411 g.UseDoubleRegister(node->InputAt(0)), | 402 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
| 412 g.UseDoubleRegister(node->InputAt(1))); | |
| 413 } | 403 } |
| 414 | 404 |
| 415 | 405 |
| 416 void InstructionSelector::VisitFloat64Div(Node* node) { | 406 void InstructionSelector::VisitFloat64Div(Node* node) { |
| 417 IA32OperandGenerator g(this); | 407 IA32OperandGenerator g(this); |
| 418 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), | 408 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), |
| 419 g.UseDoubleRegister(node->InputAt(0)), | 409 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); |
| 420 g.UseDoubleRegister(node->InputAt(1))); | |
| 421 } | 410 } |
| 422 | 411 |
| 423 | 412 |
| 424 void InstructionSelector::VisitFloat64Mod(Node* node) { | 413 void InstructionSelector::VisitFloat64Mod(Node* node) { |
| 425 IA32OperandGenerator g(this); | 414 IA32OperandGenerator g(this); |
| 426 InstructionOperand* temps[] = {g.TempRegister(eax)}; | 415 InstructionOperand* temps[] = {g.TempRegister(eax)}; |
| 427 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), | 416 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), |
| 428 g.UseDoubleRegister(node->InputAt(0)), | 417 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1, |
| 429 g.UseDoubleRegister(node->InputAt(1)), 1, temps); | 418 temps); |
| 430 } | 419 } |
| 431 | 420 |
| 432 | 421 |
| 433 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, | 422 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, |
| 434 FlagsContinuation* cont) { | 423 FlagsContinuation* cont) { |
| 435 VisitBinop(this, node, kIA32Add, cont); | 424 VisitBinop(this, node, kIA32Add, cont); |
| 436 } | 425 } |
| 437 | 426 |
| 438 | 427 |
| 439 void InstructionSelector::VisitInt32SubWithOverflow(Node* node, | 428 void InstructionSelector::VisitInt32SubWithOverflow(Node* node, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 FlagsContinuation* cont) { | 490 FlagsContinuation* cont) { |
| 502 VisitWordCompare(this, node, kIA32Cmp, cont, false); | 491 VisitWordCompare(this, node, kIA32Cmp, cont, false); |
| 503 } | 492 } |
| 504 | 493 |
| 505 | 494 |
| 506 void InstructionSelector::VisitFloat64Compare(Node* node, | 495 void InstructionSelector::VisitFloat64Compare(Node* node, |
| 507 FlagsContinuation* cont) { | 496 FlagsContinuation* cont) { |
| 508 IA32OperandGenerator g(this); | 497 IA32OperandGenerator g(this); |
| 509 Node* left = node->InputAt(0); | 498 Node* left = node->InputAt(0); |
| 510 Node* right = node->InputAt(1); | 499 Node* right = node->InputAt(1); |
| 511 VisitCompare(this, kSSEFloat64Cmp, g.UseDoubleRegister(left), g.Use(right), | 500 VisitCompare(this, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), cont); |
| 512 cont); | |
| 513 } | 501 } |
| 514 | 502 |
| 515 | 503 |
| 516 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, | 504 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
| 517 BasicBlock* deoptimization) { | 505 BasicBlock* deoptimization) { |
| 518 IA32OperandGenerator g(this); | 506 IA32OperandGenerator g(this); |
| 519 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); | 507 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); |
| 520 | 508 |
| 521 FrameStateDescriptor* frame_state_descriptor = NULL; | 509 FrameStateDescriptor* frame_state_descriptor = NULL; |
| 522 | 510 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 if (descriptor->kind() == CallDescriptor::kCallAddress && | 560 if (descriptor->kind() == CallDescriptor::kCallAddress && |
| 573 buffer.pushed_nodes.size() > 0) { | 561 buffer.pushed_nodes.size() > 0) { |
| 574 DCHECK(deoptimization == NULL && continuation == NULL); | 562 DCHECK(deoptimization == NULL && continuation == NULL); |
| 575 Emit(kPopStack | MiscField::encode(buffer.pushed_nodes.size()), NULL); | 563 Emit(kPopStack | MiscField::encode(buffer.pushed_nodes.size()), NULL); |
| 576 } | 564 } |
| 577 } | 565 } |
| 578 | 566 |
| 579 } // namespace compiler | 567 } // namespace compiler |
| 580 } // namespace internal | 568 } // namespace internal |
| 581 } // namespace v8 | 569 } // namespace v8 |
| OLD | NEW |