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

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

Issue 751543002: [turbofan] put late ssa deconstruction in register allocator behind a flag (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 6 years, 1 month 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 | « src/compiler/register-allocator.h ('k') | src/flag-definitions.h » ('j') | 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/linkage.h" 5 #include "src/compiler/linkage.h"
6 #include "src/compiler/register-allocator.h" 6 #include "src/compiler/register-allocator.h"
7 #include "src/string-stream.h" 7 #include "src/string-stream.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 return false; 93 return false;
94 } 94 }
95 95
96 96
97 #endif 97 #endif
98 98
99 99
100 LiveRange::LiveRange(int id, Zone* zone) 100 LiveRange::LiveRange(int id, Zone* zone)
101 : id_(id), 101 : id_(id),
102 spilled_(false), 102 spilled_(false),
103 is_phi_(false),
104 is_non_loop_phi_(false),
103 kind_(UNALLOCATED_REGISTERS), 105 kind_(UNALLOCATED_REGISTERS),
104 assigned_register_(kInvalidAssignment), 106 assigned_register_(kInvalidAssignment),
105 last_interval_(NULL), 107 last_interval_(NULL),
106 first_interval_(NULL), 108 first_interval_(NULL),
107 first_pos_(NULL), 109 first_pos_(NULL),
108 parent_(NULL), 110 parent_(NULL),
109 next_(NULL), 111 next_(NULL),
110 current_interval_(NULL), 112 current_interval_(NULL),
111 last_processed_use_(NULL), 113 last_processed_use_(NULL),
112 current_hint_operand_(NULL), 114 current_hint_operand_(NULL),
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); 1158 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone());
1157 const ZoneList<MoveOperands>* move_operands = move->move_operands(); 1159 const ZoneList<MoveOperands>* move_operands = move->move_operands();
1158 for (int i = 0; i < move_operands->length(); ++i) { 1160 for (int i = 0; i < move_operands->length(); ++i) {
1159 MoveOperands* cur = &move_operands->at(i); 1161 MoveOperands* cur = &move_operands->at(i);
1160 if (cur->IsIgnored()) continue; 1162 if (cur->IsIgnored()) continue;
1161 InstructionOperand* from = cur->source(); 1163 InstructionOperand* from = cur->source();
1162 InstructionOperand* to = cur->destination(); 1164 InstructionOperand* to = cur->destination();
1163 InstructionOperand* hint = to; 1165 InstructionOperand* hint = to;
1164 if (to->IsUnallocated()) { 1166 if (to->IsUnallocated()) {
1165 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); 1167 int to_vreg = UnallocatedOperand::cast(to)->virtual_register();
1166 if (live->Contains(to_vreg)) { 1168 LiveRange* to_range = LiveRangeFor(to_vreg);
1167 Define(curr_position, to, from); 1169 if (to_range->is_phi()) {
1168 live->Remove(to_vreg); 1170 DCHECK(!FLAG_turbo_delay_ssa_decon);
1171 if (to_range->is_non_loop_phi()) {
1172 hint = to_range->current_hint_operand();
1173 }
1169 } else { 1174 } else {
1170 cur->Eliminate(); 1175 if (live->Contains(to_vreg)) {
1171 continue; 1176 Define(curr_position, to, from);
1177 live->Remove(to_vreg);
1178 } else {
1179 cur->Eliminate();
1180 continue;
1181 }
1172 } 1182 }
1173 } else { 1183 } else {
1174 Define(curr_position, to, from); 1184 Define(curr_position, to, from);
1175 } 1185 }
1176 Use(block_start_position, curr_position, from, hint); 1186 Use(block_start_position, curr_position, from, hint);
1177 if (from->IsUnallocated()) { 1187 if (from->IsUnallocated()) {
1178 live->Add(UnallocatedOperand::cast(from)->virtual_register()); 1188 live->Add(UnallocatedOperand::cast(from)->virtual_register());
1179 } 1189 }
1180 } 1190 }
1181 } else { 1191 } else {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 } 1251 }
1242 } 1252 }
1243 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL); 1253 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL);
1244 Define(curr_position, temp, NULL); 1254 Define(curr_position, temp, NULL);
1245 } 1255 }
1246 } 1256 }
1247 } 1257 }
1248 } 1258 }
1249 1259
1250 1260
1251 void RegisterAllocator::ProcessPhis(const InstructionBlock* block) { 1261 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
1252 for (auto phi : block->phis()) { 1262 for (auto phi : block->phis()) {
1253 auto output = phi->output(); 1263 auto output = phi->output();
1254 int phi_vreg = phi->virtual_register(); 1264 int phi_vreg = phi->virtual_register();
1265 if (!FLAG_turbo_delay_ssa_decon) {
1266 for (size_t i = 0; i < phi->operands().size(); ++i) {
1267 InstructionBlock* cur_block =
1268 code()->InstructionBlockAt(block->predecessors()[i]);
1269 // The gap move must be added without any special processing as in
1270 // the AddConstraintsGapMove.
1271 code()->AddGapMove(cur_block->last_instruction_index() - 1,
1272 phi->inputs()[i], output);
1273 DCHECK(!InstructionAt(cur_block->last_instruction_index())
1274 ->HasPointerMap());
1275 }
1276 }
1255 LiveRange* live_range = LiveRangeFor(phi_vreg); 1277 LiveRange* live_range = LiveRangeFor(phi_vreg);
1256 BlockStartInstruction* block_start = 1278 BlockStartInstruction* block_start =
1257 code()->GetBlockStart(block->rpo_number()); 1279 code()->GetBlockStart(block->rpo_number());
1258 block_start->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()) 1280 block_start->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone())
1259 ->AddMove(output, live_range->GetSpillOperand(), code_zone()); 1281 ->AddMove(output, live_range->GetSpillOperand(), code_zone());
1260 live_range->SetSpillStartIndex(block->first_instruction_index()); 1282 live_range->SetSpillStartIndex(block->first_instruction_index());
1283 // We use the phi-ness of some nodes in some later heuristics.
1284 live_range->set_is_phi(true);
1285 if (!block->IsLoopHeader()) {
1286 live_range->set_is_non_loop_phi(true);
1287 }
1261 } 1288 }
1262 } 1289 }
1263 1290
1264 1291
1265 void RegisterAllocator::MeetRegisterConstraints() { 1292 void RegisterAllocator::MeetRegisterConstraints() {
1266 for (auto block : code()->instruction_blocks()) { 1293 for (auto block : code()->instruction_blocks()) {
1267 ProcessPhis(block);
1268 MeetRegisterConstraints(block); 1294 MeetRegisterConstraints(block);
1269 } 1295 }
1270 } 1296 }
1271 1297
1272 1298
1299 void RegisterAllocator::ResolvePhis() {
1300 // Process the blocks in reverse order.
1301 for (auto i = code()->instruction_blocks().rbegin();
1302 i != code()->instruction_blocks().rend(); ++i) {
1303 ResolvePhis(*i);
1304 }
1305 }
1306
1307
1273 ParallelMove* RegisterAllocator::GetConnectingParallelMove( 1308 ParallelMove* RegisterAllocator::GetConnectingParallelMove(
1274 LifetimePosition pos) { 1309 LifetimePosition pos) {
1275 int index = pos.InstructionIndex(); 1310 int index = pos.InstructionIndex();
1276 if (code()->IsGapAt(index)) { 1311 if (code()->IsGapAt(index)) {
1277 GapInstruction* gap = code()->GapAt(index); 1312 GapInstruction* gap = code()->GapAt(index);
1278 return gap->GetOrCreateParallelMove( 1313 return gap->GetOrCreateParallelMove(
1279 pos.IsInstructionStart() ? GapInstruction::START : GapInstruction::END, 1314 pos.IsInstructionStart() ? GapInstruction::START : GapInstruction::END,
1280 code_zone()); 1315 code_zone());
1281 } 1316 }
1282 int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1); 1317 int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1);
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 }; 1502 };
1468 1503
1469 } // namespace 1504 } // namespace
1470 1505
1471 1506
1472 void RegisterAllocator::ResolveControlFlow() { 1507 void RegisterAllocator::ResolveControlFlow() {
1473 // Lazily linearize live ranges in memory for fast lookup. 1508 // Lazily linearize live ranges in memory for fast lookup.
1474 LiveRangeFinder finder(*this); 1509 LiveRangeFinder finder(*this);
1475 for (auto block : code()->instruction_blocks()) { 1510 for (auto block : code()->instruction_blocks()) {
1476 if (CanEagerlyResolveControlFlow(block)) continue; 1511 if (CanEagerlyResolveControlFlow(block)) continue;
1477 // resolve phis 1512 if (FLAG_turbo_delay_ssa_decon) {
1478 for (auto phi : block->phis()) { 1513 // resolve phis
1479 auto* block_bound = 1514 for (auto phi : block->phis()) {
1480 finder.ArrayFor(phi->virtual_register())->FindSucc(block); 1515 auto* block_bound =
1481 auto phi_output = block_bound->range_->CreateAssignedOperand(code_zone()); 1516 finder.ArrayFor(phi->virtual_register())->FindSucc(block);
1482 phi->output()->ConvertTo(phi_output->kind(), phi_output->index()); 1517 auto phi_output =
1483 size_t pred_index = 0; 1518 block_bound->range_->CreateAssignedOperand(code_zone());
1484 for (auto pred : block->predecessors()) { 1519 phi->output()->ConvertTo(phi_output->kind(), phi_output->index());
1485 const InstructionBlock* pred_block = code()->InstructionBlockAt(pred); 1520 size_t pred_index = 0;
1486 auto* pred_bound = 1521 for (auto pred : block->predecessors()) {
1487 finder.ArrayFor(phi->operands()[pred_index])->FindPred(pred_block); 1522 const InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
1488 auto pred_op = pred_bound->range_->CreateAssignedOperand(code_zone()); 1523 auto* pred_bound = finder.ArrayFor(phi->operands()[pred_index])
1489 phi->inputs()[pred_index] = pred_op; 1524 ->FindPred(pred_block);
1490 ResolveControlFlow(block, phi_output, pred_block, pred_op); 1525 auto pred_op = pred_bound->range_->CreateAssignedOperand(code_zone());
1491 pred_index++; 1526 phi->inputs()[pred_index] = pred_op;
1527 ResolveControlFlow(block, phi_output, pred_block, pred_op);
1528 pred_index++;
1529 }
1492 } 1530 }
1493 } 1531 }
1494 BitVector* live = live_in_sets_[block->rpo_number().ToInt()]; 1532 BitVector* live = live_in_sets_[block->rpo_number().ToInt()];
1495 BitVector::Iterator iterator(live); 1533 BitVector::Iterator iterator(live);
1496 while (!iterator.Done()) { 1534 while (!iterator.Done()) {
1497 auto* array = finder.ArrayFor(iterator.Current()); 1535 auto* array = finder.ArrayFor(iterator.Current());
1498 for (auto pred : block->predecessors()) { 1536 for (auto pred : block->predecessors()) {
1499 FindResult result; 1537 FindResult result;
1500 const auto* pred_block = code()->InstructionBlockAt(pred); 1538 const auto* pred_block = code()->InstructionBlockAt(pred);
1501 array->Find(block, pred_block, &result); 1539 array->Find(block, pred_block, &result);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 1587
1550 // Process the instructions in reverse order, generating and killing 1588 // Process the instructions in reverse order, generating and killing
1551 // live values. 1589 // live values.
1552 ProcessInstructions(block, live); 1590 ProcessInstructions(block, live);
1553 // All phi output operands are killed by this block. 1591 // All phi output operands are killed by this block.
1554 for (auto phi : block->phis()) { 1592 for (auto phi : block->phis()) {
1555 // The live range interval already ends at the first instruction of the 1593 // The live range interval already ends at the first instruction of the
1556 // block. 1594 // block.
1557 int phi_vreg = phi->virtual_register(); 1595 int phi_vreg = phi->virtual_register();
1558 live->Remove(phi_vreg); 1596 live->Remove(phi_vreg);
1597 if (!FLAG_turbo_delay_ssa_decon) {
1598 InstructionOperand* hint = NULL;
1599 InstructionOperand* phi_operand = NULL;
1600 GapInstruction* gap =
1601 GetLastGap(code()->InstructionBlockAt(block->predecessors()[0]));
1602 ParallelMove* move =
1603 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone());
1604 for (int j = 0; j < move->move_operands()->length(); ++j) {
1605 InstructionOperand* to = move->move_operands()->at(j).destination();
1606 if (to->IsUnallocated() &&
1607 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) {
1608 hint = move->move_operands()->at(j).source();
1609 phi_operand = to;
1610 break;
1611 }
1612 }
1613 DCHECK(hint != NULL);
1614 LifetimePosition block_start = LifetimePosition::FromInstructionIndex(
1615 block->first_instruction_index());
1616 Define(block_start, phi_operand, hint);
1617 }
1559 } 1618 }
1560 1619
1561 // Now live is live_in for this block except not including values live 1620 // Now live is live_in for this block except not including values live
1562 // out on backward successor edges. 1621 // out on backward successor edges.
1563 live_in_sets_[block_id] = live; 1622 live_in_sets_[block_id] = live;
1564 1623
1565 if (block->IsLoopHeader()) { 1624 if (block->IsLoopHeader()) {
1566 // Add a live range stretching from the first loop instruction to the last 1625 // Add a live range stretching from the first loop instruction to the last
1567 // for each value live on entry to the header. 1626 // for each value live on entry to the header.
1568 BitVector::Iterator iterator(live); 1627 BitVector::Iterator iterator(live);
(...skipping 24 matching lines...) Expand all
1593 // TODO(bmeurer): This is a horrible hack to make sure that for constant 1652 // TODO(bmeurer): This is a horrible hack to make sure that for constant
1594 // live ranges, every use requires the constant to be in a register. 1653 // live ranges, every use requires the constant to be in a register.
1595 // Without this hack, all uses with "any" policy would get the constant 1654 // Without this hack, all uses with "any" policy would get the constant
1596 // operand assigned. 1655 // operand assigned.
1597 LiveRange* range = live_ranges_[i]; 1656 LiveRange* range = live_ranges_[i];
1598 if (range->HasAllocatedSpillOperand() && 1657 if (range->HasAllocatedSpillOperand() &&
1599 range->GetSpillOperand()->IsConstant()) { 1658 range->GetSpillOperand()->IsConstant()) {
1600 for (UsePosition* pos = range->first_pos(); pos != NULL; 1659 for (UsePosition* pos = range->first_pos(); pos != NULL;
1601 pos = pos->next_) { 1660 pos = pos->next_) {
1602 pos->register_beneficial_ = true; 1661 pos->register_beneficial_ = true;
1603 pos->requires_reg_ = true; 1662 // TODO(dcarney): should the else case assert requires_reg_ == false?
1663 // Can't mark phis as needing a register.
1664 if (!code()
1665 ->InstructionAt(pos->pos().InstructionIndex())
1666 ->IsGapMoves()) {
1667 pos->requires_reg_ = true;
1668 }
1604 } 1669 }
1605 } 1670 }
1606 } 1671 }
1607 } 1672 }
1608 } 1673 }
1609 1674
1610 1675
1611 bool RegisterAllocator::ExistsUseWithoutDefinition() { 1676 bool RegisterAllocator::ExistsUseWithoutDefinition() {
1612 bool found = false; 1677 bool found = false;
1613 BitVector::Iterator iterator(live_in_sets_[0]); 1678 BitVector::Iterator iterator(live_in_sets_[0]);
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
2414 } else { 2479 } else {
2415 DCHECK(range->Kind() == GENERAL_REGISTERS); 2480 DCHECK(range->Kind() == GENERAL_REGISTERS);
2416 assigned_registers_->Add(reg); 2481 assigned_registers_->Add(reg);
2417 } 2482 }
2418 range->set_assigned_register(reg, code_zone()); 2483 range->set_assigned_register(reg, code_zone());
2419 } 2484 }
2420 2485
2421 } 2486 }
2422 } 2487 }
2423 } // namespace v8::internal::compiler 2488 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698