| 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 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 } | 1352 } |
| 1353 } | 1353 } |
| 1354 | 1354 |
| 1355 | 1355 |
| 1356 HSideEffectMap::HSideEffectMap() : count_(0) { | 1356 HSideEffectMap::HSideEffectMap() : count_(0) { |
| 1357 memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize); | 1357 memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize); |
| 1358 } | 1358 } |
| 1359 | 1359 |
| 1360 | 1360 |
| 1361 HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) { | 1361 HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) { |
| 1362 memcpy(data_, other->data_, kNumberOfTrackedSideEffects * kPointerSize); | 1362 *this = *other; // Calls operator=. |
| 1363 } | 1363 } |
| 1364 | 1364 |
| 1365 | 1365 |
| 1366 HSideEffectMap& HSideEffectMap::operator= (const HSideEffectMap& other) { |
| 1367 memcpy(data_, other.data_, kNumberOfTrackedSideEffects * kPointerSize); |
| 1368 return *this; |
| 1369 } |
| 1370 |
| 1366 void HSideEffectMap::Kill(GVNFlagSet flags) { | 1371 void HSideEffectMap::Kill(GVNFlagSet flags) { |
| 1367 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | 1372 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
| 1368 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); | 1373 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
| 1369 if (flags.Contains(changes_flag)) { | 1374 if (flags.Contains(changes_flag)) { |
| 1370 if (data_[i] != NULL) count_--; | 1375 if (data_[i] != NULL) count_--; |
| 1371 data_[i] = NULL; | 1376 data_[i] = NULL; |
| 1372 } | 1377 } |
| 1373 } | 1378 } |
| 1374 } | 1379 } |
| 1375 | 1380 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); | 1489 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); |
| 1485 } | 1490 } |
| 1486 | 1491 |
| 1487 // Returns true if values with side effects are removed. | 1492 // Returns true if values with side effects are removed. |
| 1488 bool Analyze(); | 1493 bool Analyze(); |
| 1489 | 1494 |
| 1490 private: | 1495 private: |
| 1491 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( | 1496 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( |
| 1492 HBasicBlock* dominator, | 1497 HBasicBlock* dominator, |
| 1493 HBasicBlock* dominated); | 1498 HBasicBlock* dominated); |
| 1494 void AnalyzeBlock(HBasicBlock* block, | 1499 void AnalyzeGraph(); |
| 1495 HValueMap* map, | |
| 1496 HSideEffectMap* dominators); | |
| 1497 void ComputeBlockSideEffects(); | 1500 void ComputeBlockSideEffects(); |
| 1498 void LoopInvariantCodeMotion(); | 1501 void LoopInvariantCodeMotion(); |
| 1499 void ProcessLoopBlock(HBasicBlock* block, | 1502 void ProcessLoopBlock(HBasicBlock* block, |
| 1500 HBasicBlock* before_loop, | 1503 HBasicBlock* before_loop, |
| 1501 GVNFlagSet loop_kills, | 1504 GVNFlagSet loop_kills, |
| 1502 GVNFlagSet* accumulated_first_time_depends, | 1505 GVNFlagSet* accumulated_first_time_depends, |
| 1503 GVNFlagSet* accumulated_first_time_changes); | 1506 GVNFlagSet* accumulated_first_time_changes); |
| 1504 bool AllowCodeMotion(); | 1507 bool AllowCodeMotion(); |
| 1505 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); | 1508 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); |
| 1506 | 1509 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1523 SparseSet visited_on_paths_; | 1526 SparseSet visited_on_paths_; |
| 1524 }; | 1527 }; |
| 1525 | 1528 |
| 1526 | 1529 |
| 1527 bool HGlobalValueNumberer::Analyze() { | 1530 bool HGlobalValueNumberer::Analyze() { |
| 1528 removed_side_effects_ = false; | 1531 removed_side_effects_ = false; |
| 1529 ComputeBlockSideEffects(); | 1532 ComputeBlockSideEffects(); |
| 1530 if (FLAG_loop_invariant_code_motion) { | 1533 if (FLAG_loop_invariant_code_motion) { |
| 1531 LoopInvariantCodeMotion(); | 1534 LoopInvariantCodeMotion(); |
| 1532 } | 1535 } |
| 1533 HValueMap* map = new(zone()) HValueMap(); | 1536 AnalyzeGraph(); |
| 1534 HSideEffectMap side_effect_dominators; | |
| 1535 AnalyzeBlock(graph_->entry_block(), map, &side_effect_dominators); | |
| 1536 return removed_side_effects_; | 1537 return removed_side_effects_; |
| 1537 } | 1538 } |
| 1538 | 1539 |
| 1539 | 1540 |
| 1540 void HGlobalValueNumberer::ComputeBlockSideEffects() { | 1541 void HGlobalValueNumberer::ComputeBlockSideEffects() { |
| 1541 // The Analyze phase of GVN can be called multiple times. Clear loop side | 1542 // The Analyze phase of GVN can be called multiple times. Clear loop side |
| 1542 // effects before computing them to erase the contents from previous Analyze | 1543 // effects before computing them to erase the contents from previous Analyze |
| 1543 // passes. | 1544 // passes. |
| 1544 for (int i = 0; i < loop_side_effects_.length(); ++i) { | 1545 for (int i = 0; i < loop_side_effects_.length(); ++i) { |
| 1545 loop_side_effects_[i].RemoveAll(); | 1546 loop_side_effects_[i].RemoveAll(); |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1819 side_effects.Add(loop_side_effects_[block->block_id()]); | 1820 side_effects.Add(loop_side_effects_[block->block_id()]); |
| 1820 } | 1821 } |
| 1821 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock( | 1822 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock( |
| 1822 dominator, block)); | 1823 dominator, block)); |
| 1823 } | 1824 } |
| 1824 } | 1825 } |
| 1825 return side_effects; | 1826 return side_effects; |
| 1826 } | 1827 } |
| 1827 | 1828 |
| 1828 | 1829 |
| 1829 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, | 1830 // Each instance of this class is like a "stack frame" for the recursive |
| 1830 HValueMap* map, | 1831 // traversal of the dominator tree done during GVN (the stack is handled |
| 1831 HSideEffectMap* dominators) { | 1832 // as a double linked list). |
| 1832 TRACE_GVN_2("Analyzing block B%d%s\n", | 1833 // We reuse frames when possible so the list length is limited by the depth |
| 1833 block->block_id(), | 1834 // of the dominator tree but this forces us to initialize each frame calling |
| 1834 block->IsLoopHeader() ? " (loop header)" : ""); | 1835 // an explicit "Initialize" method instead of a using constructor. |
| 1835 | 1836 class GvnBasicBlockState: public ZoneObject { |
| 1836 // If this is a loop header kill everything killed by the loop. | 1837 public: |
| 1837 if (block->IsLoopHeader()) { | 1838 static GvnBasicBlockState* CreateEntry(Zone* zone, |
| 1838 map->Kill(loop_side_effects_[block->block_id()]); | 1839 HBasicBlock* entry_block, |
| 1839 } | 1840 HValueMap* entry_map) { |
| 1840 | 1841 return new(zone) |
| 1841 // Go through all instructions of the current block. | 1842 GvnBasicBlockState(NULL, entry_block, entry_map, NULL, zone); |
| 1842 HInstruction* instr = block->first(); | 1843 } |
| 1843 while (instr != NULL) { | 1844 |
| 1844 HInstruction* next = instr->next(); | 1845 HBasicBlock* block() { return block_; } |
| 1845 GVNFlagSet flags = instr->ChangesFlags(); | 1846 HValueMap* map() { return map_; } |
| 1846 if (!flags.IsEmpty()) { | 1847 HSideEffectMap* dominators() { return &dominators_; } |
| 1847 // Clear all instructions in the map that are affected by side effects. | 1848 |
| 1848 // Store instruction as the dominating one for tracked side effects. | 1849 GvnBasicBlockState* next_in_dominator_tree_traversal( |
| 1849 map->Kill(flags); | 1850 Zone* zone, |
| 1850 dominators->Store(flags, instr); | 1851 HBasicBlock** dominator) { |
| 1851 TRACE_GVN_2("Instruction %d %s\n", instr->id(), | 1852 // This assignment needs to happen before calling next_dominated() because |
| 1852 *GetGVNFlagsString(flags)); | 1853 // that call can reuse "this" if we are at the last dominated block. |
| 1853 } | 1854 *dominator = block(); |
| 1854 if (instr->CheckFlag(HValue::kUseGVN)) { | 1855 GvnBasicBlockState* result = next_dominated(zone); |
| 1855 ASSERT(!instr->HasObservableSideEffects()); | 1856 if (result == NULL) { |
| 1856 HValue* other = map->Lookup(instr); | 1857 GvnBasicBlockState* dominator_state = pop(); |
| 1857 if (other != NULL) { | 1858 if (dominator_state != NULL) { |
| 1858 ASSERT(instr->Equals(other) && other->Equals(instr)); | 1859 // This branch is guaranteed not to return NULL because pop() never |
| 1859 TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", | 1860 // returns a state where "is_done() == true". |
| 1860 instr->id(), | 1861 *dominator = dominator_state->block(); |
| 1861 instr->Mnemonic(), | 1862 result = dominator_state->next_dominated(zone); |
| 1862 other->id(), | |
| 1863 other->Mnemonic()); | |
| 1864 if (instr->HasSideEffects()) removed_side_effects_ = true; | |
| 1865 instr->DeleteAndReplaceWith(other); | |
| 1866 } else { | 1863 } else { |
| 1867 map->Add(instr); | 1864 // Unnecessary (we are returning NULL) but done for cleanness. |
| 1868 } | 1865 *dominator = NULL; |
| 1869 } | 1866 } |
| 1870 if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { | 1867 } |
| 1871 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | 1868 return result; |
| 1872 HValue* other = dominators->at(i); | 1869 } |
| 1873 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); | 1870 |
| 1874 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); | 1871 private: |
| 1875 if (instr->DependsOnFlags().Contains(depends_on_flag) && | 1872 void Initialize(HBasicBlock* block, |
| 1876 (other != NULL)) { | 1873 HValueMap* map, |
| 1877 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", | 1874 HSideEffectMap* dominators, |
| 1878 i, | 1875 bool copy_map, |
| 1876 Zone* zone) { |
| 1877 block_ = block; |
| 1878 map_ = copy_map ? map->Copy(zone) : map; |
| 1879 dominated_index_ = -1; |
| 1880 length_ = block->dominated_blocks()->length(); |
| 1881 if (dominators != NULL) { |
| 1882 dominators_ = *dominators; |
| 1883 } |
| 1884 } |
| 1885 bool is_done() { return dominated_index_ >= length_; } |
| 1886 |
| 1887 GvnBasicBlockState(GvnBasicBlockState* previous, |
| 1888 HBasicBlock* block, |
| 1889 HValueMap* map, |
| 1890 HSideEffectMap* dominators, |
| 1891 Zone* zone) |
| 1892 : previous_(previous), next_(NULL) { |
| 1893 Initialize(block, map, dominators, true, zone); |
| 1894 } |
| 1895 |
| 1896 GvnBasicBlockState* next_dominated(Zone* zone) { |
| 1897 dominated_index_++; |
| 1898 if (dominated_index_ == length_ - 1) { |
| 1899 // No need to copy the map for the last child in the dominator tree. |
| 1900 Initialize(block_->dominated_blocks()->at(dominated_index_), |
| 1901 map(), |
| 1902 dominators(), |
| 1903 false, |
| 1904 zone); |
| 1905 return this; |
| 1906 } else if (dominated_index_ < length_) { |
| 1907 return push(zone, |
| 1908 block_->dominated_blocks()->at(dominated_index_), |
| 1909 dominators()); |
| 1910 } else { |
| 1911 return NULL; |
| 1912 } |
| 1913 } |
| 1914 |
| 1915 GvnBasicBlockState* push(Zone* zone, |
| 1916 HBasicBlock* block, |
| 1917 HSideEffectMap* dominators) { |
| 1918 if (next_ == NULL) { |
| 1919 next_ = |
| 1920 new(zone) GvnBasicBlockState(this, block, map(), dominators, zone); |
| 1921 } else { |
| 1922 next_->Initialize(block, map(), dominators, true, zone); |
| 1923 } |
| 1924 return next_; |
| 1925 } |
| 1926 GvnBasicBlockState* pop() { |
| 1927 GvnBasicBlockState* result = previous_; |
| 1928 while (result != NULL && result->is_done()) { |
| 1929 TRACE_GVN_2("Backtracking from block B%d to block b%d\n", |
| 1930 block()->block_id(), |
| 1931 previous_->block()->block_id()) |
| 1932 result = result->previous_; |
| 1933 } |
| 1934 return result; |
| 1935 } |
| 1936 |
| 1937 GvnBasicBlockState* previous_; |
| 1938 GvnBasicBlockState* next_; |
| 1939 HBasicBlock* block_; |
| 1940 HValueMap* map_; |
| 1941 HSideEffectMap dominators_; |
| 1942 int dominated_index_; |
| 1943 int length_; |
| 1944 }; |
| 1945 |
| 1946 // This is a recursive traversal of the dominator tree but it has been turned |
| 1947 // into a loop to avoid stack overflows. |
| 1948 // The logical "stack frames" of the recursion are kept in a list of |
| 1949 // GvnBasicBlockState instances. |
| 1950 void HGlobalValueNumberer::AnalyzeGraph() { |
| 1951 HBasicBlock* entry_block = graph_->entry_block(); |
| 1952 HValueMap* entry_map = new(zone()) HValueMap(); |
| 1953 GvnBasicBlockState* current = |
| 1954 GvnBasicBlockState::CreateEntry(zone(), entry_block, entry_map); |
| 1955 |
| 1956 while (current != NULL) { |
| 1957 HBasicBlock* block = current->block(); |
| 1958 HValueMap* map = current->map(); |
| 1959 HSideEffectMap* dominators = current->dominators(); |
| 1960 |
| 1961 TRACE_GVN_2("Analyzing block B%d%s\n", |
| 1962 block->block_id(), |
| 1963 block->IsLoopHeader() ? " (loop header)" : ""); |
| 1964 |
| 1965 // If this is a loop header kill everything killed by the loop. |
| 1966 if (block->IsLoopHeader()) { |
| 1967 map->Kill(loop_side_effects_[block->block_id()]); |
| 1968 } |
| 1969 |
| 1970 // Go through all instructions of the current block. |
| 1971 HInstruction* instr = block->first(); |
| 1972 while (instr != NULL) { |
| 1973 HInstruction* next = instr->next(); |
| 1974 GVNFlagSet flags = instr->ChangesFlags(); |
| 1975 if (!flags.IsEmpty()) { |
| 1976 // Clear all instructions in the map that are affected by side effects. |
| 1977 // Store instruction as the dominating one for tracked side effects. |
| 1978 map->Kill(flags); |
| 1979 dominators->Store(flags, instr); |
| 1980 TRACE_GVN_2("Instruction %d %s\n", instr->id(), |
| 1981 *GetGVNFlagsString(flags)); |
| 1982 } |
| 1983 if (instr->CheckFlag(HValue::kUseGVN)) { |
| 1984 ASSERT(!instr->HasObservableSideEffects()); |
| 1985 HValue* other = map->Lookup(instr); |
| 1986 if (other != NULL) { |
| 1987 ASSERT(instr->Equals(other) && other->Equals(instr)); |
| 1988 TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", |
| 1879 instr->id(), | 1989 instr->id(), |
| 1880 instr->Mnemonic(), | 1990 instr->Mnemonic(), |
| 1881 other->id(), | 1991 other->id(), |
| 1882 other->Mnemonic()); | 1992 other->Mnemonic()); |
| 1883 instr->SetSideEffectDominator(changes_flag, other); | 1993 if (instr->HasSideEffects()) removed_side_effects_ = true; |
| 1994 instr->DeleteAndReplaceWith(other); |
| 1995 } else { |
| 1996 map->Add(instr); |
| 1884 } | 1997 } |
| 1885 } | 1998 } |
| 1886 } | 1999 if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { |
| 1887 instr = next; | 2000 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
| 1888 } | 2001 HValue* other = dominators->at(i); |
| 1889 | 2002 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
| 1890 // Recursively continue analysis for all immediately dominated blocks. | 2003 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); |
| 1891 int length = block->dominated_blocks()->length(); | 2004 if (instr->DependsOnFlags().Contains(depends_on_flag) && |
| 1892 for (int i = 0; i < length; ++i) { | 2005 (other != NULL)) { |
| 1893 HBasicBlock* dominated = block->dominated_blocks()->at(i); | 2006 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", |
| 1894 // No need to copy the map for the last child in the dominator tree. | 2007 i, |
| 1895 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); | 2008 instr->id(), |
| 1896 HSideEffectMap successor_dominators(dominators); | 2009 instr->Mnemonic(), |
| 1897 | 2010 other->id(), |
| 1898 // Kill everything killed on any path between this block and the | 2011 other->Mnemonic()); |
| 1899 // dominated block. We don't have to traverse these paths if the | 2012 instr->SetSideEffectDominator(changes_flag, other); |
| 1900 // value map and the dominators list is already empty. If the range | 2013 } |
| 1901 // of block ids (block_id, dominated_id) is empty there are no such | 2014 } |
| 1902 // paths. | 2015 } |
| 1903 if ((!successor_map->IsEmpty() || !successor_dominators.IsEmpty()) && | 2016 instr = next; |
| 1904 block->block_id() + 1 < dominated->block_id()) { | 2017 } |
| 1905 visited_on_paths_.Clear(); | 2018 |
| 1906 GVNFlagSet side_effects_on_all_paths = | 2019 HBasicBlock* dominator_block; |
| 1907 CollectSideEffectsOnPathsToDominatedBlock(block, dominated); | 2020 GvnBasicBlockState* next = |
| 1908 successor_map->Kill(side_effects_on_all_paths); | 2021 current->next_in_dominator_tree_traversal(zone(), &dominator_block); |
| 1909 successor_dominators.Kill(side_effects_on_all_paths); | 2022 |
| 1910 } | 2023 if (next != NULL) { |
| 1911 AnalyzeBlock(dominated, successor_map, &successor_dominators); | 2024 HBasicBlock* dominated = next->block(); |
| 2025 HValueMap* successor_map = next->map(); |
| 2026 HSideEffectMap* successor_dominators = next->dominators(); |
| 2027 |
| 2028 // Kill everything killed on any path between this block and the |
| 2029 // dominated block. We don't have to traverse these paths if the |
| 2030 // value map and the dominators list is already empty. If the range |
| 2031 // of block ids (block_id, dominated_id) is empty there are no such |
| 2032 // paths. |
| 2033 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) && |
| 2034 dominator_block->block_id() + 1 < dominated->block_id()) { |
| 2035 visited_on_paths_.Clear(); |
| 2036 GVNFlagSet side_effects_on_all_paths = |
| 2037 CollectSideEffectsOnPathsToDominatedBlock(dominator_block, |
| 2038 dominated); |
| 2039 successor_map->Kill(side_effects_on_all_paths); |
| 2040 successor_dominators->Kill(side_effects_on_all_paths); |
| 2041 } |
| 2042 } |
| 2043 current = next; |
| 1912 } | 2044 } |
| 1913 } | 2045 } |
| 1914 | 2046 |
| 1915 | 2047 |
| 1916 class HInferRepresentation BASE_EMBEDDED { | 2048 class HInferRepresentation BASE_EMBEDDED { |
| 1917 public: | 2049 public: |
| 1918 explicit HInferRepresentation(HGraph* graph) | 2050 explicit HInferRepresentation(HGraph* graph) |
| 1919 : graph_(graph), | 2051 : graph_(graph), |
| 1920 worklist_(8), | 2052 worklist_(8), |
| 1921 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } | 2053 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } |
| (...skipping 6860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8782 } | 8914 } |
| 8783 } | 8915 } |
| 8784 | 8916 |
| 8785 #ifdef DEBUG | 8917 #ifdef DEBUG |
| 8786 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 8918 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 8787 if (allocator_ != NULL) allocator_->Verify(); | 8919 if (allocator_ != NULL) allocator_->Verify(); |
| 8788 #endif | 8920 #endif |
| 8789 } | 8921 } |
| 8790 | 8922 |
| 8791 } } // namespace v8::internal | 8923 } } // namespace v8::internal |
| OLD | NEW |