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

Side by Side Diff: src/compiler/scheduler.cc

Issue 900543002: [WIP] Node splitting in Scheduler. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « src/compiler/scheduler.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 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 "src/bit-vector.h" 7 #include "src/bit-vector.h"
8 #include "src/compiler/common-operator.h" 8 #include "src/compiler/common-operator.h"
9 #include "src/compiler/control-equivalence.h" 9 #include "src/compiler/control-equivalence.h"
10 #include "src/compiler/graph.h" 10 #include "src/compiler/graph.h"
11 #include "src/compiler/node.h" 11 #include "src/compiler/node.h"
12 #include "src/compiler/node-marker.h" 12 #include "src/compiler/node-marker.h"
13 #include "src/compiler/node-properties.h" 13 #include "src/compiler/node-properties.h"
14 #include "src/zone-containers.h" 14 #include "src/zone-containers.h"
15 15
16 namespace v8 { 16 namespace v8 {
17 namespace internal { 17 namespace internal {
18 namespace compiler { 18 namespace compiler {
19 19
20 static inline void Trace(const char* msg, ...) { 20 static inline void Trace(const char* msg, ...) {
21 if (FLAG_trace_turbo_scheduler) { 21 if (FLAG_trace_turbo_scheduler) {
22 va_list arguments; 22 va_list arguments;
23 va_start(arguments, msg); 23 va_start(arguments, msg);
24 base::OS::VPrint(msg, arguments); 24 base::OS::VPrint(msg, arguments);
25 va_end(arguments); 25 va_end(arguments);
26 } 26 }
27 } 27 }
28 28
29 29
30 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule) 30 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule, Flags flags)
31 : zone_(zone), 31 : zone_(zone),
32 graph_(graph), 32 graph_(graph),
33 schedule_(schedule), 33 schedule_(schedule),
34 flags_(flags),
34 scheduled_nodes_(zone), 35 scheduled_nodes_(zone),
35 schedule_root_nodes_(zone), 36 schedule_root_nodes_(zone),
36 schedule_queue_(zone), 37 schedule_queue_(zone),
37 node_data_(graph_->NodeCount(), DefaultSchedulerData(), zone) {} 38 node_data_(graph_->NodeCount(), DefaultSchedulerData(), zone) {}
38 39
39 40
40 Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph) { 41 Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph, Flags flags) {
41 Schedule* schedule = new (graph->zone()) 42 Schedule* schedule = new (graph->zone())
42 Schedule(graph->zone(), static_cast<size_t>(graph->NodeCount())); 43 Schedule(graph->zone(), static_cast<size_t>(graph->NodeCount()));
43 Scheduler scheduler(zone, graph, schedule); 44 Scheduler scheduler(zone, graph, schedule, flags);
44 45
45 scheduler.BuildCFG(); 46 scheduler.BuildCFG();
46 scheduler.ComputeSpecialRPONumbering(); 47 scheduler.ComputeSpecialRPONumbering();
47 scheduler.GenerateImmediateDominatorTree(); 48 scheduler.GenerateImmediateDominatorTree();
48 49
49 scheduler.PrepareUses(); 50 scheduler.PrepareUses();
50 scheduler.ScheduleEarly(); 51 scheduler.ScheduleEarly();
51 scheduler.ScheduleLate(); 52 scheduler.ScheduleLate();
52 53
53 scheduler.SealFinalSchedule(); 54 scheduler.SealFinalSchedule();
(...skipping 1165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 } 1220 }
1220 1221
1221 1222
1222 // ----------------------------------------------------------------------------- 1223 // -----------------------------------------------------------------------------
1223 // Phase 5: Schedule nodes late. 1224 // Phase 5: Schedule nodes late.
1224 1225
1225 1226
1226 class ScheduleLateNodeVisitor { 1227 class ScheduleLateNodeVisitor {
1227 public: 1228 public:
1228 ScheduleLateNodeVisitor(Zone* zone, Scheduler* scheduler) 1229 ScheduleLateNodeVisitor(Zone* zone, Scheduler* scheduler)
1229 : scheduler_(scheduler), schedule_(scheduler_->schedule_) {} 1230 : scheduler_(scheduler),
1231 schedule_(scheduler_->schedule_),
1232 visited_(scheduler->zone_),
1233 stack_(scheduler->zone_) {}
1230 1234
1231 // Run the schedule late algorithm on a set of fixed root nodes. 1235 // Run the schedule late algorithm on a set of fixed root nodes.
1232 void Run(NodeVector* roots) { 1236 void Run(NodeVector* roots) {
1233 for (Node* const root : *roots) { 1237 for (Node* const root : *roots) {
1234 ProcessQueue(root); 1238 ProcessQueue(root);
1235 } 1239 }
1236 } 1240 }
1237 1241
1238 private: 1242 private:
1239 void ProcessQueue(Node* root) { 1243 void ProcessQueue(Node* root) {
1240 ZoneQueue<Node*>* queue = &(scheduler_->schedule_queue_); 1244 ZoneQueue<Node*>* queue = &(scheduler_->schedule_queue_);
1241 for (Node* node : root->inputs()) { 1245 for (Node* node : root->inputs()) {
1242 // Don't schedule coupled nodes on their own. 1246 // Don't schedule coupled nodes on their own.
1243 if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) { 1247 if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) {
1244 node = NodeProperties::GetControlInput(node); 1248 node = NodeProperties::GetControlInput(node);
1245 } 1249 }
1246 1250
1247 // Test schedulability condition by looking at unscheduled use count. 1251 // Test schedulability condition by looking at unscheduled use count.
1248 if (scheduler_->GetData(node)->unscheduled_count_ != 0) continue; 1252 if (scheduler_->GetData(node)->unscheduled_count_ != 0) continue;
1249 1253
1250 queue->push(node); 1254 queue->push(node);
1251 while (!queue->empty()) { 1255 while (!queue->empty()) {
1252 VisitNode(queue->front()); 1256 Node* const node = queue->front();
1253 queue->pop(); 1257 queue->pop();
1258 VisitNode(node);
1254 } 1259 }
1255 } 1260 }
1256 } 1261 }
1257 1262
1258 // Visits one node from the queue of schedulable nodes and determines its 1263 // Visits one node from the queue of schedulable nodes and determines its
1259 // schedule late position. Also hoists nodes out of loops to find a more 1264 // schedule late position. Also hoists nodes out of loops to find a more
1260 // optimal scheduling position. 1265 // optimal scheduling position.
1261 void VisitNode(Node* node) { 1266 void VisitNode(Node* node) {
1262 DCHECK_EQ(0, scheduler_->GetData(node)->unscheduled_count_); 1267 DCHECK_EQ(0, scheduler_->GetData(node)->unscheduled_count_);
1263 1268
(...skipping 11 matching lines...) Expand all
1275 BasicBlock* min_block = scheduler_->GetData(node)->minimum_block_; 1280 BasicBlock* min_block = scheduler_->GetData(node)->minimum_block_;
1276 DCHECK_EQ(min_block, BasicBlock::GetCommonDominator(block, min_block)); 1281 DCHECK_EQ(min_block, BasicBlock::GetCommonDominator(block, min_block));
1277 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum = B%d\n", 1282 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum = B%d\n",
1278 node->id(), node->op()->mnemonic(), block->id().ToInt(), 1283 node->id(), node->op()->mnemonic(), block->id().ToInt(),
1279 block->loop_depth(), min_block->id().ToInt()); 1284 block->loop_depth(), min_block->id().ToInt());
1280 1285
1281 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively 1286 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively
1282 // into enclosing loop pre-headers until they would preceed their schedule 1287 // into enclosing loop pre-headers until they would preceed their schedule
1283 // early position. 1288 // early position.
1284 BasicBlock* hoist_block = GetPreHeader(block); 1289 BasicBlock* hoist_block = GetPreHeader(block);
1285 while (hoist_block != NULL && 1290 if (hoist_block &&
1286 hoist_block->dominator_depth() >= min_block->dominator_depth()) { 1291 hoist_block->dominator_depth() >= min_block->dominator_depth()) {
1287 Trace(" hoisting #%d:%s to block B%d\n", node->id(), 1292 do {
1288 node->op()->mnemonic(), hoist_block->id().ToInt()); 1293 Trace(" hoisting #%d:%s to block B%d\n", node->id(),
1289 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); 1294 node->op()->mnemonic(), hoist_block->id().ToInt());
1290 block = hoist_block; 1295 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth());
1291 hoist_block = GetPreHeader(hoist_block); 1296 block = hoist_block;
1297 hoist_block = GetPreHeader(hoist_block);
1298 } while (hoist_block &&
1299 hoist_block->dominator_depth() >= min_block->dominator_depth());
1300 } else if (scheduler_->flags_ & Scheduler::kSplitNodes &&
1301 block->SuccessorCount() >= 2 &&
1302 node->op()->HasProperty(Operator::kPure)) {
1303 // Split the {node} if beneficial and return the new {block} for it.
1304 if (SplitNode(block, node)) return;
1292 } 1305 }
1293 1306
1294 // Schedule the node or a floating control structure. 1307 // Schedule the node or a floating control structure.
1295 if (NodeProperties::IsControl(node)) { 1308 if (NodeProperties::IsControl(node)) {
1296 ScheduleFloatingControl(block, node); 1309 ScheduleFloatingControl(block, node);
1297 } else { 1310 } else {
1298 ScheduleNode(block, node); 1311 ScheduleNode(block, node);
1299 } 1312 }
1300 } 1313 }
1301 1314
1315 bool SplitNode(BasicBlock* block, Node* node) {
1316 std::fill(visited_.begin(), visited_.end(), false);
1317 visited_.resize(schedule_->BasicBlockCount() + 1, false);
1318 stack_.clear();
1319
1320 // Check if the {node} has uses in {block}.
1321 for (Edge edge : node->use_edges()) {
1322 BasicBlock* use_block = GetBlockForUse(edge);
1323 if (use_block == block) {
1324 Trace(" not splitting #%d:%s, it is used in B%d\n", node->id(),
1325 node->op()->mnemonic(), block->id().ToInt());
1326 return false;
1327 }
1328 if (use_block) {
1329 visited_[use_block->id().ToSize()] = true;
1330 for (BasicBlock* predecessor : use_block->predecessors()) {
1331 stack_.push_back(predecessor);
1332 }
1333 }
1334 }
1335
1336 while (!stack_.empty()) {
1337 BasicBlock* block = stack_.back();
1338 stack_.pop_back();
1339 bool visited = visited_[block->id().ToSize()];
1340 if (visited) continue;
1341 visited = true;
1342 for (BasicBlock* successor : block->successors()) {
1343 if (!visited_[successor->id().ToSize()]) {
1344 visited = false;
1345 break;
1346 }
1347 }
1348 if (visited) {
1349 visited_[block->id().ToSize()] = true;
1350 for (BasicBlock* predecessor : block->predecessors()) {
1351 stack_.push_back(predecessor);
1352 }
1353 }
1354 }
1355
1356 if (visited_[block->id().ToSize()]) {
1357 return false;
1358 }
1359
1360 std::map<BasicBlock*, Node*> dominators;
1361 for (Edge edge : node->use_edges()) {
1362 BasicBlock* use_block = GetBlockForUse(edge);
1363 if (!use_block) continue;
1364 BasicBlock* dominator = use_block;
1365 DCHECK(visited_[dominator->id().ToSize()]);
1366 while (visited_[dominator->dominator()->id().ToSize()]) {
1367 dominator = dominator->dominator();
1368 }
1369 if (dominators.find(dominator) == dominators.end()) {
1370 if (dominators.size() == 0) {
1371 dominators.insert(std::make_pair(dominator, node));
1372 scheduler_->schedule_queue_.push(node);
1373 } else {
1374 Node* copy = CloneNode(node);
1375 dominators.insert(std::make_pair(dominator, copy));
1376 scheduler_->schedule_queue_.push(copy);
1377 }
1378 }
1379 }
1380
1381 for (Edge edge : node->use_edges()) {
1382 BasicBlock* use_block = GetBlockForUse(edge);
1383 if (!use_block) continue;
1384 for (;; use_block = use_block->dominator()) {
1385 DCHECK(visited_[use_block->id().ToSize()]);
1386 if (Node* node = dominators[use_block]) {
1387 edge.UpdateTo(node);
1388 break;
1389 }
1390 }
1391 }
1392 return true;
1393 }
1394
1302 BasicBlock* GetPreHeader(BasicBlock* block) { 1395 BasicBlock* GetPreHeader(BasicBlock* block) {
1303 if (block->IsLoopHeader()) { 1396 if (block->IsLoopHeader()) {
1304 return block->dominator(); 1397 return block->dominator();
1305 } else if (block->loop_header() != NULL) { 1398 } else if (block->loop_header() != NULL) {
1306 return block->loop_header()->dominator(); 1399 return block->loop_header()->dominator();
1307 } else { 1400 } else {
1308 return NULL; 1401 return NULL;
1309 } 1402 }
1310 } 1403 }
1311 1404
1312 BasicBlock* GetCommonDominatorOfUses(Node* node) { 1405 BasicBlock* GetCommonDominatorOfUses(Node* node) {
1313 BasicBlock* block = NULL; 1406 BasicBlock* block = nullptr;
1314 for (Edge edge : node->use_edges()) { 1407 for (Edge edge : node->use_edges()) {
1315 BasicBlock* use_block = GetBlockForUse(edge); 1408 BasicBlock* use_block = GetBlockForUse(edge);
1316 block = block == NULL ? use_block : use_block == NULL 1409 block = block == NULL ? use_block : use_block == NULL
1317 ? block 1410 ? block
1318 : BasicBlock::GetCommonDominator( 1411 : BasicBlock::GetCommonDominator(
1319 block, use_block); 1412 block, use_block);
1320 } 1413 }
1321 return block; 1414 return block;
1322 } 1415 }
1323 1416
(...skipping 30 matching lines...) Expand all
1354 void ScheduleFloatingControl(BasicBlock* block, Node* node) { 1447 void ScheduleFloatingControl(BasicBlock* block, Node* node) {
1355 scheduler_->FuseFloatingControl(block, node); 1448 scheduler_->FuseFloatingControl(block, node);
1356 } 1449 }
1357 1450
1358 void ScheduleNode(BasicBlock* block, Node* node) { 1451 void ScheduleNode(BasicBlock* block, Node* node) {
1359 schedule_->PlanNode(block, node); 1452 schedule_->PlanNode(block, node);
1360 scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node); 1453 scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node);
1361 scheduler_->UpdatePlacement(node, Scheduler::kScheduled); 1454 scheduler_->UpdatePlacement(node, Scheduler::kScheduled);
1362 } 1455 }
1363 1456
1457 Node* CloneNode(Node* node) {
1458 int const input_count = node->InputCount();
1459 Node** const inputs = scheduler_->zone_->NewArray<Node*>(input_count);
1460 for (int index = 0; index < input_count; ++index) {
1461 Node* const input = node->InputAt(index);
1462 scheduler_->IncrementUnscheduledUseCount(input, index, node);
1463 inputs[index] = input;
1464 }
1465 Node* copy = scheduler_->graph_->NewNode(node->op(), input_count, inputs);
1466 scheduler_->node_data_.resize(copy->id() + 1,
1467 scheduler_->DefaultSchedulerData());
1468 scheduler_->node_data_[copy->id()] = scheduler_->node_data_[node->id()];
1469 return copy;
1470 }
1471
1364 Scheduler* scheduler_; 1472 Scheduler* scheduler_;
1365 Schedule* schedule_; 1473 Schedule* schedule_;
1474 BoolVector visited_;
1475 BasicBlockVector stack_;
1366 }; 1476 };
1367 1477
1368 1478
1369 void Scheduler::ScheduleLate() { 1479 void Scheduler::ScheduleLate() {
1370 Trace("--- SCHEDULE LATE ------------------------------------------\n"); 1480 Trace("--- SCHEDULE LATE ------------------------------------------\n");
1371 if (FLAG_trace_turbo_scheduler) { 1481 if (FLAG_trace_turbo_scheduler) {
1372 Trace("roots: "); 1482 Trace("roots: ");
1373 for (Node* node : schedule_root_nodes_) { 1483 for (Node* node : schedule_root_nodes_) {
1374 Trace("#%d:%s ", node->id(), node->op()->mnemonic()); 1484 Trace("#%d:%s ", node->id(), node->op()->mnemonic());
1375 } 1485 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1466 for (Node* const node : *nodes) { 1576 for (Node* const node : *nodes) {
1467 schedule_->SetBlockForNode(to, node); 1577 schedule_->SetBlockForNode(to, node);
1468 scheduled_nodes_[to->id().ToSize()].push_back(node); 1578 scheduled_nodes_[to->id().ToSize()].push_back(node);
1469 } 1579 }
1470 nodes->clear(); 1580 nodes->clear();
1471 } 1581 }
1472 1582
1473 } // namespace compiler 1583 } // namespace compiler
1474 } // namespace internal 1584 } // namespace internal
1475 } // namespace v8 1585 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/scheduler.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698