| 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 |