Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 912 } | 912 } |
| 913 | 913 |
| 914 RollBackTo(last_changed_range); | 914 RollBackTo(last_changed_range); |
| 915 } | 915 } |
| 916 | 916 |
| 917 | 917 |
| 918 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) { | 918 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) { |
| 919 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); | 919 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); |
| 920 if (test->value()->IsCompare()) { | 920 if (test->value()->IsCompare()) { |
| 921 HCompare* compare = HCompare::cast(test->value()); | 921 HCompare* compare = HCompare::cast(test->value()); |
| 922 if (compare->GetInputRepresentation().IsInteger32()) { | 922 if (compare->GetInputRepresentation().IsInteger()) { |
| 923 Token::Value op = compare->token(); | 923 Token::Value op = compare->token(); |
| 924 if (test->SecondSuccessor() == dest) { | 924 if (test->SecondSuccessor() == dest) { |
| 925 op = Token::NegateCompareOp(op); | 925 op = Token::NegateCompareOp(op); |
| 926 } | 926 } |
| 927 Token::Value inverted_op = Token::InvertCompareOp(op); | 927 Token::Value inverted_op = Token::InvertCompareOp(op); |
| 928 InferControlFlowRange(op, compare->left(), compare->right()); | 928 InferControlFlowRange(op, compare->left(), compare->right()); |
| 929 InferControlFlowRange(inverted_op, compare->right(), compare->left()); | 929 InferControlFlowRange(inverted_op, compare->right(), compare->left()); |
| 930 } | 930 } |
| 931 } | 931 } |
| 932 } | 932 } |
| (...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1498 | 1498 |
| 1499 Zone* zone() { return graph_->zone(); } | 1499 Zone* zone() { return graph_->zone(); } |
| 1500 | 1500 |
| 1501 HGraph* graph_; | 1501 HGraph* graph_; |
| 1502 ZoneList<HValue*> worklist_; | 1502 ZoneList<HValue*> worklist_; |
| 1503 BitVector in_worklist_; | 1503 BitVector in_worklist_; |
| 1504 }; | 1504 }; |
| 1505 | 1505 |
| 1506 | 1506 |
| 1507 void HInferRepresentation::AddToWorklist(HValue* current) { | 1507 void HInferRepresentation::AddToWorklist(HValue* current) { |
| 1508 if (current->representation().IsSpecialization()) return; | 1508 if (current->representation().IsTerminalSpecialization()) return; |
| 1509 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; | 1509 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; |
| 1510 if (in_worklist_.Contains(current->id())) return; | 1510 if (in_worklist_.Contains(current->id())) return; |
| 1511 worklist_.Add(current); | 1511 worklist_.Add(current); |
| 1512 in_worklist_.Add(current->id()); | 1512 in_worklist_.Add(current->id()); |
| 1513 } | 1513 } |
| 1514 | 1514 |
| 1515 | 1515 |
| 1516 // This method tries to specialize the representation type of the value | 1516 // This method tries to specialize the representation type of the value |
| 1517 // given as a parameter. The value is asked to infer its representation type | 1517 // given as a parameter. The value is asked to infer its representation type |
| 1518 // based on its inputs. If the inferred type is more specialized, then this | 1518 // based on its inputs. If the inferred type is more specialized, then this |
| 1519 // becomes the new representation type of the node. | 1519 // becomes the new representation type of the node. |
| 1520 void HInferRepresentation::InferBasedOnInputs(HValue* current) { | 1520 void HInferRepresentation::InferBasedOnInputs(HValue* current) { |
| 1521 Representation r = current->representation(); | 1521 Representation r = current->representation(); |
| 1522 if (r.IsSpecialization()) return; | 1522 if (r.IsTerminalSpecialization()) return; |
| 1523 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); | 1523 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); |
| 1524 Representation inferred = current->InferredRepresentation(); | 1524 Representation inferred = current->InferredRepresentation(); |
| 1525 if (inferred.IsSpecialization()) { | 1525 if (!inferred.Equals(r)) { |
| 1526 current->ChangeRepresentation(inferred); | 1526 current->ChangeRepresentation(inferred); |
| 1527 AddDependantsToWorklist(current); | 1527 AddDependantsToWorklist(current); |
| 1528 } | 1528 } |
| 1529 } | 1529 } |
| 1530 | 1530 |
| 1531 | 1531 |
| 1532 void HInferRepresentation::AddDependantsToWorklist(HValue* current) { | 1532 void HInferRepresentation::AddDependantsToWorklist(HValue* current) { |
| 1533 for (int i = 0; i < current->uses()->length(); ++i) { | 1533 for (int i = 0; i < current->uses()->length(); ++i) { |
| 1534 AddToWorklist(current->uses()->at(i)); | 1534 AddToWorklist(current->uses()->at(i)); |
| 1535 } | 1535 } |
| 1536 for (int i = 0; i < current->OperandCount(); ++i) { | 1536 for (int i = 0; i < current->OperandCount(); ++i) { |
| 1537 AddToWorklist(current->OperandAt(i)); | 1537 AddToWorklist(current->OperandAt(i)); |
| 1538 } | 1538 } |
| 1539 } | 1539 } |
| 1540 | 1540 |
| 1541 | 1541 |
| 1542 // This method calculates whether specializing the representation of the value | 1542 // This method calculates whether specializing the representation of the value |
| 1543 // given as the parameter has a benefit in terms of less necessary type | 1543 // given as the parameter has a benefit in terms of less necessary type |
| 1544 // conversions. If there is a benefit, then the representation of the value is | 1544 // conversions. If there is a benefit, then the representation of the value is |
| 1545 // specialized. | 1545 // specialized. |
| 1546 void HInferRepresentation::InferBasedOnUses(HValue* current) { | 1546 void HInferRepresentation::InferBasedOnUses(HValue* current) { |
| 1547 Representation r = current->representation(); | 1547 Representation r = current->representation(); |
| 1548 if (r.IsSpecialization() || current->HasNoUses()) return; | 1548 if (r.IsTerminalSpecialization() || current->HasNoUses()) return; |
| 1549 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); | 1549 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); |
| 1550 Representation new_rep = TryChange(current); | 1550 Representation new_rep = TryChange(current); |
| 1551 if (!new_rep.IsNone()) { | 1551 if (!new_rep.IsNone()) { |
| 1552 if (!current->representation().Equals(new_rep)) { | 1552 if (!current->representation().Equals(new_rep)) { |
| 1553 current->ChangeRepresentation(new_rep); | 1553 current->ChangeRepresentation(new_rep); |
| 1554 AddDependantsToWorklist(current); | 1554 AddDependantsToWorklist(current); |
| 1555 } | 1555 } |
| 1556 } | 1556 } |
| 1557 } | 1557 } |
| 1558 | 1558 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1571 if (req_rep.IsNone()) continue; | 1571 if (req_rep.IsNone()) continue; |
| 1572 if (use->IsPhi()) { | 1572 if (use->IsPhi()) { |
| 1573 HPhi* phi = HPhi::cast(use); | 1573 HPhi* phi = HPhi::cast(use); |
| 1574 phi->AddIndirectUsesTo(&use_count[0]); | 1574 phi->AddIndirectUsesTo(&use_count[0]); |
| 1575 } | 1575 } |
| 1576 use_count[req_rep.kind()]++; | 1576 use_count[req_rep.kind()]++; |
| 1577 } | 1577 } |
| 1578 int tagged_count = use_count[Representation::kTagged]; | 1578 int tagged_count = use_count[Representation::kTagged]; |
| 1579 int double_count = use_count[Representation::kDouble]; | 1579 int double_count = use_count[Representation::kDouble]; |
| 1580 int int32_count = use_count[Representation::kInteger32]; | 1580 int int32_count = use_count[Representation::kInteger32]; |
| 1581 int non_tagged_count = double_count + int32_count; | 1581 int trunc_int32_count = use_count[Representation::kTruncatedInteger32]; |
| 1582 int clamped_rounded_int8_count = | |
| 1583 use_count[Representation::kClampedRoundedUInteger8]; | |
| 1584 int non_tagged_count = double_count + int32_count + | |
| 1585 trunc_int32_count + clamped_rounded_int8_count; | |
| 1586 int total_use_count = tagged_count + non_tagged_count; | |
| 1582 | 1587 |
| 1583 // If a non-loop phi has tagged uses, don't convert it to untagged. | 1588 // If a non-loop phi has tagged uses, don't convert it to untagged. |
| 1584 if (current->IsPhi() && !current->block()->IsLoopHeader()) { | 1589 if (current->IsPhi() && !current->block()->IsLoopHeader()) { |
| 1585 if (tagged_count > 0) return Representation::None(); | 1590 if (tagged_count > 0) return Representation::None(); |
| 1586 } | 1591 } |
| 1587 | 1592 |
| 1588 if (non_tagged_count >= tagged_count) { | 1593 if (non_tagged_count >= tagged_count) { |
| 1589 // More untagged than tagged. | 1594 // More untagged than tagged. |
| 1590 if (double_count > 0) { | 1595 if (double_count > 0) { |
| 1591 // There is at least one usage that is a double => guess that the | 1596 // There is at least one usage that is a double => guess that the |
| 1592 // correct representation is double. | 1597 // correct representation is double. |
| 1593 return Representation::Double(); | 1598 return Representation::Double(); |
| 1594 } else if (int32_count > 0) { | 1599 } else if (int32_count > 0) { |
| 1595 return Representation::Integer32(); | 1600 return Representation::Integer32(); |
| 1601 } else if (clamped_rounded_int8_count > 0 && | |
| 1602 clamped_rounded_int8_count == total_use_count) { | |
| 1603 return Representation::ClampedRoundedUInteger8(); | |
| 1604 } else if (trunc_int32_count > 0 && | |
| 1605 trunc_int32_count == total_use_count) { | |
| 1606 return Representation::TruncatedInteger32(); | |
| 1607 } else { | |
| 1608 return Representation::None(); | |
| 1596 } | 1609 } |
| 1597 } | 1610 } |
| 1598 return Representation::None(); | 1611 return Representation::None(); |
| 1599 } | 1612 } |
| 1600 | 1613 |
| 1601 | 1614 |
| 1602 void HInferRepresentation::Analyze() { | 1615 void HInferRepresentation::Analyze() { |
| 1603 HPhase phase("Infer representations", graph_); | 1616 HPhase phase("Infer representations", graph_); |
| 1604 | 1617 |
| 1605 // (1) Initialize bit vectors and count real uses. Each phi | 1618 // (1) Initialize bit vectors and count real uses. Each phi |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1757 next = use->block()->predecessors()->at(index)->end(); | 1770 next = use->block()->predecessors()->at(index)->end(); |
| 1758 } else { | 1771 } else { |
| 1759 next = HInstruction::cast(use); | 1772 next = HInstruction::cast(use); |
| 1760 } | 1773 } |
| 1761 | 1774 |
| 1762 // For constants we try to make the representation change at compile | 1775 // For constants we try to make the representation change at compile |
| 1763 // time. When a representation change is not possible without loss of | 1776 // time. When a representation change is not possible without loss of |
| 1764 // information we treat constants like normal instructions and insert the | 1777 // information we treat constants like normal instructions and insert the |
| 1765 // change instructions for them. | 1778 // change instructions for them. |
| 1766 HInstruction* new_value = NULL; | 1779 HInstruction* new_value = NULL; |
| 1767 bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32); | |
| 1768 if (value->IsConstant()) { | 1780 if (value->IsConstant()) { |
| 1769 HConstant* constant = HConstant::cast(value); | 1781 HConstant* constant = HConstant::cast(value); |
| 1770 // Try to create a new copy of the constant with the new representation. | 1782 // Try to create a new copy of the constant with the new representation. |
| 1771 new_value = is_truncating | 1783 new_value = to.IsTruncatedInteger32() |
| 1772 ? constant->CopyToTruncatedInt32() | 1784 ? constant->CopyToTruncatedInt32() |
| 1773 : constant->CopyToRepresentation(to); | 1785 : to.IsClampedRoundedInteger8() |
| 1786 ? constant->CopyToClampedRoundedUInt8() | |
| 1787 : constant->CopyToRepresentation(to); | |
| 1774 } | 1788 } |
| 1775 | 1789 |
| 1776 if (new_value == NULL) { | 1790 if (new_value == NULL) { |
| 1791 Representation from = value->representation(); | |
| 1792 // Don't create changes for representation differences that | |
| 1793 // won't generate code. | |
| 1794 if (from.IsInteger() && (to.IsInteger32X() || to.IsTruncatedInteger32())) { | |
| 1795 return; | |
| 1796 } | |
| 1797 | |
| 1777 new_value = | 1798 new_value = |
| 1778 new(zone()) HChange(value, value->representation(), to, is_truncating); | 1799 new(zone()) HChange(value, |
| 1800 from, | |
| 1801 to); | |
| 1779 } | 1802 } |
| 1780 | 1803 |
| 1781 new_value->InsertBefore(next); | 1804 new_value->InsertBefore(next); |
| 1782 value->ReplaceFirstAtUse(use, new_value, to); | 1805 value->ReplaceFirstAtUse(use, new_value, to); |
| 1783 } | 1806 } |
| 1784 | 1807 |
| 1785 | 1808 |
| 1786 int CompareConversionUses(HValue* a, | |
| 1787 HValue* b, | |
| 1788 Representation a_rep, | |
| 1789 Representation b_rep) { | |
| 1790 if (a_rep.kind() > b_rep.kind()) { | |
| 1791 // Make sure specializations are separated in the result array. | |
| 1792 return 1; | |
| 1793 } | |
| 1794 // Put truncating conversions before non-truncating conversions. | |
| 1795 bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32); | |
| 1796 bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32); | |
| 1797 if (a_truncate != b_truncate) { | |
| 1798 return a_truncate ? -1 : 1; | |
| 1799 } | |
| 1800 // Sort by increasing block ID. | |
| 1801 return a->block()->block_id() - b->block()->block_id(); | |
| 1802 } | |
| 1803 | |
| 1804 | |
| 1805 void HGraph::InsertRepresentationChangesForValue( | 1809 void HGraph::InsertRepresentationChangesForValue( |
| 1806 HValue* current, | 1810 HValue* current, |
| 1807 ZoneList<HValue*>* to_convert, | 1811 ZoneList<HValue*>* to_convert, |
| 1808 ZoneList<Representation>* to_convert_reps) { | 1812 ZoneList<Representation>* to_convert_reps) { |
| 1809 Representation r = current->representation(); | 1813 Representation r = current->representation(); |
| 1810 if (r.IsNone()) return; | 1814 if (r.IsNone()) return; |
| 1811 if (current->uses()->is_empty()) return; | 1815 if (current->uses()->is_empty()) return; |
| 1812 | 1816 |
| 1813 // Collect the representation changes in a sorted list. This allows | 1817 // Collect the representation changes in a sorted list. This allows |
| 1814 // us to avoid duplicate changes without searching the list. | 1818 // us to avoid duplicate changes without searching the list. |
| 1815 ASSERT(to_convert->is_empty()); | 1819 ASSERT(to_convert->is_empty()); |
| 1816 ASSERT(to_convert_reps->is_empty()); | 1820 ASSERT(to_convert_reps->is_empty()); |
| 1821 int index = 0; | |
| 1817 for (int i = 0; i < current->uses()->length(); ++i) { | 1822 for (int i = 0; i < current->uses()->length(); ++i) { |
| 1818 HValue* use = current->uses()->at(i); | 1823 HValue* use = current->uses()->at(i); |
| 1819 // The occurrences index means the index within the operand array of "use" | 1824 // The occurrences index means the index within the operand array of "use" |
| 1820 // at which "current" is used. While iterating through the use array we | 1825 // at which "current" is used. While iterating through the use array we |
| 1821 // also have to iterate over the different occurrence indices. | 1826 // also have to iterate over the different occurrence indices. |
| 1822 int occurrence_index = 0; | 1827 int occurrence_index = 0; |
| 1823 if (use->UsesMultipleTimes(current)) { | 1828 if (use->UsesMultipleTimes(current)) { |
| 1824 occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); | 1829 occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); |
| 1825 if (FLAG_trace_representation) { | 1830 if (FLAG_trace_representation) { |
| 1826 PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", | 1831 PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", |
| 1827 current->id(), | 1832 current->id(), |
| 1828 use->id(), | 1833 use->id(), |
| 1829 occurrence_index); | 1834 occurrence_index); |
| 1830 } | 1835 } |
| 1831 } | 1836 } |
| 1832 int operand_index = use->LookupOperandIndex(occurrence_index, current); | 1837 int operand_index = use->LookupOperandIndex(occurrence_index, current); |
| 1833 Representation req = use->RequiredInputRepresentation(operand_index); | 1838 Representation req = use->RequiredInputRepresentation(operand_index); |
| 1834 if (req.IsNone() || req.Equals(r)) continue; | 1839 if (req.IsNone() || req.Equals(r)) continue; |
| 1835 int index = 0; | |
| 1836 while (index < to_convert->length() && | |
| 1837 CompareConversionUses(to_convert->at(index), | |
|
fschneider
2011/05/10 10:44:53
Thanks for cleaning this up!
| |
| 1838 use, | |
| 1839 to_convert_reps->at(index), | |
| 1840 req) < 0) { | |
| 1841 ++index; | |
| 1842 } | |
| 1843 if (FLAG_trace_representation) { | |
| 1844 PrintF("Inserting a representation change to %s of %d for use at %d\n", | |
| 1845 req.Mnemonic(), | |
| 1846 current->id(), | |
| 1847 use->id()); | |
| 1848 } | |
| 1849 to_convert->InsertAt(index, use); | 1840 to_convert->InsertAt(index, use); |
| 1850 to_convert_reps->InsertAt(index, req); | 1841 to_convert_reps->InsertAt(index, req); |
| 1842 ++index; | |
| 1851 } | 1843 } |
| 1852 | 1844 |
| 1853 for (int i = 0; i < to_convert->length(); ++i) { | 1845 for (int i = 0; i < to_convert->length(); ++i) { |
| 1854 HValue* use = to_convert->at(i); | 1846 HValue* use = to_convert->at(i); |
| 1855 Representation r_to = to_convert_reps->at(i); | 1847 Representation r_to = to_convert_reps->at(i); |
| 1848 if (FLAG_trace_representation) { | |
| 1849 PrintF("Inserting a representation change to %s of %d for use at %d\n", | |
| 1850 r_to.Mnemonic(), | |
| 1851 current->id(), | |
| 1852 use->id()); | |
| 1853 } | |
| 1856 InsertRepresentationChangeForUse(current, use, r_to); | 1854 InsertRepresentationChangeForUse(current, use, r_to); |
| 1857 } | 1855 } |
| 1858 | 1856 |
| 1859 if (current->uses()->is_empty()) { | 1857 if (current->uses()->is_empty()) { |
| 1860 ASSERT(current->IsConstant()); | 1858 ASSERT(current->IsConstant()); |
| 1861 current->Delete(); | 1859 current->Delete(); |
| 1862 } | 1860 } |
| 1863 to_convert->Rewind(0); | 1861 to_convert->Rewind(0); |
| 1864 to_convert_reps->Rewind(0); | 1862 to_convert_reps->Rewind(0); |
| 1865 } | 1863 } |
| 1866 | 1864 |
| 1867 | 1865 |
| 1868 void HGraph::InsertRepresentationChanges() { | 1866 void HGraph::InsertRepresentationChanges() { |
| 1869 HPhase phase("Insert representation changes", this); | 1867 HPhase phase("Insert representation changes", this); |
|
fschneider
2011/05/10 10:44:53
Not sure that the representation computation does
| |
| 1870 | |
| 1871 | |
| 1872 // Compute truncation flag for phis: Initially assume that all | |
| 1873 // int32-phis allow truncation and iteratively remove the ones that | |
| 1874 // are used in an operation that does not allow a truncating | |
| 1875 // conversion. | |
| 1876 // TODO(fschneider): Replace this with a worklist-based iteration. | |
| 1877 for (int i = 0; i < phi_list()->length(); i++) { | |
| 1878 HPhi* phi = phi_list()->at(i); | |
| 1879 if (phi->representation().IsInteger32()) { | |
| 1880 phi->SetFlag(HValue::kTruncatingToInt32); | |
| 1881 } | |
| 1882 } | |
| 1883 bool change = true; | |
| 1884 while (change) { | |
| 1885 change = false; | |
| 1886 for (int i = 0; i < phi_list()->length(); i++) { | |
| 1887 HPhi* phi = phi_list()->at(i); | |
| 1888 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; | |
| 1889 for (int j = 0; j < phi->uses()->length(); j++) { | |
| 1890 HValue* use = phi->uses()->at(j); | |
| 1891 if (!use->CheckFlag(HValue::kTruncatingToInt32)) { | |
| 1892 phi->ClearFlag(HValue::kTruncatingToInt32); | |
| 1893 change = true; | |
| 1894 break; | |
| 1895 } | |
| 1896 } | |
| 1897 } | |
| 1898 } | |
| 1899 | |
| 1900 ZoneList<HValue*> value_list(4); | 1868 ZoneList<HValue*> value_list(4); |
| 1901 ZoneList<Representation> rep_list(4); | 1869 ZoneList<Representation> rep_list(4); |
| 1902 for (int i = 0; i < blocks_.length(); ++i) { | 1870 for (int i = 0; i < blocks_.length(); ++i) { |
| 1903 // Process phi instructions first. | 1871 // Process phi instructions first. |
| 1904 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { | 1872 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { |
| 1905 HPhi* phi = blocks_[i]->phis()->at(j); | 1873 HPhi* phi = blocks_[i]->phis()->at(j); |
| 1906 InsertRepresentationChangesForValue(phi, &value_list, &rep_list); | 1874 InsertRepresentationChangesForValue(phi, &value_list, &rep_list); |
| 1907 } | 1875 } |
| 1908 | 1876 |
| 1909 // Process normal instructions. | 1877 // Process normal instructions. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1921 for (int i = 0; i < blocks_.length(); ++i) { | 1889 for (int i = 0; i < blocks_.length(); ++i) { |
| 1922 for (HInstruction* current = blocks_[i]->first(); | 1890 for (HInstruction* current = blocks_[i]->first(); |
| 1923 current != NULL; | 1891 current != NULL; |
| 1924 current = current->next()) { | 1892 current = current->next()) { |
| 1925 if (current->IsChange()) { | 1893 if (current->IsChange()) { |
| 1926 HChange* change = HChange::cast(current); | 1894 HChange* change = HChange::cast(current); |
| 1927 // Propagate flags for negative zero checks upwards from conversions | 1895 // Propagate flags for negative zero checks upwards from conversions |
| 1928 // int32-to-tagged and int32-to-double. | 1896 // int32-to-tagged and int32-to-double. |
| 1929 Representation from = change->value()->representation(); | 1897 Representation from = change->value()->representation(); |
| 1930 ASSERT(from.Equals(change->from())); | 1898 ASSERT(from.Equals(change->from())); |
| 1931 if (from.IsInteger32()) { | 1899 if (from.IsInteger() && !change->to().IsInteger()) { |
| 1932 ASSERT(change->to().IsTagged() || change->to().IsDouble()); | 1900 ASSERT(change->to().IsTagged() || change->to().IsDouble()); |
| 1933 ASSERT(visited.IsEmpty()); | 1901 ASSERT(visited.IsEmpty()); |
| 1934 PropagateMinusZeroChecks(change->value(), &visited); | 1902 PropagateMinusZeroChecks(change->value(), &visited); |
| 1935 visited.Clear(); | 1903 visited.Clear(); |
| 1936 } | 1904 } |
| 1937 } | 1905 } |
| 1938 } | 1906 } |
| 1939 } | 1907 } |
| 1940 } | 1908 } |
| 1941 | 1909 |
| (...skipping 4208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6150 } | 6118 } |
| 6151 } | 6119 } |
| 6152 | 6120 |
| 6153 #ifdef DEBUG | 6121 #ifdef DEBUG |
| 6154 if (graph_ != NULL) graph_->Verify(); | 6122 if (graph_ != NULL) graph_->Verify(); |
| 6155 if (allocator_ != NULL) allocator_->Verify(); | 6123 if (allocator_ != NULL) allocator_->Verify(); |
| 6156 #endif | 6124 #endif |
| 6157 } | 6125 } |
| 6158 | 6126 |
| 6159 } } // namespace v8::internal | 6127 } } // namespace v8::internal |
| OLD | NEW |