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/compiler/linkage.h" | 5 #include "src/compiler/linkage.h" |
6 #include "src/compiler/pipeline-statistics.h" | 6 #include "src/compiler/pipeline-statistics.h" |
7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 | 1118 |
1119 bool RegisterAllocator::Allocate(PipelineStatistics* stats) { | 1119 bool RegisterAllocator::Allocate(PipelineStatistics* stats) { |
1120 assigned_registers_ = new (code_zone()) | 1120 assigned_registers_ = new (code_zone()) |
1121 BitVector(config()->num_general_registers(), code_zone()); | 1121 BitVector(config()->num_general_registers(), code_zone()); |
1122 assigned_double_registers_ = new (code_zone()) | 1122 assigned_double_registers_ = new (code_zone()) |
1123 BitVector(config()->num_aliased_double_registers(), code_zone()); | 1123 BitVector(config()->num_aliased_double_registers(), code_zone()); |
1124 { | 1124 { |
1125 PhaseScope phase_scope(stats, "meet register constraints"); | 1125 PhaseScope phase_scope(stats, "meet register constraints"); |
1126 MeetRegisterConstraints(); | 1126 MeetRegisterConstraints(); |
1127 } | 1127 } |
1128 if (!AllocationOk()) return false; | |
1129 { | 1128 { |
1130 PhaseScope phase_scope(stats, "resolve phis"); | 1129 PhaseScope phase_scope(stats, "resolve phis"); |
1131 ResolvePhis(); | 1130 ResolvePhis(); |
1132 } | 1131 } |
1133 { | 1132 { |
1134 PhaseScope phase_scope(stats, "build live ranges"); | 1133 PhaseScope phase_scope(stats, "build live ranges"); |
1135 BuildLiveRanges(); | 1134 BuildLiveRanges(); |
1136 } | 1135 } |
| 1136 if (FLAG_trace_turbo) { |
| 1137 OFStream os(stdout); |
| 1138 PrintableInstructionSequence printable = {config(), code()}; |
| 1139 os << "----- Instruction sequence before register allocation -----\n" |
| 1140 << printable; |
| 1141 } |
| 1142 // This can be triggered in debug mode. |
| 1143 DCHECK(!ExistsUseWithoutDefinition()); |
1137 { | 1144 { |
1138 PhaseScope phase_scope(stats, "allocate general registers"); | 1145 PhaseScope phase_scope(stats, "allocate general registers"); |
1139 AllocateGeneralRegisters(); | 1146 AllocateGeneralRegisters(); |
1140 } | 1147 } |
1141 if (!AllocationOk()) return false; | 1148 if (!AllocationOk()) return false; |
1142 { | 1149 { |
1143 PhaseScope phase_scope(stats, "allocate double registers"); | 1150 PhaseScope phase_scope(stats, "allocate double registers"); |
1144 AllocateDoubleRegisters(); | 1151 AllocateDoubleRegisters(); |
1145 } | 1152 } |
1146 if (!AllocationOk()) return false; | 1153 if (!AllocationOk()) return false; |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1480 range->EnsureInterval(start, end, local_zone()); | 1487 range->EnsureInterval(start, end, local_zone()); |
1481 iterator.Advance(); | 1488 iterator.Advance(); |
1482 } | 1489 } |
1483 | 1490 |
1484 // Insert all values into the live in sets of all blocks in the loop. | 1491 // Insert all values into the live in sets of all blocks in the loop. |
1485 for (int i = block->rpo_number().ToInt() + 1; | 1492 for (int i = block->rpo_number().ToInt() + 1; |
1486 i < block->loop_end().ToInt(); ++i) { | 1493 i < block->loop_end().ToInt(); ++i) { |
1487 live_in_sets_[i]->Union(*live); | 1494 live_in_sets_[i]->Union(*live); |
1488 } | 1495 } |
1489 } | 1496 } |
1490 | |
1491 #ifdef DEBUG | |
1492 if (block_id == 0) { | |
1493 BitVector::Iterator iterator(live); | |
1494 bool found = false; | |
1495 while (!iterator.Done()) { | |
1496 found = true; | |
1497 int operand_index = iterator.Current(); | |
1498 PrintF("Register allocator error: live v%d reached first block.\n", | |
1499 operand_index); | |
1500 LiveRange* range = LiveRangeFor(operand_index); | |
1501 PrintF(" (first use is at %d)\n", range->first_pos()->pos().Value()); | |
1502 if (debug_name() == nullptr) { | |
1503 PrintF("\n"); | |
1504 } else { | |
1505 PrintF(" (function: %s)\n", debug_name()); | |
1506 } | |
1507 iterator.Advance(); | |
1508 } | |
1509 DCHECK(!found); | |
1510 } | |
1511 #endif | |
1512 } | 1497 } |
1513 | 1498 |
1514 for (int i = 0; i < live_ranges_.length(); ++i) { | 1499 for (int i = 0; i < live_ranges_.length(); ++i) { |
1515 if (live_ranges_[i] != NULL) { | 1500 if (live_ranges_[i] != NULL) { |
1516 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); | 1501 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); |
1517 | 1502 |
1518 // TODO(bmeurer): This is a horrible hack to make sure that for constant | 1503 // TODO(bmeurer): This is a horrible hack to make sure that for constant |
1519 // live ranges, every use requires the constant to be in a register. | 1504 // live ranges, every use requires the constant to be in a register. |
1520 // Without this hack, all uses with "any" policy would get the constant | 1505 // Without this hack, all uses with "any" policy would get the constant |
1521 // operand assigned. | 1506 // operand assigned. |
(...skipping 10 matching lines...) Expand all Loading... |
1532 ->IsGapMoves()) { | 1517 ->IsGapMoves()) { |
1533 pos->requires_reg_ = true; | 1518 pos->requires_reg_ = true; |
1534 } | 1519 } |
1535 } | 1520 } |
1536 } | 1521 } |
1537 } | 1522 } |
1538 } | 1523 } |
1539 } | 1524 } |
1540 | 1525 |
1541 | 1526 |
| 1527 bool RegisterAllocator::ExistsUseWithoutDefinition() { |
| 1528 bool found = false; |
| 1529 BitVector::Iterator iterator(live_in_sets_[0]); |
| 1530 while (!iterator.Done()) { |
| 1531 found = true; |
| 1532 int operand_index = iterator.Current(); |
| 1533 PrintF("Register allocator error: live v%d reached first block.\n", |
| 1534 operand_index); |
| 1535 LiveRange* range = LiveRangeFor(operand_index); |
| 1536 PrintF(" (first use is at %d)\n", range->first_pos()->pos().Value()); |
| 1537 if (debug_name() == nullptr) { |
| 1538 PrintF("\n"); |
| 1539 } else { |
| 1540 PrintF(" (function: %s)\n", debug_name()); |
| 1541 } |
| 1542 iterator.Advance(); |
| 1543 } |
| 1544 return found; |
| 1545 } |
| 1546 |
| 1547 |
1542 bool RegisterAllocator::SafePointsAreInOrder() const { | 1548 bool RegisterAllocator::SafePointsAreInOrder() const { |
1543 int safe_point = 0; | 1549 int safe_point = 0; |
1544 const PointerMapDeque* pointer_maps = code()->pointer_maps(); | 1550 const PointerMapDeque* pointer_maps = code()->pointer_maps(); |
1545 for (PointerMapDeque::const_iterator it = pointer_maps->begin(); | 1551 for (PointerMapDeque::const_iterator it = pointer_maps->begin(); |
1546 it != pointer_maps->end(); ++it) { | 1552 it != pointer_maps->end(); ++it) { |
1547 PointerMap* map = *it; | 1553 PointerMap* map = *it; |
1548 if (safe_point > map->instruction_position()) return false; | 1554 if (safe_point > map->instruction_position()) return false; |
1549 safe_point = map->instruction_position(); | 1555 safe_point = map->instruction_position(); |
1550 } | 1556 } |
1551 return true; | 1557 return true; |
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2318 } else { | 2324 } else { |
2319 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2325 DCHECK(range->Kind() == GENERAL_REGISTERS); |
2320 assigned_registers_->Add(reg); | 2326 assigned_registers_->Add(reg); |
2321 } | 2327 } |
2322 range->set_assigned_register(reg, code_zone()); | 2328 range->set_assigned_register(reg, code_zone()); |
2323 } | 2329 } |
2324 | 2330 |
2325 } | 2331 } |
2326 } | 2332 } |
2327 } // namespace v8::internal::compiler | 2333 } // namespace v8::internal::compiler |
OLD | NEW |