Skip to content

Commit 85efc82

Browse files
committed
[FunctionAttrs] deduce attr cold on functions if all CG paths call a cold function
1 parent ffcbfa4 commit 85efc82

File tree

2 files changed

+429
-178
lines changed

2 files changed

+429
-178
lines changed

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ STATISTIC(NumNoUnwind, "Number of functions marked as nounwind");
8282
STATISTIC(NumNoFree, "Number of functions marked as nofree");
8383
STATISTIC(NumWillReturn, "Number of functions marked as willreturn");
8484
STATISTIC(NumNoSync, "Number of functions marked as nosync");
85+
STATISTIC(NumCold, "Number of functions marked as cold");
8586

8687
STATISTIC(NumThinLinkNoRecurse,
8788
"Number of functions marked as norecurse during thinlink");
@@ -1745,6 +1746,7 @@ static bool canReturn(Function &F) {
17451746
return false;
17461747
}
17471748

1749+
17481750
// Set the noreturn function attribute if possible.
17491751
static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
17501752
SmallSet<Function *, 8> &Changed) {
@@ -1760,6 +1762,65 @@ static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
17601762
}
17611763
}
17621764

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+
if (any_of(*BB, [](Instruction &I) {
1770+
if (auto *CB = dyn_cast<CallBase>(&I))
1771+
return CB->hasFnAttr(Attribute::Cold);
1772+
return false;
1773+
})) {
1774+
Visited[BB] = true;
1775+
return true;
1776+
}
1777+
1778+
auto Succs = successors(BB);
1779+
// We found a path that doesn't go through any cold callsite.
1780+
if (Succs.empty())
1781+
return false;
1782+
1783+
for (auto *Succ : Succs) {
1784+
// Start with false, this is necessary to ensure we don't turn loops into
1785+
// cold.
1786+
auto R = Visited.try_emplace(Succ, false);
1787+
if (!R.second) {
1788+
if (R.first->second)
1789+
continue;
1790+
return false;
1791+
}
1792+
if (!allBBPathsGoThroughCold(Succ, Visited))
1793+
return false;
1794+
Visited[Succ] = true;
1795+
}
1796+
1797+
return true;
1798+
}
1799+
1800+
static bool allPathsGoThroughCold(Function &F) {
1801+
SmallDenseMap<BasicBlock *, bool, 16> Visited;
1802+
Visited[&F.front()] = false;
1803+
return allBBPathsGoThroughCold(&F.front(), Visited);
1804+
}
1805+
1806+
// Set the cold function attribute if possible.
1807+
static void addColdAttrs(const SCCNodeSet &SCCNodes,
1808+
SmallSet<Function *, 8> &Changed) {
1809+
for (Function *F : SCCNodes) {
1810+
if (!F || !F->hasExactDefinition() || F->hasFnAttribute(Attribute::Naked) ||
1811+
F->hasFnAttribute(Attribute::Cold) || F->hasFnAttribute(Attribute::Hot))
1812+
continue;
1813+
1814+
// Potential TODO: We could add attribute `cold` on functions with `coldcc`.
1815+
if (allPathsGoThroughCold(*F)) {
1816+
F->addFnAttr(Attribute::Cold);
1817+
++NumCold;
1818+
Changed.insert(F);
1819+
continue;
1820+
}
1821+
}
1822+
}
1823+
17631824
static bool functionWillReturn(const Function &F) {
17641825
// We can infer and propagate function attributes only when we know that the
17651826
// definition we'll get at link time is *exactly* the definition we see now.
@@ -1789,6 +1850,7 @@ static bool functionWillReturn(const Function &F) {
17891850
});
17901851
}
17911852

1853+
17921854
// Set the willreturn function attribute if possible.
17931855
static void addWillReturn(const SCCNodeSet &SCCNodes,
17941856
SmallSet<Function *, 8> &Changed) {
@@ -1802,6 +1864,8 @@ static void addWillReturn(const SCCNodeSet &SCCNodes,
18021864
}
18031865
}
18041866

1867+
1868+
18051869
static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
18061870
SCCNodesResult Res;
18071871
Res.HasUnknownCall = false;
@@ -1853,6 +1917,7 @@ deriveAttrsInPostOrder(ArrayRef<Function *> Functions, AARGetterT &&AARGetter,
18531917
addArgumentAttrs(Nodes.SCCNodes, Changed);
18541918
inferConvergent(Nodes.SCCNodes, Changed);
18551919
addNoReturnAttrs(Nodes.SCCNodes, Changed);
1920+
addColdAttrs(Nodes.SCCNodes, Changed);
18561921
addWillReturn(Nodes.SCCNodes, Changed);
18571922
addNoUndefAttrs(Nodes.SCCNodes, Changed);
18581923

0 commit comments

Comments
 (0)