| 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 { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 } | 41 } |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 | 44 |
| 45 } // namespace | 45 } // namespace |
| 46 | 46 |
| 47 | 47 |
| 48 void RegisterAllocatorVerifier::VerifyInput( | 48 void RegisterAllocatorVerifier::VerifyInput( |
| 49 const OperandConstraint& constraint) { | 49 const OperandConstraint& constraint) { |
| 50 CHECK_NE(kSameAsFirst, constraint.type_); | 50 CHECK_NE(kSameAsFirst, constraint.type_); |
| 51 if (constraint.type_ != kImmediate) { | 51 if (constraint.type_ != kImmediate && constraint.type_ != kExplicit) { |
| 52 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, | 52 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, |
| 53 constraint.virtual_register_); | 53 constraint.virtual_register_); |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 | 56 |
| 57 | 57 |
| 58 void RegisterAllocatorVerifier::VerifyTemp( | 58 void RegisterAllocatorVerifier::VerifyTemp( |
| 59 const OperandConstraint& constraint) { | 59 const OperandConstraint& constraint) { |
| 60 CHECK_NE(kSameAsFirst, constraint.type_); | 60 CHECK_NE(kSameAsFirst, constraint.type_); |
| 61 CHECK_NE(kImmediate, constraint.type_); | 61 CHECK_NE(kImmediate, constraint.type_); |
| 62 CHECK_NE(kExplicit, constraint.type_); |
| 62 CHECK_NE(kConstant, constraint.type_); | 63 CHECK_NE(kConstant, constraint.type_); |
| 63 } | 64 } |
| 64 | 65 |
| 65 | 66 |
| 66 void RegisterAllocatorVerifier::VerifyOutput( | 67 void RegisterAllocatorVerifier::VerifyOutput( |
| 67 const OperandConstraint& constraint) { | 68 const OperandConstraint& constraint) { |
| 68 CHECK_NE(kImmediate, constraint.type_); | 69 CHECK_NE(kImmediate, constraint.type_); |
| 70 CHECK_NE(kExplicit, constraint.type_); |
| 69 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, | 71 CHECK_NE(InstructionOperand::kInvalidVirtualRegister, |
| 70 constraint.virtual_register_); | 72 constraint.virtual_register_); |
| 71 } | 73 } |
| 72 | 74 |
| 73 | 75 |
| 74 RegisterAllocatorVerifier::RegisterAllocatorVerifier( | 76 RegisterAllocatorVerifier::RegisterAllocatorVerifier( |
| 75 Zone* zone, const RegisterConfiguration* config, | 77 Zone* zone, const RegisterConfiguration* config, |
| 76 const InstructionSequence* sequence) | 78 const InstructionSequence* sequence) |
| 77 : zone_(zone), config_(config), sequence_(sequence), constraints_(zone) { | 79 : zone_(zone), config_(config), sequence_(sequence), constraints_(zone) { |
| 78 constraints_.reserve(sequence->instructions().size()); | 80 constraints_.reserve(sequence->instructions().size()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 | 138 |
| 137 | 139 |
| 138 void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op, | 140 void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op, |
| 139 OperandConstraint* constraint) { | 141 OperandConstraint* constraint) { |
| 140 constraint->value_ = kMinInt; | 142 constraint->value_ = kMinInt; |
| 141 constraint->virtual_register_ = InstructionOperand::kInvalidVirtualRegister; | 143 constraint->virtual_register_ = InstructionOperand::kInvalidVirtualRegister; |
| 142 if (op->IsConstant()) { | 144 if (op->IsConstant()) { |
| 143 constraint->type_ = kConstant; | 145 constraint->type_ = kConstant; |
| 144 constraint->value_ = ConstantOperand::cast(op)->virtual_register(); | 146 constraint->value_ = ConstantOperand::cast(op)->virtual_register(); |
| 145 constraint->virtual_register_ = constraint->value_; | 147 constraint->virtual_register_ = constraint->value_; |
| 148 } else if (op->IsExplicit()) { |
| 149 constraint->type_ = kExplicit; |
| 146 } else if (op->IsImmediate()) { | 150 } else if (op->IsImmediate()) { |
| 147 auto imm = ImmediateOperand::cast(op); | 151 auto imm = ImmediateOperand::cast(op); |
| 148 int value = imm->type() == ImmediateOperand::INLINE ? imm->inline_value() | 152 int value = imm->type() == ImmediateOperand::INLINE ? imm->inline_value() |
| 149 : imm->indexed_value(); | 153 : imm->indexed_value(); |
| 150 constraint->type_ = kImmediate; | 154 constraint->type_ = kImmediate; |
| 151 constraint->value_ = value; | 155 constraint->value_ = value; |
| 152 } else { | 156 } else { |
| 153 CHECK(op->IsUnallocated()); | 157 CHECK(op->IsUnallocated()); |
| 154 const auto* unallocated = UnallocatedOperand::cast(op); | 158 const auto* unallocated = UnallocatedOperand::cast(op); |
| 155 int vreg = unallocated->virtual_register(); | 159 int vreg = unallocated->virtual_register(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 auto imm = ImmediateOperand::cast(op); | 211 auto imm = ImmediateOperand::cast(op); |
| 208 int value = imm->type() == ImmediateOperand::INLINE | 212 int value = imm->type() == ImmediateOperand::INLINE |
| 209 ? imm->inline_value() | 213 ? imm->inline_value() |
| 210 : imm->indexed_value(); | 214 : imm->indexed_value(); |
| 211 CHECK_EQ(value, constraint->value_); | 215 CHECK_EQ(value, constraint->value_); |
| 212 return; | 216 return; |
| 213 } | 217 } |
| 214 case kRegister: | 218 case kRegister: |
| 215 CHECK(op->IsRegister()); | 219 CHECK(op->IsRegister()); |
| 216 return; | 220 return; |
| 217 case kFixedRegister: | |
| 218 CHECK(op->IsRegister()); | |
| 219 CHECK_EQ(RegisterOperand::cast(op)->GetDoubleRegister().code(), | |
| 220 constraint->value_); | |
| 221 return; | |
| 222 case kDoubleRegister: | 221 case kDoubleRegister: |
| 223 CHECK(op->IsDoubleRegister()); | 222 CHECK(op->IsDoubleRegister()); |
| 224 return; | 223 return; |
| 224 case kExplicit: |
| 225 CHECK(op->IsExplicit()); |
| 226 return; |
| 227 case kFixedRegister: |
| 228 CHECK(op->IsRegister()); |
| 229 CHECK_EQ(LocationOperand::cast(op)->GetRegister().code(), |
| 230 constraint->value_); |
| 231 return; |
| 225 case kFixedDoubleRegister: | 232 case kFixedDoubleRegister: |
| 226 CHECK(op->IsDoubleRegister()); | 233 CHECK(op->IsDoubleRegister()); |
| 227 CHECK_EQ(DoubleRegisterOperand::cast(op)->GetDoubleRegister().code(), | 234 CHECK_EQ(LocationOperand::cast(op)->GetDoubleRegister().code(), |
| 228 constraint->value_); | 235 constraint->value_); |
| 229 return; | 236 return; |
| 230 case kFixedSlot: | 237 case kFixedSlot: |
| 231 CHECK(op->IsStackSlot()); | 238 CHECK(op->IsStackSlot()); |
| 232 CHECK_EQ(StackSlotOperand::cast(op)->index(), constraint->value_); | 239 CHECK_EQ(LocationOperand::cast(op)->index(), constraint->value_); |
| 233 return; | 240 return; |
| 234 case kSlot: | 241 case kSlot: |
| 235 CHECK(op->IsStackSlot()); | 242 CHECK(op->IsStackSlot()); |
| 236 return; | 243 return; |
| 237 case kDoubleSlot: | 244 case kDoubleSlot: |
| 238 CHECK(op->IsDoubleStackSlot()); | 245 CHECK(op->IsDoubleStackSlot()); |
| 239 return; | 246 return; |
| 240 case kNone: | 247 case kNone: |
| 241 CHECK(op->IsRegister() || op->IsStackSlot()); | 248 CHECK(op->IsRegister() || op->IsStackSlot()); |
| 242 return; | 249 return; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 }; | 282 }; |
| 276 | 283 |
| 277 class PhiMap : public ZoneMap<int, PhiData*>, public ZoneObject { | 284 class PhiMap : public ZoneMap<int, PhiData*>, public ZoneObject { |
| 278 public: | 285 public: |
| 279 explicit PhiMap(Zone* zone) : ZoneMap<int, PhiData*>(zone) {} | 286 explicit PhiMap(Zone* zone) : ZoneMap<int, PhiData*>(zone) {} |
| 280 }; | 287 }; |
| 281 | 288 |
| 282 struct OperandLess { | 289 struct OperandLess { |
| 283 bool operator()(const InstructionOperand* a, | 290 bool operator()(const InstructionOperand* a, |
| 284 const InstructionOperand* b) const { | 291 const InstructionOperand* b) const { |
| 285 return a->CompareModuloType(*b); | 292 return a->CompareCanonicalized(*b); |
| 286 } | 293 } |
| 287 }; | 294 }; |
| 288 | 295 |
| 289 class OperandMap : public ZoneObject { | 296 class OperandMap : public ZoneObject { |
| 290 public: | 297 public: |
| 291 struct MapValue : public ZoneObject { | 298 struct MapValue : public ZoneObject { |
| 292 MapValue() | 299 MapValue() |
| 293 : incoming(nullptr), | 300 : incoming(nullptr), |
| 294 define_vreg(kInvalidVreg), | 301 define_vreg(kInvalidVreg), |
| 295 use_vreg(kInvalidVreg), | 302 use_vreg(kInvalidVreg), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 309 // Remove all entries with keys not in other. | 316 // Remove all entries with keys not in other. |
| 310 void Intersect(const Map& other) { | 317 void Intersect(const Map& other) { |
| 311 if (this->empty()) return; | 318 if (this->empty()) return; |
| 312 auto it = this->begin(); | 319 auto it = this->begin(); |
| 313 OperandLess less; | 320 OperandLess less; |
| 314 for (const auto& o : other) { | 321 for (const auto& o : other) { |
| 315 while (less(it->first, o.first)) { | 322 while (less(it->first, o.first)) { |
| 316 this->erase(it++); | 323 this->erase(it++); |
| 317 if (it == this->end()) return; | 324 if (it == this->end()) return; |
| 318 } | 325 } |
| 319 if (it->first->EqualsModuloType(*o.first)) { | 326 if (it->first->EqualsCanonicalized(*o.first)) { |
| 320 ++it; | 327 ++it; |
| 321 if (it == this->end()) return; | 328 if (it == this->end()) return; |
| 322 } else { | 329 } else { |
| 323 CHECK(less(o.first, it->first)); | 330 CHECK(less(o.first, it->first)); |
| 324 } | 331 } |
| 325 } | 332 } |
| 326 } | 333 } |
| 327 }; | 334 }; |
| 328 | 335 |
| 329 explicit OperandMap(Zone* zone) : map_(zone) {} | 336 explicit OperandMap(Zone* zone) : map_(zone) {} |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 auto current = block_maps->InitializeIncoming(block_index, initial_pass); | 676 auto current = block_maps->InitializeIncoming(block_index, initial_pass); |
| 670 const auto block = sequence()->instruction_blocks()[block_index]; | 677 const auto block = sequence()->instruction_blocks()[block_index]; |
| 671 for (int instr_index = block->code_start(); instr_index < block->code_end(); | 678 for (int instr_index = block->code_start(); instr_index < block->code_end(); |
| 672 ++instr_index) { | 679 ++instr_index) { |
| 673 const auto& instr_constraint = constraints_[instr_index]; | 680 const auto& instr_constraint = constraints_[instr_index]; |
| 674 const auto instr = instr_constraint.instruction_; | 681 const auto instr = instr_constraint.instruction_; |
| 675 current->RunGaps(zone(), instr); | 682 current->RunGaps(zone(), instr); |
| 676 const auto op_constraints = instr_constraint.operand_constraints_; | 683 const auto op_constraints = instr_constraint.operand_constraints_; |
| 677 size_t count = 0; | 684 size_t count = 0; |
| 678 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { | 685 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { |
| 679 if (op_constraints[count].type_ == kImmediate) continue; | 686 if (op_constraints[count].type_ == kImmediate || |
| 687 op_constraints[count].type_ == kExplicit) { |
| 688 continue; |
| 689 } |
| 680 int virtual_register = op_constraints[count].virtual_register_; | 690 int virtual_register = op_constraints[count].virtual_register_; |
| 681 auto op = instr->InputAt(i); | 691 auto op = instr->InputAt(i); |
| 682 if (!block_maps->IsPhi(virtual_register)) { | 692 if (!block_maps->IsPhi(virtual_register)) { |
| 683 current->Use(op, virtual_register, initial_pass); | 693 current->Use(op, virtual_register, initial_pass); |
| 684 } else { | 694 } else { |
| 685 auto phi = block_maps->GetPhi(virtual_register); | 695 auto phi = block_maps->GetPhi(virtual_register); |
| 686 current->UsePhi(op, phi, initial_pass); | 696 current->UsePhi(op, phi, initial_pass); |
| 687 } | 697 } |
| 688 } | 698 } |
| 689 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { | 699 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { |
| 690 current->Drop(instr->TempAt(i)); | 700 current->Drop(instr->TempAt(i)); |
| 691 } | 701 } |
| 692 if (instr->IsCall()) { | 702 if (instr->IsCall()) { |
| 693 current->DropRegisters(config()); | 703 current->DropRegisters(config()); |
| 694 } | 704 } |
| 695 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { | 705 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { |
| 696 int virtual_register = op_constraints[count].virtual_register_; | 706 int virtual_register = op_constraints[count].virtual_register_; |
| 697 current->Define(zone(), instr->OutputAt(i), virtual_register); | 707 current->Define(zone(), instr->OutputAt(i), virtual_register); |
| 698 } | 708 } |
| 699 } | 709 } |
| 700 } | 710 } |
| 701 } | 711 } |
| 702 | 712 |
| 703 } // namespace compiler | 713 } // namespace compiler |
| 704 } // namespace internal | 714 } // namespace internal |
| 705 } // namespace v8 | 715 } // namespace v8 |
| OLD | NEW |