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 |