| 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/bit-vector.h" | 5 #include "src/bit-vector.h" |
| 6 #include "src/compiler/instruction.h" | 6 #include "src/compiler/instruction.h" |
| 7 #include "src/compiler/register-allocator-verifier.h" | 7 #include "src/compiler/register-allocator-verifier.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| 11 namespace compiler { | 11 namespace compiler { |
| 12 | 12 |
| 13 static size_t OperandCount(const Instruction* instr) { | 13 static size_t OperandCount(const Instruction* instr) { |
| 14 return instr->InputCount() + instr->OutputCount() + instr->TempCount(); | 14 return instr->InputCount() + instr->OutputCount() + instr->TempCount(); |
| 15 } | 15 } |
| 16 | 16 |
| 17 | 17 |
| 18 static void VerifyGapEmpty(const GapInstruction* gap) { | 18 static void VerifyEmptyGaps(const Instruction* instr) { |
| 19 for (int i = GapInstruction::FIRST_INNER_POSITION; | 19 for (int i = Instruction::FIRST_GAP_POSITION; |
| 20 i <= GapInstruction::LAST_INNER_POSITION; i++) { | 20 i <= Instruction::LAST_GAP_POSITION; i++) { |
| 21 GapInstruction::InnerPosition inner_pos = | 21 Instruction::GapPosition inner_pos = |
| 22 static_cast<GapInstruction::InnerPosition>(i); | 22 static_cast<Instruction::GapPosition>(i); |
| 23 CHECK(!gap->GetParallelMove(inner_pos)); | 23 CHECK(instr->GetParallelMove(inner_pos) == nullptr); |
| 24 } | 24 } |
| 25 } | 25 } |
| 26 | 26 |
| 27 | 27 |
| 28 void RegisterAllocatorVerifier::VerifyInput( | 28 void RegisterAllocatorVerifier::VerifyInput( |
| 29 const OperandConstraint& constraint) { | 29 const OperandConstraint& constraint) { |
| 30 CHECK_NE(kSameAsFirst, constraint.type_); | 30 CHECK_NE(kSameAsFirst, constraint.type_); |
| 31 if (constraint.type_ != kImmediate) { | 31 if (constraint.type_ != kImmediate) { |
| 32 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, | 32 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, |
| 33 constraint.virtual_register_); | 33 constraint.virtual_register_); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 53 | 53 |
| 54 RegisterAllocatorVerifier::RegisterAllocatorVerifier( | 54 RegisterAllocatorVerifier::RegisterAllocatorVerifier( |
| 55 Zone* zone, const RegisterConfiguration* config, | 55 Zone* zone, const RegisterConfiguration* config, |
| 56 const InstructionSequence* sequence) | 56 const InstructionSequence* sequence) |
| 57 : zone_(zone), config_(config), sequence_(sequence), constraints_(zone) { | 57 : zone_(zone), config_(config), sequence_(sequence), constraints_(zone) { |
| 58 constraints_.reserve(sequence->instructions().size()); | 58 constraints_.reserve(sequence->instructions().size()); |
| 59 // TODO(dcarney): model unique constraints. | 59 // TODO(dcarney): model unique constraints. |
| 60 // Construct OperandConstraints for all InstructionOperands, eliminating | 60 // Construct OperandConstraints for all InstructionOperands, eliminating |
| 61 // kSameAsFirst along the way. | 61 // kSameAsFirst along the way. |
| 62 for (const auto* instr : sequence->instructions()) { | 62 for (const auto* instr : sequence->instructions()) { |
| 63 // All gaps should be totally unallocated at this point. |
| 64 VerifyEmptyGaps(instr); |
| 63 const size_t operand_count = OperandCount(instr); | 65 const size_t operand_count = OperandCount(instr); |
| 64 auto* op_constraints = zone->NewArray<OperandConstraint>(operand_count); | 66 auto* op_constraints = zone->NewArray<OperandConstraint>(operand_count); |
| 65 size_t count = 0; | 67 size_t count = 0; |
| 66 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { | 68 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { |
| 67 BuildConstraint(instr->InputAt(i), &op_constraints[count]); | 69 BuildConstraint(instr->InputAt(i), &op_constraints[count]); |
| 68 VerifyInput(op_constraints[count]); | 70 VerifyInput(op_constraints[count]); |
| 69 } | 71 } |
| 70 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { | 72 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { |
| 71 BuildConstraint(instr->TempAt(i), &op_constraints[count]); | 73 BuildConstraint(instr->TempAt(i), &op_constraints[count]); |
| 72 VerifyTemp(op_constraints[count]); | 74 VerifyTemp(op_constraints[count]); |
| 73 } | 75 } |
| 74 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { | 76 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { |
| 75 BuildConstraint(instr->OutputAt(i), &op_constraints[count]); | 77 BuildConstraint(instr->OutputAt(i), &op_constraints[count]); |
| 76 if (op_constraints[count].type_ == kSameAsFirst) { | 78 if (op_constraints[count].type_ == kSameAsFirst) { |
| 77 CHECK(instr->InputCount() > 0); | 79 CHECK(instr->InputCount() > 0); |
| 78 op_constraints[count].type_ = op_constraints[0].type_; | 80 op_constraints[count].type_ = op_constraints[0].type_; |
| 79 op_constraints[count].value_ = op_constraints[0].value_; | 81 op_constraints[count].value_ = op_constraints[0].value_; |
| 80 } | 82 } |
| 81 VerifyOutput(op_constraints[count]); | 83 VerifyOutput(op_constraints[count]); |
| 82 } | 84 } |
| 83 // All gaps should be totally unallocated at this point. | |
| 84 if (instr->IsGapMoves()) { | |
| 85 CHECK(operand_count == 0); | |
| 86 VerifyGapEmpty(GapInstruction::cast(instr)); | |
| 87 } | |
| 88 InstructionConstraint instr_constraint = {instr, operand_count, | 85 InstructionConstraint instr_constraint = {instr, operand_count, |
| 89 op_constraints}; | 86 op_constraints}; |
| 90 constraints()->push_back(instr_constraint); | 87 constraints()->push_back(instr_constraint); |
| 91 } | 88 } |
| 92 } | 89 } |
| 93 | 90 |
| 94 | 91 |
| 95 void RegisterAllocatorVerifier::VerifyAssignment() { | 92 void RegisterAllocatorVerifier::VerifyAssignment() { |
| 96 CHECK(sequence()->instructions().size() == constraints()->size()); | 93 CHECK(sequence()->instructions().size() == constraints()->size()); |
| 97 auto instr_it = sequence()->begin(); | 94 auto instr_it = sequence()->begin(); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 // Drop current mappings. | 319 // Drop current mappings. |
| 323 for (auto i = moves->begin(); i != moves->end(); ++i) { | 320 for (auto i = moves->begin(); i != moves->end(); ++i) { |
| 324 if (i->IsEliminated()) continue; | 321 if (i->IsEliminated()) continue; |
| 325 auto cur = map().find(i->destination()); | 322 auto cur = map().find(i->destination()); |
| 326 if (cur != map().end()) map().erase(cur); | 323 if (cur != map().end()) map().erase(cur); |
| 327 } | 324 } |
| 328 // Insert new values. | 325 // Insert new values. |
| 329 map().insert(to_insert.begin(), to_insert.end()); | 326 map().insert(to_insert.begin(), to_insert.end()); |
| 330 } | 327 } |
| 331 | 328 |
| 332 void RunGapInstruction(Zone* zone, const GapInstruction* gap) { | 329 void RunGaps(Zone* zone, const Instruction* instr) { |
| 333 for (int i = GapInstruction::FIRST_INNER_POSITION; | 330 for (int i = Instruction::FIRST_GAP_POSITION; |
| 334 i <= GapInstruction::LAST_INNER_POSITION; i++) { | 331 i <= Instruction::LAST_GAP_POSITION; i++) { |
| 335 auto inner_pos = static_cast<GapInstruction::InnerPosition>(i); | 332 auto inner_pos = static_cast<Instruction::GapPosition>(i); |
| 336 auto move = gap->GetParallelMove(inner_pos); | 333 auto move = instr->GetParallelMove(inner_pos); |
| 337 if (move == nullptr) continue; | 334 if (move == nullptr) continue; |
| 338 RunParallelMoves(zone, move); | 335 RunParallelMoves(zone, move); |
| 339 } | 336 } |
| 340 } | 337 } |
| 341 | 338 |
| 342 void Drop(const InstructionOperand* op) { | 339 void Drop(const InstructionOperand* op) { |
| 343 auto it = map().find(op); | 340 auto it = map().find(op); |
| 344 if (it != map().end()) map().erase(it); | 341 if (it != map().end()) map().erase(it); |
| 345 } | 342 } |
| 346 | 343 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 void RegisterAllocatorVerifier::VerifyGapMoves(BlockMaps* block_maps, | 638 void RegisterAllocatorVerifier::VerifyGapMoves(BlockMaps* block_maps, |
| 642 bool initial_pass) { | 639 bool initial_pass) { |
| 643 const size_t block_count = sequence()->instruction_blocks().size(); | 640 const size_t block_count = sequence()->instruction_blocks().size(); |
| 644 for (size_t block_index = 0; block_index < block_count; ++block_index) { | 641 for (size_t block_index = 0; block_index < block_count; ++block_index) { |
| 645 auto current = block_maps->InitializeIncoming(block_index, initial_pass); | 642 auto current = block_maps->InitializeIncoming(block_index, initial_pass); |
| 646 const auto block = sequence()->instruction_blocks()[block_index]; | 643 const auto block = sequence()->instruction_blocks()[block_index]; |
| 647 for (int instr_index = block->code_start(); instr_index < block->code_end(); | 644 for (int instr_index = block->code_start(); instr_index < block->code_end(); |
| 648 ++instr_index) { | 645 ++instr_index) { |
| 649 const auto& instr_constraint = constraints_[instr_index]; | 646 const auto& instr_constraint = constraints_[instr_index]; |
| 650 const auto instr = instr_constraint.instruction_; | 647 const auto instr = instr_constraint.instruction_; |
| 651 if (instr->IsSourcePosition()) continue; | 648 current->RunGaps(zone(), instr); |
| 652 if (instr->IsGapMoves()) { | |
| 653 current->RunGapInstruction(zone(), GapInstruction::cast(instr)); | |
| 654 continue; | |
| 655 } | |
| 656 const auto op_constraints = instr_constraint.operand_constraints_; | 649 const auto op_constraints = instr_constraint.operand_constraints_; |
| 657 size_t count = 0; | 650 size_t count = 0; |
| 658 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { | 651 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { |
| 659 if (op_constraints[count].type_ == kImmediate) continue; | 652 if (op_constraints[count].type_ == kImmediate) continue; |
| 660 int virtual_register = op_constraints[count].virtual_register_; | 653 int virtual_register = op_constraints[count].virtual_register_; |
| 661 auto op = instr->InputAt(i); | 654 auto op = instr->InputAt(i); |
| 662 if (!block_maps->IsPhi(virtual_register)) { | 655 if (!block_maps->IsPhi(virtual_register)) { |
| 663 current->Use(op, virtual_register, initial_pass); | 656 current->Use(op, virtual_register, initial_pass); |
| 664 } else { | 657 } else { |
| 665 auto phi = block_maps->GetPhi(virtual_register); | 658 auto phi = block_maps->GetPhi(virtual_register); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 676 int virtual_register = op_constraints[count].virtual_register_; | 669 int virtual_register = op_constraints[count].virtual_register_; |
| 677 current->Define(zone(), instr->OutputAt(i), virtual_register); | 670 current->Define(zone(), instr->OutputAt(i), virtual_register); |
| 678 } | 671 } |
| 679 } | 672 } |
| 680 } | 673 } |
| 681 } | 674 } |
| 682 | 675 |
| 683 } // namespace compiler | 676 } // namespace compiler |
| 684 } // namespace internal | 677 } // namespace internal |
| 685 } // namespace v8 | 678 } // namespace v8 |
| OLD | NEW |