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

Side by Side Diff: src/hydrogen.cc

Issue 9141016: Improve GVN handling of ElementTransitions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 }; 1346 };
1347 1347
1348 1348
1349 class HGlobalValueNumberer BASE_EMBEDDED { 1349 class HGlobalValueNumberer BASE_EMBEDDED {
1350 public: 1350 public:
1351 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) 1351 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1352 : graph_(graph), 1352 : graph_(graph),
1353 info_(info), 1353 info_(info),
1354 removed_side_effects_(false), 1354 removed_side_effects_(false),
1355 block_side_effects_(graph->blocks()->length()), 1355 block_side_effects_(graph->blocks()->length()),
1356 block_depends_on_(graph->blocks()->length()),
1356 loop_side_effects_(graph->blocks()->length()), 1357 loop_side_effects_(graph->blocks()->length()),
1357 visited_on_paths_(graph->zone(), graph->blocks()->length()) { 1358 visited_on_paths_(graph->zone(), graph->blocks()->length()) {
1358 ASSERT(info->isolate()->heap()->allow_allocation(false)); 1359 ASSERT(info->isolate()->heap()->allow_allocation(false));
1359 block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length()); 1360 block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
1361 block_depends_on_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
1360 loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length()); 1362 loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
1361 } 1363 }
1362 ~HGlobalValueNumberer() { 1364 ~HGlobalValueNumberer() {
1363 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); 1365 ASSERT(!info_->isolate()->heap()->allow_allocation(true));
1364 } 1366 }
1365 1367
1366 // Returns true if values with side effects are removed. 1368 // Returns true if values with side effects are removed.
1367 bool Analyze(); 1369 bool Analyze();
1368 1370
1369 private: 1371 private:
1370 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( 1372 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
1371 HBasicBlock* dominator, 1373 HBasicBlock* dominator,
1372 HBasicBlock* dominated); 1374 HBasicBlock* dominated);
1373 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1375 void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1374 void ComputeBlockSideEffects(); 1376 void ComputeBlockSideEffects();
1375 void LoopInvariantCodeMotion(); 1377 void LoopInvariantCodeMotion();
1376 void ProcessLoopBlock(HBasicBlock* block, 1378 void ProcessLoopBlock(HBasicBlock* block,
1377 HBasicBlock* before_loop, 1379 HBasicBlock* before_loop,
1378 GVNFlagSet loop_kills); 1380 GVNFlagSet loop_kills,
1381 GVNFlagSet conservative_first_time_depends,
1382 GVNFlagSet* accumulated_first_time_depends);
1379 bool AllowCodeMotion(); 1383 bool AllowCodeMotion();
1380 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1384 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1381 1385
1382 HGraph* graph() { return graph_; } 1386 HGraph* graph() { return graph_; }
1383 CompilationInfo* info() { return info_; } 1387 CompilationInfo* info() { return info_; }
1384 Zone* zone() { return graph_->zone(); } 1388 Zone* zone() { return graph_->zone(); }
1385 1389
1386 HGraph* graph_; 1390 HGraph* graph_;
1387 CompilationInfo* info_; 1391 CompilationInfo* info_;
1388 bool removed_side_effects_; 1392 bool removed_side_effects_;
1389 1393
1390 // A map of block IDs to their side effects. 1394 // A map of block IDs to their side effects.
1391 ZoneList<GVNFlagSet> block_side_effects_; 1395 ZoneList<GVNFlagSet> block_side_effects_;
1396 ZoneList<GVNFlagSet> block_depends_on_;
1392 1397
1393 // A map of loop header block IDs to their loop's side effects. 1398 // A map of loop header block IDs to their loop's side effects.
1394 ZoneList<GVNFlagSet> loop_side_effects_; 1399 ZoneList<GVNFlagSet> loop_side_effects_;
1395 1400
1396 // Used when collecting side effects on paths from dominator to 1401 // Used when collecting side effects on paths from dominator to
1397 // dominated. 1402 // dominated.
1398 SparseSet visited_on_paths_; 1403 SparseSet visited_on_paths_;
1399 }; 1404 };
1400 1405
1401 1406
1402 bool HGlobalValueNumberer::Analyze() { 1407 bool HGlobalValueNumberer::Analyze() {
1408 removed_side_effects_ = false;
1403 ComputeBlockSideEffects(); 1409 ComputeBlockSideEffects();
1404 if (FLAG_loop_invariant_code_motion) { 1410 if (FLAG_loop_invariant_code_motion) {
1405 LoopInvariantCodeMotion(); 1411 LoopInvariantCodeMotion();
1406 } 1412 }
1407 HValueMap* map = new(zone()) HValueMap(); 1413 HValueMap* map = new(zone()) HValueMap();
1408 AnalyzeBlock(graph_->entry_block(), map); 1414 AnalyzeBlock(graph_->entry_block(), map);
1409 return removed_side_effects_; 1415 return removed_side_effects_;
1410 } 1416 }
1411 1417
1412 1418
1413 void HGlobalValueNumberer::ComputeBlockSideEffects() { 1419 void HGlobalValueNumberer::ComputeBlockSideEffects() {
1420 for (int i = 0; i < loop_side_effects_.length(); ++i) {
1421 loop_side_effects_[i].RemoveAll();
1422 }
1414 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1423 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1415 // Compute side effects for the block. 1424 // Compute side effects for the block.
1416 HBasicBlock* block = graph_->blocks()->at(i); 1425 HBasicBlock* block = graph_->blocks()->at(i);
1417 HInstruction* instr = block->first(); 1426 HInstruction* instr = block->first();
1418 int id = block->block_id(); 1427 int id = block->block_id();
1419 GVNFlagSet side_effects; 1428 GVNFlagSet side_effects;
1429 GVNFlagSet depends;
1420 while (instr != NULL) { 1430 while (instr != NULL) {
1421 side_effects.Add(instr->ChangesFlags()); 1431 side_effects.Add(instr->ChangesFlags());
1432 depends.Add(instr->DependsOnFlags());
1422 instr = instr->next(); 1433 instr = instr->next();
1423 } 1434 }
1424 block_side_effects_[id].Add(side_effects); 1435 block_side_effects_[id].Add(side_effects);
1436 block_depends_on_[id].Add(depends);
1425 1437
1426 // Loop headers are part of their loop. 1438 // Loop headers are part of their loop.
1427 if (block->IsLoopHeader()) { 1439 if (block->IsLoopHeader()) {
1428 loop_side_effects_[id].Add(side_effects); 1440 loop_side_effects_[id].Add(side_effects);
1429 } 1441 }
1430 1442
1431 // Propagate loop side effects upwards. 1443 // Propagate loop side effects upwards.
1432 if (block->HasParentLoopHeader()) { 1444 if (block->HasParentLoopHeader()) {
1433 int header_id = block->parent_loop_header()->block_id(); 1445 int header_id = block->parent_loop_header()->block_id();
1434 loop_side_effects_[header_id].Add(block->IsLoopHeader() 1446 loop_side_effects_[header_id].Add(block->IsLoopHeader()
1435 ? loop_side_effects_[id] 1447 ? loop_side_effects_[id]
1436 : side_effects); 1448 : side_effects);
1437 } 1449 }
1438 } 1450 }
1439 } 1451 }
1440 1452
1441 1453
1442 void HGlobalValueNumberer::LoopInvariantCodeMotion() { 1454 void HGlobalValueNumberer::LoopInvariantCodeMotion() {
1443 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1455 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1444 HBasicBlock* block = graph_->blocks()->at(i); 1456 HBasicBlock* block = graph_->blocks()->at(i);
1445 if (block->IsLoopHeader()) { 1457 if (block->IsLoopHeader()) {
1446 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; 1458 GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
1447 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", 1459 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
1448 block->block_id(), 1460 block->block_id(),
1449 side_effects.ToIntegral()); 1461 side_effects.ToIntegral());
1450 1462
1463 GVNFlagSet accumulated_first_time_depends;
1451 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); 1464 HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1465 int outstanding_sucsessors = 0;
1452 for (int j = block->block_id(); j <= last->block_id(); ++j) { 1466 for (int j = block->block_id(); j <= last->block_id(); ++j) {
1453 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects); 1467 GVNFlagSet conservative_first_time_depends =
1468 accumulated_first_time_depends;
1469 HBasicBlock* analyze_block = graph_->blocks()->at(j);
1470 if (analyze_block != block) {
1471 outstanding_sucsessors -= analyze_block->predecessors()->length();
1472 }
1473 if (outstanding_sucsessors != 0) {
1474 // If more successors than predecessors have been seen in the loop up
1475 // to now, it's not possible to guarantee that the current block
1476 // dominates all of the blocks with higher IDs. In this case, assume
1477 // conservatively that those paths through loop that don't go through
1478 // the current block contain all of the loop's dependencies.
fschneider 2012/02/01 10:54:14 I don't think this works in general: e.g. in a sim
danno 2012/02/01 16:53:15 Done.
1479 conservative_first_time_depends.Add(
1480 block_depends_on_[analyze_block->block_id()]);
1481 }
1482 ProcessLoopBlock(analyze_block, block, side_effects,
1483 conservative_first_time_depends,
1484 &accumulated_first_time_depends);
1485 outstanding_sucsessors += analyze_block->end()->SuccessorCount();
1454 } 1486 }
1455 } 1487 }
1456 } 1488 }
1457 } 1489 }
1458 1490
1459 1491
1460 void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block, 1492 void HGlobalValueNumberer::ProcessLoopBlock(
1461 HBasicBlock* loop_header, 1493 HBasicBlock* block,
1462 GVNFlagSet loop_kills) { 1494 HBasicBlock* loop_header,
1495 GVNFlagSet loop_kills,
1496 GVNFlagSet conservative_first_time_depends,
1497 GVNFlagSet* accumulated_first_time_depends) {
1463 HBasicBlock* pre_header = loop_header->predecessors()->at(0); 1498 HBasicBlock* pre_header = loop_header->predecessors()->at(0);
1464 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); 1499 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
1465 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", 1500 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
1466 block->block_id(), 1501 block->block_id(),
1467 depends_flags.ToIntegral()); 1502 depends_flags.ToIntegral());
1468 HInstruction* instr = block->first(); 1503 HInstruction* instr = block->first();
1469 while (instr != NULL) { 1504 while (instr != NULL) {
1470 HInstruction* next = instr->next(); 1505 HInstruction* next = instr->next();
1471 if (instr->CheckFlag(HValue::kUseGVN) && 1506 bool hoisted = false;
1472 !instr->gvn_flags().ContainsAnyOf(depends_flags)) { 1507 if (instr->CheckFlag(HValue::kUseGVN)) {
1473 TraceGVN("Checking instruction %d (%s)\n", 1508 TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, "
1509 "conservative depends 0x%X, loop kills 0x%X\n",
1474 instr->id(), 1510 instr->id(),
1475 instr->Mnemonic()); 1511 instr->Mnemonic(),
1476 bool inputs_loop_invariant = true; 1512 instr->gvn_flags().ToIntegral(),
1477 for (int i = 0; i < instr->OperandCount(); ++i) { 1513 (conservative_first_time_depends).ToIntegral(),
1478 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 1514 depends_flags.ToIntegral());
1479 inputs_loop_invariant = false; 1515 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
1516 if (!can_hoist &&
1517 !instr->HasObservableSideEffects() &&
1518 instr->HasOneTimeSideEffects()) {
1519 // It's only possible to hoist one time side effects if there are no
1520 // dependencies on their changes from the loop header to the current
1521 // instruction.
1522 GVNFlagSet converted_changes =
1523 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags());
1524 TraceGVN("Checking dependencies on one-time instruction %d (%s) "
1525 "converted changes 0x%X, conservative depends 0x%X\n",
1526 instr->id(),
1527 instr->Mnemonic(),
1528 converted_changes.ToIntegral(),
1529 (conservative_first_time_depends).ToIntegral());
1530 can_hoist =
1531 !conservative_first_time_depends.ContainsAnyOf(converted_changes);
1532 }
1533
1534 if (can_hoist) {
1535 bool inputs_loop_invariant = true;
1536 for (int i = 0; i < instr->OperandCount(); ++i) {
1537 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
1538 inputs_loop_invariant = false;
1539 }
1540 }
1541
1542 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
1543 TraceGVN("Found loop invariant instruction %d\n", instr->id());
1544 // Move the instruction out of the loop.
1545 instr->Unlink();
1546 instr->InsertBefore(pre_header->end());
1547 if (instr->HasSideEffects()) removed_side_effects_ = true;
1548 hoisted = true;
1480 } 1549 }
1481 } 1550 }
1482 1551 }
1483 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { 1552 if (!hoisted) {
1484 TraceGVN("Found loop invariant instruction %d\n", instr->id()); 1553 // Hoisting an instruction to the preheader causes its DependsOn flags to
1485 // Move the instruction out of the loop. 1554 // not prevent hosting OneTimeSideEffecct instructions.
1486 instr->Unlink(); 1555 accumulated_first_time_depends->Add(instr->DependsOnFlags());
1487 instr->InsertBefore(pre_header->end());
1488 }
1489 } 1556 }
1490 instr = next; 1557 instr = next;
1491 } 1558 }
1492 } 1559 }
1493 1560
1494 1561
1495 bool HGlobalValueNumberer::AllowCodeMotion() { 1562 bool HGlobalValueNumberer::AllowCodeMotion() {
1496 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; 1563 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1497 } 1564 }
1498 1565
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1540 while (instr != NULL) { 1607 while (instr != NULL) {
1541 HInstruction* next = instr->next(); 1608 HInstruction* next = instr->next();
1542 GVNFlagSet flags = instr->ChangesFlags(); 1609 GVNFlagSet flags = instr->ChangesFlags();
1543 if (!flags.IsEmpty()) { 1610 if (!flags.IsEmpty()) {
1544 // Clear all instructions in the map that are affected by side effects. 1611 // Clear all instructions in the map that are affected by side effects.
1545 map->Kill(flags); 1612 map->Kill(flags);
1546 TraceGVN("Instruction %d kills\n", instr->id()); 1613 TraceGVN("Instruction %d kills\n", instr->id());
1547 } 1614 }
1548 if (instr->CheckFlag(HValue::kUseGVN)) { 1615 if (instr->CheckFlag(HValue::kUseGVN)) {
1549 ASSERT(!instr->HasObservableSideEffects()); 1616 ASSERT(!instr->HasObservableSideEffects());
1617 ASSERT(!instr->HasSideEffects() || instr->HasOneTimeSideEffects());
1550 HValue* other = map->Lookup(instr); 1618 HValue* other = map->Lookup(instr);
1551 if (other != NULL) { 1619 if (other != NULL) {
1552 ASSERT(instr->Equals(other) && other->Equals(instr)); 1620 ASSERT(instr->Equals(other) && other->Equals(instr));
1553 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", 1621 TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
1554 instr->id(), 1622 instr->id(),
1555 instr->Mnemonic(), 1623 instr->Mnemonic(),
1556 other->id(), 1624 other->id(),
1557 other->Mnemonic()); 1625 other->Mnemonic());
1558 if (instr->HasSideEffects()) removed_side_effects_ = true; 1626 if (instr->HasSideEffects()) removed_side_effects_ = true;
1559 instr->DeleteAndReplaceWith(other); 1627 instr->DeleteAndReplaceWith(other);
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after
2387 2455
2388 // Perform common subexpression elimination and loop-invariant code motion. 2456 // Perform common subexpression elimination and loop-invariant code motion.
2389 if (FLAG_use_gvn) { 2457 if (FLAG_use_gvn) {
2390 HPhase phase("Global value numbering", graph()); 2458 HPhase phase("Global value numbering", graph());
2391 HGlobalValueNumberer gvn(graph(), info()); 2459 HGlobalValueNumberer gvn(graph(), info());
2392 bool removed_side_effects = gvn.Analyze(); 2460 bool removed_side_effects = gvn.Analyze();
2393 // Trigger a second analysis pass to further eliminate duplicate values that 2461 // Trigger a second analysis pass to further eliminate duplicate values that
2394 // could only be discovered by removing side-effect-generating instructions 2462 // could only be discovered by removing side-effect-generating instructions
2395 // during the first pass. 2463 // during the first pass.
2396 if (FLAG_smi_only_arrays && removed_side_effects) { 2464 if (FLAG_smi_only_arrays && removed_side_effects) {
2397 gvn.Analyze(); 2465 removed_side_effects = gvn.Analyze();
2466 ASSERT(!removed_side_effects);
2398 } 2467 }
2399 } 2468 }
2400 2469
2401 if (FLAG_use_range) { 2470 if (FLAG_use_range) {
2402 HRangeAnalysis rangeAnalysis(graph()); 2471 HRangeAnalysis rangeAnalysis(graph());
2403 rangeAnalysis.Analyze(); 2472 rangeAnalysis.Analyze();
2404 } 2473 }
2405 graph()->ComputeMinusZeroChecks(); 2474 graph()->ComputeMinusZeroChecks();
2406 2475
2407 // Eliminate redundant stack checks on backwards branches. 2476 // Eliminate redundant stack checks on backwards branches.
(...skipping 5047 matching lines...) Expand 10 before | Expand all | Expand 10 after
7455 } 7524 }
7456 } 7525 }
7457 7526
7458 #ifdef DEBUG 7527 #ifdef DEBUG
7459 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7528 if (graph_ != NULL) graph_->Verify(false); // No full verify.
7460 if (allocator_ != NULL) allocator_->Verify(); 7529 if (allocator_ != NULL) allocator_->Verify();
7461 #endif 7530 #endif
7462 } 7531 }
7463 7532
7464 } } // namespace v8::internal 7533 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/hydrogen-instructions.h » ('j') | test/mjsunit/elements-transition-hoisting.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698