diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 0317a8bcb6bc7cd9d8f3804afd274cacc8ba551c..13de7fa81a8a3ea1d8afd3f0a69c7d64e5ea73ab 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1732,13 +1732,16 @@ static void RemoveAttribute(Function *F, Attribute::AttrKind A) { /// idea here is that we don't want to mess with the convention if the user /// explicitly requested something with performance implications like coldcc, /// GHC, or anyregcc. -static bool hasChangeableCC(Function *F) { +static bool hasChangeableCCImpl(Function *F) { CallingConv::ID CC = F->getCallingConv(); // FIXME: Is it worth transforming x86_stdcallcc and x86_fastcallcc? if (CC != CallingConv::C && CC != CallingConv::X86_ThisCall) return false; + if (F->isVarArg()) + return false; + // FIXME: Change CC for the whole chain of musttail calls when possible. // // Can't change CC of the function that either has musttail calls, or is a @@ -1758,7 +1761,16 @@ static bool hasChangeableCC(Function *F) { if (BB.getTerminatingMustTailCall()) return false; - return true; + return !F->hasAddressTaken(); +} + +using ChangeableCCCacheTy = SmallDenseMap; +static bool hasChangeableCC(Function *F, + ChangeableCCCacheTy &ChangeableCCCache) { + auto Res = ChangeableCCCache.try_emplace(F, false); + if (Res.second) + Res.first->second = hasChangeableCCImpl(F); + return Res.first->second; } /// Return true if the block containing the call site has a BlockFrequency of @@ -1812,7 +1824,8 @@ static void changeCallSitesToColdCC(Function *F) { // coldcc calling convention. static bool hasOnlyColdCalls(Function &F, - function_ref GetBFI) { + function_ref GetBFI, + ChangeableCCCacheTy &ChangeableCCCache) { for (BasicBlock &BB : F) { for (Instruction &I : BB) { if (CallInst *CI = dyn_cast(&I)) { @@ -1831,8 +1844,7 @@ hasOnlyColdCalls(Function &F, if (!CalledFn->hasLocalLinkage()) return false; // Check if it's valid to use coldcc calling convention. - if (!hasChangeableCC(CalledFn) || CalledFn->isVarArg() || - CalledFn->hasAddressTaken()) + if (!hasChangeableCC(CalledFn, ChangeableCCCache)) return false; BlockFrequencyInfo &CallerBFI = GetBFI(F); if (!isColdCallSite(*CI, CallerBFI)) @@ -1962,9 +1974,10 @@ OptimizeFunctions(Module &M, bool Changed = false; + ChangeableCCCacheTy ChangeableCCCache; std::vector AllCallsCold; for (Function &F : llvm::make_early_inc_range(M)) - if (hasOnlyColdCalls(F, GetBFI)) + if (hasOnlyColdCalls(F, GetBFI, ChangeableCCCache)) AllCallsCold.push_back(&F); // Optimize functions. @@ -2026,7 +2039,7 @@ OptimizeFunctions(Module &M, continue; } - if (hasChangeableCC(&F) && !F.isVarArg() && !F.hasAddressTaken()) { + if (hasChangeableCC(&F, ChangeableCCCache)) { NumInternalFunc++; TargetTransformInfo &TTI = GetTTI(F); // Change the calling convention to coldcc if either stress testing is @@ -2036,6 +2049,7 @@ OptimizeFunctions(Module &M, if (EnableColdCCStressTest || (TTI.useColdCCForColdCall(F) && isValidCandidateForColdCC(F, GetBFI, AllCallsCold))) { + ChangeableCCCache.erase(&F); F.setCallingConv(CallingConv::Cold); changeCallSitesToColdCC(&F); Changed = true; @@ -2043,7 +2057,7 @@ OptimizeFunctions(Module &M, } } - if (hasChangeableCC(&F) && !F.isVarArg() && !F.hasAddressTaken()) { + if (hasChangeableCC(&F, ChangeableCCCache)) { // If this function has a calling convention worth changing, is not a // varargs function, and is only called directly, promote it to use the // Fast calling convention.