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 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 } | 637 } |
638 | 638 |
639 | 639 |
640 void HGraph::Canonicalize() { | 640 void HGraph::Canonicalize() { |
641 if (!FLAG_use_canonicalizing) return; | 641 if (!FLAG_use_canonicalizing) return; |
642 HPhase phase("Canonicalize", this); | 642 HPhase phase("Canonicalize", this); |
643 for (int i = 0; i < blocks()->length(); ++i) { | 643 for (int i = 0; i < blocks()->length(); ++i) { |
644 HInstruction* instr = blocks()->at(i)->first(); | 644 HInstruction* instr = blocks()->at(i)->first(); |
645 while (instr != NULL) { | 645 while (instr != NULL) { |
646 HValue* value = instr->Canonicalize(); | 646 HValue* value = instr->Canonicalize(); |
647 if (value != instr) instr->ReplaceAndDelete(value); | 647 if (value != instr) instr->DeleteAndReplaceWith(value); |
648 instr = instr->next(); | 648 instr = instr->next(); |
649 } | 649 } |
650 } | 650 } |
651 } | 651 } |
652 | 652 |
653 | 653 |
654 void HGraph::OrderBlocks() { | 654 void HGraph::OrderBlocks() { |
655 HPhase phase("Block ordering"); | 655 HPhase phase("Block ordering"); |
656 BitVector visited(blocks_.length()); | 656 BitVector visited(blocks_.length()); |
657 | 657 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); | 719 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); |
720 } | 720 } |
721 } | 721 } |
722 } | 722 } |
723 } | 723 } |
724 | 724 |
725 | 725 |
726 void HGraph::EliminateRedundantPhis() { | 726 void HGraph::EliminateRedundantPhis() { |
727 HPhase phase("Redundant phi elimination", this); | 727 HPhase phase("Redundant phi elimination", this); |
728 | 728 |
729 // Worklist of phis that can potentially be eliminated. Initialized | 729 // Worklist of phis that can potentially be eliminated. Initialized with |
730 // with all phi nodes. When elimination of a phi node modifies | 730 // all phi nodes. When elimination of a phi node modifies another phi node |
731 // another phi node the modified phi node is added to the worklist. | 731 // the modified phi node is added to the worklist. |
732 ZoneList<HPhi*> worklist(blocks_.length()); | 732 ZoneList<HPhi*> worklist(blocks_.length()); |
733 for (int i = 0; i < blocks_.length(); ++i) { | 733 for (int i = 0; i < blocks_.length(); ++i) { |
734 worklist.AddAll(*blocks_[i]->phis()); | 734 worklist.AddAll(*blocks_[i]->phis()); |
735 } | 735 } |
736 | 736 |
737 while (!worklist.is_empty()) { | 737 while (!worklist.is_empty()) { |
738 HPhi* phi = worklist.RemoveLast(); | 738 HPhi* phi = worklist.RemoveLast(); |
739 HBasicBlock* block = phi->block(); | 739 HBasicBlock* block = phi->block(); |
740 | 740 |
741 // Skip phi node if it was already replaced. | 741 // Skip phi node if it was already replaced. |
742 if (block == NULL) continue; | 742 if (block == NULL) continue; |
743 | 743 |
744 // Get replacement value if phi is redundant. | 744 // Get replacement value if phi is redundant. |
745 HValue* value = phi->GetRedundantReplacement(); | 745 HValue* replacement = phi->GetRedundantReplacement(); |
746 | 746 |
747 if (value != NULL) { | 747 if (replacement != NULL) { |
748 // Iterate through uses finding the ones that should be | 748 // Iterate through the uses and replace them all. |
749 // replaced. | 749 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
750 SmallPointerList<HValue>* uses = phi->uses(); | 750 HValue* value = it.value(); |
751 while (!uses->is_empty()) { | 751 value->SetOperandAt(it.index(), replacement); |
752 HValue* use = uses->RemoveLast(); | 752 if (value->IsPhi()) worklist.Add(HPhi::cast(value)); |
753 if (use != NULL) { | |
754 phi->ReplaceAtUse(use, value); | |
755 if (use->IsPhi()) worklist.Add(HPhi::cast(use)); | |
756 } | |
757 } | 753 } |
758 block->RemovePhi(phi); | 754 block->RemovePhi(phi); |
759 } | 755 } |
760 } | 756 } |
761 } | 757 } |
762 | 758 |
763 | 759 |
764 void HGraph::EliminateUnreachablePhis() { | 760 void HGraph::EliminateUnreachablePhis() { |
765 HPhase phase("Unreachable phi elimination", this); | 761 HPhase phase("Unreachable phi elimination", this); |
766 | 762 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 BitVector in_worklist(GetMaximumValueID()); | 820 BitVector in_worklist(GetMaximumValueID()); |
825 for (int i = 0; i < worklist->length(); ++i) { | 821 for (int i = 0; i < worklist->length(); ++i) { |
826 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); | 822 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); |
827 in_worklist.Add(worklist->at(i)->id()); | 823 in_worklist.Add(worklist->at(i)->id()); |
828 } | 824 } |
829 | 825 |
830 while (!worklist->is_empty()) { | 826 while (!worklist->is_empty()) { |
831 HValue* current = worklist->RemoveLast(); | 827 HValue* current = worklist->RemoveLast(); |
832 in_worklist.Remove(current->id()); | 828 in_worklist.Remove(current->id()); |
833 if (current->UpdateInferredType()) { | 829 if (current->UpdateInferredType()) { |
834 for (int j = 0; j < current->uses()->length(); j++) { | 830 for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) { |
835 HValue* use = current->uses()->at(j); | 831 HValue* use = it.value(); |
836 if (!in_worklist.Contains(use->id())) { | 832 if (!in_worklist.Contains(use->id())) { |
837 in_worklist.Add(use->id()); | 833 in_worklist.Add(use->id()); |
838 worklist->Add(use); | 834 worklist->Add(use); |
839 } | 835 } |
840 } | 836 } |
841 } | 837 } |
842 } | 838 } |
843 } | 839 } |
844 | 840 |
845 | 841 |
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 TraceGVN("Instruction %d kills\n", instr->id()); | 1434 TraceGVN("Instruction %d kills\n", instr->id()); |
1439 } else if (instr->CheckFlag(HValue::kUseGVN)) { | 1435 } else if (instr->CheckFlag(HValue::kUseGVN)) { |
1440 HValue* other = map->Lookup(instr); | 1436 HValue* other = map->Lookup(instr); |
1441 if (other != NULL) { | 1437 if (other != NULL) { |
1442 ASSERT(instr->Equals(other) && other->Equals(instr)); | 1438 ASSERT(instr->Equals(other) && other->Equals(instr)); |
1443 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", | 1439 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", |
1444 instr->id(), | 1440 instr->id(), |
1445 instr->Mnemonic(), | 1441 instr->Mnemonic(), |
1446 other->id(), | 1442 other->id(), |
1447 other->Mnemonic()); | 1443 other->Mnemonic()); |
1448 instr->ReplaceAndDelete(other); | 1444 instr->DeleteAndReplaceWith(other); |
1449 } else { | 1445 } else { |
1450 map->Add(instr); | 1446 map->Add(instr); |
1451 } | 1447 } |
1452 } | 1448 } |
1453 instr = next; | 1449 instr = next; |
1454 } | 1450 } |
1455 | 1451 |
1456 // Recursively continue analysis for all immediately dominated blocks. | 1452 // Recursively continue analysis for all immediately dominated blocks. |
1457 int length = block->dominated_blocks()->length(); | 1453 int length = block->dominated_blocks()->length(); |
1458 for (int i = 0; i < length; ++i) { | 1454 for (int i = 0; i < length; ++i) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1522 if (r.IsSpecialization()) return; | 1518 if (r.IsSpecialization()) return; |
1523 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); | 1519 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); |
1524 Representation inferred = current->InferredRepresentation(); | 1520 Representation inferred = current->InferredRepresentation(); |
1525 if (inferred.IsSpecialization()) { | 1521 if (inferred.IsSpecialization()) { |
1526 current->ChangeRepresentation(inferred); | 1522 current->ChangeRepresentation(inferred); |
1527 AddDependantsToWorklist(current); | 1523 AddDependantsToWorklist(current); |
1528 } | 1524 } |
1529 } | 1525 } |
1530 | 1526 |
1531 | 1527 |
1532 void HInferRepresentation::AddDependantsToWorklist(HValue* current) { | 1528 void HInferRepresentation::AddDependantsToWorklist(HValue* value) { |
1533 for (int i = 0; i < current->uses()->length(); ++i) { | 1529 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { |
1534 AddToWorklist(current->uses()->at(i)); | 1530 AddToWorklist(it.value()); |
1535 } | 1531 } |
1536 for (int i = 0; i < current->OperandCount(); ++i) { | 1532 for (int i = 0; i < value->OperandCount(); ++i) { |
1537 AddToWorklist(current->OperandAt(i)); | 1533 AddToWorklist(value->OperandAt(i)); |
1538 } | 1534 } |
1539 } | 1535 } |
1540 | 1536 |
1541 | 1537 |
1542 // This method calculates whether specializing the representation of the value | 1538 // This method calculates whether specializing the representation of the value |
1543 // given as the parameter has a benefit in terms of less necessary type | 1539 // 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 | 1540 // conversions. If there is a benefit, then the representation of the value is |
1545 // specialized. | 1541 // specialized. |
1546 void HInferRepresentation::InferBasedOnUses(HValue* current) { | 1542 void HInferRepresentation::InferBasedOnUses(HValue* value) { |
1547 Representation r = current->representation(); | 1543 Representation r = value->representation(); |
1548 if (r.IsSpecialization() || current->HasNoUses()) return; | 1544 if (r.IsSpecialization() || value->HasNoUses()) return; |
1549 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); | 1545 ASSERT(value->CheckFlag(HValue::kFlexibleRepresentation)); |
1550 Representation new_rep = TryChange(current); | 1546 Representation new_rep = TryChange(value); |
1551 if (!new_rep.IsNone()) { | 1547 if (!new_rep.IsNone()) { |
1552 if (!current->representation().Equals(new_rep)) { | 1548 if (!value->representation().Equals(new_rep)) { |
1553 current->ChangeRepresentation(new_rep); | 1549 value->ChangeRepresentation(new_rep); |
1554 AddDependantsToWorklist(current); | 1550 AddDependantsToWorklist(value); |
1555 } | 1551 } |
1556 } | 1552 } |
1557 } | 1553 } |
1558 | 1554 |
1559 | 1555 |
1560 Representation HInferRepresentation::TryChange(HValue* current) { | 1556 Representation HInferRepresentation::TryChange(HValue* value) { |
1561 // Array of use counts for each representation. | 1557 // Array of use counts for each representation. |
1562 int use_count[Representation::kNumRepresentations]; | 1558 int use_count[Representation::kNumRepresentations] = { 0 }; |
1563 for (int i = 0; i < Representation::kNumRepresentations; i++) { | |
1564 use_count[i] = 0; | |
1565 } | |
1566 | 1559 |
1567 for (int i = 0; i < current->uses()->length(); ++i) { | 1560 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { |
1568 HValue* use = current->uses()->at(i); | 1561 HValue* use = it.value(); |
1569 int index = use->LookupOperandIndex(0, current); | 1562 Representation rep = use->RequiredInputRepresentation(it.index()); |
1570 Representation req_rep = use->RequiredInputRepresentation(index); | 1563 if (rep.IsNone()) continue; |
1571 if (req_rep.IsNone()) continue; | 1564 if (use->IsPhi()) HPhi::cast(use)->AddIndirectUsesTo(&use_count[0]); |
1572 if (use->IsPhi()) { | 1565 ++use_count[rep.kind()]; |
1573 HPhi* phi = HPhi::cast(use); | |
1574 phi->AddIndirectUsesTo(&use_count[0]); | |
1575 } | |
1576 use_count[req_rep.kind()]++; | |
1577 } | 1566 } |
1578 int tagged_count = use_count[Representation::kTagged]; | 1567 int tagged_count = use_count[Representation::kTagged]; |
1579 int double_count = use_count[Representation::kDouble]; | 1568 int double_count = use_count[Representation::kDouble]; |
1580 int int32_count = use_count[Representation::kInteger32]; | 1569 int int32_count = use_count[Representation::kInteger32]; |
1581 int non_tagged_count = double_count + int32_count; | 1570 int non_tagged_count = double_count + int32_count; |
1582 | 1571 |
1583 // If a non-loop phi has tagged uses, don't convert it to untagged. | 1572 // If a non-loop phi has tagged uses, don't convert it to untagged. |
1584 if (current->IsPhi() && !current->block()->IsLoopHeader()) { | 1573 if (value->IsPhi() && !value->block()->IsLoopHeader()) { |
1585 if (tagged_count > 0) return Representation::None(); | 1574 if (tagged_count > 0) return Representation::None(); |
1586 } | 1575 } |
1587 | 1576 |
1588 if (non_tagged_count >= tagged_count) { | 1577 if (non_tagged_count >= tagged_count) { |
1589 // More untagged than tagged. | 1578 // More untagged than tagged. |
1590 if (double_count > 0) { | 1579 if (double_count > 0) { |
1591 // There is at least one usage that is a double => guess that the | 1580 // There is at least one usage that is a double => guess that the |
1592 // correct representation is double. | 1581 // correct representation is double. |
1593 return Representation::Double(); | 1582 return Representation::Double(); |
1594 } else if (int32_count > 0) { | 1583 } else if (int32_count > 0) { |
1595 return Representation::Integer32(); | 1584 return Representation::Integer32(); |
1596 } | 1585 } |
1597 } | 1586 } |
1598 return Representation::None(); | 1587 return Representation::None(); |
1599 } | 1588 } |
1600 | 1589 |
1601 | 1590 |
1602 void HInferRepresentation::Analyze() { | 1591 void HInferRepresentation::Analyze() { |
1603 HPhase phase("Infer representations", graph_); | 1592 HPhase phase("Infer representations", graph_); |
1604 | 1593 |
1605 // (1) Initialize bit vectors and count real uses. Each phi | 1594 // (1) Initialize bit vectors and count real uses. Each phi gets a |
1606 // gets a bit-vector of length <number of phis>. | 1595 // bit-vector of length <number of phis>. |
1607 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); | 1596 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); |
1608 int num_phis = phi_list->length(); | 1597 int phi_count = phi_list->length(); |
1609 ScopedVector<BitVector*> connected_phis(num_phis); | 1598 ScopedVector<BitVector*> connected_phis(phi_count); |
1610 for (int i = 0; i < num_phis; i++) { | 1599 for (int i = 0; i < phi_count; ++i) { |
1611 phi_list->at(i)->InitRealUses(i); | 1600 phi_list->at(i)->InitRealUses(i); |
1612 connected_phis[i] = new(zone()) BitVector(num_phis); | 1601 connected_phis[i] = new(zone()) BitVector(phi_count); |
1613 connected_phis[i]->Add(i); | 1602 connected_phis[i]->Add(i); |
1614 } | 1603 } |
1615 | 1604 |
1616 // (2) Do a fixed point iteration to find the set of connected phis. | 1605 // (2) Do a fixed point iteration to find the set of connected phis. A |
1617 // A phi is connected to another phi if its value is used either | 1606 // phi is connected to another phi if its value is used either directly or |
1618 // directly or indirectly through a transitive closure of the def-use | 1607 // indirectly through a transitive closure of the def-use relation. |
1619 // relation. | |
1620 bool change = true; | 1608 bool change = true; |
1621 while (change) { | 1609 while (change) { |
1622 change = false; | 1610 change = false; |
1623 for (int i = 0; i < num_phis; i++) { | 1611 for (int i = 0; i < phi_count; ++i) { |
1624 HPhi* phi = phi_list->at(i); | 1612 HPhi* phi = phi_list->at(i); |
1625 for (int j = 0; j < phi->uses()->length(); j++) { | 1613 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
1626 HValue* use = phi->uses()->at(j); | 1614 HValue* use = it.value(); |
1627 if (use->IsPhi()) { | 1615 if (use->IsPhi()) { |
1628 int phi_use = HPhi::cast(use)->phi_id(); | 1616 int id = HPhi::cast(use)->phi_id(); |
1629 if (connected_phis[i]->UnionIsChanged(*connected_phis[phi_use])) { | 1617 change = change || |
1630 change = true; | 1618 connected_phis[i]->UnionIsChanged(*connected_phis[id]); |
1631 } | |
1632 } | 1619 } |
1633 } | 1620 } |
1634 } | 1621 } |
1635 } | 1622 } |
1636 | 1623 |
1637 // (3) Sum up the non-phi use counts of all connected phis. | 1624 // (3) Sum up the non-phi use counts of all connected phis. Don't include |
1638 // Don't include the non-phi uses of the phi itself. | 1625 // the non-phi uses of the phi itself. |
1639 for (int i = 0; i < num_phis; i++) { | 1626 for (int i = 0; i < phi_count; ++i) { |
1640 HPhi* phi = phi_list->at(i); | 1627 HPhi* phi = phi_list->at(i); |
1641 for (BitVector::Iterator it(connected_phis.at(i)); | 1628 for (BitVector::Iterator it(connected_phis.at(i)); |
1642 !it.Done(); | 1629 !it.Done(); |
1643 it.Advance()) { | 1630 it.Advance()) { |
1644 int index = it.Current(); | 1631 int index = it.Current(); |
1645 if (index != i) { | 1632 if (index != i) { |
1646 HPhi* it_use = phi_list->at(it.Current()); | 1633 HPhi* it_use = phi_list->at(it.Current()); |
1647 phi->AddNonPhiUsesFrom(it_use); | 1634 phi->AddNonPhiUsesFrom(it_use); |
1648 } | 1635 } |
1649 } | 1636 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 PropagateMinusZeroChecks(div->left(), visited); | 1726 PropagateMinusZeroChecks(div->left(), visited); |
1740 PropagateMinusZeroChecks(div->right(), visited); | 1727 PropagateMinusZeroChecks(div->right(), visited); |
1741 } | 1728 } |
1742 | 1729 |
1743 current = current->EnsureAndPropagateNotMinusZero(visited); | 1730 current = current->EnsureAndPropagateNotMinusZero(visited); |
1744 } | 1731 } |
1745 } | 1732 } |
1746 | 1733 |
1747 | 1734 |
1748 void HGraph::InsertRepresentationChangeForUse(HValue* value, | 1735 void HGraph::InsertRepresentationChangeForUse(HValue* value, |
1749 HValue* use, | 1736 HValue* use_value, |
| 1737 int use_index, |
1750 Representation to) { | 1738 Representation to) { |
1751 // Insert the representation change right before its use. For phi-uses we | 1739 // Insert the representation change right before its use. For phi-uses we |
1752 // insert at the end of the corresponding predecessor. | 1740 // insert at the end of the corresponding predecessor. |
1753 HInstruction* next = NULL; | 1741 HInstruction* next = NULL; |
1754 if (use->IsPhi()) { | 1742 if (use_value->IsPhi()) { |
1755 int index = 0; | 1743 next = use_value->block()->predecessors()->at(use_index)->end(); |
1756 while (use->OperandAt(index) != value) ++index; | |
1757 next = use->block()->predecessors()->at(index)->end(); | |
1758 } else { | 1744 } else { |
1759 next = HInstruction::cast(use); | 1745 next = HInstruction::cast(use_value); |
1760 } | 1746 } |
1761 | 1747 |
1762 // For constants we try to make the representation change at compile | 1748 // For constants we try to make the representation change at compile |
1763 // time. When a representation change is not possible without loss of | 1749 // time. When a representation change is not possible without loss of |
1764 // information we treat constants like normal instructions and insert the | 1750 // information we treat constants like normal instructions and insert the |
1765 // change instructions for them. | 1751 // change instructions for them. |
1766 HInstruction* new_value = NULL; | 1752 HInstruction* new_value = NULL; |
1767 bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32); | 1753 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); |
1768 if (value->IsConstant()) { | 1754 if (value->IsConstant()) { |
1769 HConstant* constant = HConstant::cast(value); | 1755 HConstant* constant = HConstant::cast(value); |
1770 // Try to create a new copy of the constant with the new representation. | 1756 // Try to create a new copy of the constant with the new representation. |
1771 new_value = is_truncating | 1757 new_value = is_truncating |
1772 ? constant->CopyToTruncatedInt32() | 1758 ? constant->CopyToTruncatedInt32() |
1773 : constant->CopyToRepresentation(to); | 1759 : constant->CopyToRepresentation(to); |
1774 } | 1760 } |
1775 | 1761 |
1776 if (new_value == NULL) { | 1762 if (new_value == NULL) { |
1777 new_value = | 1763 new_value = |
1778 new(zone()) HChange(value, value->representation(), to, is_truncating); | 1764 new(zone()) HChange(value, value->representation(), to, is_truncating); |
1779 } | 1765 } |
1780 | 1766 |
1781 new_value->InsertBefore(next); | 1767 new_value->InsertBefore(next); |
1782 value->ReplaceFirstAtUse(use, new_value, to); | 1768 use_value->SetOperandAt(use_index, new_value); |
1783 } | 1769 } |
1784 | 1770 |
1785 | 1771 |
1786 int CompareConversionUses(HValue* a, | 1772 void HGraph::InsertRepresentationChangesForValue(HValue* value) { |
1787 HValue* b, | 1773 Representation r = value->representation(); |
1788 Representation a_rep, | 1774 if (r.IsNone()) return; |
1789 Representation b_rep) { | 1775 if (value->HasNoUses()) return; |
1790 if (a_rep.kind() > b_rep.kind()) { | 1776 |
1791 // Make sure specializations are separated in the result array. | 1777 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { |
1792 return 1; | 1778 HValue* use_value = it.value(); |
| 1779 int use_index = it.index(); |
| 1780 Representation req = use_value->RequiredInputRepresentation(use_index); |
| 1781 if (req.IsNone() || req.Equals(r)) continue; |
| 1782 InsertRepresentationChangeForUse(value, use_value, use_index, req); |
1793 } | 1783 } |
1794 // Put truncating conversions before non-truncating conversions. | 1784 if (value->HasNoUses()) { |
1795 bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32); | 1785 ASSERT(value->IsConstant()); |
1796 bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32); | 1786 value->DeleteAndReplaceWith(NULL); |
1797 if (a_truncate != b_truncate) { | |
1798 return a_truncate ? -1 : 1; | |
1799 } | 1787 } |
1800 // Sort by increasing block ID. | |
1801 return a->block()->block_id() - b->block()->block_id(); | |
1802 } | 1788 } |
1803 | 1789 |
1804 | 1790 |
1805 void HGraph::InsertRepresentationChangesForValue( | |
1806 HValue* current, | |
1807 ZoneList<HValue*>* to_convert, | |
1808 ZoneList<Representation>* to_convert_reps) { | |
1809 Representation r = current->representation(); | |
1810 if (r.IsNone()) return; | |
1811 if (current->uses()->is_empty()) return; | |
1812 | |
1813 // Collect the representation changes in a sorted list. This allows | |
1814 // us to avoid duplicate changes without searching the list. | |
1815 ASSERT(to_convert->is_empty()); | |
1816 ASSERT(to_convert_reps->is_empty()); | |
1817 for (int i = 0; i < current->uses()->length(); ++i) { | |
1818 HValue* use = current->uses()->at(i); | |
1819 // 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 | |
1821 // also have to iterate over the different occurrence indices. | |
1822 int occurrence_index = 0; | |
1823 if (use->UsesMultipleTimes(current)) { | |
1824 occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); | |
1825 if (FLAG_trace_representation) { | |
1826 PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", | |
1827 current->id(), | |
1828 use->id(), | |
1829 occurrence_index); | |
1830 } | |
1831 } | |
1832 int operand_index = use->LookupOperandIndex(occurrence_index, current); | |
1833 Representation req = use->RequiredInputRepresentation(operand_index); | |
1834 if (req.IsNone() || req.Equals(r)) continue; | |
1835 int index = 0; | |
1836 while (index < to_convert->length() && | |
1837 CompareConversionUses(to_convert->at(index), | |
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); | |
1850 to_convert_reps->InsertAt(index, req); | |
1851 } | |
1852 | |
1853 for (int i = 0; i < to_convert->length(); ++i) { | |
1854 HValue* use = to_convert->at(i); | |
1855 Representation r_to = to_convert_reps->at(i); | |
1856 InsertRepresentationChangeForUse(current, use, r_to); | |
1857 } | |
1858 | |
1859 if (current->uses()->is_empty()) { | |
1860 ASSERT(current->IsConstant()); | |
1861 current->Delete(); | |
1862 } | |
1863 to_convert->Rewind(0); | |
1864 to_convert_reps->Rewind(0); | |
1865 } | |
1866 | |
1867 | |
1868 void HGraph::InsertRepresentationChanges() { | 1791 void HGraph::InsertRepresentationChanges() { |
1869 HPhase phase("Insert representation changes", this); | 1792 HPhase phase("Insert representation changes", this); |
1870 | 1793 |
1871 | 1794 |
1872 // Compute truncation flag for phis: Initially assume that all | 1795 // Compute truncation flag for phis: Initially assume that all |
1873 // int32-phis allow truncation and iteratively remove the ones that | 1796 // int32-phis allow truncation and iteratively remove the ones that |
1874 // are used in an operation that does not allow a truncating | 1797 // are used in an operation that does not allow a truncating |
1875 // conversion. | 1798 // conversion. |
1876 // TODO(fschneider): Replace this with a worklist-based iteration. | 1799 // TODO(fschneider): Replace this with a worklist-based iteration. |
1877 for (int i = 0; i < phi_list()->length(); i++) { | 1800 for (int i = 0; i < phi_list()->length(); i++) { |
1878 HPhi* phi = phi_list()->at(i); | 1801 HPhi* phi = phi_list()->at(i); |
1879 if (phi->representation().IsInteger32()) { | 1802 if (phi->representation().IsInteger32()) { |
1880 phi->SetFlag(HValue::kTruncatingToInt32); | 1803 phi->SetFlag(HValue::kTruncatingToInt32); |
1881 } | 1804 } |
1882 } | 1805 } |
1883 bool change = true; | 1806 bool change = true; |
1884 while (change) { | 1807 while (change) { |
1885 change = false; | 1808 change = false; |
1886 for (int i = 0; i < phi_list()->length(); i++) { | 1809 for (int i = 0; i < phi_list()->length(); i++) { |
1887 HPhi* phi = phi_list()->at(i); | 1810 HPhi* phi = phi_list()->at(i); |
1888 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; | 1811 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; |
1889 for (int j = 0; j < phi->uses()->length(); j++) { | 1812 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
1890 HValue* use = phi->uses()->at(j); | 1813 HValue* use = it.value(); |
1891 if (!use->CheckFlag(HValue::kTruncatingToInt32)) { | 1814 if (!use->CheckFlag(HValue::kTruncatingToInt32)) { |
1892 phi->ClearFlag(HValue::kTruncatingToInt32); | 1815 phi->ClearFlag(HValue::kTruncatingToInt32); |
1893 change = true; | 1816 change = true; |
1894 break; | 1817 break; |
1895 } | 1818 } |
1896 } | 1819 } |
1897 } | 1820 } |
1898 } | 1821 } |
1899 | 1822 |
1900 ZoneList<HValue*> value_list(4); | |
1901 ZoneList<Representation> rep_list(4); | |
1902 for (int i = 0; i < blocks_.length(); ++i) { | 1823 for (int i = 0; i < blocks_.length(); ++i) { |
1903 // Process phi instructions first. | 1824 // Process phi instructions first. |
1904 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { | 1825 const ZoneList<HPhi*>* phis = blocks_[i]->phis(); |
1905 HPhi* phi = blocks_[i]->phis()->at(j); | 1826 for (int j = 0; j < phis->length(); j++) { |
1906 InsertRepresentationChangesForValue(phi, &value_list, &rep_list); | 1827 InsertRepresentationChangesForValue(phis->at(j)); |
1907 } | 1828 } |
1908 | 1829 |
1909 // Process normal instructions. | 1830 // Process normal instructions. |
1910 HInstruction* current = blocks_[i]->first(); | 1831 HInstruction* current = blocks_[i]->first(); |
1911 while (current != NULL) { | 1832 while (current != NULL) { |
1912 InsertRepresentationChangesForValue(current, &value_list, &rep_list); | 1833 InsertRepresentationChangesForValue(current); |
1913 current = current->next(); | 1834 current = current->next(); |
1914 } | 1835 } |
1915 } | 1836 } |
1916 } | 1837 } |
1917 | 1838 |
1918 | 1839 |
1919 void HGraph::ComputeMinusZeroChecks() { | 1840 void HGraph::ComputeMinusZeroChecks() { |
1920 BitVector visited(GetMaximumValueID()); | 1841 BitVector visited(GetMaximumValueID()); |
1921 for (int i = 0; i < blocks_.length(); ++i) { | 1842 for (int i = 0; i < blocks_.length(); ++i) { |
1922 for (HInstruction* current = blocks_[i]->first(); | 1843 for (HInstruction* current = blocks_[i]->first(); |
(...skipping 4013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5936 phi->PrintTo(&trace_); | 5857 phi->PrintTo(&trace_); |
5937 trace_.Add("\n"); | 5858 trace_.Add("\n"); |
5938 } | 5859 } |
5939 } | 5860 } |
5940 | 5861 |
5941 { | 5862 { |
5942 Tag HIR_tag(this, "HIR"); | 5863 Tag HIR_tag(this, "HIR"); |
5943 HInstruction* instruction = current->first(); | 5864 HInstruction* instruction = current->first(); |
5944 while (instruction != NULL) { | 5865 while (instruction != NULL) { |
5945 int bci = 0; | 5866 int bci = 0; |
5946 int uses = instruction->uses()->length(); | 5867 int uses = instruction->UseCount(); |
5947 trace_.Add("%d %d ", bci, uses); | 5868 trace_.Add("%d %d ", bci, uses); |
5948 instruction->PrintNameTo(&trace_); | 5869 instruction->PrintNameTo(&trace_); |
5949 trace_.Add(" "); | 5870 trace_.Add(" "); |
5950 instruction->PrintTo(&trace_); | 5871 instruction->PrintTo(&trace_); |
5951 trace_.Add(" <|@\n"); | 5872 trace_.Add(" <|@\n"); |
5952 instruction = instruction->next(); | 5873 instruction = instruction->next(); |
5953 } | 5874 } |
5954 } | 5875 } |
5955 | 5876 |
5956 | 5877 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6150 } | 6071 } |
6151 } | 6072 } |
6152 | 6073 |
6153 #ifdef DEBUG | 6074 #ifdef DEBUG |
6154 if (graph_ != NULL) graph_->Verify(); | 6075 if (graph_ != NULL) graph_->Verify(); |
6155 if (allocator_ != NULL) allocator_->Verify(); | 6076 if (allocator_ != NULL) allocator_->Verify(); |
6156 #endif | 6077 #endif |
6157 } | 6078 } |
6158 | 6079 |
6159 } } // namespace v8::internal | 6080 } } // namespace v8::internal |
OLD | NEW |