Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1397)

Side by Side Diff: src/hydrogen.cc

Issue 10520004: Transform HGlobalValueNumberer::AnalyzeBlock from recursive into an iteraive loop keeping the trave… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698