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

Side by Side Diff: src/hydrogen.cc

Issue 10572033: Merged r11712 into 3.10 branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/3.10
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') | src/version.cc » ('j') | 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=.
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 // 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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/version.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698