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

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

Issue 738853002: [turbofan]: delay ssa deconstruction in register allocator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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/compiler/register-allocator-verifier.cc » ('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 973 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 const ZoneList<MoveOperands>* move_operands = move->move_operands(); 984 const ZoneList<MoveOperands>* move_operands = move->move_operands();
985 for (int i = 0; i < move_operands->length(); ++i) { 985 for (int i = 0; i < move_operands->length(); ++i) {
986 MoveOperands* cur = &move_operands->at(i); 986 MoveOperands* cur = &move_operands->at(i);
987 if (cur->IsIgnored()) continue; 987 if (cur->IsIgnored()) continue;
988 InstructionOperand* from = cur->source(); 988 InstructionOperand* from = cur->source();
989 InstructionOperand* to = cur->destination(); 989 InstructionOperand* to = cur->destination();
990 InstructionOperand* hint = to; 990 InstructionOperand* hint = to;
991 if (to->IsUnallocated()) { 991 if (to->IsUnallocated()) {
992 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); 992 int to_vreg = UnallocatedOperand::cast(to)->virtual_register();
993 LiveRange* to_range = LiveRangeFor(to_vreg); 993 LiveRange* to_range = LiveRangeFor(to_vreg);
994 // TODO(dcarney): this in no longer reachable.
Jarin 2014/11/19 15:43:04 How about DCHECK(!to_range->is_phi()), then?
dcarney 2014/11/19 15:55:48 i just nuked all the is_phi stuff instead
994 if (to_range->is_phi()) { 995 if (to_range->is_phi()) {
995 if (to_range->is_non_loop_phi()) { 996 if (to_range->is_non_loop_phi()) {
996 hint = to_range->current_hint_operand(); 997 hint = to_range->current_hint_operand();
997 } 998 }
998 } else { 999 } else {
999 if (live->Contains(to_vreg)) { 1000 if (live->Contains(to_vreg)) {
1000 Define(curr_position, to, from); 1001 Define(curr_position, to, from);
1001 live->Remove(to_vreg); 1002 live->Remove(to_vreg);
1002 } else { 1003 } else {
1003 cur->Eliminate(); 1004 cur->Eliminate();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 } 1076 }
1076 } 1077 }
1077 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL); 1078 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL);
1078 Define(curr_position, temp, NULL); 1079 Define(curr_position, temp, NULL);
1079 } 1080 }
1080 } 1081 }
1081 } 1082 }
1082 } 1083 }
1083 1084
1084 1085
1085 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) { 1086 void RegisterAllocator::ProcessPhis(const InstructionBlock* block) {
1086 for (auto phi : block->phis()) { 1087 for (auto phi : block->phis()) {
1087 UnallocatedOperand* phi_operand = 1088 auto output = phi->output();
1088 new (code_zone()) UnallocatedOperand(UnallocatedOperand::NONE);
1089 int phi_vreg = phi->virtual_register(); 1089 int phi_vreg = phi->virtual_register();
1090 phi_operand->set_virtual_register(phi_vreg);
1091
1092 for (size_t i = 0; i < phi->operands().size(); ++i) {
1093 UnallocatedOperand* operand =
1094 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY);
1095 operand->set_virtual_register(phi->operands()[i]);
1096 InstructionBlock* cur_block =
1097 code()->InstructionBlockAt(block->predecessors()[i]);
1098 // The gap move must be added without any special processing as in
1099 // the AddConstraintsGapMove.
1100 code()->AddGapMove(cur_block->last_instruction_index() - 1, operand,
1101 phi_operand);
1102
1103 Instruction* branch = InstructionAt(cur_block->last_instruction_index());
1104 DCHECK(!branch->HasPointerMap());
1105 USE(branch);
1106 }
1107
1108 LiveRange* live_range = LiveRangeFor(phi_vreg); 1090 LiveRange* live_range = LiveRangeFor(phi_vreg);
1109 BlockStartInstruction* block_start = 1091 BlockStartInstruction* block_start =
1110 code()->GetBlockStart(block->rpo_number()); 1092 code()->GetBlockStart(block->rpo_number());
1111 block_start->GetOrCreateParallelMove(GapInstruction::START, code_zone()) 1093 block_start->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone())
1112 ->AddMove(phi_operand, live_range->GetSpillOperand(), code_zone()); 1094 ->AddMove(output, live_range->GetSpillOperand(), code_zone());
1113 live_range->SetSpillStartIndex(block->first_instruction_index()); 1095 live_range->SetSpillStartIndex(block->first_instruction_index());
1114
1115 // We use the phi-ness of some nodes in some later heuristics. 1096 // We use the phi-ness of some nodes in some later heuristics.
1116 live_range->set_is_phi(true); 1097 live_range->set_is_phi(true);
1117 if (!block->IsLoopHeader()) { 1098 if (!block->IsLoopHeader()) {
1118 live_range->set_is_non_loop_phi(true); 1099 live_range->set_is_non_loop_phi(true);
1119 } 1100 }
1120 } 1101 }
1121 } 1102 }
1122 1103
1123 1104
1124 void RegisterAllocator::MeetRegisterConstraints() { 1105 void RegisterAllocator::MeetRegisterConstraints() {
1125 for (auto block : code()->instruction_blocks()) { 1106 for (auto block : code()->instruction_blocks()) {
1107 ProcessPhis(block);
1126 MeetRegisterConstraints(block); 1108 MeetRegisterConstraints(block);
1127 if (!AllocationOk()) return;
1128 } 1109 }
1129 } 1110 }
1130 1111
1131
1132 void RegisterAllocator::ResolvePhis() {
1133 // Process the blocks in reverse order.
1134 for (auto i = code()->instruction_blocks().rbegin();
1135 i != code()->instruction_blocks().rend(); ++i) {
1136 ResolvePhis(*i);
1137 }
1138 }
1139
1140 1112
1141 ParallelMove* RegisterAllocator::GetConnectingParallelMove( 1113 ParallelMove* RegisterAllocator::GetConnectingParallelMove(
1142 LifetimePosition pos) { 1114 LifetimePosition pos) {
1143 int index = pos.InstructionIndex(); 1115 int index = pos.InstructionIndex();
1144 if (code()->IsGapAt(index)) { 1116 if (code()->IsGapAt(index)) {
1145 GapInstruction* gap = code()->GapAt(index); 1117 GapInstruction* gap = code()->GapAt(index);
1146 return gap->GetOrCreateParallelMove( 1118 return gap->GetOrCreateParallelMove(
1147 pos.IsInstructionStart() ? GapInstruction::START : GapInstruction::END, 1119 pos.IsInstructionStart() ? GapInstruction::START : GapInstruction::END,
1148 code_zone()); 1120 code_zone());
1149 } 1121 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 if (bound->start_.Value() <= position.Value()) { 1231 if (bound->start_.Value() <= position.Value()) {
1260 if (position.Value() < bound->end_.Value()) return bound; 1232 if (position.Value() < bound->end_.Value()) return bound;
1261 DCHECK(left_index < current_index); 1233 DCHECK(left_index < current_index);
1262 left_index = current_index; 1234 left_index = current_index;
1263 } else { 1235 } else {
1264 right_index = current_index; 1236 right_index = current_index;
1265 } 1237 }
1266 } 1238 }
1267 } 1239 }
1268 1240
1241 LiveRangeBound* FindPred(const InstructionBlock* pred) {
1242 const LifetimePosition pred_end =
1243 LifetimePosition::FromInstructionIndex(pred->last_instruction_index());
1244 return Find(pred_end);
1245 }
1246
1247 LiveRangeBound* FindSucc(const InstructionBlock* succ) {
1248 const LifetimePosition succ_start =
1249 LifetimePosition::FromInstructionIndex(succ->first_instruction_index());
1250 return Find(succ_start);
1251 }
1252
1269 void Find(const InstructionBlock* block, const InstructionBlock* pred, 1253 void Find(const InstructionBlock* block, const InstructionBlock* pred,
1270 FindResult* result) const { 1254 FindResult* result) const {
1271 const LifetimePosition pred_end = 1255 const LifetimePosition pred_end =
1272 LifetimePosition::FromInstructionIndex(pred->last_instruction_index()); 1256 LifetimePosition::FromInstructionIndex(pred->last_instruction_index());
1273 LiveRangeBound* bound = Find(pred_end); 1257 LiveRangeBound* bound = Find(pred_end);
1274 result->pred_cover_ = bound->range_; 1258 result->pred_cover_ = bound->range_;
1275 const LifetimePosition cur_start = LifetimePosition::FromInstructionIndex( 1259 const LifetimePosition cur_start = LifetimePosition::FromInstructionIndex(
1276 block->first_instruction_index()); 1260 block->first_instruction_index());
1277 // Common case. 1261 // Common case.
1278 if (bound->CanCover(cur_start)) { 1262 if (bound->CanCover(cur_start)) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 }; 1307 };
1324 1308
1325 } // namespace 1309 } // namespace
1326 1310
1327 1311
1328 void RegisterAllocator::ResolveControlFlow() { 1312 void RegisterAllocator::ResolveControlFlow() {
1329 // Lazily linearize live ranges in memory for fast lookup. 1313 // Lazily linearize live ranges in memory for fast lookup.
1330 LiveRangeFinder finder(*this); 1314 LiveRangeFinder finder(*this);
1331 for (auto block : code()->instruction_blocks()) { 1315 for (auto block : code()->instruction_blocks()) {
1332 if (CanEagerlyResolveControlFlow(block)) continue; 1316 if (CanEagerlyResolveControlFlow(block)) continue;
1317 /* resolve phis */
Jarin 2014/11/19 15:43:04 // style comment?
dcarney 2014/11/19 15:55:48 Done.
1318 for (auto phi : block->phis()) {
1319 // TODO(dcarney): optimize this - no need to CreateAssignedOperand here
1320 // and in ResolveControlFlow.
1321 auto* block_bound =
Jarin 2014/11/19 15:43:04 Yeah, this would deserve some comment and/or clean
dcarney 2014/11/19 15:55:48 cleaned up
1322 finder.ArrayFor(phi->virtual_register())->FindSucc(block);
1323 auto phi_output = block_bound->range_->CreateAssignedOperand(code_zone());
1324 phi->output()->ConvertTo(phi_output->kind(), phi_output->index());
1325 size_t pred_index = 0;
1326 for (auto pred : block->predecessors()) {
1327 const InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
1328 auto* pred_bound =
1329 finder.ArrayFor(phi->operands()[pred_index])->FindPred(pred_block);
1330 phi->inputs()[pred_index] =
1331 pred_bound->range_->CreateAssignedOperand(code_zone());
1332 ResolveControlFlow(block, block_bound->range_, pred_block,
1333 pred_bound->range_);
1334 pred_index++;
1335 }
1336 }
1333 BitVector* live = live_in_sets_[block->rpo_number().ToInt()]; 1337 BitVector* live = live_in_sets_[block->rpo_number().ToInt()];
1334 BitVector::Iterator iterator(live); 1338 BitVector::Iterator iterator(live);
1335 while (!iterator.Done()) { 1339 while (!iterator.Done()) {
1336 LiveRangeBoundArray* array = finder.ArrayFor(iterator.Current()); 1340 auto* array = finder.ArrayFor(iterator.Current());
1337 for (auto pred : block->predecessors()) { 1341 for (auto pred : block->predecessors()) {
1338 FindResult result; 1342 FindResult result;
1339 const InstructionBlock* pred_block = code()->InstructionBlockAt(pred); 1343 const auto* pred_block = code()->InstructionBlockAt(pred);
1340 array->Find(block, pred_block, &result); 1344 array->Find(block, pred_block, &result);
1341 if (result.cur_cover_ == result.pred_cover_ || 1345 if (result.cur_cover_ == result.pred_cover_ ||
1342 result.cur_cover_->IsSpilled()) 1346 result.cur_cover_->IsSpilled())
1343 continue; 1347 continue;
1344 ResolveControlFlow(block, result.cur_cover_, pred_block, 1348 ResolveControlFlow(block, result.cur_cover_, pred_block,
1345 result.pred_cover_); 1349 result.pred_cover_);
1346 } 1350 }
1347 iterator.Advance(); 1351 iterator.Advance();
1348 } 1352 }
1349 } 1353 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 1392
1389 // Process the instructions in reverse order, generating and killing 1393 // Process the instructions in reverse order, generating and killing
1390 // live values. 1394 // live values.
1391 ProcessInstructions(block, live); 1395 ProcessInstructions(block, live);
1392 // All phi output operands are killed by this block. 1396 // All phi output operands are killed by this block.
1393 for (auto phi : block->phis()) { 1397 for (auto phi : block->phis()) {
1394 // The live range interval already ends at the first instruction of the 1398 // The live range interval already ends at the first instruction of the
1395 // block. 1399 // block.
1396 int phi_vreg = phi->virtual_register(); 1400 int phi_vreg = phi->virtual_register();
1397 live->Remove(phi_vreg); 1401 live->Remove(phi_vreg);
1398
1399 InstructionOperand* hint = NULL;
1400 InstructionOperand* phi_operand = NULL;
1401 GapInstruction* gap =
1402 GetLastGap(code()->InstructionBlockAt(block->predecessors()[0]));
1403
1404 // TODO(titzer): no need to create the parallel move if it doesn't exit.
1405 ParallelMove* move =
1406 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone());
1407 for (int j = 0; j < move->move_operands()->length(); ++j) {
1408 InstructionOperand* to = move->move_operands()->at(j).destination();
1409 if (to->IsUnallocated() &&
1410 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) {
1411 hint = move->move_operands()->at(j).source();
1412 phi_operand = to;
1413 break;
1414 }
1415 }
1416 DCHECK(hint != NULL);
1417
1418 LifetimePosition block_start = LifetimePosition::FromInstructionIndex(
1419 block->first_instruction_index());
1420 Define(block_start, phi_operand, hint);
1421 } 1402 }
1422 1403
1423 // Now live is live_in for this block except not including values live 1404 // Now live is live_in for this block except not including values live
1424 // out on backward successor edges. 1405 // out on backward successor edges.
1425 live_in_sets_[block_id] = live; 1406 live_in_sets_[block_id] = live;
1426 1407
1427 if (block->IsLoopHeader()) { 1408 if (block->IsLoopHeader()) {
1428 // Add a live range stretching from the first loop instruction to the last 1409 // Add a live range stretching from the first loop instruction to the last
1429 // for each value live on entry to the header. 1410 // for each value live on entry to the header.
1430 BitVector::Iterator iterator(live); 1411 BitVector::Iterator iterator(live);
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 } else { 2257 } else {
2277 DCHECK(range->Kind() == GENERAL_REGISTERS); 2258 DCHECK(range->Kind() == GENERAL_REGISTERS);
2278 assigned_registers_->Add(reg); 2259 assigned_registers_->Add(reg);
2279 } 2260 }
2280 range->set_assigned_register(reg, code_zone()); 2261 range->set_assigned_register(reg, code_zone());
2281 } 2262 }
2282 2263
2283 } 2264 }
2284 } 2265 }
2285 } // namespace v8::internal::compiler 2266 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/register-allocator-verifier.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698