Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1314 ASSERT(new_element_pos != kNil); | 1314 ASSERT(new_element_pos != kNil); |
| 1315 free_list_head_ = lists_[free_list_head_].next; | 1315 free_list_head_ = lists_[free_list_head_].next; |
| 1316 lists_[new_element_pos].value = value; | 1316 lists_[new_element_pos].value = value; |
| 1317 lists_[new_element_pos].next = array_[pos].next; | 1317 lists_[new_element_pos].next = array_[pos].next; |
| 1318 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); | 1318 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); |
| 1319 array_[pos].next = new_element_pos; | 1319 array_[pos].next = new_element_pos; |
| 1320 } | 1320 } |
| 1321 } | 1321 } |
| 1322 | 1322 |
| 1323 | 1323 |
| 1324 HSideEffectMap::HSideEffectMap() : count_(0) { | |
| 1325 memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize); | |
| 1326 } | |
| 1327 | |
| 1328 | |
| 1329 HSideEffectMap::HSideEffectMap(HSideEffectMap& other) : count_(other.count_) { | |
| 1330 memcpy(data_, other.data_, kNumberOfTrackedSideEffects * kPointerSize); | |
| 1331 } | |
| 1332 | |
| 1333 | |
| 1334 void HSideEffectMap::Kill(GVNFlagSet flags) { | |
| 1335 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | |
| 1336 GVNFlag changes_flag = static_cast<GVNFlag>(i * 2); | |
| 1337 if (flags.Contains(changes_flag)) { | |
| 1338 if (data_[i] != NULL) count_--; | |
| 1339 data_[i] = NULL; | |
| 1340 } | |
| 1341 } | |
| 1342 } | |
| 1343 | |
| 1344 | |
| 1345 void HSideEffectMap::Store(GVNFlagSet flags, HInstruction* instr) { | |
| 1346 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | |
| 1347 GVNFlag changes_flag = static_cast<GVNFlag>(i * 2); | |
| 1348 if (flags.Contains(changes_flag)) { | |
| 1349 if (data_[i] == NULL) count_++; | |
| 1350 data_[i] = instr; | |
| 1351 } | |
| 1352 } | |
| 1353 } | |
| 1354 | |
| 1355 | |
| 1324 class HStackCheckEliminator BASE_EMBEDDED { | 1356 class HStackCheckEliminator BASE_EMBEDDED { |
| 1325 public: | 1357 public: |
| 1326 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } | 1358 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } |
| 1327 | 1359 |
| 1328 void Process(); | 1360 void Process(); |
| 1329 | 1361 |
| 1330 private: | 1362 private: |
| 1331 HGraph* graph_; | 1363 HGraph* graph_; |
| 1332 }; | 1364 }; |
| 1333 | 1365 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1420 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); | 1452 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); |
| 1421 } | 1453 } |
| 1422 | 1454 |
| 1423 // Returns true if values with side effects are removed. | 1455 // Returns true if values with side effects are removed. |
| 1424 bool Analyze(); | 1456 bool Analyze(); |
| 1425 | 1457 |
| 1426 private: | 1458 private: |
| 1427 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( | 1459 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( |
| 1428 HBasicBlock* dominator, | 1460 HBasicBlock* dominator, |
| 1429 HBasicBlock* dominated); | 1461 HBasicBlock* dominated); |
| 1430 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); | 1462 void AnalyzeBlock(HBasicBlock* block, |
| 1463 HValueMap* map, | |
| 1464 HSideEffectMap& dominators); | |
| 1431 void ComputeBlockSideEffects(); | 1465 void ComputeBlockSideEffects(); |
| 1432 void LoopInvariantCodeMotion(); | 1466 void LoopInvariantCodeMotion(); |
| 1433 void ProcessLoopBlock(HBasicBlock* block, | 1467 void ProcessLoopBlock(HBasicBlock* block, |
| 1434 HBasicBlock* before_loop, | 1468 HBasicBlock* before_loop, |
| 1435 GVNFlagSet loop_kills, | 1469 GVNFlagSet loop_kills, |
| 1436 GVNFlagSet* accumulated_first_time_depends, | 1470 GVNFlagSet* accumulated_first_time_depends, |
| 1437 GVNFlagSet* accumulated_first_time_changes); | 1471 GVNFlagSet* accumulated_first_time_changes); |
| 1438 bool AllowCodeMotion(); | 1472 bool AllowCodeMotion(); |
| 1439 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); | 1473 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); |
| 1440 | 1474 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1458 }; | 1492 }; |
| 1459 | 1493 |
| 1460 | 1494 |
| 1461 bool HGlobalValueNumberer::Analyze() { | 1495 bool HGlobalValueNumberer::Analyze() { |
| 1462 removed_side_effects_ = false; | 1496 removed_side_effects_ = false; |
| 1463 ComputeBlockSideEffects(); | 1497 ComputeBlockSideEffects(); |
| 1464 if (FLAG_loop_invariant_code_motion) { | 1498 if (FLAG_loop_invariant_code_motion) { |
| 1465 LoopInvariantCodeMotion(); | 1499 LoopInvariantCodeMotion(); |
| 1466 } | 1500 } |
| 1467 HValueMap* map = new(zone()) HValueMap(); | 1501 HValueMap* map = new(zone()) HValueMap(); |
| 1468 AnalyzeBlock(graph_->entry_block(), map); | 1502 HSideEffectMap side_effect_dominators; |
| 1503 AnalyzeBlock(graph_->entry_block(), map, side_effect_dominators); | |
| 1469 return removed_side_effects_; | 1504 return removed_side_effects_; |
| 1470 } | 1505 } |
| 1471 | 1506 |
| 1472 | 1507 |
| 1473 void HGlobalValueNumberer::ComputeBlockSideEffects() { | 1508 void HGlobalValueNumberer::ComputeBlockSideEffects() { |
| 1474 // The Analyze phase of GVN can be called multiple times. Clear loop side | 1509 // The Analyze phase of GVN can be called multiple times. Clear loop side |
| 1475 // effects before computing them to erase the contents from previous Analyze | 1510 // effects before computing them to erase the contents from previous Analyze |
| 1476 // passes. | 1511 // passes. |
| 1477 for (int i = 0; i < loop_side_effects_.length(); ++i) { | 1512 for (int i = 0; i < loop_side_effects_.length(); ++i) { |
| 1478 loop_side_effects_[i].RemoveAll(); | 1513 loop_side_effects_[i].RemoveAll(); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1653 side_effects.Add(loop_side_effects_[block->block_id()]); | 1688 side_effects.Add(loop_side_effects_[block->block_id()]); |
| 1654 } | 1689 } |
| 1655 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock( | 1690 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock( |
| 1656 dominator, block)); | 1691 dominator, block)); |
| 1657 } | 1692 } |
| 1658 } | 1693 } |
| 1659 return side_effects; | 1694 return side_effects; |
| 1660 } | 1695 } |
| 1661 | 1696 |
| 1662 | 1697 |
| 1663 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { | 1698 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, |
| 1699 HValueMap* map, | |
| 1700 HSideEffectMap& dominators) { | |
|
Erik Corry
2012/04/10 12:06:52
This should be a pointer argument: http://google-s
Michael Starzinger
2012/04/11 09:53:08
Done.
| |
| 1664 TraceGVN("Analyzing block B%d%s\n", | 1701 TraceGVN("Analyzing block B%d%s\n", |
| 1665 block->block_id(), | 1702 block->block_id(), |
| 1666 block->IsLoopHeader() ? " (loop header)" : ""); | 1703 block->IsLoopHeader() ? " (loop header)" : ""); |
| 1667 | 1704 |
| 1668 // If this is a loop header kill everything killed by the loop. | 1705 // If this is a loop header kill everything killed by the loop. |
| 1669 if (block->IsLoopHeader()) { | 1706 if (block->IsLoopHeader()) { |
| 1670 map->Kill(loop_side_effects_[block->block_id()]); | 1707 map->Kill(loop_side_effects_[block->block_id()]); |
| 1671 } | 1708 } |
| 1672 | 1709 |
| 1673 // Go through all instructions of the current block. | 1710 // Go through all instructions of the current block. |
| 1674 HInstruction* instr = block->first(); | 1711 HInstruction* instr = block->first(); |
| 1675 while (instr != NULL) { | 1712 while (instr != NULL) { |
| 1676 HInstruction* next = instr->next(); | 1713 HInstruction* next = instr->next(); |
| 1677 GVNFlagSet flags = instr->ChangesFlags(); | 1714 GVNFlagSet flags = instr->ChangesFlags(); |
| 1678 if (!flags.IsEmpty()) { | 1715 if (!flags.IsEmpty()) { |
| 1679 // Clear all instructions in the map that are affected by side effects. | 1716 // Clear all instructions in the map that are affected by side effects. |
| 1717 // Store instruction as the dominating one for tracked side effects. | |
| 1680 map->Kill(flags); | 1718 map->Kill(flags); |
| 1719 dominators.Store(flags, instr); | |
| 1681 TraceGVN("Instruction %d kills\n", instr->id()); | 1720 TraceGVN("Instruction %d kills\n", instr->id()); |
| 1682 } | 1721 } |
| 1683 if (instr->CheckFlag(HValue::kUseGVN)) { | 1722 if (instr->CheckFlag(HValue::kUseGVN)) { |
| 1684 ASSERT(!instr->HasObservableSideEffects()); | 1723 ASSERT(!instr->HasObservableSideEffects()); |
| 1685 HValue* other = map->Lookup(instr); | 1724 HValue* other = map->Lookup(instr); |
| 1686 if (other != NULL) { | 1725 if (other != NULL) { |
| 1687 ASSERT(instr->Equals(other) && other->Equals(instr)); | 1726 ASSERT(instr->Equals(other) && other->Equals(instr)); |
| 1688 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", | 1727 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", |
| 1689 instr->id(), | 1728 instr->id(), |
| 1690 instr->Mnemonic(), | 1729 instr->Mnemonic(), |
| 1691 other->id(), | 1730 other->id(), |
| 1692 other->Mnemonic()); | 1731 other->Mnemonic()); |
| 1693 if (instr->HasSideEffects()) removed_side_effects_ = true; | 1732 if (instr->HasSideEffects()) removed_side_effects_ = true; |
| 1694 instr->DeleteAndReplaceWith(other); | 1733 instr->DeleteAndReplaceWith(other); |
| 1695 } else { | 1734 } else { |
| 1696 map->Add(instr); | 1735 map->Add(instr); |
| 1697 } | 1736 } |
| 1698 } | 1737 } |
| 1738 if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { | |
| 1739 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | |
| 1740 GVNFlag changes_flag = static_cast<GVNFlag>(i * 2); | |
| 1741 GVNFlag depends_on_flag = static_cast<GVNFlag>(i * 2 + 1); | |
|
Erik Corry
2012/04/10 12:06:52
This would be cleaner with a variable to hold domi
Michael Starzinger
2012/04/11 09:53:08
Done.
| |
| 1742 if (instr->DependsOnFlags().Contains(depends_on_flag) && | |
| 1743 (dominators[i] != NULL)) { | |
| 1744 TraceGVN("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", | |
| 1745 i, | |
| 1746 instr->id(), | |
| 1747 instr->Mnemonic(), | |
| 1748 dominators[i]->id(), | |
| 1749 dominators[i]->Mnemonic()); | |
| 1750 instr->SetSideEffectDominator(changes_flag, dominators[i]); | |
| 1751 } | |
| 1752 } | |
| 1753 } | |
| 1699 instr = next; | 1754 instr = next; |
| 1700 } | 1755 } |
| 1701 | 1756 |
| 1702 // Recursively continue analysis for all immediately dominated blocks. | 1757 // Recursively continue analysis for all immediately dominated blocks. |
| 1703 int length = block->dominated_blocks()->length(); | 1758 int length = block->dominated_blocks()->length(); |
| 1704 for (int i = 0; i < length; ++i) { | 1759 for (int i = 0; i < length; ++i) { |
| 1705 HBasicBlock* dominated = block->dominated_blocks()->at(i); | 1760 HBasicBlock* dominated = block->dominated_blocks()->at(i); |
| 1706 // No need to copy the map for the last child in the dominator tree. | 1761 // No need to copy the map for the last child in the dominator tree. |
| 1707 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); | 1762 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); |
| 1763 HSideEffectMap successor_dominators(dominators); | |
| 1708 | 1764 |
| 1709 // Kill everything killed on any path between this block and the | 1765 // Kill everything killed on any path between this block and the |
| 1710 // dominated block. | 1766 // dominated block. We don't have to traverse these paths if the |
| 1711 // We don't have to traverse these paths if the value map is | 1767 // value map and the dominators list is already empty. If the range |
| 1712 // already empty. | 1768 // of block ids (block_id, dominated_id) is empty there are no such |
| 1713 // If the range of block ids (block_id, dominated_id) is empty | 1769 // paths. |
| 1714 // there are no such paths. | 1770 if ((!successor_map->IsEmpty() || !successor_dominators.IsEmpty()) && |
| 1715 if (!successor_map->IsEmpty() && | |
| 1716 block->block_id() + 1 < dominated->block_id()) { | 1771 block->block_id() + 1 < dominated->block_id()) { |
| 1717 visited_on_paths_.Clear(); | 1772 visited_on_paths_.Clear(); |
| 1718 successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block, | 1773 GVNFlagSet side_effects_on_all_paths = |
| 1719 dominated)); | 1774 CollectSideEffectsOnPathsToDominatedBlock(block, dominated); |
| 1775 successor_map->Kill(side_effects_on_all_paths); | |
| 1776 successor_dominators.Kill(side_effects_on_all_paths); | |
| 1720 } | 1777 } |
| 1721 AnalyzeBlock(dominated, successor_map); | 1778 AnalyzeBlock(dominated, successor_map, successor_dominators); |
| 1722 } | 1779 } |
| 1723 } | 1780 } |
| 1724 | 1781 |
| 1725 | 1782 |
| 1726 class HInferRepresentation BASE_EMBEDDED { | 1783 class HInferRepresentation BASE_EMBEDDED { |
| 1727 public: | 1784 public: |
| 1728 explicit HInferRepresentation(HGraph* graph) | 1785 explicit HInferRepresentation(HGraph* graph) |
| 1729 : graph_(graph), | 1786 : graph_(graph), |
| 1730 worklist_(8), | 1787 worklist_(8), |
| 1731 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } | 1788 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } |
| (...skipping 6499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8231 } | 8288 } |
| 8232 } | 8289 } |
| 8233 | 8290 |
| 8234 #ifdef DEBUG | 8291 #ifdef DEBUG |
| 8235 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 8292 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 8236 if (allocator_ != NULL) allocator_->Verify(); | 8293 if (allocator_ != NULL) allocator_->Verify(); |
| 8237 #endif | 8294 #endif |
| 8238 } | 8295 } |
| 8239 | 8296 |
| 8240 } } // namespace v8::internal | 8297 } } // namespace v8::internal |
| OLD | NEW |