| 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 #ifndef V8_COMPILER_INSTRUCTION_H_ | 5 #ifndef V8_COMPILER_INSTRUCTION_H_ |
| 6 #define V8_COMPILER_INSTRUCTION_H_ | 6 #define V8_COMPILER_INSTRUCTION_H_ |
| 7 | 7 |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <iosfwd> | 9 #include <iosfwd> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 // Forward declarations. | 26 // Forward declarations. |
| 27 class Schedule; | 27 class Schedule; |
| 28 | 28 |
| 29 | 29 |
| 30 class InstructionOperand { | 30 class InstructionOperand { |
| 31 public: | 31 public: |
| 32 static const int kInvalidVirtualRegister = -1; | 32 static const int kInvalidVirtualRegister = -1; |
| 33 | 33 |
| 34 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with | 34 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with |
| 35 // kInvalidVirtualRegister and some DCHECKS. | 35 // kInvalidVirtualRegister and some DCHECKS. |
| 36 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, EXPLICIT, ALLOCATED }; | 36 enum Kind { |
| 37 INVALID, |
| 38 UNALLOCATED, |
| 39 CONSTANT, |
| 40 IMMEDIATE, |
| 41 // Location operand kinds. |
| 42 EXPLICIT, |
| 43 ALLOCATED, |
| 44 FIRST_LOCATION_OPERAND_KIND = EXPLICIT |
| 45 // Location operand kinds must be last. |
| 46 }; |
| 37 | 47 |
| 38 InstructionOperand() : InstructionOperand(INVALID) {} | 48 InstructionOperand() : InstructionOperand(INVALID) {} |
| 39 | 49 |
| 40 Kind kind() const { return KindField::decode(value_); } | 50 Kind kind() const { return KindField::decode(value_); } |
| 41 | 51 |
| 42 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ | 52 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |
| 43 bool Is##name() const { return kind() == type; } | 53 bool Is##name() const { return kind() == type; } |
| 44 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) | 54 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
| 45 // UnallocatedOperands are place-holder operands created before register | 55 // UnallocatedOperands are place-holder operands created before register |
| 46 // allocation. They later are assigned registers and become AllocatedOperands. | 56 // allocation. They later are assigned registers and become AllocatedOperands. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 57 // ExplicitOperands do not participate in register allocation. They are | 67 // ExplicitOperands do not participate in register allocation. They are |
| 58 // created by the instruction selector for direct access to registers and | 68 // created by the instruction selector for direct access to registers and |
| 59 // stack slots, completely bypassing the register allocator. They are never | 69 // stack slots, completely bypassing the register allocator. They are never |
| 60 // associated with a virtual register | 70 // associated with a virtual register |
| 61 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT) | 71 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT) |
| 62 // AllocatedOperands are registers or stack slots that are assigned by the | 72 // AllocatedOperands are registers or stack slots that are assigned by the |
| 63 // register allocator and are always associated with a virtual register. | 73 // register allocator and are always associated with a virtual register. |
| 64 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) | 74 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) |
| 65 #undef INSTRUCTION_OPERAND_PREDICATE | 75 #undef INSTRUCTION_OPERAND_PREDICATE |
| 66 | 76 |
| 77 inline bool IsAnyLocationOperand() const; |
| 78 inline bool IsLocationOperand() const; |
| 79 inline bool IsFPLocationOperand() const; |
| 67 inline bool IsAnyRegister() const; | 80 inline bool IsAnyRegister() const; |
| 68 inline bool IsRegister() const; | 81 inline bool IsRegister() const; |
| 69 inline bool IsFPRegister() const; | 82 inline bool IsFPRegister() const; |
| 70 inline bool IsFloatRegister() const; | 83 inline bool IsFloatRegister() const; |
| 71 inline bool IsDoubleRegister() const; | 84 inline bool IsDoubleRegister() const; |
| 72 inline bool IsSimd128Register() const; | 85 inline bool IsSimd128Register() const; |
| 86 inline bool IsAnyStackSlot() const; |
| 73 inline bool IsStackSlot() const; | 87 inline bool IsStackSlot() const; |
| 74 inline bool IsFPStackSlot() const; | 88 inline bool IsFPStackSlot() const; |
| 75 inline bool IsFloatStackSlot() const; | 89 inline bool IsFloatStackSlot() const; |
| 76 inline bool IsDoubleStackSlot() const; | 90 inline bool IsDoubleStackSlot() const; |
| 77 inline bool IsSimd128StackSlot() const; | 91 inline bool IsSimd128StackSlot() const; |
| 78 | 92 |
| 79 template <typename SubKindOperand> | 93 template <typename SubKindOperand> |
| 80 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { | 94 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { |
| 81 void* buffer = zone->New(sizeof(op)); | 95 void* buffer = zone->New(sizeof(op)); |
| 82 return new (buffer) SubKindOperand(op); | 96 return new (buffer) SubKindOperand(op); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 case MachineRepresentation::kWord8: | 489 case MachineRepresentation::kWord8: |
| 476 case MachineRepresentation::kWord16: | 490 case MachineRepresentation::kWord16: |
| 477 case MachineRepresentation::kNone: | 491 case MachineRepresentation::kNone: |
| 478 return false; | 492 return false; |
| 479 } | 493 } |
| 480 UNREACHABLE(); | 494 UNREACHABLE(); |
| 481 return false; | 495 return false; |
| 482 } | 496 } |
| 483 | 497 |
| 484 static LocationOperand* cast(InstructionOperand* op) { | 498 static LocationOperand* cast(InstructionOperand* op) { |
| 485 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind()); | 499 DCHECK(op->IsAnyLocationOperand()); |
| 486 return static_cast<LocationOperand*>(op); | 500 return static_cast<LocationOperand*>(op); |
| 487 } | 501 } |
| 488 | 502 |
| 489 static const LocationOperand* cast(const InstructionOperand* op) { | 503 static const LocationOperand* cast(const InstructionOperand* op) { |
| 490 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind()); | 504 DCHECK(op->IsAnyLocationOperand()); |
| 491 return static_cast<const LocationOperand*>(op); | 505 return static_cast<const LocationOperand*>(op); |
| 492 } | 506 } |
| 493 | 507 |
| 494 static LocationOperand cast(const InstructionOperand& op) { | 508 static LocationOperand cast(const InstructionOperand& op) { |
| 495 DCHECK(ALLOCATED == op.kind() || EXPLICIT == op.kind()); | 509 DCHECK(op.IsAnyLocationOperand()); |
| 496 return *static_cast<const LocationOperand*>(&op); | 510 return *static_cast<const LocationOperand*>(&op); |
| 497 } | 511 } |
| 498 | 512 |
| 499 STATIC_ASSERT(KindField::kSize == 3); | 513 STATIC_ASSERT(KindField::kSize == 3); |
| 500 class LocationKindField : public BitField64<LocationKind, 3, 2> {}; | 514 class LocationKindField : public BitField64<LocationKind, 3, 2> {}; |
| 501 class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {}; | 515 class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {}; |
| 502 class IndexField : public BitField64<int32_t, 35, 29> {}; | 516 class IndexField : public BitField64<int32_t, 35, 29> {}; |
| 503 }; | 517 }; |
| 504 | 518 |
| 505 | 519 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 525 MachineRepresentation rep, int index) { | 539 MachineRepresentation rep, int index) { |
| 526 return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index)); | 540 return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index)); |
| 527 } | 541 } |
| 528 | 542 |
| 529 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); | 543 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); |
| 530 }; | 544 }; |
| 531 | 545 |
| 532 | 546 |
| 533 #undef INSTRUCTION_OPERAND_CASTS | 547 #undef INSTRUCTION_OPERAND_CASTS |
| 534 | 548 |
| 549 bool InstructionOperand::IsAnyLocationOperand() const { |
| 550 return this->kind() >= FIRST_LOCATION_OPERAND_KIND; |
| 551 } |
| 552 |
| 553 bool InstructionOperand::IsLocationOperand() const { |
| 554 return IsAnyLocationOperand() && |
| 555 !IsFloatingPoint(LocationOperand::cast(this)->representation()); |
| 556 } |
| 557 |
| 558 bool InstructionOperand::IsFPLocationOperand() const { |
| 559 return IsAnyLocationOperand() && |
| 560 IsFloatingPoint(LocationOperand::cast(this)->representation()); |
| 561 } |
| 535 | 562 |
| 536 bool InstructionOperand::IsAnyRegister() const { | 563 bool InstructionOperand::IsAnyRegister() const { |
| 537 return (IsAllocated() || IsExplicit()) && | 564 return IsAnyLocationOperand() && |
| 538 LocationOperand::cast(this)->location_kind() == | 565 LocationOperand::cast(this)->location_kind() == |
| 539 LocationOperand::REGISTER; | 566 LocationOperand::REGISTER; |
| 540 } | 567 } |
| 541 | 568 |
| 542 | 569 |
| 543 bool InstructionOperand::IsRegister() const { | 570 bool InstructionOperand::IsRegister() const { |
| 544 return IsAnyRegister() && | 571 return IsAnyRegister() && |
| 545 !IsFloatingPoint(LocationOperand::cast(this)->representation()); | 572 !IsFloatingPoint(LocationOperand::cast(this)->representation()); |
| 546 } | 573 } |
| 547 | 574 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 561 LocationOperand::cast(this)->representation() == | 588 LocationOperand::cast(this)->representation() == |
| 562 MachineRepresentation::kFloat64; | 589 MachineRepresentation::kFloat64; |
| 563 } | 590 } |
| 564 | 591 |
| 565 bool InstructionOperand::IsSimd128Register() const { | 592 bool InstructionOperand::IsSimd128Register() const { |
| 566 return IsAnyRegister() && | 593 return IsAnyRegister() && |
| 567 LocationOperand::cast(this)->representation() == | 594 LocationOperand::cast(this)->representation() == |
| 568 MachineRepresentation::kSimd128; | 595 MachineRepresentation::kSimd128; |
| 569 } | 596 } |
| 570 | 597 |
| 598 bool InstructionOperand::IsAnyStackSlot() const { |
| 599 return IsAnyLocationOperand() && |
| 600 LocationOperand::cast(this)->location_kind() == |
| 601 LocationOperand::STACK_SLOT; |
| 602 } |
| 603 |
| 571 bool InstructionOperand::IsStackSlot() const { | 604 bool InstructionOperand::IsStackSlot() const { |
| 572 return (IsAllocated() || IsExplicit()) && | 605 return IsAnyStackSlot() && |
| 573 LocationOperand::cast(this)->location_kind() == | |
| 574 LocationOperand::STACK_SLOT && | |
| 575 !IsFloatingPoint(LocationOperand::cast(this)->representation()); | 606 !IsFloatingPoint(LocationOperand::cast(this)->representation()); |
| 576 } | 607 } |
| 577 | 608 |
| 578 bool InstructionOperand::IsFPStackSlot() const { | 609 bool InstructionOperand::IsFPStackSlot() const { |
| 579 return (IsAllocated() || IsExplicit()) && | 610 return IsAnyStackSlot() && |
| 580 LocationOperand::cast(this)->location_kind() == | |
| 581 LocationOperand::STACK_SLOT && | |
| 582 IsFloatingPoint(LocationOperand::cast(this)->representation()); | 611 IsFloatingPoint(LocationOperand::cast(this)->representation()); |
| 583 } | 612 } |
| 584 | 613 |
| 585 bool InstructionOperand::IsFloatStackSlot() const { | 614 bool InstructionOperand::IsFloatStackSlot() const { |
| 586 return (IsAllocated() || IsExplicit()) && | 615 return IsAnyLocationOperand() && |
| 587 LocationOperand::cast(this)->location_kind() == | 616 LocationOperand::cast(this)->location_kind() == |
| 588 LocationOperand::STACK_SLOT && | 617 LocationOperand::STACK_SLOT && |
| 589 LocationOperand::cast(this)->representation() == | 618 LocationOperand::cast(this)->representation() == |
| 590 MachineRepresentation::kFloat32; | 619 MachineRepresentation::kFloat32; |
| 591 } | 620 } |
| 592 | 621 |
| 593 bool InstructionOperand::IsDoubleStackSlot() const { | 622 bool InstructionOperand::IsDoubleStackSlot() const { |
| 594 return (IsAllocated() || IsExplicit()) && | 623 return IsAnyLocationOperand() && |
| 595 LocationOperand::cast(this)->location_kind() == | 624 LocationOperand::cast(this)->location_kind() == |
| 596 LocationOperand::STACK_SLOT && | 625 LocationOperand::STACK_SLOT && |
| 597 LocationOperand::cast(this)->representation() == | 626 LocationOperand::cast(this)->representation() == |
| 598 MachineRepresentation::kFloat64; | 627 MachineRepresentation::kFloat64; |
| 599 } | 628 } |
| 600 | 629 |
| 601 bool InstructionOperand::IsSimd128StackSlot() const { | 630 bool InstructionOperand::IsSimd128StackSlot() const { |
| 602 return (IsAllocated() || IsExplicit()) && | 631 return IsAnyLocationOperand() && |
| 603 LocationOperand::cast(this)->location_kind() == | 632 LocationOperand::cast(this)->location_kind() == |
| 604 LocationOperand::STACK_SLOT && | 633 LocationOperand::STACK_SLOT && |
| 605 LocationOperand::cast(this)->representation() == | 634 LocationOperand::cast(this)->representation() == |
| 606 MachineRepresentation::kSimd128; | 635 MachineRepresentation::kSimd128; |
| 607 } | 636 } |
| 608 | 637 |
| 609 uint64_t InstructionOperand::GetCanonicalizedValue() const { | 638 uint64_t InstructionOperand::GetCanonicalizedValue() const { |
| 610 if (IsAllocated() || IsExplicit()) { | 639 if (IsAnyLocationOperand()) { |
| 611 MachineRepresentation canonical = MachineRepresentation::kNone; | 640 MachineRepresentation canonical = MachineRepresentation::kNone; |
| 612 if (IsFPRegister()) { | 641 if (IsFPRegister()) { |
| 613 // We treat all FP register operands the same for simple aliasing. | 642 // We treat all FP register operands the same for simple aliasing. |
| 614 canonical = MachineRepresentation::kFloat64; | 643 canonical = MachineRepresentation::kFloat64; |
| 615 } | 644 } |
| 616 return InstructionOperand::KindField::update( | 645 return InstructionOperand::KindField::update( |
| 617 LocationOperand::RepresentationField::update(this->value_, canonical), | 646 LocationOperand::RepresentationField::update(this->value_, canonical), |
| 618 LocationOperand::EXPLICIT); | 647 LocationOperand::EXPLICIT); |
| 619 } | 648 } |
| 620 return this->value_; | 649 return this->value_; |
| (...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1502 | 1531 |
| 1503 | 1532 |
| 1504 std::ostream& operator<<(std::ostream& os, | 1533 std::ostream& operator<<(std::ostream& os, |
| 1505 const PrintableInstructionSequence& code); | 1534 const PrintableInstructionSequence& code); |
| 1506 | 1535 |
| 1507 } // namespace compiler | 1536 } // namespace compiler |
| 1508 } // namespace internal | 1537 } // namespace internal |
| 1509 } // namespace v8 | 1538 } // namespace v8 |
| 1510 | 1539 |
| 1511 #endif // V8_COMPILER_INSTRUCTION_H_ | 1540 #endif // V8_COMPILER_INSTRUCTION_H_ |
| OLD | NEW |