Skip to content

Commit 12c6ee8

Browse files
nikictru
authored andcommitted
[GlobalOpt] Cache whether CC is changeable (#71381)
The hasAddressTaken() call in hasOnlyColdCalls() has quadratic complexity if there are many cold calls to a function: We're going to visit each call of the function, and then for each of them iterate all the users of the function. We've recently encountered a case where GlobalOpt spends more than an hour in these hasAddressTaken() checks when full LTO is used. Avoid this by moving the hasAddressTaken() check into hasChangeableCC() and caching its result, so it is only computed once per function. (cherry picked from commit e360a16)
1 parent 0a12742 commit 12c6ee8

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

llvm/lib/Transforms/IPO/GlobalOpt.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,13 +1701,16 @@ static void RemoveAttribute(Function *F, Attribute::AttrKind A) {
17011701
/// idea here is that we don't want to mess with the convention if the user
17021702
/// explicitly requested something with performance implications like coldcc,
17031703
/// GHC, or anyregcc.
1704-
static bool hasChangeableCC(Function *F) {
1704+
static bool hasChangeableCCImpl(Function *F) {
17051705
CallingConv::ID CC = F->getCallingConv();
17061706

17071707
// FIXME: Is it worth transforming x86_stdcallcc and x86_fastcallcc?
17081708
if (CC != CallingConv::C && CC != CallingConv::X86_ThisCall)
17091709
return false;
17101710

1711+
if (F->isVarArg())
1712+
return false;
1713+
17111714
// FIXME: Change CC for the whole chain of musttail calls when possible.
17121715
//
17131716
// Can't change CC of the function that either has musttail calls, or is a
@@ -1727,7 +1730,16 @@ static bool hasChangeableCC(Function *F) {
17271730
if (BB.getTerminatingMustTailCall())
17281731
return false;
17291732

1730-
return true;
1733+
return !F->hasAddressTaken();
1734+
}
1735+
1736+
using ChangeableCCCacheTy = SmallDenseMap<Function *, bool, 8>;
1737+
static bool hasChangeableCC(Function *F,
1738+
ChangeableCCCacheTy &ChangeableCCCache) {
1739+
auto Res = ChangeableCCCache.try_emplace(F, false);
1740+
if (Res.second)
1741+
Res.first->second = hasChangeableCCImpl(F);
1742+
return Res.first->second;
17311743
}
17321744

17331745
/// Return true if the block containing the call site has a BlockFrequency of
@@ -1781,7 +1793,8 @@ static void changeCallSitesToColdCC(Function *F) {
17811793
// coldcc calling convention.
17821794
static bool
17831795
hasOnlyColdCalls(Function &F,
1784-
function_ref<BlockFrequencyInfo &(Function &)> GetBFI) {
1796+
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
1797+
ChangeableCCCacheTy &ChangeableCCCache) {
17851798
for (BasicBlock &BB : F) {
17861799
for (Instruction &I : BB) {
17871800
if (CallInst *CI = dyn_cast<CallInst>(&I)) {
@@ -1800,8 +1813,7 @@ hasOnlyColdCalls(Function &F,
18001813
if (!CalledFn->hasLocalLinkage())
18011814
return false;
18021815
// Check if it's valid to use coldcc calling convention.
1803-
if (!hasChangeableCC(CalledFn) || CalledFn->isVarArg() ||
1804-
CalledFn->hasAddressTaken())
1816+
if (!hasChangeableCC(CalledFn, ChangeableCCCache))
18051817
return false;
18061818
BlockFrequencyInfo &CallerBFI = GetBFI(F);
18071819
if (!isColdCallSite(*CI, CallerBFI))
@@ -1931,9 +1943,10 @@ OptimizeFunctions(Module &M,
19311943

19321944
bool Changed = false;
19331945

1946+
ChangeableCCCacheTy ChangeableCCCache;
19341947
std::vector<Function *> AllCallsCold;
19351948
for (Function &F : llvm::make_early_inc_range(M))
1936-
if (hasOnlyColdCalls(F, GetBFI))
1949+
if (hasOnlyColdCalls(F, GetBFI, ChangeableCCCache))
19371950
AllCallsCold.push_back(&F);
19381951

19391952
// Optimize functions.
@@ -1995,7 +2008,7 @@ OptimizeFunctions(Module &M,
19952008
continue;
19962009
}
19972010

1998-
if (hasChangeableCC(&F) && !F.isVarArg() && !F.hasAddressTaken()) {
2011+
if (hasChangeableCC(&F, ChangeableCCCache)) {
19992012
NumInternalFunc++;
20002013
TargetTransformInfo &TTI = GetTTI(F);
20012014
// Change the calling convention to coldcc if either stress testing is
@@ -2005,14 +2018,15 @@ OptimizeFunctions(Module &M,
20052018
if (EnableColdCCStressTest ||
20062019
(TTI.useColdCCForColdCall(F) &&
20072020
isValidCandidateForColdCC(F, GetBFI, AllCallsCold))) {
2021+
ChangeableCCCache.erase(&F);
20082022
F.setCallingConv(CallingConv::Cold);
20092023
changeCallSitesToColdCC(&F);
20102024
Changed = true;
20112025
NumColdCC++;
20122026
}
20132027
}
20142028

2015-
if (hasChangeableCC(&F) && !F.isVarArg() && !F.hasAddressTaken()) {
2029+
if (hasChangeableCC(&F, ChangeableCCCache)) {
20162030
// If this function has a calling convention worth changing, is not a
20172031
// varargs function, and is only called directly, promote it to use the
20182032
// Fast calling convention.

0 commit comments

Comments
 (0)