| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 auto imm = ImmediateOperand::cast(op); | 213 auto imm = ImmediateOperand::cast(op); |
| 210 int value = imm->type() == ImmediateOperand::INLINE | 214 int value = imm->type() == ImmediateOperand::INLINE |
| 211 ? imm->inline_value() | 215 ? imm->inline_value() |
| 212 : imm->indexed_value(); | 216 : imm->indexed_value(); |
| 213 CHECK_EQ(value, constraint->value_); | 217 CHECK_EQ(value, constraint->value_); |
| 214 return; | 218 return; |
| 215 } | 219 } |
| 216 case kRegister: | 220 case kRegister: |
| 217 CHECK(op->IsRegister()); | 221 CHECK(op->IsRegister()); |
| 218 return; | 222 return; |
| 219 case kFixedRegister: | |
| 220 CHECK(op->IsRegister()); | |
| 221 CHECK_EQ(RegisterOperand::cast(op)->GetDoubleRegister().code(), | |
| 222 constraint->value_); | |
| 223 return; | |
| 224 case kDoubleRegister: | 223 case kDoubleRegister: |
| 225 CHECK(op->IsDoubleRegister()); | 224 CHECK(op->IsDoubleRegister()); |
| 226 return; | 225 return; |
| 226 case kExplicit: |
| 227 CHECK(op->IsExplicit()); |
| 228 return; |
| 229 case kFixedRegister: |
| 230 CHECK(op->IsRegister()); |
| 231 CHECK_EQ(LocationOperand::cast(op)->GetRegister().code(), |
| 232 constraint->value_); |
| 233 return; |
| 227 case kFixedDoubleRegister: | 234 case kFixedDoubleRegister: |
| 228 CHECK(op->IsDoubleRegister()); | 235 CHECK(op->IsDoubleRegister()); |
| 229 CHECK_EQ(DoubleRegisterOperand::cast(op)->GetDoubleRegister().code(), | 236 CHECK_EQ(LocationOperand::cast(op)->GetDoubleRegister().code(), |
| 230 constraint->value_); | 237 constraint->value_); |
| 231 return; | 238 return; |
| 232 case kFixedSlot: | 239 case kFixedSlot: |
| 233 CHECK(op->IsStackSlot()); | 240 CHECK(op->IsStackSlot()); |
| 234 CHECK_EQ(StackSlotOperand::cast(op)->index(), constraint->value_); | 241 CHECK_EQ(LocationOperand::cast(op)->index(), constraint->value_); |
| 235 return; | 242 return; |
| 236 case kSlot: | 243 case kSlot: |
| 237 CHECK(op->IsStackSlot()); | 244 CHECK(op->IsStackSlot()); |
| 238 return; | 245 return; |
| 239 case kDoubleSlot: | 246 case kDoubleSlot: |
| 240 CHECK(op->IsDoubleStackSlot()); | 247 CHECK(op->IsDoubleStackSlot()); |
| 241 return; | 248 return; |
| 242 case kNone: | 249 case kNone: |
| 243 CHECK(op->IsRegister() || op->IsStackSlot()); | 250 CHECK(op->IsRegister() || op->IsStackSlot()); |
| 244 return; | 251 return; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 }; | 284 }; |
| 278 | 285 |
| 279 class PhiMap : public ZoneMap<int, PhiData*>, public ZoneObject { | 286 class PhiMap : public ZoneMap<int, PhiData*>, public ZoneObject { |
| 280 public: | 287 public: |
| 281 explicit PhiMap(Zone* zone) : ZoneMap<int, PhiData*>(zone) {} | 288 explicit PhiMap(Zone* zone) : ZoneMap<int, PhiData*>(zone) {} |
| 282 }; | 289 }; |
| 283 | 290 |
| 284 struct OperandLess { | 291 struct OperandLess { |
| 285 bool operator()(const InstructionOperand* a, | 292 bool operator()(const InstructionOperand* a, |
| 286 const InstructionOperand* b) const { | 293 const InstructionOperand* b) const { |
| 287 return a->CompareModuloType(*b); | 294 return a->CompareCanonicalizeType(*b); |
| 288 } | 295 } |
| 289 }; | 296 }; |
| 290 | 297 |
| 291 class OperandMap : public ZoneObject { | 298 class OperandMap : public ZoneObject { |
| 292 public: | 299 public: |
| 293 struct MapValue : public ZoneObject { | 300 struct MapValue : public ZoneObject { |
| 294 MapValue() | 301 MapValue() |
| 295 : incoming(nullptr), | 302 : incoming(nullptr), |
| 296 define_vreg(kInvalidVreg), | 303 define_vreg(kInvalidVreg), |
| 297 use_vreg(kInvalidVreg), | 304 use_vreg(kInvalidVreg), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 311 // Remove all entries with keys not in other. | 318 // Remove all entries with keys not in other. |
| 312 void Intersect(const Map& other) { | 319 void Intersect(const Map& other) { |
| 313 if (this->empty()) return; | 320 if (this->empty()) return; |
| 314 auto it = this->begin(); | 321 auto it = this->begin(); |
| 315 OperandLess less; | 322 OperandLess less; |
| 316 for (const auto& o : other) { | 323 for (const auto& o : other) { |
| 317 while (less(it->first, o.first)) { | 324 while (less(it->first, o.first)) { |
| 318 this->erase(it++); | 325 this->erase(it++); |
| 319 if (it == this->end()) return; | 326 if (it == this->end()) return; |
| 320 } | 327 } |
| 321 if (it->first->EqualsModuloType(*o.first)) { | 328 if (it->first->EqualsCanonicalizeType(*o.first)) { |
| 322 ++it; | 329 ++it; |
| 323 if (it == this->end()) return; | 330 if (it == this->end()) return; |
| 324 } else { | 331 } else { |
| 325 CHECK(less(o.first, it->first)); | 332 CHECK(less(o.first, it->first)); |
| 326 } | 333 } |
| 327 } | 334 } |
| 328 } | 335 } |
| 329 }; | 336 }; |
| 330 | 337 |
| 331 explicit OperandMap(Zone* zone) : map_(zone) {} | 338 explicit OperandMap(Zone* zone) : map_(zone) {} |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 auto current = block_maps->InitializeIncoming(block_index, initial_pass); | 678 auto current = block_maps->InitializeIncoming(block_index, initial_pass); |
| 672 const auto block = sequence()->instruction_blocks()[block_index]; | 679 const auto block = sequence()->instruction_blocks()[block_index]; |
| 673 for (int instr_index = block->code_start(); instr_index < block->code_end(); | 680 for (int instr_index = block->code_start(); instr_index < block->code_end(); |
| 674 ++instr_index) { | 681 ++instr_index) { |
| 675 const auto& instr_constraint = constraints_[instr_index]; | 682 const auto& instr_constraint = constraints_[instr_index]; |
| 676 const auto instr = instr_constraint.instruction_; | 683 const auto instr = instr_constraint.instruction_; |
| 677 current->RunGaps(zone(), instr); | 684 current->RunGaps(zone(), instr); |
| 678 const auto op_constraints = instr_constraint.operand_constraints_; | 685 const auto op_constraints = instr_constraint.operand_constraints_; |
| 679 size_t count = 0; | 686 size_t count = 0; |
| 680 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { | 687 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { |
| 681 if (op_constraints[count].type_ == kImmediate) continue; | 688 if (op_constraints[count].type_ == kImmediate || |
| 689 op_constraints[count].type_ == kExplicit) { |
| 690 continue; |
| 691 } |
| 682 int virtual_register = op_constraints[count].virtual_register_; | 692 int virtual_register = op_constraints[count].virtual_register_; |
| 683 auto op = instr->InputAt(i); | 693 auto op = instr->InputAt(i); |
| 684 if (!block_maps->IsPhi(virtual_register)) { | 694 if (!block_maps->IsPhi(virtual_register)) { |
| 685 current->Use(op, virtual_register, initial_pass); | 695 current->Use(op, virtual_register, initial_pass); |
| 686 } else { | 696 } else { |
| 687 auto phi = block_maps->GetPhi(virtual_register); | 697 auto phi = block_maps->GetPhi(virtual_register); |
| 688 current->UsePhi(op, phi, initial_pass); | 698 current->UsePhi(op, phi, initial_pass); |
| 689 } | 699 } |
| 690 } | 700 } |
| 691 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { | 701 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { |
| 692 current->Drop(instr->TempAt(i)); | 702 current->Drop(instr->TempAt(i)); |
| 693 } | 703 } |
| 694 if (instr->IsCall()) { | 704 if (instr->IsCall()) { |
| 695 current->DropRegisters(config()); | 705 current->DropRegisters(config()); |
| 696 } | 706 } |
| 697 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { | 707 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { |
| 698 int virtual_register = op_constraints[count].virtual_register_; | 708 int virtual_register = op_constraints[count].virtual_register_; |
| 699 current->Define(zone(), instr->OutputAt(i), virtual_register); | 709 current->Define(zone(), instr->OutputAt(i), virtual_register); |
| 700 } | 710 } |
| 701 } | 711 } |
| 702 } | 712 } |
| 703 } | 713 } |
| 704 | 714 |
| 705 } // namespace compiler | 715 } // namespace compiler |
| 706 } // namespace internal | 716 } // namespace internal |
| 707 } // namespace v8 | 717 } // namespace v8 |
| OLD | NEW |