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 |