| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/precompiler.h" | 5 #include "vm/precompiler.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/branch_optimizer.h" | 9 #include "vm/branch_optimizer.h" |
| 10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
| (...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 optimizer.ApplyClassIds(); | 1774 optimizer.ApplyClassIds(); |
| 1775 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1775 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1776 } | 1776 } |
| 1777 | 1777 |
| 1778 // Propagate types for potentially newly added instructions by | 1778 // Propagate types for potentially newly added instructions by |
| 1779 // ApplyClassIds(). Must occur before canonicalization. | 1779 // ApplyClassIds(). Must occur before canonicalization. |
| 1780 FlowGraphTypePropagator::Propagate(flow_graph); | 1780 FlowGraphTypePropagator::Propagate(flow_graph); |
| 1781 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1781 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1782 | 1782 |
| 1783 // Do optimizations that depend on the propagated type information. | 1783 // Do optimizations that depend on the propagated type information. |
| 1784 if (optimizer.Canonicalize()) { | 1784 if (flow_graph->Canonicalize()) { |
| 1785 // Invoke Canonicalize twice in order to fully canonicalize patterns | 1785 // Invoke Canonicalize twice in order to fully canonicalize patterns |
| 1786 // like "if (a & const == 0) { }". | 1786 // like "if (a & const == 0) { }". |
| 1787 optimizer.Canonicalize(); | 1787 flow_graph->Canonicalize(); |
| 1788 } | 1788 } |
| 1789 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1789 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1790 | 1790 |
| 1791 { | 1791 { |
| 1792 #ifndef PRODUCT | 1792 #ifndef PRODUCT |
| 1793 TimelineDurationScope tds2(thread(), | 1793 TimelineDurationScope tds2(thread(), |
| 1794 compiler_timeline, | 1794 compiler_timeline, |
| 1795 "BranchSimplifier"); | 1795 "BranchSimplifier"); |
| 1796 #endif // !PRODUCT | 1796 #endif // !PRODUCT |
| 1797 BranchSimplifier::Simplify(flow_graph); | 1797 BranchSimplifier::Simplify(flow_graph); |
| 1798 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1798 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1799 | 1799 |
| 1800 IfConverter::Simplify(flow_graph); | 1800 IfConverter::Simplify(flow_graph); |
| 1801 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1801 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1802 } | 1802 } |
| 1803 | 1803 |
| 1804 if (FLAG_constant_propagation) { | 1804 if (FLAG_constant_propagation) { |
| 1805 #ifndef PRODUCT | 1805 #ifndef PRODUCT |
| 1806 TimelineDurationScope tds2(thread(), | 1806 TimelineDurationScope tds2(thread(), |
| 1807 compiler_timeline, | 1807 compiler_timeline, |
| 1808 "ConstantPropagation"); | 1808 "ConstantPropagation"); |
| 1809 #endif // !PRODUCT | 1809 #endif // !PRODUCT |
| 1810 ConstantPropagator::Optimize(flow_graph); | 1810 ConstantPropagator::Optimize(flow_graph); |
| 1811 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1811 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1812 // A canonicalization pass to remove e.g. smi checks on smi constants. | 1812 // A canonicalization pass to remove e.g. smi checks on smi constants. |
| 1813 optimizer.Canonicalize(); | 1813 flow_graph->Canonicalize(); |
| 1814 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1814 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1815 // Canonicalization introduced more opportunities for constant | 1815 // Canonicalization introduced more opportunities for constant |
| 1816 // propagation. | 1816 // propagation. |
| 1817 ConstantPropagator::Optimize(flow_graph); | 1817 ConstantPropagator::Optimize(flow_graph); |
| 1818 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1818 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1819 } | 1819 } |
| 1820 | 1820 |
| 1821 // Optimistically convert loop phis that have a single non-smi input | 1821 // Optimistically convert loop phis that have a single non-smi input |
| 1822 // coming from the loop pre-header into smi-phis. | 1822 // coming from the loop pre-header into smi-phis. |
| 1823 if (FLAG_loop_invariant_code_motion) { | 1823 if (FLAG_loop_invariant_code_motion) { |
| 1824 LICM licm(flow_graph); | 1824 LICM licm(flow_graph); |
| 1825 licm.OptimisticallySpecializeSmiPhis(); | 1825 licm.OptimisticallySpecializeSmiPhis(); |
| 1826 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1826 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1827 } | 1827 } |
| 1828 | 1828 |
| 1829 // Propagate types and eliminate even more type tests. | 1829 // Propagate types and eliminate even more type tests. |
| 1830 // Recompute types after constant propagation to infer more precise | 1830 // Recompute types after constant propagation to infer more precise |
| 1831 // types for uses that were previously reached by now eliminated phis. | 1831 // types for uses that were previously reached by now eliminated phis. |
| 1832 FlowGraphTypePropagator::Propagate(flow_graph); | 1832 FlowGraphTypePropagator::Propagate(flow_graph); |
| 1833 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1833 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1834 | 1834 |
| 1835 { | 1835 { |
| 1836 #ifndef PRODUCT | 1836 #ifndef PRODUCT |
| 1837 TimelineDurationScope tds2(thread(), | 1837 TimelineDurationScope tds2(thread(), |
| 1838 compiler_timeline, | 1838 compiler_timeline, |
| 1839 "SelectRepresentations"); | 1839 "SelectRepresentations"); |
| 1840 #endif // !PRODUCT | 1840 #endif // !PRODUCT |
| 1841 // Where beneficial convert Smi operations into Int32 operations. | 1841 // Where beneficial convert Smi operations into Int32 operations. |
| 1842 // Only meanigful for 32bit platforms right now. | 1842 // Only meanigful for 32bit platforms right now. |
| 1843 optimizer.WidenSmiToInt32(); | 1843 flow_graph->WidenSmiToInt32(); |
| 1844 | 1844 |
| 1845 // Unbox doubles. Performed after constant propagation to minimize | 1845 // Unbox doubles. Performed after constant propagation to minimize |
| 1846 // interference from phis merging double values and tagged | 1846 // interference from phis merging double values and tagged |
| 1847 // values coming from dead paths. | 1847 // values coming from dead paths. |
| 1848 optimizer.SelectRepresentations(); | 1848 flow_graph->SelectRepresentations(); |
| 1849 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1849 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1850 } | 1850 } |
| 1851 | 1851 |
| 1852 { | 1852 { |
| 1853 #ifndef PRODUCT | 1853 #ifndef PRODUCT |
| 1854 TimelineDurationScope tds2(thread(), | 1854 TimelineDurationScope tds2(thread(), |
| 1855 compiler_timeline, | 1855 compiler_timeline, |
| 1856 "CommonSubexpressionElinination"); | 1856 "CommonSubexpressionElinination"); |
| 1857 #endif // !PRODUCT | 1857 #endif // !PRODUCT |
| 1858 if (FLAG_common_subexpression_elimination || | 1858 if (FLAG_common_subexpression_elimination || |
| 1859 FLAG_loop_invariant_code_motion) { | 1859 FLAG_loop_invariant_code_motion) { |
| 1860 flow_graph->ComputeBlockEffects(); | 1860 flow_graph->ComputeBlockEffects(); |
| 1861 } | 1861 } |
| 1862 | 1862 |
| 1863 if (FLAG_common_subexpression_elimination) { | 1863 if (FLAG_common_subexpression_elimination) { |
| 1864 if (DominatorBasedCSE::Optimize(flow_graph)) { | 1864 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 1865 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1865 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1866 optimizer.Canonicalize(); | 1866 flow_graph->Canonicalize(); |
| 1867 // Do another round of CSE to take secondary effects into account: | 1867 // Do another round of CSE to take secondary effects into account: |
| 1868 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) | 1868 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) |
| 1869 // TODO(fschneider): Change to a one-pass optimization pass. | 1869 // TODO(fschneider): Change to a one-pass optimization pass. |
| 1870 if (DominatorBasedCSE::Optimize(flow_graph)) { | 1870 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 1871 optimizer.Canonicalize(); | 1871 flow_graph->Canonicalize(); |
| 1872 } | 1872 } |
| 1873 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1873 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1874 } | 1874 } |
| 1875 } | 1875 } |
| 1876 | 1876 |
| 1877 // Run loop-invariant code motion right after load elimination since | 1877 // Run loop-invariant code motion right after load elimination since |
| 1878 // it depends on the numbering of loads from the previous | 1878 // it depends on the numbering of loads from the previous |
| 1879 // load-elimination. | 1879 // load-elimination. |
| 1880 if (FLAG_loop_invariant_code_motion) { | 1880 if (FLAG_loop_invariant_code_motion) { |
| 1881 LICM licm(flow_graph); | 1881 LICM licm(flow_graph); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1943 compiler_timeline, | 1943 compiler_timeline, |
| 1944 "TryCatchAnalyzer::Optimize"); | 1944 "TryCatchAnalyzer::Optimize"); |
| 1945 #endif // !PRODUCT | 1945 #endif // !PRODUCT |
| 1946 // Optimize try-blocks. | 1946 // Optimize try-blocks. |
| 1947 TryCatchAnalyzer::Optimize(flow_graph); | 1947 TryCatchAnalyzer::Optimize(flow_graph); |
| 1948 } | 1948 } |
| 1949 | 1949 |
| 1950 // Detach environments from the instructions that can't deoptimize. | 1950 // Detach environments from the instructions that can't deoptimize. |
| 1951 // Do it before we attempt to perform allocation sinking to minimize | 1951 // Do it before we attempt to perform allocation sinking to minimize |
| 1952 // amount of materializations it has to perform. | 1952 // amount of materializations it has to perform. |
| 1953 optimizer.EliminateEnvironments(); | 1953 flow_graph->EliminateEnvironments(); |
| 1954 | 1954 |
| 1955 { | 1955 { |
| 1956 #ifndef PRODUCT | 1956 #ifndef PRODUCT |
| 1957 TimelineDurationScope tds2(thread(), | 1957 TimelineDurationScope tds2(thread(), |
| 1958 compiler_timeline, | 1958 compiler_timeline, |
| 1959 "EliminateDeadPhis"); | 1959 "EliminateDeadPhis"); |
| 1960 #endif // !PRODUCT | 1960 #endif // !PRODUCT |
| 1961 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 1961 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
| 1962 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1962 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1963 } | 1963 } |
| 1964 | 1964 |
| 1965 if (optimizer.Canonicalize()) { | 1965 if (flow_graph->Canonicalize()) { |
| 1966 optimizer.Canonicalize(); | 1966 flow_graph->Canonicalize(); |
| 1967 } | 1967 } |
| 1968 | 1968 |
| 1969 // Attempt to sink allocations of temporary non-escaping objects to | 1969 // Attempt to sink allocations of temporary non-escaping objects to |
| 1970 // the deoptimization path. | 1970 // the deoptimization path. |
| 1971 AllocationSinking* sinking = NULL; | 1971 AllocationSinking* sinking = NULL; |
| 1972 if (FLAG_allocation_sinking && | 1972 if (FLAG_allocation_sinking && |
| 1973 (flow_graph->graph_entry()->SuccessorCount() == 1)) { | 1973 (flow_graph->graph_entry()->SuccessorCount() == 1)) { |
| 1974 #ifndef PRODUCT | 1974 #ifndef PRODUCT |
| 1975 TimelineDurationScope tds2(thread(), | 1975 TimelineDurationScope tds2(thread(), |
| 1976 compiler_timeline, | 1976 compiler_timeline, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1989 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1989 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 1990 | 1990 |
| 1991 { | 1991 { |
| 1992 #ifndef PRODUCT | 1992 #ifndef PRODUCT |
| 1993 TimelineDurationScope tds2(thread(), | 1993 TimelineDurationScope tds2(thread(), |
| 1994 compiler_timeline, | 1994 compiler_timeline, |
| 1995 "SelectRepresentations"); | 1995 "SelectRepresentations"); |
| 1996 #endif // !PRODUCT | 1996 #endif // !PRODUCT |
| 1997 // Ensure that all phis inserted by optimization passes have | 1997 // Ensure that all phis inserted by optimization passes have |
| 1998 // consistent representations. | 1998 // consistent representations. |
| 1999 optimizer.SelectRepresentations(); | 1999 flow_graph->SelectRepresentations(); |
| 2000 } | 2000 } |
| 2001 | 2001 |
| 2002 if (optimizer.Canonicalize()) { | 2002 if (flow_graph->Canonicalize()) { |
| 2003 // To fully remove redundant boxing (e.g. BoxDouble used only in | 2003 // To fully remove redundant boxing (e.g. BoxDouble used only in |
| 2004 // environments and UnboxDouble instructions) instruction we | 2004 // environments and UnboxDouble instructions) instruction we |
| 2005 // first need to replace all their uses and then fold them away. | 2005 // first need to replace all their uses and then fold them away. |
| 2006 // For now we just repeat Canonicalize twice to do that. | 2006 // For now we just repeat Canonicalize twice to do that. |
| 2007 // TODO(vegorov): implement a separate representation folding pass. | 2007 // TODO(vegorov): implement a separate representation folding pass. |
| 2008 optimizer.Canonicalize(); | 2008 flow_graph->Canonicalize(); |
| 2009 } | 2009 } |
| 2010 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2010 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 2011 | 2011 |
| 2012 if (sinking != NULL) { | 2012 if (sinking != NULL) { |
| 2013 #ifndef PRODUCT | 2013 #ifndef PRODUCT |
| 2014 TimelineDurationScope tds2( | 2014 TimelineDurationScope tds2( |
| 2015 thread(), | 2015 thread(), |
| 2016 compiler_timeline, | 2016 compiler_timeline, |
| 2017 "AllocationSinking::DetachMaterializations"); | 2017 "AllocationSinking::DetachMaterializations"); |
| 2018 #endif // !PRODUCT | 2018 #endif // !PRODUCT |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2228 CompilationPipeline::New(thread->zone(), function); | 2228 CompilationPipeline::New(thread->zone(), function); |
| 2229 | 2229 |
| 2230 ASSERT(FLAG_precompilation); | 2230 ASSERT(FLAG_precompilation); |
| 2231 const bool optimized = function.IsOptimizable(); // False for natives. | 2231 const bool optimized = function.IsOptimizable(); // False for natives. |
| 2232 return PrecompileFunctionHelper(pipeline, function, optimized); | 2232 return PrecompileFunctionHelper(pipeline, function, optimized); |
| 2233 } | 2233 } |
| 2234 | 2234 |
| 2235 #endif // DART_PRECOMPILER | 2235 #endif // DART_PRECOMPILER |
| 2236 | 2236 |
| 2237 } // namespace dart | 2237 } // namespace dart |
| OLD | NEW |