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 |