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/generic-node-inl.h" | 5 #include "src/compiler/generic-node-inl.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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 g.UseImmediate(right)); | 398 g.UseImmediate(right)); |
399 } else { | 399 } else { |
400 if (g.CanBeBetterLeftOperand(right)) { | 400 if (g.CanBeBetterLeftOperand(right)) { |
401 std::swap(left, right); | 401 std::swap(left, right); |
402 } | 402 } |
403 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 403 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
404 g.Use(right)); | 404 g.Use(right)); |
405 } | 405 } |
406 } | 406 } |
407 | 407 |
| 408 |
| 409 void VisitMulHigh(InstructionSelector* selector, Node* node, |
| 410 ArchOpcode opcode) { |
| 411 X64OperandGenerator g(selector); |
| 412 Node* left = node->InputAt(0); |
| 413 Node* right = node->InputAt(1); |
| 414 if (selector->IsLive(left) && !selector->IsLive(right)) { |
| 415 std::swap(left, right); |
| 416 } |
| 417 selector->Emit(opcode, g.DefineAsFixed(node, rdx), g.UseFixed(left, rax), |
| 418 g.UseUnique(right)); |
| 419 } |
| 420 |
| 421 |
| 422 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 423 X64OperandGenerator g(selector); |
| 424 InstructionOperand* temps[] = {g.TempRegister(rdx)}; |
| 425 selector->Emit( |
| 426 opcode, g.DefineAsFixed(node, rax), g.UseFixed(node->InputAt(0), rax), |
| 427 g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps); |
| 428 } |
| 429 |
| 430 |
| 431 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 432 X64OperandGenerator g(selector); |
| 433 selector->Emit(opcode, g.DefineAsFixed(node, rdx), |
| 434 g.UseFixed(node->InputAt(0), rax), |
| 435 g.UseUniqueRegister(node->InputAt(1))); |
| 436 } |
| 437 |
408 } // namespace | 438 } // namespace |
409 | 439 |
410 | 440 |
411 void InstructionSelector::VisitInt32Mul(Node* node) { | 441 void InstructionSelector::VisitInt32Mul(Node* node) { |
412 VisitMul(this, node, kX64Imul32); | 442 VisitMul(this, node, kX64Imul32); |
413 } | 443 } |
414 | 444 |
415 | 445 |
416 void InstructionSelector::VisitInt64Mul(Node* node) { | 446 void InstructionSelector::VisitInt64Mul(Node* node) { |
417 VisitMul(this, node, kX64Imul); | 447 VisitMul(this, node, kX64Imul); |
418 } | 448 } |
419 | 449 |
420 | 450 |
421 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 451 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
422 X64OperandGenerator g(this); | 452 VisitMulHigh(this, node, kX64ImulHigh32); |
423 Emit(kX64ImulHigh32, g.DefineAsFixed(node, rdx), | |
424 g.UseFixed(node->InputAt(0), rax), | |
425 g.UseUniqueRegister(node->InputAt(1))); | |
426 } | 453 } |
427 | 454 |
428 | 455 |
429 static void VisitDiv(InstructionSelector* selector, Node* node, | |
430 ArchOpcode opcode) { | |
431 X64OperandGenerator g(selector); | |
432 InstructionOperand* temps[] = {g.TempRegister(rdx)}; | |
433 selector->Emit( | |
434 opcode, g.DefineAsFixed(node, rax), g.UseFixed(node->InputAt(0), rax), | |
435 g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps); | |
436 } | |
437 | |
438 | |
439 void InstructionSelector::VisitInt32Div(Node* node) { | 456 void InstructionSelector::VisitInt32Div(Node* node) { |
440 VisitDiv(this, node, kX64Idiv32); | 457 VisitDiv(this, node, kX64Idiv32); |
441 } | 458 } |
442 | 459 |
443 | 460 |
444 void InstructionSelector::VisitInt64Div(Node* node) { | 461 void InstructionSelector::VisitInt64Div(Node* node) { |
445 VisitDiv(this, node, kX64Idiv); | 462 VisitDiv(this, node, kX64Idiv); |
446 } | 463 } |
447 | 464 |
448 | 465 |
449 void InstructionSelector::VisitUint32Div(Node* node) { | 466 void InstructionSelector::VisitUint32Div(Node* node) { |
450 VisitDiv(this, node, kX64Udiv32); | 467 VisitDiv(this, node, kX64Udiv32); |
451 } | 468 } |
452 | 469 |
453 | 470 |
454 void InstructionSelector::VisitUint64Div(Node* node) { | 471 void InstructionSelector::VisitUint64Div(Node* node) { |
455 VisitDiv(this, node, kX64Udiv); | 472 VisitDiv(this, node, kX64Udiv); |
456 } | 473 } |
457 | 474 |
458 | 475 |
459 static void VisitMod(InstructionSelector* selector, Node* node, | |
460 ArchOpcode opcode) { | |
461 X64OperandGenerator g(selector); | |
462 selector->Emit(opcode, g.DefineAsFixed(node, rdx), | |
463 g.UseFixed(node->InputAt(0), rax), | |
464 g.UseUniqueRegister(node->InputAt(1))); | |
465 } | |
466 | |
467 | |
468 void InstructionSelector::VisitInt32Mod(Node* node) { | 476 void InstructionSelector::VisitInt32Mod(Node* node) { |
469 VisitMod(this, node, kX64Idiv32); | 477 VisitMod(this, node, kX64Idiv32); |
470 } | 478 } |
471 | 479 |
472 | 480 |
473 void InstructionSelector::VisitInt64Mod(Node* node) { | 481 void InstructionSelector::VisitInt64Mod(Node* node) { |
474 VisitMod(this, node, kX64Idiv); | 482 VisitMod(this, node, kX64Idiv); |
475 } | 483 } |
476 | 484 |
477 | 485 |
478 void InstructionSelector::VisitUint32Mod(Node* node) { | 486 void InstructionSelector::VisitUint32Mod(Node* node) { |
479 VisitMod(this, node, kX64Udiv32); | 487 VisitMod(this, node, kX64Udiv32); |
480 } | 488 } |
481 | 489 |
482 | 490 |
483 void InstructionSelector::VisitUint64Mod(Node* node) { | 491 void InstructionSelector::VisitUint64Mod(Node* node) { |
484 VisitMod(this, node, kX64Udiv); | 492 VisitMod(this, node, kX64Udiv); |
485 } | 493 } |
486 | 494 |
487 | 495 |
| 496 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
| 497 VisitMulHigh(this, node, kX64UmulHigh32); |
| 498 } |
| 499 |
| 500 |
488 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { | 501 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { |
489 X64OperandGenerator g(this); | 502 X64OperandGenerator g(this); |
490 Emit(kSSECvtss2sd, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 503 Emit(kSSECvtss2sd, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
491 } | 504 } |
492 | 505 |
493 | 506 |
494 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { | 507 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { |
495 X64OperandGenerator g(this); | 508 X64OperandGenerator g(this); |
496 Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); | 509 Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
497 } | 510 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 case IrOpcode::kInt32Sub: | 550 case IrOpcode::kInt32Sub: |
538 case IrOpcode::kInt32Mul: | 551 case IrOpcode::kInt32Mul: |
539 case IrOpcode::kInt32MulHigh: | 552 case IrOpcode::kInt32MulHigh: |
540 case IrOpcode::kInt32Div: | 553 case IrOpcode::kInt32Div: |
541 case IrOpcode::kInt32LessThan: | 554 case IrOpcode::kInt32LessThan: |
542 case IrOpcode::kInt32LessThanOrEqual: | 555 case IrOpcode::kInt32LessThanOrEqual: |
543 case IrOpcode::kInt32Mod: | 556 case IrOpcode::kInt32Mod: |
544 case IrOpcode::kUint32Div: | 557 case IrOpcode::kUint32Div: |
545 case IrOpcode::kUint32LessThan: | 558 case IrOpcode::kUint32LessThan: |
546 case IrOpcode::kUint32LessThanOrEqual: | 559 case IrOpcode::kUint32LessThanOrEqual: |
547 case IrOpcode::kUint32Mod: { | 560 case IrOpcode::kUint32Mod: |
| 561 case IrOpcode::kUint32MulHigh: { |
548 // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the | 562 // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the |
549 // zero-extension is a no-op. | 563 // zero-extension is a no-op. |
550 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); | 564 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); |
551 return; | 565 return; |
552 } | 566 } |
553 default: | 567 default: |
554 break; | 568 break; |
555 } | 569 } |
556 Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value)); | 570 Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value)); |
557 } | 571 } |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 if (CpuFeatures::IsSupported(SSE4_1)) { | 1070 if (CpuFeatures::IsSupported(SSE4_1)) { |
1057 return MachineOperatorBuilder::kFloat64Floor | | 1071 return MachineOperatorBuilder::kFloat64Floor | |
1058 MachineOperatorBuilder::kFloat64Ceil | | 1072 MachineOperatorBuilder::kFloat64Ceil | |
1059 MachineOperatorBuilder::kFloat64RoundTruncate; | 1073 MachineOperatorBuilder::kFloat64RoundTruncate; |
1060 } | 1074 } |
1061 return MachineOperatorBuilder::kNoFlags; | 1075 return MachineOperatorBuilder::kNoFlags; |
1062 } | 1076 } |
1063 } // namespace compiler | 1077 } // namespace compiler |
1064 } // namespace internal | 1078 } // namespace internal |
1065 } // namespace v8 | 1079 } // namespace v8 |
OLD | NEW |