Skip to content

Commit e7e6ddc

Browse files
committed
Fix stack overflow in allPathsGoThroughCold
1 parent d6ad551 commit e7e6ddc

File tree

1 file changed

+41
-41
lines changed

1 file changed

+41
-41
lines changed

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include <iterator>
6363
#include <map>
6464
#include <optional>
65+
#include <stack>
6566
#include <vector>
6667

6768
using namespace llvm;
@@ -1762,54 +1763,53 @@ static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
17621763
}
17631764
}
17641765

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+
}
17841787

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())
17971791
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);
17981808
}
1799-
if (!allBBPathsGoThroughCold(Succ, Visited))
1800-
return false;
1801-
Visited[Succ] = true;
18021809
}
1803-
18041810
return true;
18051811
}
18061812

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-
18131813
// Set the cold function attribute if possible.
18141814
static void addColdAttrs(const SCCNodeSet &SCCNodes,
18151815
SmallSet<Function *, 8> &Changed) {

0 commit comments

Comments
 (0)