| 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 namespace { |
| 14 |
| 15 size_t OperandCount(const Instruction* instr) { |
| 14 return instr->InputCount() + instr->OutputCount() + instr->TempCount(); | 16 return instr->InputCount() + instr->OutputCount() + instr->TempCount(); |
| 15 } | 17 } |
| 16 | 18 |
| 17 | 19 |
| 18 static void VerifyEmptyGaps(const Instruction* instr) { | 20 void VerifyEmptyGaps(const Instruction* instr) { |
| 19 for (int i = Instruction::FIRST_GAP_POSITION; | 21 for (int i = Instruction::FIRST_GAP_POSITION; |
| 20 i <= Instruction::LAST_GAP_POSITION; i++) { | 22 i <= Instruction::LAST_GAP_POSITION; i++) { |
| 21 Instruction::GapPosition inner_pos = | 23 Instruction::GapPosition inner_pos = |
| 22 static_cast<Instruction::GapPosition>(i); | 24 static_cast<Instruction::GapPosition>(i); |
| 23 CHECK(instr->GetParallelMove(inner_pos) == nullptr); | 25 CHECK(instr->GetParallelMove(inner_pos) == nullptr); |
| 24 } | 26 } |
| 25 } | 27 } |
| 26 | 28 |
| 27 | 29 |
| 30 void VerifyAllocatedGaps(const Instruction* instr) { |
| 31 for (int i = Instruction::FIRST_GAP_POSITION; |
| 32 i <= Instruction::LAST_GAP_POSITION; i++) { |
| 33 Instruction::GapPosition inner_pos = |
| 34 static_cast<Instruction::GapPosition>(i); |
| 35 auto moves = instr->GetParallelMove(inner_pos); |
| 36 if (moves == nullptr) continue; |
| 37 for (auto move : *moves) { |
| 38 if (move->IsRedundant()) continue; |
| 39 CHECK(move->source().IsAllocated() || move->source().IsConstant()); |
| 40 CHECK(move->destination().IsAllocated()); |
| 41 } |
| 42 } |
| 43 } |
| 44 |
| 45 } // namespace |
| 46 |
| 47 |
| 28 void RegisterAllocatorVerifier::VerifyInput( | 48 void RegisterAllocatorVerifier::VerifyInput( |
| 29 const OperandConstraint& constraint) { | 49 const OperandConstraint& constraint) { |
| 30 CHECK_NE(kSameAsFirst, constraint.type_); | 50 CHECK_NE(kSameAsFirst, constraint.type_); |
| 31 if (constraint.type_ != kImmediate) { | 51 if (constraint.type_ != kImmediate) { |
| 32 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, | 52 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, |
| 33 constraint.virtual_register_); | 53 constraint.virtual_register_); |
| 34 } | 54 } |
| 35 } | 55 } |
| 36 | 56 |
| 37 | 57 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 constraints()->push_back(instr_constraint); | 107 constraints()->push_back(instr_constraint); |
| 88 } | 108 } |
| 89 } | 109 } |
| 90 | 110 |
| 91 | 111 |
| 92 void RegisterAllocatorVerifier::VerifyAssignment() { | 112 void RegisterAllocatorVerifier::VerifyAssignment() { |
| 93 CHECK(sequence()->instructions().size() == constraints()->size()); | 113 CHECK(sequence()->instructions().size() == constraints()->size()); |
| 94 auto instr_it = sequence()->begin(); | 114 auto instr_it = sequence()->begin(); |
| 95 for (const auto& instr_constraint : *constraints()) { | 115 for (const auto& instr_constraint : *constraints()) { |
| 96 const auto* instr = instr_constraint.instruction_; | 116 const auto* instr = instr_constraint.instruction_; |
| 117 // All gaps should be totally allocated at this point. |
| 118 VerifyAllocatedGaps(instr); |
| 97 const size_t operand_count = instr_constraint.operand_constaints_size_; | 119 const size_t operand_count = instr_constraint.operand_constaints_size_; |
| 98 const auto* op_constraints = instr_constraint.operand_constraints_; | 120 const auto* op_constraints = instr_constraint.operand_constraints_; |
| 99 CHECK_EQ(instr, *instr_it); | 121 CHECK_EQ(instr, *instr_it); |
| 100 CHECK(operand_count == OperandCount(instr)); | 122 CHECK(operand_count == OperandCount(instr)); |
| 101 size_t count = 0; | 123 size_t count = 0; |
| 102 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { | 124 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { |
| 103 CheckConstraint(instr->InputAt(i), &op_constraints[count]); | 125 CheckConstraint(instr->InputAt(i), &op_constraints[count]); |
| 104 } | 126 } |
| 105 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { | 127 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { |
| 106 CheckConstraint(instr->TempAt(i), &op_constraints[count]); | 128 CheckConstraint(instr->TempAt(i), &op_constraints[count]); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 // Remove all entries with keys not in other. | 313 // Remove all entries with keys not in other. |
| 292 void Intersect(const Map& other) { | 314 void Intersect(const Map& other) { |
| 293 if (this->empty()) return; | 315 if (this->empty()) return; |
| 294 auto it = this->begin(); | 316 auto it = this->begin(); |
| 295 OperandLess less; | 317 OperandLess less; |
| 296 for (const auto& o : other) { | 318 for (const auto& o : other) { |
| 297 while (less(it->first, o.first)) { | 319 while (less(it->first, o.first)) { |
| 298 this->erase(it++); | 320 this->erase(it++); |
| 299 if (it == this->end()) return; | 321 if (it == this->end()) return; |
| 300 } | 322 } |
| 301 if (it->first->Equals(o.first)) { | 323 if (*it->first == *o.first) { |
| 302 ++it; | 324 ++it; |
| 303 if (it == this->end()) return; | 325 if (it == this->end()) return; |
| 304 } else { | 326 } else { |
| 305 CHECK(less(o.first, it->first)); | 327 CHECK(less(o.first, it->first)); |
| 306 } | 328 } |
| 307 } | 329 } |
| 308 } | 330 } |
| 309 }; | 331 }; |
| 310 | 332 |
| 311 explicit OperandMap(Zone* zone) : map_(zone) {} | 333 explicit OperandMap(Zone* zone) : map_(zone) {} |
| 312 | 334 |
| 313 Map& map() { return map_; } | 335 Map& map() { return map_; } |
| 314 | 336 |
| 315 void RunParallelMoves(Zone* zone, const ParallelMove* move) { | 337 void RunParallelMoves(Zone* zone, const ParallelMove* moves) { |
| 316 // Compute outgoing mappings. | 338 // Compute outgoing mappings. |
| 317 Map to_insert(zone); | 339 Map to_insert(zone); |
| 318 auto moves = move->move_operands(); | 340 for (auto move : *moves) { |
| 319 for (auto i = moves->begin(); i != moves->end(); ++i) { | 341 if (move->IsEliminated()) continue; |
| 320 if (i->IsEliminated()) continue; | 342 auto cur = map().find(&move->source()); |
| 321 auto cur = map().find(i->source()); | |
| 322 CHECK(cur != map().end()); | 343 CHECK(cur != map().end()); |
| 323 auto res = | 344 auto res = |
| 324 to_insert.insert(std::make_pair(i->destination(), cur->second)); | 345 to_insert.insert(std::make_pair(&move->destination(), cur->second)); |
| 325 // Ensure injectivity of moves. | 346 // Ensure injectivity of moves. |
| 326 CHECK(res.second); | 347 CHECK(res.second); |
| 327 } | 348 } |
| 328 // Drop current mappings. | 349 // Drop current mappings. |
| 329 for (auto i = moves->begin(); i != moves->end(); ++i) { | 350 for (auto move : *moves) { |
| 330 if (i->IsEliminated()) continue; | 351 if (move->IsEliminated()) continue; |
| 331 auto cur = map().find(i->destination()); | 352 auto cur = map().find(&move->destination()); |
| 332 if (cur != map().end()) map().erase(cur); | 353 if (cur != map().end()) map().erase(cur); |
| 333 } | 354 } |
| 334 // Insert new values. | 355 // Insert new values. |
| 335 map().insert(to_insert.begin(), to_insert.end()); | 356 map().insert(to_insert.begin(), to_insert.end()); |
| 336 } | 357 } |
| 337 | 358 |
| 338 void RunGaps(Zone* zone, const Instruction* instr) { | 359 void RunGaps(Zone* zone, const Instruction* instr) { |
| 339 for (int i = Instruction::FIRST_GAP_POSITION; | 360 for (int i = Instruction::FIRST_GAP_POSITION; |
| 340 i <= Instruction::LAST_GAP_POSITION; i++) { | 361 i <= Instruction::LAST_GAP_POSITION; i++) { |
| 341 auto inner_pos = static_cast<Instruction::GapPosition>(i); | 362 auto inner_pos = static_cast<Instruction::GapPosition>(i); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 int virtual_register = op_constraints[count].virtual_register_; | 699 int virtual_register = op_constraints[count].virtual_register_; |
| 679 current->Define(zone(), instr->OutputAt(i), virtual_register); | 700 current->Define(zone(), instr->OutputAt(i), virtual_register); |
| 680 } | 701 } |
| 681 } | 702 } |
| 682 } | 703 } |
| 683 } | 704 } |
| 684 | 705 |
| 685 } // namespace compiler | 706 } // namespace compiler |
| 686 } // namespace internal | 707 } // namespace internal |
| 687 } // namespace v8 | 708 } // namespace v8 |
| OLD | NEW |