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 |