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

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

Issue 626493002: [turbofan] compress live_in bitvectors (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « src/compiler/register-allocator.h ('k') | 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/compiler/register-allocator.h" 5 #include "src/compiler/register-allocator.h"
6 6
7 #include "src/compiler/generic-node-inl.h" 7 #include "src/compiler/generic-node-inl.h"
8 #include "src/compiler/linkage.h" 8 #include "src/compiler/linkage.h"
9 #include "src/hydrogen.h" 9 #include "src/hydrogen.h"
10 #include "src/string-stream.h" 10 #include "src/string-stream.h"
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 if (a == NULL || a->start().Value() > other->End().Value()) break; 493 if (a == NULL || a->start().Value() > other->End().Value()) break;
494 AdvanceLastProcessedMarker(a, advance_last_processed_up_to); 494 AdvanceLastProcessedMarker(a, advance_last_processed_up_to);
495 } else { 495 } else {
496 b = b->next(); 496 b = b->next();
497 } 497 }
498 } 498 }
499 return LifetimePosition::Invalid(); 499 return LifetimePosition::Invalid();
500 } 500 }
501 501
502 502
503 namespace {
504
505 class VregMapping {
506 public:
507 explicit VregMapping(Zone* zone)
508 : zone_(zone), vregs_(zone), mapping_(zone) {}
509
510 int GetVreg(size_t mapped) {
511 DCHECK_LT(mapped, vregs_.size());
512 return vregs_[mapped];
513 }
514 size_t GetMapping(int vreg) {
515 int mapped = mapping_[vreg];
516 if (mapped != -1) return static_cast<size_t>(mapped);
517 // Insert.
518 size_t new_mapping = vregs_.size();
519 vregs_.push_back(vreg);
520 mapping_[vreg] = static_cast<int>(new_mapping);
521 return new_mapping;
522 }
523 void Initialize(size_t expected_size, size_t max_vregs) {
524 DCHECK(vregs_.empty());
525 DCHECK(mapping_.empty());
526 vregs_.reserve(expected_size);
527 mapping_.insert(mapping_.begin(), max_vregs, -1);
528 }
529
530 private:
531 Zone* zone_;
532 IntVector vregs_;
533 IntVector mapping_;
534 DISALLOW_COPY_AND_ASSIGN(VregMapping);
535 };
536
537
538 class LiveInSet : public ZoneObject {
539 public:
540 LiveInSet(Zone* zone, VregMapping* mapping, size_t initial_size)
541 : bits_(initial_size, false, zone), mapping_(mapping) {}
542
543 void Add(int vreg) {
544 size_t mapped = mapping_->GetMapping(vreg);
545 if (mapped >= bits_.size()) {
546 // TODO(dcarney): need a better resizing heuristic.
547 size_t new_size = mapped + 10;
548 bits_.resize(new_size, false);
549 }
550 bits_[mapped] = true;
551 }
552
553 void Remove(int vreg) {
554 size_t mapped = mapping_->GetMapping(vreg);
555 if (mapped >= bits_.size()) return;
556 bits_[mapped] = false;
557 }
558
559 bool Contains(int vreg) {
560 size_t mapped = mapping_->GetMapping(vreg);
561 if (mapped >= bits_.size()) return false;
562 return bits_[mapped];
563 }
564
565 void Union(LiveInSet* other) {
566 if (other->bits_.size() > this->bits_.size()) {
567 bits_.resize(other->bits_.size(), false);
568 }
569 BoolVector::iterator j = bits_.begin();
570 for (BoolVector::iterator i = other->bits_.begin(); i != other->bits_.end();
571 ++i, ++j) {
572 if (!*i) continue;
573 *j = true;
574 }
575 }
576
577 class Iterator {
578 public:
579 explicit Iterator(LiveInSet* set) : set_(set), offset_(0) { Advance(); }
580
581 bool Done() { return offset_ > set_->bits_.size(); }
582 void Advance() {
583 for (BoolVector::iterator i = set_->bits_.begin() + offset_;
584 i != set_->bits_.end(); ++i, ++offset_) {
585 if (*i) break;
586 }
587 ++offset_; // Advance one past match.
588 }
589 int Current() {
590 DCHECK(!Done());
591 return set_->mapping_->GetVreg(offset_ - 1);
592 }
593
594 private:
595 LiveInSet* set_;
596 size_t offset_;
597 };
598
599 private:
600 BoolVector bits_;
601 VregMapping* mapping_;
602 };
603
604 } // namespace
605
606
607 class RegisterAllocator::LiveInSets : public ZoneObject {
608 public:
609 LiveInSets(size_t basic_block_count, Zone* zone)
610 : zone_(zone),
611 live_ins_(basic_block_count, NULL, LiveIns::allocator_type(zone)),
612 mapping_(zone) {}
613 ~LiveInSets() {}
614
615 LiveInSet* For(BasicBlock* block) { return live_ins_[block->rpo_number()]; }
616 LiveInSet* For(int rpo_number) { return live_ins_[rpo_number]; }
617
618 void Initialize(size_t max_vregs) {
619 // Assume some level of compression.
620 size_t expected_size = std::min(static_cast<size_t>(500), max_vregs);
621 mapping_.Initialize(expected_size, max_vregs);
622 for (LiveIns::iterator i = live_ins_.begin(); i != live_ins_.end(); ++i) {
623 (*i) = new (zone_) LiveInSet(zone_, &mapping_, expected_size);
624 }
625 }
626
627 private:
628 typedef std::vector<LiveInSet*, zone_allocator<LiveInSet*> > LiveIns;
629
630 Zone* zone_;
631 LiveIns live_ins_;
632 VregMapping mapping_;
633 };
634
635
503 RegisterAllocator::RegisterAllocator(InstructionSequence* code) 636 RegisterAllocator::RegisterAllocator(InstructionSequence* code)
504 : zone_(code->isolate()), 637 : zone_(code->isolate()),
505 code_(code), 638 code_(code),
506 live_in_sets_(code->BasicBlockCount(), zone()), 639 live_in_sets_(new (zone()) LiveInSets(code->BasicBlockCount(), zone())),
507 live_ranges_(code->VirtualRegisterCount() * 2, zone()), 640 live_ranges_(code->VirtualRegisterCount() * 2, zone()),
508 fixed_live_ranges_(NULL), 641 fixed_live_ranges_(NULL),
509 fixed_double_live_ranges_(NULL), 642 fixed_double_live_ranges_(NULL),
510 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, zone()), 643 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, zone()),
511 active_live_ranges_(8, zone()), 644 active_live_ranges_(8, zone()),
512 inactive_live_ranges_(8, zone()), 645 inactive_live_ranges_(8, zone()),
513 reusable_slots_(8, zone()), 646 reusable_slots_(8, zone()),
514 mode_(UNALLOCATED_REGISTERS), 647 mode_(UNALLOCATED_REGISTERS),
515 num_registers_(-1), 648 num_registers_(-1),
516 allocation_ok_(true) {} 649 allocation_ok_(true) {}
517 650
518 651
519 void RegisterAllocator::InitializeLivenessAnalysis() { 652 void RegisterAllocator::ComputeLiveOut(BasicBlock* block) {
520 // Initialize the live_in sets for each block to NULL.
521 int block_count = code()->BasicBlockCount();
522 live_in_sets_.Initialize(block_count, zone());
523 live_in_sets_.AddBlock(NULL, block_count, zone());
524 }
525
526
527 BitVector* RegisterAllocator::ComputeLiveOut(BasicBlock* block) {
528 // Compute live out for the given block, except not including backward 653 // Compute live out for the given block, except not including backward
529 // successor edges. 654 // successor edges.
530 BitVector* live_out = 655 LiveInSet* live_out = live_in_sets_->For(block);
531 new (zone()) BitVector(code()->VirtualRegisterCount(), zone());
532
533 // Process all successor blocks. 656 // Process all successor blocks.
534 for (BasicBlock::Successors::iterator i = block->successors_begin(); 657 for (BasicBlock::Successors::iterator i = block->successors_begin();
535 i != block->successors_end(); ++i) { 658 i != block->successors_end(); ++i) {
536 // Add values live on entry to the successor. Note the successor's 659 // Add values live on entry to the successor. Note the successor's
537 // live_in will not be computed yet for backwards edges. 660 // live_in will not be computed yet for backwards edges.
538 BasicBlock* successor = *i; 661 BasicBlock* successor = *i;
539 BitVector* live_in = live_in_sets_[successor->rpo_number()]; 662 LiveInSet* live_in = live_in_sets_->For(successor);
540 if (live_in != NULL) live_out->Union(*live_in); 663 if (live_in != NULL) live_out->Union(live_in);
541 664
542 // All phi input operands corresponding to this successor edge are live 665 // All phi input operands corresponding to this successor edge are live
543 // out from this block. 666 // out from this block.
544 size_t index = successor->PredecessorIndexOf(block); 667 size_t index = successor->PredecessorIndexOf(block);
545 DCHECK(index < successor->PredecessorCount()); 668 DCHECK(index < successor->PredecessorCount());
546 for (BasicBlock::const_iterator j = successor->begin(); 669 for (BasicBlock::const_iterator j = successor->begin();
547 j != successor->end(); ++j) { 670 j != successor->end(); ++j) {
548 Node* phi = *j; 671 Node* phi = *j;
549 if (phi->opcode() != IrOpcode::kPhi) continue; 672 if (phi->opcode() != IrOpcode::kPhi) continue;
550 Node* input = phi->InputAt(static_cast<int>(index)); 673 Node* input = phi->InputAt(static_cast<int>(index));
551 live_out->Add(input->id()); 674 live_out->Add(input->id());
552 } 675 }
553 } 676 }
554
555 return live_out;
556 } 677 }
557 678
558 679
559 void RegisterAllocator::AddInitialIntervals(BasicBlock* block, 680 void RegisterAllocator::AddInitialIntervals(BasicBlock* block) {
560 BitVector* live_out) {
561 // Add an interval that includes the entire block to the live range for 681 // Add an interval that includes the entire block to the live range for
562 // each live_out value. 682 // each live_out value.
563 LifetimePosition start = 683 LifetimePosition start =
564 LifetimePosition::FromInstructionIndex(block->first_instruction_index()); 684 LifetimePosition::FromInstructionIndex(block->first_instruction_index());
565 LifetimePosition end = LifetimePosition::FromInstructionIndex( 685 LifetimePosition end = LifetimePosition::FromInstructionIndex(
566 block->last_instruction_index()).NextInstruction(); 686 block->last_instruction_index()).NextInstruction();
567 BitVector::Iterator iterator(live_out); 687 LiveInSet::Iterator iterator(live_in_sets_->For(block));
568 while (!iterator.Done()) { 688 while (!iterator.Done()) {
569 int operand_index = iterator.Current(); 689 int operand_index = iterator.Current();
570 LiveRange* range = LiveRangeFor(operand_index); 690 LiveRange* range = LiveRangeFor(operand_index);
571 range->AddUseInterval(start, end, zone()); 691 range->AddUseInterval(start, end, zone());
572 iterator.Advance(); 692 iterator.Advance();
573 } 693 }
574 } 694 }
575 695
576 696
577 int RegisterAllocator::FixedDoubleLiveRangeID(int index) { 697 int RegisterAllocator::FixedDoubleLiveRangeID(int index) {
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 bool RegisterAllocator::IsOutputDoubleRegisterOf(Instruction* instr, 1049 bool RegisterAllocator::IsOutputDoubleRegisterOf(Instruction* instr,
930 int index) { 1050 int index) {
931 for (size_t i = 0; i < instr->OutputCount(); i++) { 1051 for (size_t i = 0; i < instr->OutputCount(); i++) {
932 InstructionOperand* output = instr->OutputAt(i); 1052 InstructionOperand* output = instr->OutputAt(i);
933 if (output->IsDoubleRegister() && output->index() == index) return true; 1053 if (output->IsDoubleRegister() && output->index() == index) return true;
934 } 1054 }
935 return false; 1055 return false;
936 } 1056 }
937 1057
938 1058
939 void RegisterAllocator::ProcessInstructions(BasicBlock* block, 1059 void RegisterAllocator::ProcessInstructions(BasicBlock* block) {
940 BitVector* live) { 1060 LiveInSet* live = live_in_sets_->For(block);
941 int block_start = block->first_instruction_index(); 1061 int block_start = block->first_instruction_index();
942 1062
943 LifetimePosition block_start_position = 1063 LifetimePosition block_start_position =
944 LifetimePosition::FromInstructionIndex(block_start); 1064 LifetimePosition::FromInstructionIndex(block_start);
945 1065
946 for (int index = block->last_instruction_index(); index >= block_start; 1066 for (int index = block->last_instruction_index(); index >= block_start;
947 index--) { 1067 index--) {
948 LifetimePosition curr_position = 1068 LifetimePosition curr_position =
949 LifetimePosition::FromInstructionIndex(index); 1069 LifetimePosition::FromInstructionIndex(index);
950 1070
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 if (block->PredecessorCount() != 1) return false; 1372 if (block->PredecessorCount() != 1) return false;
1253 return block->PredecessorAt(0)->rpo_number() == block->rpo_number() - 1; 1373 return block->PredecessorAt(0)->rpo_number() == block->rpo_number() - 1;
1254 } 1374 }
1255 1375
1256 1376
1257 void RegisterAllocator::ResolveControlFlow() { 1377 void RegisterAllocator::ResolveControlFlow() {
1258 RegisterAllocatorPhase phase("L_Resolve control flow", this); 1378 RegisterAllocatorPhase phase("L_Resolve control flow", this);
1259 for (int block_id = 1; block_id < code()->BasicBlockCount(); ++block_id) { 1379 for (int block_id = 1; block_id < code()->BasicBlockCount(); ++block_id) {
1260 BasicBlock* block = code()->BlockAt(block_id); 1380 BasicBlock* block = code()->BlockAt(block_id);
1261 if (CanEagerlyResolveControlFlow(block)) continue; 1381 if (CanEagerlyResolveControlFlow(block)) continue;
1262 BitVector* live = live_in_sets_[block->rpo_number()]; 1382 LiveInSet* live = live_in_sets_->For(block);
1263 BitVector::Iterator iterator(live); 1383 LiveInSet::Iterator iterator(live);
1264 while (!iterator.Done()) { 1384 while (!iterator.Done()) {
1265 int operand_index = iterator.Current(); 1385 int operand_index = iterator.Current();
1266 for (BasicBlock::Predecessors::iterator i = block->predecessors_begin(); 1386 for (BasicBlock::Predecessors::iterator i = block->predecessors_begin();
1267 i != block->predecessors_end(); ++i) { 1387 i != block->predecessors_end(); ++i) {
1268 BasicBlock* cur = *i; 1388 BasicBlock* cur = *i;
1269 LiveRange* cur_range = LiveRangeFor(operand_index); 1389 LiveRange* cur_range = LiveRangeFor(operand_index);
1270 ResolveControlFlow(cur_range, block, cur); 1390 ResolveControlFlow(cur_range, block, cur);
1271 } 1391 }
1272 iterator.Advance(); 1392 iterator.Advance();
1273 } 1393 }
1274 } 1394 }
1275 } 1395 }
1276 1396
1277 1397
1278 void RegisterAllocator::BuildLiveRanges() { 1398 void RegisterAllocator::BuildLiveRanges() {
1279 RegisterAllocatorPhase phase("L_Build live ranges", this); 1399 RegisterAllocatorPhase phase("L_Build live ranges", this);
1280 InitializeLivenessAnalysis(); 1400
1401 live_in_sets_->Initialize(code()->VirtualRegisterCount());
1402
1281 // Process the blocks in reverse order. 1403 // Process the blocks in reverse order.
1282 for (int block_id = code()->BasicBlockCount() - 1; block_id >= 0; 1404 for (int block_id = code()->BasicBlockCount() - 1; block_id >= 0;
1283 --block_id) { 1405 --block_id) {
1284 BasicBlock* block = code()->BlockAt(block_id); 1406 BasicBlock* block = code()->BlockAt(block_id);
1285 BitVector* live = ComputeLiveOut(block); 1407 ComputeLiveOut(block);
1286 // Initially consider all live_out values live for the entire block. We 1408 // Initially consider all live_out values live for the entire block. We
1287 // will shorten these intervals if necessary. 1409 // will shorten these intervals if necessary.
1288 AddInitialIntervals(block, live); 1410 AddInitialIntervals(block);
1289 1411
1290 // Process the instructions in reverse order, generating and killing 1412 // Process the instructions in reverse order, generating and killing
1291 // live values. 1413 // live values.
1292 ProcessInstructions(block, live); 1414 ProcessInstructions(block);
1415
1416 LiveInSet* live = live_in_sets_->For(block);
1293 // All phi output operands are killed by this block. 1417 // All phi output operands are killed by this block.
1294 for (BasicBlock::const_iterator i = block->begin(); i != block->end(); 1418 for (BasicBlock::const_iterator i = block->begin(); i != block->end();
1295 ++i) { 1419 ++i) {
1296 Node* phi = *i; 1420 Node* phi = *i;
1297 if (phi->opcode() != IrOpcode::kPhi) continue; 1421 if (phi->opcode() != IrOpcode::kPhi) continue;
1298 1422
1299 // The live range interval already ends at the first instruction of the 1423 // The live range interval already ends at the first instruction of the
1300 // block. 1424 // block.
1301 live->Remove(phi->id()); 1425 live->Remove(phi->id());
1302 1426
(...skipping 15 matching lines...) Expand all
1318 } 1442 }
1319 DCHECK(hint != NULL); 1443 DCHECK(hint != NULL);
1320 1444
1321 LifetimePosition block_start = LifetimePosition::FromInstructionIndex( 1445 LifetimePosition block_start = LifetimePosition::FromInstructionIndex(
1322 block->first_instruction_index()); 1446 block->first_instruction_index());
1323 Define(block_start, phi_operand, hint); 1447 Define(block_start, phi_operand, hint);
1324 } 1448 }
1325 1449
1326 // Now live is live_in for this block except not including values live 1450 // Now live is live_in for this block except not including values live
1327 // out on backward successor edges. 1451 // out on backward successor edges.
1328 live_in_sets_[block_id] = live;
1329
1330 if (block->IsLoopHeader()) { 1452 if (block->IsLoopHeader()) {
1331 // Add a live range stretching from the first loop instruction to the last 1453 // Add a live range stretching from the first loop instruction to the last
1332 // for each value live on entry to the header. 1454 // for each value live on entry to the header.
1333 BitVector::Iterator iterator(live); 1455 LiveInSet::Iterator iterator(live);
1334 LifetimePosition start = LifetimePosition::FromInstructionIndex( 1456 LifetimePosition start = LifetimePosition::FromInstructionIndex(
1335 block->first_instruction_index()); 1457 block->first_instruction_index());
1336 int end_index = 1458 int end_index =
1337 code()->BlockAt(block->loop_end())->last_instruction_index(); 1459 code()->BlockAt(block->loop_end())->last_instruction_index();
1338 LifetimePosition end = 1460 LifetimePosition end =
1339 LifetimePosition::FromInstructionIndex(end_index).NextInstruction(); 1461 LifetimePosition::FromInstructionIndex(end_index).NextInstruction();
1340 while (!iterator.Done()) { 1462 while (!iterator.Done()) {
1341 int operand_index = iterator.Current(); 1463 int operand_index = iterator.Current();
1342 LiveRange* range = LiveRangeFor(operand_index); 1464 LiveRange* range = LiveRangeFor(operand_index);
1343 range->EnsureInterval(start, end, zone()); 1465 range->EnsureInterval(start, end, zone());
1344 iterator.Advance(); 1466 iterator.Advance();
1345 } 1467 }
1346 1468
1347 // Insert all values into the live in sets of all blocks in the loop. 1469 // Insert all values into the live in sets of all blocks in the loop.
1348 for (int i = block->rpo_number() + 1; i < block->loop_end(); ++i) { 1470 for (int i = block->rpo_number() + 1; i < block->loop_end(); ++i) {
1349 live_in_sets_[i]->Union(*live); 1471 live_in_sets_->For(i)->Union(live);
1350 } 1472 }
1351 } 1473 }
1352 1474
1353 #ifdef DEBUG 1475 #ifdef DEBUG
1354 if (block_id == 0) { 1476 if (block_id == 0) {
1355 BitVector::Iterator iterator(live); 1477 LiveInSet::Iterator iterator(live);
1356 bool found = false; 1478 bool found = false;
1357 while (!iterator.Done()) { 1479 while (!iterator.Done()) {
1358 found = true; 1480 found = true;
1359 int operand_index = iterator.Current(); 1481 int operand_index = iterator.Current();
1360 PrintF("Register allocator error: live v%d reached first block.\n", 1482 PrintF("Register allocator error: live v%d reached first block.\n",
1361 operand_index); 1483 operand_index);
1362 LiveRange* range = LiveRangeFor(operand_index); 1484 LiveRange* range = LiveRangeFor(operand_index);
1363 PrintF(" (first use is at %d)\n", range->first_pos()->pos().Value()); 1485 PrintF(" (first use is at %d)\n", range->first_pos()->pos().Value());
1364 CompilationInfo* info = code()->linkage()->info(); 1486 CompilationInfo* info = code()->linkage()->info();
1365 if (info->IsStub()) { 1487 if (info->IsStub()) {
(...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after
2220 allocator_zone_start_allocation_size_; 2342 allocator_zone_start_allocation_size_;
2221 isolate()->GetTStatistics()->SaveTiming(name(), base::TimeDelta(), size); 2343 isolate()->GetTStatistics()->SaveTiming(name(), base::TimeDelta(), size);
2222 } 2344 }
2223 #ifdef DEBUG 2345 #ifdef DEBUG
2224 if (allocator_ != NULL) allocator_->Verify(); 2346 if (allocator_ != NULL) allocator_->Verify();
2225 #endif 2347 #endif
2226 } 2348 }
2227 } 2349 }
2228 } 2350 }
2229 } // namespace v8::internal::compiler 2351 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698