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

Side by Side Diff: runtime/vm/flow_graph.cc

Issue 1700103002: VM: Move representation selection code out of the flow graph optimizer. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: remove some dead code Created 4 years, 10 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
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_compiler.h » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph.h" 5 #include "vm/flow_graph.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/flow_graph_compiler.h"
10 #include "vm/flow_graph_range_analysis.h"
9 #include "vm/il_printer.h" 11 #include "vm/il_printer.h"
10 #include "vm/intermediate_language.h" 12 #include "vm/intermediate_language.h"
11 #include "vm/growable_array.h" 13 #include "vm/growable_array.h"
12 #include "vm/object_store.h" 14 #include "vm/object_store.h"
13 #include "vm/report.h" 15 #include "vm/report.h"
14 16
15 namespace dart { 17 namespace dart {
16 18
19 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32)
20 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass.");
21 #endif
17 DEFINE_FLAG(bool, prune_dead_locals, true, "optimize dead locals away"); 22 DEFINE_FLAG(bool, prune_dead_locals, true, "optimize dead locals away");
18 DECLARE_FLAG(bool, emit_edge_counters); 23 DECLARE_FLAG(bool, emit_edge_counters);
19 DECLARE_FLAG(bool, reorder_basic_blocks); 24 DECLARE_FLAG(bool, reorder_basic_blocks);
20 DECLARE_FLAG(bool, trace_optimization); 25 DECLARE_FLAG(bool, trace_optimization);
21 DECLARE_FLAG(bool, verify_compiler); 26 DECLARE_FLAG(bool, verify_compiler);
22 27
23 28
24 FlowGraph::FlowGraph(const ParsedFunction& parsed_function, 29 FlowGraph::FlowGraph(const ParsedFunction& parsed_function,
25 GraphEntryInstr* graph_entry, 30 GraphEntryInstr* graph_entry,
26 intptr_t max_block_id) 31 intptr_t max_block_id)
(...skipping 1399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1426 IsSideEffectFreePath(block, instr->GetBlock()); 1431 IsSideEffectFreePath(block, instr->GetBlock());
1427 } 1432 }
1428 1433
1429 1434
1430 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, 1435 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from,
1431 BlockEntryInstr* to) const { 1436 BlockEntryInstr* to) const {
1432 return available_at_[to->postorder_number()]->Contains( 1437 return available_at_[to->postorder_number()]->Contains(
1433 from->postorder_number()); 1438 from->postorder_number());
1434 } 1439 }
1435 1440
1441
1442 // Quick access to the current zone.
1443 #define Z (zone())
1444
1445
1446 void FlowGraph::ConvertUse(Value* use, Representation from_rep) {
1447 const Representation to_rep =
1448 use->instruction()->RequiredInputRepresentation(use->use_index());
1449 if (from_rep == to_rep || to_rep == kNoRepresentation) {
1450 return;
1451 }
1452 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/ false);
1453 }
1454
1455
1456 static bool IsUnboxedInteger(Representation rep) {
1457 return (rep == kUnboxedInt32) ||
1458 (rep == kUnboxedUint32) ||
1459 (rep == kUnboxedMint);
1460 }
1461
1462
1463 static bool ShouldInlineSimd() {
1464 return FlowGraphCompiler::SupportsUnboxedSimd128();
1465 }
1466
1467
1468 static bool CanUnboxDouble() {
1469 return FlowGraphCompiler::SupportsUnboxedDoubles();
1470 }
1471
1472
1473 static bool CanConvertUnboxedMintToDouble() {
1474 return FlowGraphCompiler::CanConvertUnboxedMintToDouble();
1475 }
1476
1477
1478 void FlowGraph::InsertConversion(Representation from,
1479 Representation to,
1480 Value* use,
1481 bool is_environment_use) {
1482 Instruction* insert_before;
1483 Instruction* deopt_target;
1484 PhiInstr* phi = use->instruction()->AsPhi();
1485 if (phi != NULL) {
1486 ASSERT(phi->is_alive());
1487 // For phis conversions have to be inserted in the predecessor.
1488 insert_before =
1489 phi->block()->PredecessorAt(use->use_index())->last_instruction();
1490 deopt_target = NULL;
1491 } else {
1492 deopt_target = insert_before = use->instruction();
1493 }
1494
1495 Definition* converted = NULL;
1496 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) {
1497 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ?
1498 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId;
1499 converted = new(Z) UnboxedIntConverterInstr(from,
1500 to,
1501 use->CopyWithType(),
1502 deopt_id);
1503 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) {
1504 converted = new Int32ToDoubleInstr(use->CopyWithType());
1505 } else if ((from == kUnboxedMint) &&
1506 (to == kUnboxedDouble) &&
1507 CanConvertUnboxedMintToDouble()) {
1508 const intptr_t deopt_id = (deopt_target != NULL) ?
1509 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId;
1510 ASSERT(CanUnboxDouble());
1511 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id);
1512 } else if ((from == kTagged) && Boxing::Supports(to)) {
1513 const intptr_t deopt_id = (deopt_target != NULL) ?
1514 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId;
1515 converted = UnboxInstr::Create(to, use->CopyWithType(), deopt_id);
1516 } else if ((to == kTagged) && Boxing::Supports(from)) {
1517 converted = BoxInstr::Create(from, use->CopyWithType());
1518 } else {
1519 // We have failed to find a suitable conversion instruction.
1520 // Insert two "dummy" conversion instructions with the correct
1521 // "from" and "to" representation. The inserted instructions will
1522 // trigger a deoptimization if executed. See #12417 for a discussion.
1523 const intptr_t deopt_id = (deopt_target != NULL) ?
1524 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId;
1525 ASSERT(Boxing::Supports(from));
1526 ASSERT(Boxing::Supports(to));
1527 Definition* boxed = BoxInstr::Create(from, use->CopyWithType());
1528 use->BindTo(boxed);
1529 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
1530 converted = UnboxInstr::Create(to, new(Z) Value(boxed), deopt_id);
1531 }
1532 ASSERT(converted != NULL);
1533 InsertBefore(insert_before, converted, use->instruction()->env(),
1534 FlowGraph::kValue);
1535 if (is_environment_use) {
1536 use->BindToEnvironment(converted);
1537 } else {
1538 use->BindTo(converted);
1539 }
1540
1541 if ((to == kUnboxedInt32) && (phi != NULL)) {
1542 // Int32 phis are unboxed optimistically. Ensure that unboxing
1543 // has deoptimization target attached from the goto instruction.
1544 CopyDeoptTarget(converted, insert_before);
1545 }
1546 }
1547
1548
1549 void FlowGraph::ConvertEnvironmentUse(Value* use, Representation from_rep) {
1550 const Representation to_rep = kTagged;
1551 if (from_rep == to_rep) {
1552 return;
1553 }
1554 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/ true);
1555 }
1556
1557
1558 void FlowGraph::InsertConversionsFor(Definition* def) {
1559 const Representation from_rep = def->representation();
1560
1561 for (Value::Iterator it(def->input_use_list());
1562 !it.Done();
1563 it.Advance()) {
1564 ConvertUse(it.Current(), from_rep);
1565 }
1566
1567 if (graph_entry()->SuccessorCount() > 1) {
1568 for (Value::Iterator it(def->env_use_list());
1569 !it.Done();
1570 it.Advance()) {
1571 Value* use = it.Current();
1572 if (use->instruction()->MayThrow() &&
1573 use->instruction()->GetBlock()->InsideTryBlock()) {
1574 // Environment uses at calls inside try-blocks must be converted to
1575 // tagged representation.
1576 ConvertEnvironmentUse(it.Current(), from_rep);
1577 }
1578 }
1579 }
1580 }
1581
1582
1583 static void UnboxPhi(PhiInstr* phi) {
1584 Representation unboxed = phi->representation();
1585
1586 switch (phi->Type()->ToCid()) {
1587 case kDoubleCid:
1588 if (CanUnboxDouble()) {
1589 unboxed = kUnboxedDouble;
1590 }
1591 break;
1592 case kFloat32x4Cid:
1593 if (ShouldInlineSimd()) {
1594 unboxed = kUnboxedFloat32x4;
1595 }
1596 break;
1597 case kInt32x4Cid:
1598 if (ShouldInlineSimd()) {
1599 unboxed = kUnboxedInt32x4;
1600 }
1601 break;
1602 case kFloat64x2Cid:
1603 if (ShouldInlineSimd()) {
1604 unboxed = kUnboxedFloat64x2;
1605 }
1606 break;
1607 }
1608
1609 if ((kSmiBits < 32) &&
1610 (unboxed == kTagged) &&
1611 phi->Type()->IsInt() &&
1612 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt64)) {
1613 // On 32-bit platforms conservatively unbox phis that:
1614 // - are proven to be of type Int;
1615 // - fit into 64bits range;
1616 // - have either constants or Box() operations as inputs;
1617 // - have at least one Box() operation as an input;
1618 // - are used in at least 1 Unbox() operation.
1619 bool should_unbox = false;
1620 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1621 Definition* input = phi->InputAt(i)->definition();
1622 if (input->IsBox() &&
1623 RangeUtils::Fits(input->range(),
1624 RangeBoundary::kRangeBoundaryInt64)) {
1625 should_unbox = true;
1626 } else if (!input->IsConstant()) {
1627 should_unbox = false;
1628 break;
1629 }
1630 }
1631
1632 if (should_unbox) {
1633 // We checked inputs. Check if phi is used in at least one unbox
1634 // operation.
1635 bool has_unboxed_use = false;
1636 for (Value* use = phi->input_use_list();
1637 use != NULL;
1638 use = use->next_use()) {
1639 Instruction* instr = use->instruction();
1640 if (instr->IsUnbox()) {
1641 has_unboxed_use = true;
1642 break;
1643 } else if (IsUnboxedInteger(
1644 instr->RequiredInputRepresentation(use->use_index()))) {
1645 has_unboxed_use = true;
1646 break;
1647 }
1648 }
1649
1650 if (!has_unboxed_use) {
1651 should_unbox = false;
1652 }
1653 }
1654
1655 if (should_unbox) {
1656 unboxed =
1657 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32)
1658 ? kUnboxedInt32 : kUnboxedMint;
1659 }
1660 }
1661
1662 phi->set_representation(unboxed);
1663 }
1664
1665
1666 void FlowGraph::SelectRepresentations() {
1667 // Conservatively unbox all phis that were proven to be of Double,
1668 // Float32x4, or Int32x4 type.
1669 for (BlockIterator block_it = reverse_postorder_iterator();
1670 !block_it.Done();
1671 block_it.Advance()) {
1672 JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry();
1673 if (join_entry != NULL) {
1674 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
1675 PhiInstr* phi = it.Current();
1676 UnboxPhi(phi);
1677 }
1678 }
1679 }
1680
1681 // Process all instructions and insert conversions where needed.
1682 // Visit incoming parameters and constants.
1683 for (intptr_t i = 0;
1684 i < graph_entry()->initial_definitions()->length();
1685 i++) {
1686 InsertConversionsFor((*graph_entry()->initial_definitions())[i]);
1687 }
1688
1689 for (BlockIterator block_it = reverse_postorder_iterator();
1690 !block_it.Done();
1691 block_it.Advance()) {
1692 BlockEntryInstr* entry = block_it.Current();
1693 JoinEntryInstr* join_entry = entry->AsJoinEntry();
1694 if (join_entry != NULL) {
1695 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
1696 PhiInstr* phi = it.Current();
1697 ASSERT(phi != NULL);
1698 ASSERT(phi->is_alive());
1699 InsertConversionsFor(phi);
1700 }
1701 }
1702 CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry();
1703 if (catch_entry != NULL) {
1704 for (intptr_t i = 0;
1705 i < catch_entry->initial_definitions()->length();
1706 i++) {
1707 InsertConversionsFor((*catch_entry->initial_definitions())[i]);
1708 }
1709 }
1710 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
1711 Definition* def = it.Current()->AsDefinition();
1712 if (def != NULL) {
1713 InsertConversionsFor(def);
1714 }
1715 }
1716 }
1717 }
1718
1719
1720 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32)
1721 // Smi widening pass is only meaningful on platforms where Smi
1722 // is smaller than 32bit. For now only support it on ARM and ia32.
1723 static bool CanBeWidened(BinarySmiOpInstr* smi_op) {
1724 return BinaryInt32OpInstr::IsSupported(smi_op->op_kind(),
1725 smi_op->left(),
1726 smi_op->right());
1727 }
1728
1729
1730 static bool BenefitsFromWidening(BinarySmiOpInstr* smi_op) {
1731 // TODO(vegorov): when shifts with non-constants shift count are supported
1732 // add them here as we save untagging for the count.
1733 switch (smi_op->op_kind()) {
1734 case Token::kMUL:
1735 case Token::kSHR:
1736 // For kMUL we save untagging of the argument for kSHR
1737 // we save tagging of the result.
1738 return true;
1739
1740 default:
1741 return false;
1742 }
1743 }
1744
1745
1746 void FlowGraph::WidenSmiToInt32() {
1747 GrowableArray<BinarySmiOpInstr*> candidates;
1748
1749 // Step 1. Collect all instructions that potentially benefit from widening of
1750 // their operands (or their result) into int32 range.
1751 for (BlockIterator block_it = reverse_postorder_iterator();
1752 !block_it.Done();
1753 block_it.Advance()) {
1754 for (ForwardInstructionIterator instr_it(block_it.Current());
1755 !instr_it.Done();
1756 instr_it.Advance()) {
1757 BinarySmiOpInstr* smi_op = instr_it.Current()->AsBinarySmiOp();
1758 if ((smi_op != NULL) &&
1759 smi_op->HasSSATemp() &&
1760 BenefitsFromWidening(smi_op) &&
1761 CanBeWidened(smi_op)) {
1762 candidates.Add(smi_op);
1763 }
1764 }
1765 }
1766
1767 if (candidates.is_empty()) {
1768 return;
1769 }
1770
1771 // Step 2. For each block in the graph compute which loop it belongs to.
1772 // We will use this information later during computation of the widening's
1773 // gain: we are going to assume that only conversion occuring inside the
1774 // same loop should be counted against the gain, all other conversions
1775 // can be hoisted and thus cost nothing compared to the loop cost itself.
1776 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = LoopHeaders();
1777
1778 GrowableArray<intptr_t> loops(preorder().length());
1779 for (intptr_t i = 0; i < preorder().length(); i++) {
1780 loops.Add(-1);
1781 }
1782
1783 for (intptr_t loop_id = 0; loop_id < loop_headers.length(); ++loop_id) {
1784 for (BitVector::Iterator loop_it(loop_headers[loop_id]->loop_info());
1785 !loop_it.Done();
1786 loop_it.Advance()) {
1787 loops[loop_it.Current()] = loop_id;
1788 }
1789 }
1790
1791 // Step 3. For each candidate transitively collect all other BinarySmiOpInstr
1792 // and PhiInstr that depend on it and that it depends on and count amount of
1793 // untagging operations that we save in assumption that this whole graph of
1794 // values is using kUnboxedInt32 representation instead of kTagged.
1795 // Convert those graphs that have positive gain to kUnboxedInt32.
1796
1797 // BitVector containing SSA indexes of all processed definitions. Used to skip
1798 // those candidates that belong to dependency graph of another candidate.
1799 BitVector* processed =
1800 new(Z) BitVector(Z, current_ssa_temp_index());
1801
1802 // Worklist used to collect dependency graph.
1803 DefinitionWorklist worklist(this, candidates.length());
1804 for (intptr_t i = 0; i < candidates.length(); i++) {
1805 BinarySmiOpInstr* op = candidates[i];
1806 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) {
1807 continue;
1808 }
1809
1810 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1811 THR_Print("analysing candidate: %s\n", op->ToCString());
1812 }
1813 worklist.Clear();
1814 worklist.Add(op);
1815
1816 // Collect dependency graph. Note: more items are added to worklist
1817 // inside this loop.
1818 intptr_t gain = 0;
1819 for (intptr_t j = 0; j < worklist.definitions().length(); j++) {
1820 Definition* defn = worklist.definitions()[j];
1821
1822 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1823 THR_Print("> %s\n", defn->ToCString());
1824 }
1825
1826 if (defn->IsBinarySmiOp() &&
1827 BenefitsFromWidening(defn->AsBinarySmiOp())) {
1828 gain++;
1829 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1830 THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString());
1831 }
1832 }
1833
1834 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()];
1835
1836 // Process all inputs.
1837 for (intptr_t k = 0; k < defn->InputCount(); k++) {
1838 Definition* input = defn->InputAt(k)->definition();
1839 if (input->IsBinarySmiOp() &&
1840 CanBeWidened(input->AsBinarySmiOp())) {
1841 worklist.Add(input);
1842 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) {
1843 worklist.Add(input);
1844 } else if (input->IsBinaryMintOp()) {
1845 // Mint operation produces untagged result. We avoid tagging.
1846 gain++;
1847 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1848 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString());
1849 }
1850 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] &&
1851 (input->Type()->ToCid() == kSmiCid)) {
1852 // Input comes from the same loop, is known to be smi and requires
1853 // untagging.
1854 // TODO(vegorov) this heuristic assumes that values that are not
1855 // known to be smi have to be checked and this check can be
1856 // coalesced with untagging. Start coalescing them.
1857 gain--;
1858 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1859 THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString());
1860 }
1861 }
1862 }
1863
1864 // Process all uses.
1865 for (Value* use = defn->input_use_list();
1866 use != NULL;
1867 use = use->next_use()) {
1868 Instruction* instr = use->instruction();
1869 Definition* use_defn = instr->AsDefinition();
1870 if (use_defn == NULL) {
1871 // We assume that tagging before returning or pushing argument costs
1872 // very little compared to the cost of the return/call itself.
1873 if (!instr->IsReturn() && !instr->IsPushArgument()) {
1874 gain--;
1875 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1876 THR_Print("v [%" Pd "] (u) %s\n",
1877 gain,
1878 use->instruction()->ToCString());
1879 }
1880 }
1881 continue;
1882 } else if (use_defn->IsBinarySmiOp() &&
1883 CanBeWidened(use_defn->AsBinarySmiOp())) {
1884 worklist.Add(use_defn);
1885 } else if (use_defn->IsPhi() &&
1886 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) {
1887 worklist.Add(use_defn);
1888 } else if (use_defn->IsBinaryMintOp()) {
1889 // BinaryMintOp requires untagging of its inputs.
1890 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost
1891 // sign extension operation.
1892 gain++;
1893 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1894 THR_Print("^ [%" Pd "] (u) %s\n",
1895 gain,
1896 use->instruction()->ToCString());
1897 }
1898 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) {
1899 gain--;
1900 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1901 THR_Print("v [%" Pd "] (u) %s\n",
1902 gain,
1903 use->instruction()->ToCString());
1904 }
1905 }
1906 }
1907 }
1908
1909 processed->AddAll(worklist.contains_vector());
1910
1911 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1912 THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain);
1913 }
1914
1915 if (gain > 0) {
1916 // We have positive gain from widening. Convert all BinarySmiOpInstr into
1917 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32.
1918 for (intptr_t j = 0; j < worklist.definitions().length(); j++) {
1919 Definition* defn = worklist.definitions()[j];
1920 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp());
1921
1922 if (defn->IsBinarySmiOp()) {
1923 BinarySmiOpInstr* smi_op = defn->AsBinarySmiOp();
1924 BinaryInt32OpInstr* int32_op = new(Z) BinaryInt32OpInstr(
1925 smi_op->op_kind(),
1926 smi_op->left()->CopyWithType(),
1927 smi_op->right()->CopyWithType(),
1928 smi_op->DeoptimizationTarget());
1929
1930 smi_op->ReplaceWith(int32_op, NULL);
1931 } else if (defn->IsPhi()) {
1932 defn->AsPhi()->set_representation(kUnboxedInt32);
1933 ASSERT(defn->Type()->IsInt());
1934 }
1935 }
1936 }
1937 }
1938 }
1939 #else
1940 void FlowGraph::WidenSmiToInt32() {
1941 // TODO(vegorov) ideally on 64-bit platforms we would like to narrow smi
1942 // operations to 32-bit where it saves tagging and untagging and allows
1943 // to use shorted (and faster) instructions. But we currently don't
1944 // save enough range information in the ICData to drive this decision.
1945 }
1946 #endif
1947
1948
1949 void FlowGraph::EliminateEnvironments() {
1950 // After this pass we can no longer perform LICM and hoist instructions
1951 // that can deoptimize.
1952
1953 disallow_licm();
1954 for (BlockIterator block_it = reverse_postorder_iterator();
1955 !block_it.Done();
1956 block_it.Advance()) {
1957 BlockEntryInstr* block = block_it.Current();
1958 block->RemoveEnvironment();
1959 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1960 Instruction* current = it.Current();
1961 if (!current->CanDeoptimize()) {
1962 // TODO(srdjan): --source-lines needs deopt environments to get at
1963 // the code for this instruction, however, leaving the environment
1964 // changes code.
1965 current->RemoveEnvironment();
1966 }
1967 }
1968 }
1969 }
1970
1971
1972 bool FlowGraph::Canonicalize() {
1973 bool changed = false;
1974
1975 for (BlockIterator block_it = reverse_postorder_iterator();
1976 !block_it.Done();
1977 block_it.Advance()) {
1978 for (ForwardInstructionIterator it(block_it.Current());
1979 !it.Done();
1980 it.Advance()) {
1981 Instruction* current = it.Current();
1982 if (current->HasUnmatchedInputRepresentations()) {
1983 // Can't canonicalize this instruction until all conversions for its
1984 // inputs are inserted.
1985 continue;
1986 }
1987
1988 Instruction* replacement = current->Canonicalize(this);
1989
1990 if (replacement != current) {
1991 // For non-definitions Canonicalize should return either NULL or
1992 // this.
1993 ASSERT((replacement == NULL) || current->IsDefinition());
1994 ReplaceCurrentInstruction(&it, current, replacement);
1995 changed = true;
1996 }
1997 }
1998 }
1999 return changed;
2000 }
2001
2002
1436 } // namespace dart 2003 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_compiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698