OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/scheduler.h" | 5 #include "src/compiler/scheduler.h" |
6 | 6 |
7 #include <iomanip> | 7 #include <iomanip> |
8 | 8 |
9 #include "src/bit-vector.h" | 9 #include "src/bit-vector.h" |
10 #include "src/compiler/common-operator.h" | 10 #include "src/compiler/common-operator.h" |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 break; | 361 break; |
362 default: | 362 default: |
363 break; | 363 break; |
364 } | 364 } |
365 } | 365 } |
366 | 366 |
367 BasicBlock* BuildBlockForNode(Node* node) { | 367 BasicBlock* BuildBlockForNode(Node* node) { |
368 BasicBlock* block = schedule_->block(node); | 368 BasicBlock* block = schedule_->block(node); |
369 if (block == NULL) { | 369 if (block == NULL) { |
370 block = schedule_->NewBasicBlock(); | 370 block = schedule_->NewBasicBlock(); |
371 Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(), | 371 Trace("Create block id:%d for #%d:%s\n", block->id().ToInt(), node->id(), |
372 node->op()->mnemonic()); | 372 node->op()->mnemonic()); |
373 FixNode(block, node); | 373 FixNode(block, node); |
374 } | 374 } |
375 return block; | 375 return block; |
376 } | 376 } |
377 | 377 |
378 void BuildBlocksForSuccessors(Node* node) { | 378 void BuildBlocksForSuccessors(Node* node) { |
379 size_t const successor_cnt = node->op()->ControlOutputCount(); | 379 size_t const successor_cnt = node->op()->ControlOutputCount(); |
380 Node** successors = zone_->NewArray<Node*>(successor_cnt); | 380 Node** successors = zone_->NewArray<Node*>(successor_cnt); |
381 NodeProperties::CollectControlProjections(node, successors, successor_cnt); | 381 NodeProperties::CollectControlProjections(node, successors, successor_cnt); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 void ConnectThrow(Node* thr) { | 497 void ConnectThrow(Node* thr) { |
498 Node* throw_control = NodeProperties::GetControlInput(thr); | 498 Node* throw_control = NodeProperties::GetControlInput(thr); |
499 BasicBlock* throw_block = FindPredecessorBlock(throw_control); | 499 BasicBlock* throw_block = FindPredecessorBlock(throw_control); |
500 TraceConnect(thr, throw_block, NULL); | 500 TraceConnect(thr, throw_block, NULL); |
501 schedule_->AddThrow(throw_block, thr); | 501 schedule_->AddThrow(throw_block, thr); |
502 } | 502 } |
503 | 503 |
504 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { | 504 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { |
505 DCHECK_NOT_NULL(block); | 505 DCHECK_NOT_NULL(block); |
506 if (succ == NULL) { | 506 if (succ == NULL) { |
507 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), | 507 Trace("Connect #%d:%s, id:%d -> end\n", node->id(), |
508 block->id().ToInt()); | 508 node->op()->mnemonic(), block->id().ToInt()); |
509 } else { | 509 } else { |
510 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), | 510 Trace("Connect #%d:%s, id:%d -> id:%d\n", node->id(), |
511 block->id().ToInt(), succ->id().ToInt()); | 511 node->op()->mnemonic(), block->id().ToInt(), succ->id().ToInt()); |
512 } | 512 } |
513 } | 513 } |
514 | 514 |
515 bool IsExceptionalCall(Node* node) { | 515 bool IsExceptionalCall(Node* node) { |
516 for (Node* const use : node->uses()) { | 516 for (Node* const use : node->uses()) { |
517 if (use->opcode() == IrOpcode::kIfException) return true; | 517 if (use->opcode() == IrOpcode::kIfException) return true; |
518 } | 518 } |
519 return false; | 519 return false; |
520 } | 520 } |
521 | 521 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 } | 870 } |
871 current->set_loop_header(current_header); | 871 current->set_loop_header(current_header); |
872 | 872 |
873 // Push a new loop onto the stack if this loop is a loop header. | 873 // Push a new loop onto the stack if this loop is a loop header. |
874 if (HasLoopNumber(current)) { | 874 if (HasLoopNumber(current)) { |
875 ++loop_depth; | 875 ++loop_depth; |
876 current_loop = &loops_[GetLoopNumber(current)]; | 876 current_loop = &loops_[GetLoopNumber(current)]; |
877 BasicBlock* end = current_loop->end; | 877 BasicBlock* end = current_loop->end; |
878 current->set_loop_end(end == NULL ? BeyondEndSentinel() : end); | 878 current->set_loop_end(end == NULL ? BeyondEndSentinel() : end); |
879 current_header = current_loop->header; | 879 current_header = current_loop->header; |
880 Trace("B%d is a loop header, increment loop depth to %d\n", | 880 Trace("id:%d is a loop header, increment loop depth to %d\n", |
881 current->id().ToInt(), loop_depth); | 881 current->id().ToInt(), loop_depth); |
882 } | 882 } |
883 | 883 |
884 current->set_loop_depth(loop_depth); | 884 current->set_loop_depth(loop_depth); |
885 | 885 |
886 if (current->loop_header() == NULL) { | 886 if (current->loop_header() == NULL) { |
887 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), | 887 Trace("id:%d is not in a loop (depth == %d)\n", current->id().ToInt(), |
888 current->loop_depth()); | 888 current->loop_depth()); |
889 } else { | 889 } else { |
890 Trace("B%d has loop header B%d, (depth == %d)\n", current->id().ToInt(), | 890 Trace("id:%d has loop header id:%d, (depth == %d)\n", |
891 current->loop_header()->id().ToInt(), current->loop_depth()); | 891 current->id().ToInt(), current->loop_header()->id().ToInt(), |
| 892 current->loop_depth()); |
892 } | 893 } |
893 } | 894 } |
894 } | 895 } |
895 | 896 |
896 // Computes loop membership from the backedges of the control flow graph. | 897 // Computes loop membership from the backedges of the control flow graph. |
897 void ComputeLoopInfo(ZoneVector<SpecialRPOStackFrame>& queue, | 898 void ComputeLoopInfo(ZoneVector<SpecialRPOStackFrame>& queue, |
898 size_t num_loops, ZoneVector<Backedge>* backedges) { | 899 size_t num_loops, ZoneVector<Backedge>* backedges) { |
899 // Extend existing loop membership vectors. | 900 // Extend existing loop membership vectors. |
900 for (LoopInfo& loop : loops_) { | 901 for (LoopInfo& loop : loops_) { |
901 BitVector* new_members = new (zone_) | 902 BitVector* new_members = new (zone_) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 } | 948 } |
948 | 949 |
949 #if DEBUG | 950 #if DEBUG |
950 void PrintRPO() { | 951 void PrintRPO() { |
951 OFStream os(stdout); | 952 OFStream os(stdout); |
952 os << "RPO with " << loops_.size() << " loops"; | 953 os << "RPO with " << loops_.size() << " loops"; |
953 if (loops_.size() > 0) { | 954 if (loops_.size() > 0) { |
954 os << " ("; | 955 os << " ("; |
955 for (size_t i = 0; i < loops_.size(); i++) { | 956 for (size_t i = 0; i < loops_.size(); i++) { |
956 if (i > 0) os << " "; | 957 if (i > 0) os << " "; |
957 os << "B" << loops_[i].header->id(); | 958 os << "id:" << loops_[i].header->id(); |
958 } | 959 } |
959 os << ")"; | 960 os << ")"; |
960 } | 961 } |
961 os << ":\n"; | 962 os << ":\n"; |
962 | 963 |
963 for (BasicBlock* block = order_; block != NULL; block = block->rpo_next()) { | 964 for (BasicBlock* block = order_; block != NULL; block = block->rpo_next()) { |
964 os << std::setw(5) << block->rpo_number() << ":"; | 965 os << std::setw(5) << "B" << block->rpo_number() << ":"; |
965 for (size_t i = 0; i < loops_.size(); i++) { | 966 for (size_t i = 0; i < loops_.size(); i++) { |
966 bool range = loops_[i].header->LoopContains(block); | 967 bool range = loops_[i].header->LoopContains(block); |
967 bool membership = loops_[i].header != block && range; | 968 bool membership = loops_[i].header != block && range; |
968 os << (membership ? " |" : " "); | 969 os << (membership ? " |" : " "); |
969 os << (range ? "x" : " "); | 970 os << (range ? "x" : " "); |
970 } | 971 } |
971 os << " B" << block->id() << ": "; | 972 os << " id:" << block->id() << ": "; |
972 if (block->loop_end() != NULL) { | 973 if (block->loop_end() != NULL) { |
973 os << " range: [" << block->rpo_number() << ", " | 974 os << " range: [B" << block->rpo_number() << ", B" |
974 << block->loop_end()->rpo_number() << ")"; | 975 << block->loop_end()->rpo_number() << ")"; |
975 } | 976 } |
976 if (block->loop_header() != NULL) { | 977 if (block->loop_header() != NULL) { |
977 os << " header: B" << block->loop_header()->id(); | 978 os << " header: id:" << block->loop_header()->id(); |
978 } | 979 } |
979 if (block->loop_depth() > 0) { | 980 if (block->loop_depth() > 0) { |
980 os << " depth: " << block->loop_depth(); | 981 os << " depth: " << block->loop_depth(); |
981 } | 982 } |
982 os << "\n"; | 983 os << "\n"; |
983 } | 984 } |
984 } | 985 } |
985 | 986 |
986 void VerifySpecialRPO() { | 987 void VerifySpecialRPO() { |
987 BasicBlockVector* order = schedule_->rpo_order(); | 988 BasicBlockVector* order = schedule_->rpo_order(); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1088 // except for backwards edges have been visited. | 1089 // except for backwards edges have been visited. |
1089 for (++pred; pred != end; ++pred) { | 1090 for (++pred; pred != end; ++pred) { |
1090 // Don't examine backwards edges. | 1091 // Don't examine backwards edges. |
1091 if ((*pred)->dominator_depth() < 0) continue; | 1092 if ((*pred)->dominator_depth() < 0) continue; |
1092 dominator = BasicBlock::GetCommonDominator(dominator, *pred); | 1093 dominator = BasicBlock::GetCommonDominator(dominator, *pred); |
1093 deferred = deferred & (*pred)->deferred(); | 1094 deferred = deferred & (*pred)->deferred(); |
1094 } | 1095 } |
1095 block->set_dominator(dominator); | 1096 block->set_dominator(dominator); |
1096 block->set_dominator_depth(dominator->dominator_depth() + 1); | 1097 block->set_dominator_depth(dominator->dominator_depth() + 1); |
1097 block->set_deferred(deferred | block->deferred()); | 1098 block->set_deferred(deferred | block->deferred()); |
1098 Trace("Block B%d's idom is B%d, depth = %d\n", block->id().ToInt(), | 1099 Trace("Block id:%d's idom is id:%d, depth = %d\n", block->id().ToInt(), |
1099 dominator->id().ToInt(), block->dominator_depth()); | 1100 dominator->id().ToInt(), block->dominator_depth()); |
1100 } | 1101 } |
1101 } | 1102 } |
1102 | 1103 |
1103 | 1104 |
1104 void Scheduler::GenerateImmediateDominatorTree() { | 1105 void Scheduler::GenerateImmediateDominatorTree() { |
1105 Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n"); | 1106 Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n"); |
1106 | 1107 |
1107 // Seed start block to be the first dominator. | 1108 // Seed start block to be the first dominator. |
1108 schedule_->start()->set_dominator_depth(0); | 1109 schedule_->start()->set_dominator_depth(0); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1207 | 1208 |
1208 private: | 1209 private: |
1209 // Visits one node from the queue and propagates its current schedule early | 1210 // Visits one node from the queue and propagates its current schedule early |
1210 // position to all uses. This in turn might push more nodes onto the queue. | 1211 // position to all uses. This in turn might push more nodes onto the queue. |
1211 void VisitNode(Node* node) { | 1212 void VisitNode(Node* node) { |
1212 Scheduler::SchedulerData* data = scheduler_->GetData(node); | 1213 Scheduler::SchedulerData* data = scheduler_->GetData(node); |
1213 | 1214 |
1214 // Fixed nodes already know their schedule early position. | 1215 // Fixed nodes already know their schedule early position. |
1215 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { | 1216 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { |
1216 data->minimum_block_ = schedule_->block(node); | 1217 data->minimum_block_ = schedule_->block(node); |
1217 Trace("Fixing #%d:%s minimum_block = B%d, dominator_depth = %d\n", | 1218 Trace("Fixing #%d:%s minimum_block = id:%d, dominator_depth = %d\n", |
1218 node->id(), node->op()->mnemonic(), | 1219 node->id(), node->op()->mnemonic(), |
1219 data->minimum_block_->id().ToInt(), | 1220 data->minimum_block_->id().ToInt(), |
1220 data->minimum_block_->dominator_depth()); | 1221 data->minimum_block_->dominator_depth()); |
1221 } | 1222 } |
1222 | 1223 |
1223 // No need to propagate unconstrained schedule early positions. | 1224 // No need to propagate unconstrained schedule early positions. |
1224 if (data->minimum_block_ == schedule_->start()) return; | 1225 if (data->minimum_block_ == schedule_->start()) return; |
1225 | 1226 |
1226 // Propagate schedule early position. | 1227 // Propagate schedule early position. |
1227 DCHECK(data->minimum_block_ != NULL); | 1228 DCHECK(data->minimum_block_ != NULL); |
(...skipping 17 matching lines...) Expand all Loading... |
1245 PropagateMinimumPositionToNode(block, control); | 1246 PropagateMinimumPositionToNode(block, control); |
1246 } | 1247 } |
1247 | 1248 |
1248 // Propagate new position if it is deeper down the dominator tree than the | 1249 // Propagate new position if it is deeper down the dominator tree than the |
1249 // current. Note that all inputs need to have minimum block position inside | 1250 // current. Note that all inputs need to have minimum block position inside |
1250 // the dominator chain of {node}'s minimum block position. | 1251 // the dominator chain of {node}'s minimum block position. |
1251 DCHECK(InsideSameDominatorChain(block, data->minimum_block_)); | 1252 DCHECK(InsideSameDominatorChain(block, data->minimum_block_)); |
1252 if (block->dominator_depth() > data->minimum_block_->dominator_depth()) { | 1253 if (block->dominator_depth() > data->minimum_block_->dominator_depth()) { |
1253 data->minimum_block_ = block; | 1254 data->minimum_block_ = block; |
1254 queue_.push(node); | 1255 queue_.push(node); |
1255 Trace("Propagating #%d:%s minimum_block = B%d, dominator_depth = %d\n", | 1256 Trace("Propagating #%d:%s minimum_block = id:%d, dominator_depth = %d\n", |
1256 node->id(), node->op()->mnemonic(), | 1257 node->id(), node->op()->mnemonic(), |
1257 data->minimum_block_->id().ToInt(), | 1258 data->minimum_block_->id().ToInt(), |
1258 data->minimum_block_->dominator_depth()); | 1259 data->minimum_block_->dominator_depth()); |
1259 } | 1260 } |
1260 } | 1261 } |
1261 | 1262 |
1262 #if DEBUG | 1263 #if DEBUG |
1263 bool InsideSameDominatorChain(BasicBlock* b1, BasicBlock* b2) { | 1264 bool InsideSameDominatorChain(BasicBlock* b1, BasicBlock* b2) { |
1264 BasicBlock* dominator = BasicBlock::GetCommonDominator(b1, b2); | 1265 BasicBlock* dominator = BasicBlock::GetCommonDominator(b1, b2); |
1265 return dominator == b1 || dominator == b2; | 1266 return dominator == b1 || dominator == b2; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 | 1342 |
1342 // Determine the dominating block for all of the uses of this node. It is | 1343 // Determine the dominating block for all of the uses of this node. It is |
1343 // the latest block that this node can be scheduled in. | 1344 // the latest block that this node can be scheduled in. |
1344 Trace("Scheduling #%d:%s\n", node->id(), node->op()->mnemonic()); | 1345 Trace("Scheduling #%d:%s\n", node->id(), node->op()->mnemonic()); |
1345 BasicBlock* block = GetCommonDominatorOfUses(node); | 1346 BasicBlock* block = GetCommonDominatorOfUses(node); |
1346 DCHECK_NOT_NULL(block); | 1347 DCHECK_NOT_NULL(block); |
1347 | 1348 |
1348 // The schedule early block dominates the schedule late block. | 1349 // The schedule early block dominates the schedule late block. |
1349 BasicBlock* min_block = scheduler_->GetData(node)->minimum_block_; | 1350 BasicBlock* min_block = scheduler_->GetData(node)->minimum_block_; |
1350 DCHECK_EQ(min_block, BasicBlock::GetCommonDominator(block, min_block)); | 1351 DCHECK_EQ(min_block, BasicBlock::GetCommonDominator(block, min_block)); |
1351 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum = B%d\n", | 1352 Trace( |
1352 node->id(), node->op()->mnemonic(), block->id().ToInt(), | 1353 "Schedule late of #%d:%s is id:%d at loop depth %d, minimum = id:%d\n", |
1353 block->loop_depth(), min_block->id().ToInt()); | 1354 node->id(), node->op()->mnemonic(), block->id().ToInt(), |
| 1355 block->loop_depth(), min_block->id().ToInt()); |
1354 | 1356 |
1355 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively | 1357 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively |
1356 // into enclosing loop pre-headers until they would preceed their schedule | 1358 // into enclosing loop pre-headers until they would preceed their schedule |
1357 // early position. | 1359 // early position. |
1358 BasicBlock* hoist_block = GetHoistBlock(block); | 1360 BasicBlock* hoist_block = GetHoistBlock(block); |
1359 if (hoist_block && | 1361 if (hoist_block && |
1360 hoist_block->dominator_depth() >= min_block->dominator_depth()) { | 1362 hoist_block->dominator_depth() >= min_block->dominator_depth()) { |
1361 do { | 1363 do { |
1362 Trace(" hoisting #%d:%s to block B%d\n", node->id(), | 1364 Trace(" hoisting #%d:%s to block id:%d\n", node->id(), |
1363 node->op()->mnemonic(), hoist_block->id().ToInt()); | 1365 node->op()->mnemonic(), hoist_block->id().ToInt()); |
1364 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); | 1366 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); |
1365 block = hoist_block; | 1367 block = hoist_block; |
1366 hoist_block = GetHoistBlock(hoist_block); | 1368 hoist_block = GetHoistBlock(hoist_block); |
1367 } while (hoist_block && | 1369 } while (hoist_block && |
1368 hoist_block->dominator_depth() >= min_block->dominator_depth()); | 1370 hoist_block->dominator_depth() >= min_block->dominator_depth()); |
1369 } else if (scheduler_->flags_ & Scheduler::kSplitNodes) { | 1371 } else if (scheduler_->flags_ & Scheduler::kSplitNodes) { |
1370 // Split the {node} if beneficial and return the new {block} for it. | 1372 // Split the {node} if beneficial and return the new {block} for it. |
1371 block = SplitNode(block, node); | 1373 block = SplitNode(block, node); |
1372 } | 1374 } |
(...skipping 29 matching lines...) Expand all Loading... |
1402 // Clear marking bits. | 1404 // Clear marking bits. |
1403 DCHECK(marking_queue_.empty()); | 1405 DCHECK(marking_queue_.empty()); |
1404 std::fill(marked_.begin(), marked_.end(), false); | 1406 std::fill(marked_.begin(), marked_.end(), false); |
1405 marked_.resize(schedule_->BasicBlockCount() + 1, false); | 1407 marked_.resize(schedule_->BasicBlockCount() + 1, false); |
1406 | 1408 |
1407 // Check if the {node} has uses in {block}. | 1409 // Check if the {node} has uses in {block}. |
1408 for (Edge edge : node->use_edges()) { | 1410 for (Edge edge : node->use_edges()) { |
1409 BasicBlock* use_block = GetBlockForUse(edge); | 1411 BasicBlock* use_block = GetBlockForUse(edge); |
1410 if (use_block == nullptr || marked_[use_block->id().ToSize()]) continue; | 1412 if (use_block == nullptr || marked_[use_block->id().ToSize()]) continue; |
1411 if (use_block == block) { | 1413 if (use_block == block) { |
1412 Trace(" not splitting #%d:%s, it is used in B%d\n", node->id(), | 1414 Trace(" not splitting #%d:%s, it is used in id:%d\n", node->id(), |
1413 node->op()->mnemonic(), block->id().ToInt()); | 1415 node->op()->mnemonic(), block->id().ToInt()); |
1414 marking_queue_.clear(); | 1416 marking_queue_.clear(); |
1415 return block; | 1417 return block; |
1416 } | 1418 } |
1417 MarkBlock(use_block); | 1419 MarkBlock(use_block); |
1418 } | 1420 } |
1419 | 1421 |
1420 // Compute transitive marking closure; a block is marked if all its | 1422 // Compute transitive marking closure; a block is marked if all its |
1421 // successors are marked. | 1423 // successors are marked. |
1422 do { | 1424 do { |
1423 BasicBlock* top_block = marking_queue_.front(); | 1425 BasicBlock* top_block = marking_queue_.front(); |
1424 marking_queue_.pop_front(); | 1426 marking_queue_.pop_front(); |
1425 if (marked_[top_block->id().ToSize()]) continue; | 1427 if (marked_[top_block->id().ToSize()]) continue; |
1426 bool marked = true; | 1428 bool marked = true; |
1427 for (BasicBlock* successor : top_block->successors()) { | 1429 for (BasicBlock* successor : top_block->successors()) { |
1428 if (!marked_[successor->id().ToSize()]) { | 1430 if (!marked_[successor->id().ToSize()]) { |
1429 marked = false; | 1431 marked = false; |
1430 break; | 1432 break; |
1431 } | 1433 } |
1432 } | 1434 } |
1433 if (marked) MarkBlock(top_block); | 1435 if (marked) MarkBlock(top_block); |
1434 } while (!marking_queue_.empty()); | 1436 } while (!marking_queue_.empty()); |
1435 | 1437 |
1436 // If the (common dominator) {block} is marked, we know that all paths from | 1438 // If the (common dominator) {block} is marked, we know that all paths from |
1437 // {block} to the end contain at least one use of {node}, and hence there's | 1439 // {block} to the end contain at least one use of {node}, and hence there's |
1438 // no point in splitting the {node} in this case. | 1440 // no point in splitting the {node} in this case. |
1439 if (marked_[block->id().ToSize()]) { | 1441 if (marked_[block->id().ToSize()]) { |
1440 Trace(" not splitting #%d:%s, its common dominator B%d is perfect\n", | 1442 Trace(" not splitting #%d:%s, its common dominator id:%d is perfect\n", |
1441 node->id(), node->op()->mnemonic(), block->id().ToInt()); | 1443 node->id(), node->op()->mnemonic(), block->id().ToInt()); |
1442 return block; | 1444 return block; |
1443 } | 1445 } |
1444 | 1446 |
1445 // Split {node} for uses according to the previously computed marking | 1447 // Split {node} for uses according to the previously computed marking |
1446 // closure. Every marking partition has a unique dominator, which get's a | 1448 // closure. Every marking partition has a unique dominator, which get's a |
1447 // copy of the {node} with the exception of the first partition, which get's | 1449 // copy of the {node} with the exception of the first partition, which get's |
1448 // the {node} itself. | 1450 // the {node} itself. |
1449 ZoneMap<BasicBlock*, Node*> dominators(scheduler_->zone_); | 1451 ZoneMap<BasicBlock*, Node*> dominators(scheduler_->zone_); |
1450 for (Edge edge : node->use_edges()) { | 1452 for (Edge edge : node->use_edges()) { |
1451 BasicBlock* use_block = GetBlockForUse(edge); | 1453 BasicBlock* use_block = GetBlockForUse(edge); |
1452 if (use_block == nullptr) continue; | 1454 if (use_block == nullptr) continue; |
1453 while (marked_[use_block->dominator()->id().ToSize()]) { | 1455 while (marked_[use_block->dominator()->id().ToSize()]) { |
1454 use_block = use_block->dominator(); | 1456 use_block = use_block->dominator(); |
1455 } | 1457 } |
1456 auto& use_node = dominators[use_block]; | 1458 auto& use_node = dominators[use_block]; |
1457 if (use_node == nullptr) { | 1459 if (use_node == nullptr) { |
1458 if (dominators.size() == 1u) { | 1460 if (dominators.size() == 1u) { |
1459 // Place the {node} at {use_block}. | 1461 // Place the {node} at {use_block}. |
1460 block = use_block; | 1462 block = use_block; |
1461 use_node = node; | 1463 use_node = node; |
1462 Trace(" pushing #%d:%s down to B%d\n", node->id(), | 1464 Trace(" pushing #%d:%s down to id:%d\n", node->id(), |
1463 node->op()->mnemonic(), block->id().ToInt()); | 1465 node->op()->mnemonic(), block->id().ToInt()); |
1464 } else { | 1466 } else { |
1465 // Place a copy of {node} at {use_block}. | 1467 // Place a copy of {node} at {use_block}. |
1466 use_node = CloneNode(node); | 1468 use_node = CloneNode(node); |
1467 Trace(" cloning #%d:%s for B%d\n", use_node->id(), | 1469 Trace(" cloning #%d:%s for id:%d\n", use_node->id(), |
1468 use_node->op()->mnemonic(), use_block->id().ToInt()); | 1470 use_node->op()->mnemonic(), use_block->id().ToInt()); |
1469 scheduler_->schedule_queue_.push(use_node); | 1471 scheduler_->schedule_queue_.push(use_node); |
1470 } | 1472 } |
1471 } | 1473 } |
1472 edge.UpdateTo(use_node); | 1474 edge.UpdateTo(use_node); |
1473 } | 1475 } |
1474 return block; | 1476 return block; |
1475 } | 1477 } |
1476 | 1478 |
1477 BasicBlock* GetHoistBlock(BasicBlock* block) { | 1479 BasicBlock* GetHoistBlock(BasicBlock* block) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1534 // If the use is from a fixed (i.e. non-floating) merge, we use the | 1536 // If the use is from a fixed (i.e. non-floating) merge, we use the |
1535 // predecessor block of the current input to the merge. | 1537 // predecessor block of the current input to the merge. |
1536 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { | 1538 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { |
1537 Trace(" input@%d into a fixed merge #%d:%s\n", edge.index(), use->id(), | 1539 Trace(" input@%d into a fixed merge #%d:%s\n", edge.index(), use->id(), |
1538 use->op()->mnemonic()); | 1540 use->op()->mnemonic()); |
1539 return FindPredecessorBlock(edge.to()); | 1541 return FindPredecessorBlock(edge.to()); |
1540 } | 1542 } |
1541 } | 1543 } |
1542 BasicBlock* result = schedule_->block(use); | 1544 BasicBlock* result = schedule_->block(use); |
1543 if (result == NULL) return NULL; | 1545 if (result == NULL) return NULL; |
1544 Trace(" must dominate use #%d:%s in B%d\n", use->id(), | 1546 Trace(" must dominate use #%d:%s in id:%d\n", use->id(), |
1545 use->op()->mnemonic(), result->id().ToInt()); | 1547 use->op()->mnemonic(), result->id().ToInt()); |
1546 return result; | 1548 return result; |
1547 } | 1549 } |
1548 | 1550 |
1549 void ScheduleFloatingControl(BasicBlock* block, Node* node) { | 1551 void ScheduleFloatingControl(BasicBlock* block, Node* node) { |
1550 scheduler_->FuseFloatingControl(block, node); | 1552 scheduler_->FuseFloatingControl(block, node); |
1551 } | 1553 } |
1552 | 1554 |
1553 void ScheduleNode(BasicBlock* block, Node* node) { | 1555 void ScheduleNode(BasicBlock* block, Node* node) { |
1554 schedule_->PlanNode(block, node); | 1556 schedule_->PlanNode(block, node); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 MovePlannedNodes(block, schedule_->block(node)); | 1667 MovePlannedNodes(block, schedule_->block(node)); |
1666 | 1668 |
1667 if (FLAG_trace_turbo_scheduler) { | 1669 if (FLAG_trace_turbo_scheduler) { |
1668 OFStream os(stdout); | 1670 OFStream os(stdout); |
1669 os << "Schedule after control flow fusion:\n" << *schedule_; | 1671 os << "Schedule after control flow fusion:\n" << *schedule_; |
1670 } | 1672 } |
1671 } | 1673 } |
1672 | 1674 |
1673 | 1675 |
1674 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) { | 1676 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) { |
1675 Trace("Move planned nodes from B%d to B%d\n", from->id().ToInt(), | 1677 Trace("Move planned nodes from id:%d to id:%d\n", from->id().ToInt(), |
1676 to->id().ToInt()); | 1678 to->id().ToInt()); |
1677 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]); | 1679 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]); |
1678 for (Node* const node : *nodes) { | 1680 for (Node* const node : *nodes) { |
1679 schedule_->SetBlockForNode(to, node); | 1681 schedule_->SetBlockForNode(to, node); |
1680 scheduled_nodes_[to->id().ToSize()].push_back(node); | 1682 scheduled_nodes_[to->id().ToSize()].push_back(node); |
1681 } | 1683 } |
1682 nodes->clear(); | 1684 nodes->clear(); |
1683 } | 1685 } |
1684 | 1686 |
1685 } // namespace compiler | 1687 } // namespace compiler |
1686 } // namespace internal | 1688 } // namespace internal |
1687 } // namespace v8 | 1689 } // namespace v8 |
OLD | NEW |