Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(622)

Side by Side Diff: src/compiler/register-allocator-verifier.cc

Issue 1740543002: [turbofan] removed "auto" from register-allocator-verifier (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 14 matching lines...) Expand all
25 CHECK(instr->GetParallelMove(inner_pos) == nullptr); 25 CHECK(instr->GetParallelMove(inner_pos) == nullptr);
26 } 26 }
27 } 27 }
28 28
29 29
30 void VerifyAllocatedGaps(const Instruction* instr) { 30 void VerifyAllocatedGaps(const Instruction* instr) {
31 for (int i = Instruction::FIRST_GAP_POSITION; 31 for (int i = Instruction::FIRST_GAP_POSITION;
32 i <= Instruction::LAST_GAP_POSITION; i++) { 32 i <= Instruction::LAST_GAP_POSITION; i++) {
33 Instruction::GapPosition inner_pos = 33 Instruction::GapPosition inner_pos =
34 static_cast<Instruction::GapPosition>(i); 34 static_cast<Instruction::GapPosition>(i);
35 auto moves = instr->GetParallelMove(inner_pos); 35 const ParallelMove* moves = instr->GetParallelMove(inner_pos);
36 if (moves == nullptr) continue; 36 if (moves == nullptr) continue;
37 for (auto move : *moves) { 37 for (const MoveOperands* move : *moves) {
38 if (move->IsRedundant()) continue; 38 if (move->IsRedundant()) continue;
39 CHECK(move->source().IsAllocated() || move->source().IsConstant()); 39 CHECK(move->source().IsAllocated() || move->source().IsConstant());
40 CHECK(move->destination().IsAllocated()); 40 CHECK(move->destination().IsAllocated());
41 } 41 }
42 } 42 }
43 } 43 }
44 44
45 } // namespace 45 } // namespace
46 46
47 47
(...skipping 26 matching lines...) Expand all
74 74
75 75
76 RegisterAllocatorVerifier::RegisterAllocatorVerifier( 76 RegisterAllocatorVerifier::RegisterAllocatorVerifier(
77 Zone* zone, const RegisterConfiguration* config, 77 Zone* zone, const RegisterConfiguration* config,
78 const InstructionSequence* sequence) 78 const InstructionSequence* sequence)
79 : zone_(zone), config_(config), sequence_(sequence), constraints_(zone) { 79 : zone_(zone), config_(config), sequence_(sequence), constraints_(zone) {
80 constraints_.reserve(sequence->instructions().size()); 80 constraints_.reserve(sequence->instructions().size());
81 // TODO(dcarney): model unique constraints. 81 // TODO(dcarney): model unique constraints.
82 // Construct OperandConstraints for all InstructionOperands, eliminating 82 // Construct OperandConstraints for all InstructionOperands, eliminating
83 // kSameAsFirst along the way. 83 // kSameAsFirst along the way.
84 for (const auto* instr : sequence->instructions()) { 84 for (const Instruction* instr : sequence->instructions()) {
85 // All gaps should be totally unallocated at this point. 85 // All gaps should be totally unallocated at this point.
86 VerifyEmptyGaps(instr); 86 VerifyEmptyGaps(instr);
87 const size_t operand_count = OperandCount(instr); 87 const size_t operand_count = OperandCount(instr);
88 auto* op_constraints = zone->NewArray<OperandConstraint>(operand_count); 88 OperandConstraint* op_constraints =
89 zone->NewArray<OperandConstraint>(operand_count);
89 size_t count = 0; 90 size_t count = 0;
90 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { 91 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) {
91 BuildConstraint(instr->InputAt(i), &op_constraints[count]); 92 BuildConstraint(instr->InputAt(i), &op_constraints[count]);
92 VerifyInput(op_constraints[count]); 93 VerifyInput(op_constraints[count]);
93 } 94 }
94 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { 95 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) {
95 BuildConstraint(instr->TempAt(i), &op_constraints[count]); 96 BuildConstraint(instr->TempAt(i), &op_constraints[count]);
96 VerifyTemp(op_constraints[count]); 97 VerifyTemp(op_constraints[count]);
97 } 98 }
98 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { 99 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) {
99 BuildConstraint(instr->OutputAt(i), &op_constraints[count]); 100 BuildConstraint(instr->OutputAt(i), &op_constraints[count]);
100 if (op_constraints[count].type_ == kSameAsFirst) { 101 if (op_constraints[count].type_ == kSameAsFirst) {
101 CHECK(instr->InputCount() > 0); 102 CHECK(instr->InputCount() > 0);
102 op_constraints[count].type_ = op_constraints[0].type_; 103 op_constraints[count].type_ = op_constraints[0].type_;
103 op_constraints[count].value_ = op_constraints[0].value_; 104 op_constraints[count].value_ = op_constraints[0].value_;
104 } 105 }
105 VerifyOutput(op_constraints[count]); 106 VerifyOutput(op_constraints[count]);
106 } 107 }
107 InstructionConstraint instr_constraint = {instr, operand_count, 108 InstructionConstraint instr_constraint = {instr, operand_count,
108 op_constraints}; 109 op_constraints};
109 constraints()->push_back(instr_constraint); 110 constraints()->push_back(instr_constraint);
110 } 111 }
111 } 112 }
112 113
113 114
114 void RegisterAllocatorVerifier::VerifyAssignment() { 115 void RegisterAllocatorVerifier::VerifyAssignment() {
115 CHECK(sequence()->instructions().size() == constraints()->size()); 116 CHECK(sequence()->instructions().size() == constraints()->size());
116 auto instr_it = sequence()->begin(); 117 auto instr_it = sequence()->begin();
117 for (const auto& instr_constraint : *constraints()) { 118 for (const auto& instr_constraint : *constraints()) {
118 const auto* instr = instr_constraint.instruction_; 119 const Instruction* instr = instr_constraint.instruction_;
119 // All gaps should be totally allocated at this point. 120 // All gaps should be totally allocated at this point.
120 VerifyAllocatedGaps(instr); 121 VerifyAllocatedGaps(instr);
121 const size_t operand_count = instr_constraint.operand_constaints_size_; 122 const size_t operand_count = instr_constraint.operand_constaints_size_;
122 const auto* op_constraints = instr_constraint.operand_constraints_; 123 const OperandConstraint* op_constraints =
124 instr_constraint.operand_constraints_;
123 CHECK_EQ(instr, *instr_it); 125 CHECK_EQ(instr, *instr_it);
124 CHECK(operand_count == OperandCount(instr)); 126 CHECK(operand_count == OperandCount(instr));
125 size_t count = 0; 127 size_t count = 0;
126 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { 128 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) {
127 CheckConstraint(instr->InputAt(i), &op_constraints[count]); 129 CheckConstraint(instr->InputAt(i), &op_constraints[count]);
128 } 130 }
129 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { 131 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) {
130 CheckConstraint(instr->TempAt(i), &op_constraints[count]); 132 CheckConstraint(instr->TempAt(i), &op_constraints[count]);
131 } 133 }
132 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { 134 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) {
133 CheckConstraint(instr->OutputAt(i), &op_constraints[count]); 135 CheckConstraint(instr->OutputAt(i), &op_constraints[count]);
134 } 136 }
135 ++instr_it; 137 ++instr_it;
136 } 138 }
137 } 139 }
138 140
139 141
140 void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op, 142 void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op,
141 OperandConstraint* constraint) { 143 OperandConstraint* constraint) {
142 constraint->value_ = kMinInt; 144 constraint->value_ = kMinInt;
143 constraint->virtual_register_ = InstructionOperand::kInvalidVirtualRegister; 145 constraint->virtual_register_ = InstructionOperand::kInvalidVirtualRegister;
144 if (op->IsConstant()) { 146 if (op->IsConstant()) {
145 constraint->type_ = kConstant; 147 constraint->type_ = kConstant;
146 constraint->value_ = ConstantOperand::cast(op)->virtual_register(); 148 constraint->value_ = ConstantOperand::cast(op)->virtual_register();
147 constraint->virtual_register_ = constraint->value_; 149 constraint->virtual_register_ = constraint->value_;
148 } else if (op->IsExplicit()) { 150 } else if (op->IsExplicit()) {
149 constraint->type_ = kExplicit; 151 constraint->type_ = kExplicit;
150 } else if (op->IsImmediate()) { 152 } else if (op->IsImmediate()) {
151 auto imm = ImmediateOperand::cast(op); 153 const ImmediateOperand* imm = ImmediateOperand::cast(op);
152 int value = imm->type() == ImmediateOperand::INLINE ? imm->inline_value() 154 int value = imm->type() == ImmediateOperand::INLINE ? imm->inline_value()
153 : imm->indexed_value(); 155 : imm->indexed_value();
154 constraint->type_ = kImmediate; 156 constraint->type_ = kImmediate;
155 constraint->value_ = value; 157 constraint->value_ = value;
156 } else { 158 } else {
157 CHECK(op->IsUnallocated()); 159 CHECK(op->IsUnallocated());
158 const auto* unallocated = UnallocatedOperand::cast(op); 160 const UnallocatedOperand* unallocated = UnallocatedOperand::cast(op);
159 int vreg = unallocated->virtual_register(); 161 int vreg = unallocated->virtual_register();
160 constraint->virtual_register_ = vreg; 162 constraint->virtual_register_ = vreg;
161 if (unallocated->basic_policy() == UnallocatedOperand::FIXED_SLOT) { 163 if (unallocated->basic_policy() == UnallocatedOperand::FIXED_SLOT) {
162 constraint->type_ = sequence()->IsFloat(vreg) ? kDoubleSlot : kSlot; 164 constraint->type_ = sequence()->IsFloat(vreg) ? kDoubleSlot : kSlot;
163 constraint->value_ = unallocated->fixed_slot_index(); 165 constraint->value_ = unallocated->fixed_slot_index();
164 } else { 166 } else {
165 switch (unallocated->extended_policy()) { 167 switch (unallocated->extended_policy()) {
166 case UnallocatedOperand::ANY: 168 case UnallocatedOperand::ANY:
167 case UnallocatedOperand::NONE: 169 case UnallocatedOperand::NONE:
168 if (sequence()->IsFloat(vreg)) { 170 if (sequence()->IsFloat(vreg)) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 void RegisterAllocatorVerifier::CheckConstraint( 208 void RegisterAllocatorVerifier::CheckConstraint(
207 const InstructionOperand* op, const OperandConstraint* constraint) { 209 const InstructionOperand* op, const OperandConstraint* constraint) {
208 switch (constraint->type_) { 210 switch (constraint->type_) {
209 case kConstant: 211 case kConstant:
210 CHECK(op->IsConstant()); 212 CHECK(op->IsConstant());
211 CHECK_EQ(ConstantOperand::cast(op)->virtual_register(), 213 CHECK_EQ(ConstantOperand::cast(op)->virtual_register(),
212 constraint->value_); 214 constraint->value_);
213 return; 215 return;
214 case kImmediate: { 216 case kImmediate: {
215 CHECK(op->IsImmediate()); 217 CHECK(op->IsImmediate());
216 auto imm = ImmediateOperand::cast(op); 218 const ImmediateOperand* imm = ImmediateOperand::cast(op);
217 int value = imm->type() == ImmediateOperand::INLINE 219 int value = imm->type() == ImmediateOperand::INLINE
218 ? imm->inline_value() 220 ? imm->inline_value()
219 : imm->indexed_value(); 221 : imm->indexed_value();
220 CHECK_EQ(value, constraint->value_); 222 CHECK_EQ(value, constraint->value_);
221 return; 223 return;
222 } 224 }
223 case kRegister: 225 case kRegister:
224 CHECK(op->IsRegister()); 226 CHECK(op->IsRegister());
225 return; 227 return;
226 case kDoubleRegister: 228 case kDoubleRegister:
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 : public ZoneMap<const InstructionOperand*, MapValue*, OperandLess> { 319 : public ZoneMap<const InstructionOperand*, MapValue*, OperandLess> {
318 public: 320 public:
319 explicit Map(Zone* zone) 321 explicit Map(Zone* zone)
320 : ZoneMap<const InstructionOperand*, MapValue*, OperandLess>(zone) {} 322 : ZoneMap<const InstructionOperand*, MapValue*, OperandLess>(zone) {}
321 323
322 // Remove all entries with keys not in other. 324 // Remove all entries with keys not in other.
323 void Intersect(const Map& other) { 325 void Intersect(const Map& other) {
324 if (this->empty()) return; 326 if (this->empty()) return;
325 auto it = this->begin(); 327 auto it = this->begin();
326 OperandLess less; 328 OperandLess less;
327 for (const auto& o : other) { 329 for (const std::pair<const InstructionOperand*, MapValue*>& o : other) {
328 while (less(it->first, o.first)) { 330 while (less(it->first, o.first)) {
329 this->erase(it++); 331 this->erase(it++);
330 if (it == this->end()) return; 332 if (it == this->end()) return;
331 } 333 }
332 if (it->first->EqualsCanonicalized(*o.first)) { 334 if (it->first->EqualsCanonicalized(*o.first)) {
333 ++it; 335 ++it;
334 if (it == this->end()) return; 336 if (it == this->end()) return;
335 } else { 337 } else {
336 CHECK(less(o.first, it->first)); 338 CHECK(less(o.first, it->first));
337 } 339 }
338 } 340 }
339 } 341 }
340 }; 342 };
341 343
342 explicit OperandMap(Zone* zone) : map_(zone) {} 344 explicit OperandMap(Zone* zone) : map_(zone) {}
343 345
344 Map& map() { return map_; } 346 Map& map() { return map_; }
345 347
346 void RunParallelMoves(Zone* zone, const ParallelMove* moves) { 348 void RunParallelMoves(Zone* zone, const ParallelMove* moves) {
347 // Compute outgoing mappings. 349 // Compute outgoing mappings.
348 Map to_insert(zone); 350 Map to_insert(zone);
349 for (auto move : *moves) { 351 for (const MoveOperands* move : *moves) {
350 if (move->IsEliminated()) continue; 352 if (move->IsEliminated()) continue;
351 auto cur = map().find(&move->source()); 353 auto cur = map().find(&move->source());
352 CHECK(cur != map().end()); 354 CHECK(cur != map().end());
353 auto res = 355 auto res =
354 to_insert.insert(std::make_pair(&move->destination(), cur->second)); 356 to_insert.insert(std::make_pair(&move->destination(), cur->second));
355 // Ensure injectivity of moves. 357 // Ensure injectivity of moves.
356 CHECK(res.second); 358 CHECK(res.second);
357 } 359 }
358 // Drop current mappings. 360 // Drop current mappings.
359 for (auto move : *moves) { 361 for (const MoveOperands* move : *moves) {
360 if (move->IsEliminated()) continue; 362 if (move->IsEliminated()) continue;
361 auto cur = map().find(&move->destination()); 363 auto cur = map().find(&move->destination());
362 if (cur != map().end()) map().erase(cur); 364 if (cur != map().end()) map().erase(cur);
363 } 365 }
364 // Insert new values. 366 // Insert new values.
365 map().insert(to_insert.begin(), to_insert.end()); 367 map().insert(to_insert.begin(), to_insert.end());
366 } 368 }
367 369
368 void RunGaps(Zone* zone, const Instruction* instr) { 370 void RunGaps(Zone* zone, const Instruction* instr) {
369 for (int i = Instruction::FIRST_GAP_POSITION; 371 for (int i = Instruction::FIRST_GAP_POSITION;
370 i <= Instruction::LAST_GAP_POSITION; i++) { 372 i <= Instruction::LAST_GAP_POSITION; i++) {
371 auto inner_pos = static_cast<Instruction::GapPosition>(i); 373 Instruction::GapPosition inner_pos =
372 auto move = instr->GetParallelMove(inner_pos); 374 static_cast<Instruction::GapPosition>(i);
375 const ParallelMove* move = instr->GetParallelMove(inner_pos);
373 if (move == nullptr) continue; 376 if (move == nullptr) continue;
374 RunParallelMoves(zone, move); 377 RunParallelMoves(zone, move);
375 } 378 }
376 } 379 }
377 380
378 void Drop(const InstructionOperand* op) { 381 void Drop(const InstructionOperand* op) {
379 auto it = map().find(op); 382 auto it = map().find(op);
380 if (it != map().end()) map().erase(it); 383 if (it != map().end()) map().erase(it);
381 } 384 }
382 385
383 void DropRegisters(const RegisterConfiguration* config) { 386 void DropRegisters(const RegisterConfiguration* config) {
384 // TODO(dcarney): sort map by kind and drop range. 387 // TODO(dcarney): sort map by kind and drop range.
385 for (auto it = map().begin(); it != map().end();) { 388 for (auto it = map().begin(); it != map().end();) {
386 auto op = it->first; 389 const InstructionOperand* op = it->first;
387 if (op->IsRegister() || op->IsDoubleRegister()) { 390 if (op->IsRegister() || op->IsDoubleRegister()) {
388 map().erase(it++); 391 map().erase(it++);
389 } else { 392 } else {
390 ++it; 393 ++it;
391 } 394 }
392 } 395 }
393 } 396 }
394 397
395 MapValue* Define(Zone* zone, const InstructionOperand* op, 398 MapValue* Define(Zone* zone, const InstructionOperand* op,
396 int virtual_register) { 399 int virtual_register) {
397 auto value = new (zone) MapValue(); 400 MapValue* value = new (zone) MapValue();
398 value->define_vreg = virtual_register; 401 value->define_vreg = virtual_register;
399 auto res = map().insert(std::make_pair(op, value)); 402 auto res = map().insert(std::make_pair(op, value));
400 if (!res.second) res.first->second = value; 403 if (!res.second) res.first->second = value;
401 return value; 404 return value;
402 } 405 }
403 406
404 void Use(const InstructionOperand* op, int use_vreg, bool initial_pass) { 407 void Use(const InstructionOperand* op, int use_vreg, bool initial_pass) {
405 auto it = map().find(op); 408 auto it = map().find(op);
406 CHECK(it != map().end()); 409 CHECK(it != map().end());
407 auto v = it->second; 410 MapValue* v = it->second;
408 if (v->define_vreg != kInvalidVreg) { 411 if (v->define_vreg != kInvalidVreg) {
409 CHECK_EQ(v->define_vreg, use_vreg); 412 CHECK_EQ(v->define_vreg, use_vreg);
410 } 413 }
411 // Already used this vreg in this block. 414 // Already used this vreg in this block.
412 if (v->use_vreg != kInvalidVreg) { 415 if (v->use_vreg != kInvalidVreg) {
413 CHECK_EQ(v->use_vreg, use_vreg); 416 CHECK_EQ(v->use_vreg, use_vreg);
414 return; 417 return;
415 } 418 }
416 if (!initial_pass) { 419 if (!initial_pass) {
417 // A value may be defined and used in this block or the use must have 420 // A value may be defined and used in this block or the use must have
(...skipping 20 matching lines...) Expand all
438 return; 441 return;
439 } 442 }
440 // Use of a non-phi value without definition. 443 // Use of a non-phi value without definition.
441 CHECK(false); 444 CHECK(false);
442 } 445 }
443 446
444 void UsePhi(const InstructionOperand* op, const PhiData* phi, 447 void UsePhi(const InstructionOperand* op, const PhiData* phi,
445 bool initial_pass) { 448 bool initial_pass) {
446 auto it = map().find(op); 449 auto it = map().find(op);
447 CHECK(it != map().end()); 450 CHECK(it != map().end());
448 auto v = it->second; 451 MapValue* v = it->second;
449 int use_vreg = phi->virtual_register; 452 int use_vreg = phi->virtual_register;
450 // Phis are not defined. 453 // Phis are not defined.
451 CHECK_EQ(kInvalidVreg, v->define_vreg); 454 CHECK_EQ(kInvalidVreg, v->define_vreg);
452 // Already used this vreg in this block. 455 // Already used this vreg in this block.
453 if (v->use_vreg != kInvalidVreg) { 456 if (v->use_vreg != kInvalidVreg) {
454 CHECK_EQ(v->use_vreg, use_vreg); 457 CHECK_EQ(v->use_vreg, use_vreg);
455 return; 458 return;
456 } 459 }
457 if (!initial_pass) { 460 if (!initial_pass) {
458 // A used phi must have propagated its use to a predecessor. 461 // A used phi must have propagated its use to a predecessor.
459 CHECK_EQ(v->succ_vreg, use_vreg); 462 CHECK_EQ(v->succ_vreg, use_vreg);
460 // Mark the use. 463 // Mark the use.
461 v->use_vreg = use_vreg; 464 v->use_vreg = use_vreg;
462 return; 465 return;
463 } 466 }
464 // Go up the block list starting at the first predecessor and ensure this 467 // Go up the block list starting at the first predecessor and ensure this
465 // phi has a correct use or definition. 468 // phi has a correct use or definition.
466 for (v = v->incoming; v != nullptr; v = v->incoming) { 469 for (v = v->incoming; v != nullptr; v = v->incoming) {
467 // Value unused in block. 470 // Value unused in block.
468 if (v->define_vreg == kInvalidVreg && v->use_vreg == kInvalidVreg) { 471 if (v->define_vreg == kInvalidVreg && v->use_vreg == kInvalidVreg) {
469 continue; 472 continue;
470 } 473 }
471 // Found correct definition or use. 474 // Found correct definition or use.
472 if (v->define_vreg != kInvalidVreg) { 475 if (v->define_vreg != kInvalidVreg) {
473 CHECK(v->define_vreg == phi->first_pred_vreg); 476 CHECK(v->define_vreg == phi->first_pred_vreg);
474 } else if (v->use_vreg != phi->first_pred_vreg) { 477 } else if (v->use_vreg != phi->first_pred_vreg) {
475 // Walk the phi chain, hunting for a matching phi use. 478 // Walk the phi chain, hunting for a matching phi use.
476 auto p = phi; 479 const PhiData* p = phi;
477 for (; p != nullptr; p = p->first_pred_phi) { 480 for (; p != nullptr; p = p->first_pred_phi) {
478 if (p->virtual_register == v->use_vreg) break; 481 if (p->virtual_register == v->use_vreg) break;
479 } 482 }
480 CHECK(p); 483 CHECK(p);
481 } 484 }
482 // Mark the use. 485 // Mark the use.
483 it->second->use_vreg = use_vreg; 486 it->second->use_vreg = use_vreg;
484 return; 487 return;
485 } 488 }
486 // Use of a phi value without definition. 489 // Use of a phi value without definition.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 return initial_pass ? InitializeFromFirstPredecessor(block_index) 525 return initial_pass ? InitializeFromFirstPredecessor(block_index)
523 : InitializeFromIntersection(block_index); 526 : InitializeFromIntersection(block_index);
524 } 527 }
525 528
526 void PropagateUsesBackwards() { 529 void PropagateUsesBackwards() {
527 typedef std::set<size_t, std::greater<size_t>, zone_allocator<size_t>> 530 typedef std::set<size_t, std::greater<size_t>, zone_allocator<size_t>>
528 BlockIds; 531 BlockIds;
529 BlockIds block_ids((BlockIds::key_compare()), 532 BlockIds block_ids((BlockIds::key_compare()),
530 zone_allocator<size_t>(zone())); 533 zone_allocator<size_t>(zone()));
531 // First ensure that incoming contains only keys in all predecessors. 534 // First ensure that incoming contains only keys in all predecessors.
532 for (auto block : sequence()->instruction_blocks()) { 535 for (const InstructionBlock* block : sequence()->instruction_blocks()) {
533 size_t index = block->rpo_number().ToSize(); 536 size_t index = block->rpo_number().ToSize();
534 block_ids.insert(index); 537 block_ids.insert(index);
535 auto& succ_map = incoming_maps_[index]->map(); 538 OperandMap::Map& succ_map = incoming_maps_[index]->map();
536 for (size_t i = 0; i < block->PredecessorCount(); ++i) { 539 for (size_t i = 0; i < block->PredecessorCount(); ++i) {
537 auto pred_rpo = block->predecessors()[i]; 540 RpoNumber pred_rpo = block->predecessors()[i];
538 succ_map.Intersect(outgoing_maps_[pred_rpo.ToSize()]->map()); 541 succ_map.Intersect(outgoing_maps_[pred_rpo.ToSize()]->map());
539 } 542 }
540 } 543 }
541 // Back propagation fixpoint. 544 // Back propagation fixpoint.
542 while (!block_ids.empty()) { 545 while (!block_ids.empty()) {
543 // Pop highest block_id. 546 // Pop highest block_id.
544 auto block_id_it = block_ids.begin(); 547 auto block_id_it = block_ids.begin();
545 const size_t succ_index = *block_id_it; 548 const size_t succ_index = *block_id_it;
546 block_ids.erase(block_id_it); 549 block_ids.erase(block_id_it);
547 // Propagate uses back to their definition blocks using succ_vreg. 550 // Propagate uses back to their definition blocks using succ_vreg.
548 auto block = sequence()->instruction_blocks()[succ_index]; 551 const InstructionBlock* block =
549 auto& succ_map = incoming_maps_[succ_index]->map(); 552 sequence()->instruction_blocks()[succ_index];
553 OperandMap::Map& succ_map = incoming_maps_[succ_index]->map();
550 for (size_t i = 0; i < block->PredecessorCount(); ++i) { 554 for (size_t i = 0; i < block->PredecessorCount(); ++i) {
551 for (auto& succ_val : succ_map) { 555 for (auto& succ_val : succ_map) {
552 // An incoming map contains no defines. 556 // An incoming map contains no defines.
553 CHECK_EQ(kInvalidVreg, succ_val.second->define_vreg); 557 CHECK_EQ(kInvalidVreg, succ_val.second->define_vreg);
554 // Compute succ_vreg. 558 // Compute succ_vreg.
555 int succ_vreg = succ_val.second->succ_vreg; 559 int succ_vreg = succ_val.second->succ_vreg;
556 if (succ_vreg == kInvalidVreg) { 560 if (succ_vreg == kInvalidVreg) {
557 succ_vreg = succ_val.second->use_vreg; 561 succ_vreg = succ_val.second->use_vreg;
558 // Initialize succ_vreg in back propagation chain. 562 // Initialize succ_vreg in back propagation chain.
559 succ_val.second->succ_vreg = succ_vreg; 563 succ_val.second->succ_vreg = succ_vreg;
560 } 564 }
561 if (succ_vreg == kInvalidVreg) continue; 565 if (succ_vreg == kInvalidVreg) continue;
562 // May need to transition phi. 566 // May need to transition phi.
563 if (IsPhi(succ_vreg)) { 567 if (IsPhi(succ_vreg)) {
564 auto phi = GetPhi(succ_vreg); 568 const PhiData* phi = GetPhi(succ_vreg);
565 if (phi->definition_rpo.ToSize() == succ_index) { 569 if (phi->definition_rpo.ToSize() == succ_index) {
566 // phi definition block, transition to pred value. 570 // phi definition block, transition to pred value.
567 succ_vreg = phi->operands[i]; 571 succ_vreg = phi->operands[i];
568 } 572 }
569 } 573 }
570 // Push succ_vreg up to all predecessors. 574 // Push succ_vreg up to all predecessors.
571 auto pred_rpo = block->predecessors()[i]; 575 RpoNumber pred_rpo = block->predecessors()[i];
572 auto& pred_map = outgoing_maps_[pred_rpo.ToSize()]->map(); 576 OperandMap::Map& pred_map = outgoing_maps_[pred_rpo.ToSize()]->map();
573 auto& pred_val = *pred_map.find(succ_val.first); 577 auto& pred_val = *pred_map.find(succ_val.first);
574 if (pred_val.second->use_vreg != kInvalidVreg) { 578 if (pred_val.second->use_vreg != kInvalidVreg) {
575 CHECK_EQ(succ_vreg, pred_val.second->use_vreg); 579 CHECK_EQ(succ_vreg, pred_val.second->use_vreg);
576 } 580 }
577 if (pred_val.second->define_vreg != kInvalidVreg) { 581 if (pred_val.second->define_vreg != kInvalidVreg) {
578 CHECK_EQ(succ_vreg, pred_val.second->define_vreg); 582 CHECK_EQ(succ_vreg, pred_val.second->define_vreg);
579 } 583 }
580 if (pred_val.second->succ_vreg != kInvalidVreg) { 584 if (pred_val.second->succ_vreg != kInvalidVreg) {
581 if (succ_vreg != pred_val.second->succ_vreg) { 585 if (succ_vreg != pred_val.second->succ_vreg) {
582 // When a block introduces 2 identical phis A and B, and both are 586 // When a block introduces 2 identical phis A and B, and both are
(...skipping 16 matching lines...) Expand all
599 } 603 }
600 } 604 }
601 } else { 605 } else {
602 pred_val.second->succ_vreg = succ_vreg; 606 pred_val.second->succ_vreg = succ_vreg;
603 block_ids.insert(pred_rpo.ToSize()); 607 block_ids.insert(pred_rpo.ToSize());
604 } 608 }
605 } 609 }
606 } 610 }
607 } 611 }
608 // Clear uses and back links for second pass. 612 // Clear uses and back links for second pass.
609 for (auto operand_map : incoming_maps_) { 613 for (OperandMap* operand_map : incoming_maps_) {
610 for (auto& succ_val : operand_map->map()) { 614 for (auto& succ_val : operand_map->map()) {
611 succ_val.second->incoming = nullptr; 615 succ_val.second->incoming = nullptr;
612 succ_val.second->use_vreg = kInvalidVreg; 616 succ_val.second->use_vreg = kInvalidVreg;
613 } 617 }
614 } 618 }
615 } 619 }
616 620
617 private: 621 private:
618 OperandMap* InitializeFromFirstPredecessor(size_t block_index) { 622 OperandMap* InitializeFromFirstPredecessor(size_t block_index) {
619 auto to_init = outgoing_maps_[block_index]; 623 OperandMap* to_init = outgoing_maps_[block_index];
620 CHECK(to_init->map().empty()); 624 CHECK(to_init->map().empty());
621 auto block = sequence()->instruction_blocks()[block_index]; 625 const InstructionBlock* block =
626 sequence()->instruction_blocks()[block_index];
622 if (block->predecessors().empty()) return to_init; 627 if (block->predecessors().empty()) return to_init;
623 size_t predecessor_index = block->predecessors()[0].ToSize(); 628 size_t predecessor_index = block->predecessors()[0].ToSize();
624 // Ensure not a backedge. 629 // Ensure not a backedge.
625 CHECK(predecessor_index < block->rpo_number().ToSize()); 630 CHECK(predecessor_index < block->rpo_number().ToSize());
626 auto incoming = outgoing_maps_[predecessor_index]; 631 OperandMap* incoming = outgoing_maps_[predecessor_index];
627 // Copy map and replace values. 632 // Copy map and replace values.
628 to_init->map() = incoming->map(); 633 to_init->map() = incoming->map();
629 for (auto& it : to_init->map()) { 634 for (auto& it : to_init->map()) {
630 auto incoming = it.second; 635 OperandMap::MapValue* incoming = it.second;
631 it.second = new (zone()) OperandMap::MapValue(); 636 it.second = new (zone()) OperandMap::MapValue();
632 it.second->incoming = incoming; 637 it.second->incoming = incoming;
633 } 638 }
634 // Copy to incoming map for second pass. 639 // Copy to incoming map for second pass.
635 incoming_maps_[block_index]->map() = to_init->map(); 640 incoming_maps_[block_index]->map() = to_init->map();
636 return to_init; 641 return to_init;
637 } 642 }
638 643
639 OperandMap* InitializeFromIntersection(size_t block_index) { 644 OperandMap* InitializeFromIntersection(size_t block_index) {
640 return incoming_maps_[block_index]; 645 return incoming_maps_[block_index];
641 } 646 }
642 647
643 void InitializeOperandMaps() { 648 void InitializeOperandMaps() {
644 size_t block_count = sequence()->instruction_blocks().size(); 649 size_t block_count = sequence()->instruction_blocks().size();
645 incoming_maps_.reserve(block_count); 650 incoming_maps_.reserve(block_count);
646 outgoing_maps_.reserve(block_count); 651 outgoing_maps_.reserve(block_count);
647 for (size_t i = 0; i < block_count; ++i) { 652 for (size_t i = 0; i < block_count; ++i) {
648 incoming_maps_.push_back(new (zone()) OperandMap(zone())); 653 incoming_maps_.push_back(new (zone()) OperandMap(zone()));
649 outgoing_maps_.push_back(new (zone()) OperandMap(zone())); 654 outgoing_maps_.push_back(new (zone()) OperandMap(zone()));
650 } 655 }
651 } 656 }
652 657
653 void InitializePhis() { 658 void InitializePhis() {
654 const size_t block_count = sequence()->instruction_blocks().size(); 659 const size_t block_count = sequence()->instruction_blocks().size();
655 for (size_t block_index = 0; block_index < block_count; ++block_index) { 660 for (size_t block_index = 0; block_index < block_count; ++block_index) {
656 const auto block = sequence()->instruction_blocks()[block_index]; 661 const InstructionBlock* block =
657 for (auto phi : block->phis()) { 662 sequence()->instruction_blocks()[block_index];
663 for (const PhiInstruction* phi : block->phis()) {
658 int first_pred_vreg = phi->operands()[0]; 664 int first_pred_vreg = phi->operands()[0];
659 const PhiData* first_pred_phi = nullptr; 665 const PhiData* first_pred_phi = nullptr;
660 if (IsPhi(first_pred_vreg)) { 666 if (IsPhi(first_pred_vreg)) {
661 first_pred_phi = GetPhi(first_pred_vreg); 667 first_pred_phi = GetPhi(first_pred_vreg);
662 first_pred_vreg = first_pred_phi->first_pred_vreg; 668 first_pred_vreg = first_pred_phi->first_pred_vreg;
663 } 669 }
664 CHECK(!IsPhi(first_pred_vreg)); 670 CHECK(!IsPhi(first_pred_vreg));
665 auto phi_data = new (zone()) PhiData( 671 PhiData* phi_data = new (zone()) PhiData(
666 block->rpo_number(), phi, first_pred_vreg, first_pred_phi, zone()); 672 block->rpo_number(), phi, first_pred_vreg, first_pred_phi, zone());
667 auto res = 673 auto res =
668 phi_map_.insert(std::make_pair(phi->virtual_register(), phi_data)); 674 phi_map_.insert(std::make_pair(phi->virtual_register(), phi_data));
669 CHECK(res.second); 675 CHECK(res.second);
670 phi_map_guard_.Add(phi->virtual_register()); 676 phi_map_guard_.Add(phi->virtual_register());
671 } 677 }
672 } 678 }
673 } 679 }
674 680
675 typedef ZoneVector<OperandMap*> OperandMaps; 681 typedef ZoneVector<OperandMap*> OperandMaps;
(...skipping 17 matching lines...) Expand all
693 block_maps.PropagateUsesBackwards(); 699 block_maps.PropagateUsesBackwards();
694 VerifyGapMoves(&block_maps, false); 700 VerifyGapMoves(&block_maps, false);
695 } 701 }
696 702
697 703
698 // Compute and verify outgoing values for every block. 704 // Compute and verify outgoing values for every block.
699 void RegisterAllocatorVerifier::VerifyGapMoves(BlockMaps* block_maps, 705 void RegisterAllocatorVerifier::VerifyGapMoves(BlockMaps* block_maps,
700 bool initial_pass) { 706 bool initial_pass) {
701 const size_t block_count = sequence()->instruction_blocks().size(); 707 const size_t block_count = sequence()->instruction_blocks().size();
702 for (size_t block_index = 0; block_index < block_count; ++block_index) { 708 for (size_t block_index = 0; block_index < block_count; ++block_index) {
703 auto current = block_maps->InitializeIncoming(block_index, initial_pass); 709 OperandMap* current =
704 const auto block = sequence()->instruction_blocks()[block_index]; 710 block_maps->InitializeIncoming(block_index, initial_pass);
711 const InstructionBlock* block =
712 sequence()->instruction_blocks()[block_index];
705 for (int instr_index = block->code_start(); instr_index < block->code_end(); 713 for (int instr_index = block->code_start(); instr_index < block->code_end();
706 ++instr_index) { 714 ++instr_index) {
707 const auto& instr_constraint = constraints_[instr_index]; 715 const InstructionConstraint& instr_constraint = constraints_[instr_index];
708 const auto instr = instr_constraint.instruction_; 716 const Instruction* instr = instr_constraint.instruction_;
709 current->RunGaps(zone(), instr); 717 current->RunGaps(zone(), instr);
710 const auto op_constraints = instr_constraint.operand_constraints_; 718 const OperandConstraint* op_constraints =
719 instr_constraint.operand_constraints_;
711 size_t count = 0; 720 size_t count = 0;
712 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { 721 for (size_t i = 0; i < instr->InputCount(); ++i, ++count) {
713 if (op_constraints[count].type_ == kImmediate || 722 if (op_constraints[count].type_ == kImmediate ||
714 op_constraints[count].type_ == kExplicit) { 723 op_constraints[count].type_ == kExplicit) {
715 continue; 724 continue;
716 } 725 }
717 int virtual_register = op_constraints[count].virtual_register_; 726 int virtual_register = op_constraints[count].virtual_register_;
718 auto op = instr->InputAt(i); 727 const InstructionOperand* op = instr->InputAt(i);
719 if (!block_maps->IsPhi(virtual_register)) { 728 if (!block_maps->IsPhi(virtual_register)) {
720 current->Use(op, virtual_register, initial_pass); 729 current->Use(op, virtual_register, initial_pass);
721 } else { 730 } else {
722 auto phi = block_maps->GetPhi(virtual_register); 731 const PhiData* phi = block_maps->GetPhi(virtual_register);
723 current->UsePhi(op, phi, initial_pass); 732 current->UsePhi(op, phi, initial_pass);
724 } 733 }
725 } 734 }
726 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { 735 for (size_t i = 0; i < instr->TempCount(); ++i, ++count) {
727 current->Drop(instr->TempAt(i)); 736 current->Drop(instr->TempAt(i));
728 } 737 }
729 if (instr->IsCall()) { 738 if (instr->IsCall()) {
730 current->DropRegisters(config()); 739 current->DropRegisters(config());
731 } 740 }
732 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { 741 for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) {
(...skipping 13 matching lines...) Expand all
746 USE(insert_result); 755 USE(insert_result);
747 } 756 }
748 } 757 }
749 } 758 }
750 } 759 }
751 } 760 }
752 761
753 } // namespace compiler 762 } // namespace compiler
754 } // namespace internal 763 } // namespace internal
755 } // namespace v8 764 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698