OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1545 if (block->HasParentLoopHeader()) { | 1545 if (block->HasParentLoopHeader()) { |
1546 int header_id = block->parent_loop_header()->block_id(); | 1546 int header_id = block->parent_loop_header()->block_id(); |
1547 loop_side_effects_[header_id].Add(block->IsLoopHeader() | 1547 loop_side_effects_[header_id].Add(block->IsLoopHeader() |
1548 ? loop_side_effects_[id] | 1548 ? loop_side_effects_[id] |
1549 : side_effects); | 1549 : side_effects); |
1550 } | 1550 } |
1551 } | 1551 } |
1552 } | 1552 } |
1553 | 1553 |
1554 | 1554 |
1555 #if DEBUG | |
1556 SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) { | |
1557 char buffer[kLastFlag * 128]; | |
1558 const char* separator = ""; | |
1559 const char* comma = ", "; | |
1560 buffer[0] = 0; | |
1561 uint32_t set_depends_on = 0; | |
1562 uint32_t set_changes = 0; | |
1563 for (int bit = 0; bit < 31; ++bit) { | |
Michael Starzinger
2012/04/24 15:04:08
Better use "kAfterLastFlag" instead of "31" here.
| |
1564 if ((flags.ToIntegral() & (1 << bit)) != 0) { | |
1565 if (bit % 2 == 0) { | |
1566 set_changes++; | |
1567 } else { | |
1568 set_depends_on++; | |
1569 } | |
1570 } | |
1571 } | |
1572 bool positive_changes = set_changes < 8; | |
Michael Starzinger
2012/04/24 15:04:08
It would also be nice if "8" would somehow be base
| |
1573 bool positive_depends_on = set_depends_on < 8; | |
1574 if (set_changes > 0) { | |
1575 if (positive_changes) { | |
1576 strcat(buffer, "changes ["); | |
1577 } else { | |
1578 strcat(buffer, "changes all except ["); | |
1579 } | |
1580 for (int bit = 0; bit < 31; ++bit) { | |
Michael Starzinger
2012/04/24 15:04:08
Likewise.
| |
1581 if (((flags.ToIntegral() & (1 << bit)) != 0) == positive_changes) { | |
1582 switch (static_cast<GVNFlag>(bit)) { | |
1583 #define DECLARE_FLAG(type) \ | |
1584 case kChanges##type: \ | |
1585 strcat(buffer, separator); \ | |
1586 strcat(buffer, #type); \ | |
1587 separator = comma; \ | |
1588 break; | |
1589 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG) | |
1590 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) | |
1591 #undef DECLARE_FLAG | |
1592 default: | |
1593 break; | |
1594 } | |
1595 } | |
1596 } | |
1597 strcat(buffer, "]"); | |
1598 } | |
1599 if (set_depends_on > 0) { | |
1600 separator = ""; | |
1601 if (set_changes > 0) { | |
1602 strcat(buffer, ", "); | |
1603 } | |
1604 if (positive_depends_on) { | |
1605 strcat(buffer, "depends on ["); | |
1606 } else { | |
1607 strcat(buffer, "depends on all except ["); | |
1608 } | |
1609 for (int bit = 0; bit < 31; ++bit) { | |
Michael Starzinger
2012/04/24 15:04:08
Likewise.
| |
1610 if (((flags.ToIntegral() & (1 << bit)) != 0) == positive_depends_on) { | |
1611 switch (static_cast<GVNFlag>(bit)) { | |
1612 #define DECLARE_FLAG(type) \ | |
1613 case kDependsOn##type: \ | |
1614 strcat(buffer, separator); \ | |
1615 strcat(buffer, #type); \ | |
1616 separator = comma; \ | |
1617 break; | |
1618 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG) | |
1619 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) | |
1620 #undef DECLARE_FLAG | |
1621 default: | |
1622 break; | |
1623 } | |
1624 } | |
1625 } | |
1626 strcat(buffer, "]"); | |
1627 } | |
1628 char* result = new char[strlen(buffer) + 1]; | |
1629 strcpy(result, buffer); | |
1630 return SmartArrayPointer<char>(result); | |
1631 } | |
1632 #endif | |
1633 | |
1634 | |
1555 void HGlobalValueNumberer::LoopInvariantCodeMotion() { | 1635 void HGlobalValueNumberer::LoopInvariantCodeMotion() { |
1556 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1636 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
1557 HBasicBlock* block = graph_->blocks()->at(i); | 1637 HBasicBlock* block = graph_->blocks()->at(i); |
1558 if (block->IsLoopHeader()) { | 1638 if (block->IsLoopHeader()) { |
1559 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; | 1639 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; |
1560 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", | 1640 TraceGVN("Try loop invariant motion for block B%d %s\n", |
1561 block->block_id(), | 1641 block->block_id(), |
1562 side_effects.ToIntegral()); | 1642 *GetGVNFlagsString(side_effects)); |
1563 | 1643 |
1564 GVNFlagSet accumulated_first_time_depends; | 1644 GVNFlagSet accumulated_first_time_depends; |
1565 GVNFlagSet accumulated_first_time_changes; | 1645 GVNFlagSet accumulated_first_time_changes; |
1566 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); | 1646 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); |
1567 for (int j = block->block_id(); j <= last->block_id(); ++j) { | 1647 for (int j = block->block_id(); j <= last->block_id(); ++j) { |
1568 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects, | 1648 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects, |
1569 &accumulated_first_time_depends, | 1649 &accumulated_first_time_depends, |
1570 &accumulated_first_time_changes); | 1650 &accumulated_first_time_changes); |
1571 } | 1651 } |
1572 } | 1652 } |
1573 } | 1653 } |
1574 } | 1654 } |
1575 | 1655 |
1576 | 1656 |
1577 void HGlobalValueNumberer::ProcessLoopBlock( | 1657 void HGlobalValueNumberer::ProcessLoopBlock( |
1578 HBasicBlock* block, | 1658 HBasicBlock* block, |
1579 HBasicBlock* loop_header, | 1659 HBasicBlock* loop_header, |
1580 GVNFlagSet loop_kills, | 1660 GVNFlagSet loop_kills, |
1581 GVNFlagSet* first_time_depends, | 1661 GVNFlagSet* first_time_depends, |
1582 GVNFlagSet* first_time_changes) { | 1662 GVNFlagSet* first_time_changes) { |
1583 HBasicBlock* pre_header = loop_header->predecessors()->at(0); | 1663 HBasicBlock* pre_header = loop_header->predecessors()->at(0); |
1584 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); | 1664 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); |
1585 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", | 1665 TraceGVN("Loop invariant motion for B%d %s\n", |
1586 block->block_id(), | 1666 block->block_id(), |
1587 depends_flags.ToIntegral()); | 1667 *GetGVNFlagsString(depends_flags)); |
1588 HInstruction* instr = block->first(); | 1668 HInstruction* instr = block->first(); |
1589 while (instr != NULL) { | 1669 while (instr != NULL) { |
1590 HInstruction* next = instr->next(); | 1670 HInstruction* next = instr->next(); |
1591 bool hoisted = false; | 1671 bool hoisted = false; |
1592 if (instr->CheckFlag(HValue::kUseGVN)) { | 1672 if (instr->CheckFlag(HValue::kUseGVN)) { |
1593 TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, " | 1673 TraceGVN("Checking instruction %d (%s) %s. Loop %s\n", |
1594 "loop kills 0x%X\n", | |
1595 instr->id(), | 1674 instr->id(), |
1596 instr->Mnemonic(), | 1675 instr->Mnemonic(), |
1597 instr->gvn_flags().ToIntegral(), | 1676 *GetGVNFlagsString(instr->gvn_flags()), |
1598 depends_flags.ToIntegral()); | 1677 *GetGVNFlagsString(loop_kills)); |
1599 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); | 1678 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); |
1600 if (instr->IsTransitionElementsKind()) { | 1679 if (instr->IsTransitionElementsKind()) { |
1601 // It's possible to hoist transitions out of a loop as long as the | 1680 // It's possible to hoist transitions out of a loop as long as the |
1602 // hoisting wouldn't move the transition past a DependsOn of one of it's | 1681 // hoisting wouldn't move the transition past a DependsOn of one of it's |
1603 // changes or any instructions that might change an objects map or | 1682 // changes or any instructions that might change an objects map or |
1604 // elements contents. | 1683 // elements contents. |
1605 GVNFlagSet changes = instr->ChangesFlags(); | 1684 GVNFlagSet changes = instr->ChangesFlags(); |
1606 GVNFlagSet hoist_depends_blockers = | 1685 GVNFlagSet hoist_depends_blockers = |
1607 HValue::ConvertChangesToDependsFlags(changes); | 1686 HValue::ConvertChangesToDependsFlags(changes); |
1608 // In addition to not hoisting transitions above other instructions that | 1687 // In addition to not hoisting transitions above other instructions that |
1609 // change dependencies that the transition changes, it must not be | 1688 // change dependencies that the transition changes, it must not be |
1610 // hoisted above map changes and stores to an elements backing store | 1689 // hoisted above map changes and stores to an elements backing store |
1611 // that the transition might change. | 1690 // that the transition might change. |
1612 GVNFlagSet hoist_change_blockers = changes; | 1691 GVNFlagSet hoist_change_blockers = changes; |
1613 hoist_change_blockers.Add(kChangesMaps); | 1692 hoist_change_blockers.Add(kChangesMaps); |
1614 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); | 1693 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); |
1615 if (trans->original_map()->has_fast_double_elements()) { | 1694 if (trans->original_map()->has_fast_double_elements()) { |
1616 hoist_change_blockers.Add(kChangesDoubleArrayElements); | 1695 hoist_change_blockers.Add(kChangesDoubleArrayElements); |
1617 } | 1696 } |
1618 if (trans->transitioned_map()->has_fast_double_elements()) { | 1697 if (trans->transitioned_map()->has_fast_double_elements()) { |
1619 hoist_change_blockers.Add(kChangesArrayElements); | 1698 hoist_change_blockers.Add(kChangesArrayElements); |
1620 } | 1699 } |
1621 TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) " | 1700 TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) " |
1622 "hoist depends blockers 0x%X, hoist change blockers 0x%X, " | 1701 "hoist blockers: %s %s; " |
1623 "accumulated depends 0x%X, accumulated changes 0x%X\n", | 1702 "first-time accumulated: %s %s\n", |
1624 instr->id(), | 1703 instr->id(), |
1625 instr->Mnemonic(), | 1704 instr->Mnemonic(), |
1626 hoist_depends_blockers.ToIntegral(), | 1705 *GetGVNFlagsString(hoist_depends_blockers), |
1627 hoist_change_blockers.ToIntegral(), | 1706 *GetGVNFlagsString(hoist_change_blockers), |
1628 first_time_depends->ToIntegral(), | 1707 *GetGVNFlagsString(*first_time_depends), |
1629 first_time_changes->ToIntegral()); | 1708 *GetGVNFlagsString(*first_time_changes)); |
1630 // It's possible to hoist transition from the current loop loop only if | 1709 // It's possible to hoist transition from the current loop loop only if |
1631 // they dominate all of the successor blocks in the same loop and there | 1710 // they dominate all of the successor blocks in the same loop and there |
1632 // are not any instructions that have Changes/DependsOn that intervene | 1711 // are not any instructions that have Changes/DependsOn that intervene |
1633 // between it and the beginning of the loop header. | 1712 // between it and the beginning of the loop header. |
1634 bool in_nested_loop = block != loop_header && | 1713 bool in_nested_loop = block != loop_header && |
1635 ((block->parent_loop_header() != loop_header) || | 1714 ((block->parent_loop_header() != loop_header) || |
1636 block->IsLoopHeader()); | 1715 block->IsLoopHeader()); |
1637 can_hoist = !in_nested_loop && | 1716 can_hoist = !in_nested_loop && |
1638 block->IsLoopSuccessorDominator() && | 1717 block->IsLoopSuccessorDominator() && |
1639 !first_time_depends->ContainsAnyOf(hoist_depends_blockers) && | 1718 !first_time_depends->ContainsAnyOf(hoist_depends_blockers) && |
(...skipping 14 matching lines...) Expand all Loading... | |
1654 instr->Unlink(); | 1733 instr->Unlink(); |
1655 instr->InsertBefore(pre_header->end()); | 1734 instr->InsertBefore(pre_header->end()); |
1656 if (instr->HasSideEffects()) removed_side_effects_ = true; | 1735 if (instr->HasSideEffects()) removed_side_effects_ = true; |
1657 hoisted = true; | 1736 hoisted = true; |
1658 } | 1737 } |
1659 } | 1738 } |
1660 } | 1739 } |
1661 if (!hoisted) { | 1740 if (!hoisted) { |
1662 // If an instruction is not hoisted, we have to account for its side | 1741 // If an instruction is not hoisted, we have to account for its side |
1663 // effects when hoisting later HTransitionElementsKind instructions. | 1742 // effects when hoisting later HTransitionElementsKind instructions. |
1743 GVNFlagSet previous_depends = *first_time_depends; | |
1744 GVNFlagSet previous_changes = *first_time_changes; | |
1664 first_time_depends->Add(instr->DependsOnFlags()); | 1745 first_time_depends->Add(instr->DependsOnFlags()); |
1665 first_time_changes->Add(instr->ChangesFlags()); | 1746 first_time_changes->Add(instr->ChangesFlags()); |
1747 if (!(previous_depends == *first_time_depends)) { | |
1748 TraceGVN("Updated first-time accumulated %s\n", | |
1749 *GetGVNFlagsString(*first_time_depends)); | |
1750 } | |
1751 if (!(previous_changes == *first_time_changes)) { | |
1752 TraceGVN("Updated first-time accumulated %s\n", | |
1753 *GetGVNFlagsString(*first_time_changes)); | |
1754 } | |
1666 } | 1755 } |
1667 instr = next; | 1756 instr = next; |
1668 } | 1757 } |
1669 } | 1758 } |
1670 | 1759 |
1671 | 1760 |
1672 bool HGlobalValueNumberer::AllowCodeMotion() { | 1761 bool HGlobalValueNumberer::AllowCodeMotion() { |
1673 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; | 1762 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; |
1674 } | 1763 } |
1675 | 1764 |
(...skipping 6690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8366 } | 8455 } |
8367 } | 8456 } |
8368 | 8457 |
8369 #ifdef DEBUG | 8458 #ifdef DEBUG |
8370 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 8459 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
8371 if (allocator_ != NULL) allocator_->Verify(); | 8460 if (allocator_ != NULL) allocator_->Verify(); |
8372 #endif | 8461 #endif |
8373 } | 8462 } |
8374 | 8463 |
8375 } } // namespace v8::internal | 8464 } } // namespace v8::internal |
OLD | NEW |