|
62 | 62 | #include <iterator>
|
63 | 63 | #include <map>
|
64 | 64 | #include <optional>
|
| 65 | +#include <stack> |
65 | 66 | #include <vector>
|
66 | 67 |
|
67 | 68 | using namespace llvm;
|
@@ -1762,54 +1763,53 @@ static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
|
1762 | 1763 | }
|
1763 | 1764 | }
|
1764 | 1765 |
|
1765 |
| -static bool |
1766 |
| -allBBPathsGoThroughCold(BasicBlock *BB, |
1767 |
| - SmallDenseMap<BasicBlock *, bool, 16> &Visited) { |
1768 |
| - // If BB contains a cold callsite this path through the CG is cold. |
1769 |
| - // Ignore whether the instructions actually are guranteed to transfer |
1770 |
| - // execution. Divergent behavior is considered unlikely. |
1771 |
| - if (any_of(*BB, [](Instruction &I) { |
1772 |
| - if (auto *CB = dyn_cast<CallBase>(&I)) |
1773 |
| - return CB->hasFnAttr(Attribute::Cold); |
1774 |
| - return false; |
1775 |
| - })) { |
1776 |
| - Visited[BB] = true; |
1777 |
| - return true; |
1778 |
| - } |
1779 |
| - |
1780 |
| - auto Succs = successors(BB); |
1781 |
| - // We found a path that doesn't go through any cold callsite. |
1782 |
| - if (Succs.empty()) |
1783 |
| - return false; |
| 1766 | +static bool allPathsGoThroughCold(Function &F) { |
| 1767 | + SmallDenseMap<BasicBlock *, bool, 16> ColdPaths; |
| 1768 | + ColdPaths[&F.front()] = false; |
| 1769 | + std::stack<BasicBlock *> Jobs; |
| 1770 | + Jobs.push(&F.front()); |
| 1771 | + |
| 1772 | + while (!Jobs.empty()) { |
| 1773 | + BasicBlock *BB = Jobs.top(); |
| 1774 | + Jobs.pop(); |
| 1775 | + |
| 1776 | + // If block contains a cold callsite this path through the CG is cold. |
| 1777 | + // Ignore whether the instructions actually are guaranteed to transfer |
| 1778 | + // execution. Divergent behavior is considered unlikely. |
| 1779 | + if (any_of(*BB, [](Instruction &I) { |
| 1780 | + if (auto *CB = dyn_cast<CallBase>(&I)) |
| 1781 | + return CB->hasFnAttr(Attribute::Cold); |
| 1782 | + return false; |
| 1783 | + })) { |
| 1784 | + ColdPaths[BB] = true; |
| 1785 | + continue; |
| 1786 | + } |
1784 | 1787 |
|
1785 |
| - // We didn't find a cold callsite in this BB, so check that all successors |
1786 |
| - // contain a cold callsite (or that their successors do). |
1787 |
| - // Potential TODO: We could use static branch hints to assume certain |
1788 |
| - // successor paths are inherently cold, irrespective of if they contain a cold |
1789 |
| - // callsite. |
1790 |
| - for (auto *Succ : Succs) { |
1791 |
| - // Start with false, this is necessary to ensure we don't turn loops into |
1792 |
| - // cold. |
1793 |
| - auto R = Visited.try_emplace(Succ, false); |
1794 |
| - if (!R.second) { |
1795 |
| - if (R.first->second) |
1796 |
| - continue; |
| 1788 | + auto Succs = successors(BB); |
| 1789 | + // We found a path that doesn't go through any cold callsite. |
| 1790 | + if (Succs.empty()) |
1797 | 1791 | return false;
|
| 1792 | + |
| 1793 | + // We didn't find a cold callsite in this BB, so check that all successors |
| 1794 | + // contain a cold callsite (or that their successors do). |
| 1795 | + // Potential TODO: We could use static branch hints to assume certain |
| 1796 | + // successor paths are inherently cold, irrespective of if they contain a |
| 1797 | + // cold callsite. |
| 1798 | + for (llvm::BasicBlock *Succ : Succs) { |
| 1799 | + // Start with false, this is necessary to ensure we don't turn loops into |
| 1800 | + // cold. |
| 1801 | + auto [iter, inserted] = ColdPaths.try_emplace(Succ, false); |
| 1802 | + if (!inserted) { |
| 1803 | + if (iter->second) |
| 1804 | + continue; |
| 1805 | + return false; |
| 1806 | + } |
| 1807 | + Jobs.push(Succ); |
1798 | 1808 | }
|
1799 |
| - if (!allBBPathsGoThroughCold(Succ, Visited)) |
1800 |
| - return false; |
1801 |
| - Visited[Succ] = true; |
1802 | 1809 | }
|
1803 |
| - |
1804 | 1810 | return true;
|
1805 | 1811 | }
|
1806 | 1812 |
|
1807 |
| -static bool allPathsGoThroughCold(Function &F) { |
1808 |
| - SmallDenseMap<BasicBlock *, bool, 16> Visited; |
1809 |
| - Visited[&F.front()] = false; |
1810 |
| - return allBBPathsGoThroughCold(&F.front(), Visited); |
1811 |
| -} |
1812 |
| - |
1813 | 1813 | // Set the cold function attribute if possible.
|
1814 | 1814 | static void addColdAttrs(const SCCNodeSet &SCCNodes,
|
1815 | 1815 | SmallSet<Function *, 8> &Changed) {
|
|
0 commit comments