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 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= |
|
Jakob Kummerow
2012/06/04 16:33:58
nit: full stop at the end of the comment please.
| |
| 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 class GvnBasicBlockState: public ZoneObject { |
| 1830 HValueMap* map, | 1831 public: |
| 1831 HSideEffectMap* dominators) { | 1832 static GvnBasicBlockState* CreateEntry(Zone* zone, |
| 1832 TRACE_GVN_2("Analyzing block B%d%s\n", | 1833 HBasicBlock* entry_block, |
| 1833 block->block_id(), | 1834 HValueMap* entry_map) { |
| 1834 block->IsLoopHeader() ? " (loop header)" : ""); | 1835 return new(zone) |
| 1835 | 1836 GvnBasicBlockState(NULL, entry_block, entry_map, NULL, zone); |
| 1836 // If this is a loop header kill everything killed by the loop. | 1837 } |
| 1837 if (block->IsLoopHeader()) { | 1838 |
| 1838 map->Kill(loop_side_effects_[block->block_id()]); | 1839 HBasicBlock* block() { return block_; } |
| 1839 } | 1840 HValueMap* map() { return map_; } |
| 1840 | 1841 HSideEffectMap* dominators() { return &dominators_; } |
| 1841 // Go through all instructions of the current block. | 1842 |
| 1842 HInstruction* instr = block->first(); | 1843 GvnBasicBlockState* next_in_dominator_tree_traversal( |
| 1843 while (instr != NULL) { | 1844 Zone* zone, |
| 1844 HInstruction* next = instr->next(); | 1845 HBasicBlock** dominator) { |
| 1845 GVNFlagSet flags = instr->ChangesFlags(); | 1846 // This assignment needs to happen before calling next_dominated() because |
| 1846 if (!flags.IsEmpty()) { | 1847 // that call can reuse "this" if we are at the last dominated block. |
| 1847 // Clear all instructions in the map that are affected by side effects. | 1848 *dominator = block(); |
| 1848 // Store instruction as the dominating one for tracked side effects. | 1849 GvnBasicBlockState* result = next_dominated(zone); |
| 1849 map->Kill(flags); | 1850 if (result == NULL) { |
| 1850 dominators->Store(flags, instr); | 1851 GvnBasicBlockState* dominator_state = pop(); |
| 1851 TRACE_GVN_2("Instruction %d %s\n", instr->id(), | 1852 if (dominator_state != NULL) { |
| 1852 *GetGVNFlagsString(flags)); | 1853 // This branch is guaranteed not to return NULL because pop() never |
| 1853 } | 1854 // returns a state where "is_done() == true". |
| 1854 if (instr->CheckFlag(HValue::kUseGVN)) { | 1855 *dominator = dominator_state->block(); |
| 1855 ASSERT(!instr->HasObservableSideEffects()); | 1856 result = dominator_state->next_dominated(zone); |
| 1856 HValue* other = map->Lookup(instr); | |
| 1857 if (other != NULL) { | |
| 1858 ASSERT(instr->Equals(other) && other->Equals(instr)); | |
| 1859 TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", | |
| 1860 instr->id(), | |
| 1861 instr->Mnemonic(), | |
| 1862 other->id(), | |
| 1863 other->Mnemonic()); | |
| 1864 if (instr->HasSideEffects()) removed_side_effects_ = true; | |
| 1865 instr->DeleteAndReplaceWith(other); | |
| 1866 } else { | 1857 } else { |
| 1867 map->Add(instr); | 1858 *dominator = NULL; |
|
Jakob Kummerow
2012/06/04 16:33:58
IIUC, the value of *dominator doesn't matter when
| |
| 1868 } | 1859 result = NULL; |
|
Jakob Kummerow
2012/06/04 16:33:58
Unnecessary; result == NULL here anyway.
| |
| 1869 } | 1860 } |
| 1870 if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { | 1861 } |
| 1871 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | 1862 return result; |
| 1872 HValue* other = dominators->at(i); | 1863 } |
| 1873 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); | 1864 |
| 1874 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); | 1865 private: |
| 1875 if (instr->DependsOnFlags().Contains(depends_on_flag) && | 1866 void Initialize(HBasicBlock* block, |
| 1876 (other != NULL)) { | 1867 HValueMap* map, |
| 1877 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", | 1868 HSideEffectMap* dominators, |
| 1878 i, | 1869 bool copy_map, |
| 1870 Zone* zone) { | |
| 1871 block_ = block; | |
| 1872 map_ = copy_map ? map->Copy(zone) : map; | |
| 1873 dominated_index_ = -1; | |
| 1874 length_ = block->dominated_blocks()->length(); | |
| 1875 if (dominators != NULL) { | |
| 1876 dominators_ = *dominators; | |
| 1877 } | |
| 1878 } | |
| 1879 bool is_done() { return dominated_index_ >= length_; } | |
| 1880 | |
| 1881 GvnBasicBlockState(GvnBasicBlockState* previous, | |
| 1882 HBasicBlock* block, | |
| 1883 HValueMap* map, | |
| 1884 HSideEffectMap* dominators, | |
| 1885 Zone* zone) | |
| 1886 : previous_(previous), next_(NULL) { | |
| 1887 Initialize(block, map, dominators, true, zone); | |
| 1888 } | |
| 1889 | |
| 1890 GvnBasicBlockState* next_dominated(Zone* zone) { | |
| 1891 dominated_index_++; | |
| 1892 if (dominated_index_ == length_ - 1) { | |
| 1893 Initialize(block_->dominated_blocks()->at(dominated_index_), | |
| 1894 map(), | |
| 1895 dominators(), | |
| 1896 false, | |
| 1897 zone); | |
| 1898 return this; | |
| 1899 } else if (dominated_index_ < length_) { | |
| 1900 return push(zone, | |
| 1901 block_->dominated_blocks()->at(dominated_index_), | |
| 1902 dominators()); | |
| 1903 } else { | |
| 1904 return NULL; | |
| 1905 } | |
| 1906 } | |
| 1907 | |
| 1908 GvnBasicBlockState* push(Zone* zone, | |
| 1909 HBasicBlock* block, | |
| 1910 HSideEffectMap* dominators) { | |
| 1911 if (next_ == NULL) { | |
| 1912 next_ = | |
| 1913 new(zone) GvnBasicBlockState(this, block, map(), dominators, zone); | |
| 1914 } else { | |
| 1915 next_->Initialize(block, map(), dominators, true, zone); | |
| 1916 } | |
| 1917 return next_; | |
| 1918 } | |
| 1919 GvnBasicBlockState* pop() { | |
| 1920 GvnBasicBlockState* result = previous_; | |
| 1921 while (result != NULL && result->is_done()) { | |
| 1922 TRACE_GVN_2("Backtracking from block B%d to block b%d\n", | |
| 1923 block()->block_id(), | |
| 1924 previous_->block()->block_id()) | |
| 1925 result = result->previous_; | |
| 1926 } | |
| 1927 return result; | |
| 1928 } | |
| 1929 | |
| 1930 GvnBasicBlockState* previous_; | |
| 1931 GvnBasicBlockState* next_; | |
| 1932 HBasicBlock* block_; | |
| 1933 HValueMap* map_; | |
| 1934 HSideEffectMap dominators_; | |
| 1935 int dominated_index_; | |
| 1936 int length_; | |
| 1937 }; | |
| 1938 | |
| 1939 | |
| 1940 void HGlobalValueNumberer::AnalyzeGraph() { | |
| 1941 HBasicBlock* entry_block = graph_->entry_block(); | |
| 1942 HValueMap* entry_map = new(zone()) HValueMap(); | |
| 1943 GvnBasicBlockState* current = | |
| 1944 GvnBasicBlockState::CreateEntry(zone(), entry_block, entry_map); | |
| 1945 | |
| 1946 while (current != NULL) { | |
| 1947 HBasicBlock* block = current->block(); | |
| 1948 HValueMap* map = current->map(); | |
| 1949 HSideEffectMap* dominators = current->dominators(); | |
| 1950 | |
| 1951 TRACE_GVN_2("Analyzing block B%d%s\n", | |
| 1952 block->block_id(), | |
| 1953 block->IsLoopHeader() ? " (loop header)" : ""); | |
| 1954 | |
| 1955 // If this is a loop header kill everything killed by the loop. | |
| 1956 if (block->IsLoopHeader()) { | |
| 1957 map->Kill(loop_side_effects_[block->block_id()]); | |
| 1958 } | |
| 1959 | |
| 1960 // Go through all instructions of the current block. | |
| 1961 HInstruction* instr = block->first(); | |
| 1962 while (instr != NULL) { | |
| 1963 HInstruction* next = instr->next(); | |
| 1964 GVNFlagSet flags = instr->ChangesFlags(); | |
| 1965 if (!flags.IsEmpty()) { | |
| 1966 // Clear all instructions in the map that are affected by side effects. | |
| 1967 // Store instruction as the dominating one for tracked side effects. | |
| 1968 map->Kill(flags); | |
| 1969 dominators->Store(flags, instr); | |
| 1970 TRACE_GVN_2("Instruction %d %s\n", instr->id(), | |
| 1971 *GetGVNFlagsString(flags)); | |
| 1972 } | |
| 1973 if (instr->CheckFlag(HValue::kUseGVN)) { | |
| 1974 ASSERT(!instr->HasObservableSideEffects()); | |
| 1975 HValue* other = map->Lookup(instr); | |
| 1976 if (other != NULL) { | |
| 1977 ASSERT(instr->Equals(other) && other->Equals(instr)); | |
| 1978 TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", | |
| 1879 instr->id(), | 1979 instr->id(), |
| 1880 instr->Mnemonic(), | 1980 instr->Mnemonic(), |
| 1881 other->id(), | 1981 other->id(), |
| 1882 other->Mnemonic()); | 1982 other->Mnemonic()); |
| 1883 instr->SetSideEffectDominator(changes_flag, other); | 1983 if (instr->HasSideEffects()) removed_side_effects_ = true; |
| 1984 instr->DeleteAndReplaceWith(other); | |
| 1985 } else { | |
| 1986 map->Add(instr); | |
| 1884 } | 1987 } |
| 1885 } | 1988 } |
| 1886 } | 1989 if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { |
| 1887 instr = next; | 1990 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
| 1888 } | 1991 HValue* other = dominators->at(i); |
| 1889 | 1992 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
| 1890 // Recursively continue analysis for all immediately dominated blocks. | 1993 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); |
| 1891 int length = block->dominated_blocks()->length(); | 1994 if (instr->DependsOnFlags().Contains(depends_on_flag) && |
| 1892 for (int i = 0; i < length; ++i) { | 1995 (other != NULL)) { |
| 1893 HBasicBlock* dominated = block->dominated_blocks()->at(i); | 1996 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. | 1997 i, |
| 1895 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); | 1998 instr->id(), |
| 1896 HSideEffectMap successor_dominators(dominators); | 1999 instr->Mnemonic(), |
| 1897 | 2000 other->id(), |
| 1898 // Kill everything killed on any path between this block and the | 2001 other->Mnemonic()); |
| 1899 // dominated block. We don't have to traverse these paths if the | 2002 instr->SetSideEffectDominator(changes_flag, other); |
| 1900 // value map and the dominators list is already empty. If the range | 2003 } |
| 1901 // of block ids (block_id, dominated_id) is empty there are no such | 2004 } |
| 1902 // paths. | 2005 } |
| 1903 if ((!successor_map->IsEmpty() || !successor_dominators.IsEmpty()) && | 2006 instr = next; |
| 1904 block->block_id() + 1 < dominated->block_id()) { | 2007 } |
| 1905 visited_on_paths_.Clear(); | 2008 |
| 1906 GVNFlagSet side_effects_on_all_paths = | 2009 HBasicBlock *dominator_block; |
|
Jakob Kummerow
2012/06/04 16:33:58
nit: s/ */* /
| |
| 1907 CollectSideEffectsOnPathsToDominatedBlock(block, dominated); | 2010 GvnBasicBlockState* next = |
| 1908 successor_map->Kill(side_effects_on_all_paths); | 2011 current->next_in_dominator_tree_traversal(zone(), &dominator_block); |
| 1909 successor_dominators.Kill(side_effects_on_all_paths); | 2012 |
| 1910 } | 2013 if (next != NULL) { |
| 1911 AnalyzeBlock(dominated, successor_map, &successor_dominators); | 2014 HBasicBlock* dominated = next->block(); |
| 2015 // No need to copy the map for the last child in the dominator tree. | |
|
Jakob Kummerow
2012/06/04 16:33:58
I think this comment should go inside GvnBasicBloc
| |
| 2016 HValueMap* successor_map = next->map(); | |
| 2017 HSideEffectMap* successor_dominators = next->dominators(); | |
| 2018 | |
| 2019 // Kill everything killed on any path between this block and the | |
| 2020 // dominated block. We don't have to traverse these paths if the | |
| 2021 // value map and the dominators list is already empty. If the range | |
| 2022 // of block ids (block_id, dominated_id) is empty there are no such | |
| 2023 // paths. | |
| 2024 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) && | |
| 2025 dominator_block->block_id() + 1 < dominated->block_id()) { | |
| 2026 visited_on_paths_.Clear(); | |
| 2027 GVNFlagSet side_effects_on_all_paths = | |
| 2028 CollectSideEffectsOnPathsToDominatedBlock(dominator_block, dominated ); | |
|
Jakob Kummerow
2012/06/04 16:33:58
nit: long line
| |
| 2029 successor_map->Kill(side_effects_on_all_paths); | |
| 2030 successor_dominators->Kill(side_effects_on_all_paths); | |
| 2031 } | |
| 2032 } | |
| 2033 current = next; | |
| 1912 } | 2034 } |
| 1913 } | 2035 } |
| 1914 | 2036 |
| 1915 | 2037 |
| 1916 class HInferRepresentation BASE_EMBEDDED { | 2038 class HInferRepresentation BASE_EMBEDDED { |
| 1917 public: | 2039 public: |
| 1918 explicit HInferRepresentation(HGraph* graph) | 2040 explicit HInferRepresentation(HGraph* graph) |
| 1919 : graph_(graph), | 2041 : graph_(graph), |
| 1920 worklist_(8), | 2042 worklist_(8), |
| 1921 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } | 2043 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } |
| (...skipping 7043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8965 } | 9087 } |
| 8966 } | 9088 } |
| 8967 | 9089 |
| 8968 #ifdef DEBUG | 9090 #ifdef DEBUG |
| 8969 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9091 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 8970 if (allocator_ != NULL) allocator_->Verify(); | 9092 if (allocator_ != NULL) allocator_->Verify(); |
| 8971 #endif | 9093 #endif |
| 8972 } | 9094 } |
| 8973 | 9095 |
| 8974 } } // namespace v8::internal | 9096 } } // namespace v8::internal |
| OLD | NEW |