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 |