diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -321,7 +321,8 @@ /// This method will evaluate \p Pred on call sites and return /// true if \p Pred holds in every call sites. However, this is only possible /// all call sites are known, hence the function has internal linkage. - bool checkForAllCallSites(Function &F, std::function &Pred, + bool checkForAllCallSites(Function &F, + const function_ref &Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites); diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -1043,7 +1043,7 @@ unsigned ArgNo = getArgNo(); // Callback function - std::function CallSiteCheck = [&](CallSite CS) { + auto CallSiteCheck = [&](CallSite CS) { assert(CS && "Sanity check: Call site was not initialized properly!"); auto *NonNullAA = @@ -1245,6 +1245,11 @@ void initialize(Attributor &A) override { const Function &F = getAnchorScope(); + if (F.hasInternalLinkage()) { + LLVM_DEBUG(dbgs() << "[INIT] skipped internal function\n"); + return; + } + ToBeExploredPaths.insert(&(F.getEntryBlock().front())); AssumedLiveBlocks.insert(&(F.getEntryBlock())); for (size_t i = 0; i < ToBeExploredPaths.size(); ++i) @@ -1467,10 +1472,32 @@ } ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) { + Function &F = getAnchorScope(); + ChangeStatus Status = ChangeStatus::UNCHANGED; + + if (F.hasInternalLinkage()) { + auto CallSiteCheck = [&](CallSite) { return false; }; + + // All callsites of F are dead. + if (A.checkForAllCallSites(F, CallSiteCheck, *this, true)){ + LLVM_DEBUG(dbgs() << "[UPDATEIMPL] All call sites are dead\n"); + return ChangeStatus::UNCHANGED; + } + + // There exists at least one live call site, so we explore the function. + + Status = ChangeStatus::CHANGED; + ToBeExploredPaths.insert(&(F.getEntryBlock().front())); + AssumedLiveBlocks.insert(&(F.getEntryBlock())); + for (size_t i = 0; i < ToBeExploredPaths.size(); ++i) + if (const Instruction *NextNoReturnI = + findNextNoReturn(A, ToBeExploredPaths[i])) + NoReturnCalls.insert(NextNoReturnI); + } + // Temporary collection to iterate over existing noreturn instructions. This // will alow easier modification of NoReturnCalls collection SmallVector NoReturnChanged; - ChangeStatus Status = ChangeStatus::UNCHANGED; for (const Instruction *I : NoReturnCalls) NoReturnChanged.push_back(I); @@ -1774,7 +1801,7 @@ bool IsGlobal = isAssumedGlobal(); // Callback function - std::function CallSiteCheck = [&](CallSite CS) -> bool { + auto CallSiteCheck = [&](CallSite CS) { assert(CS && "Sanity check: Call site was not initialized properly!"); // Check that DereferenceableAA is AADereferenceableCallSiteArgument. @@ -1950,7 +1977,7 @@ auto BeforeState = getAssumed(); // Callback function - std::function CallSiteCheck = [&](CallSite CS) { + auto CallSiteCheck = [&](CallSite CS) { assert(CS && "Sanity check: Call site was not initialized properly!"); auto *AlignAA = A.getAAFor(*this, *CS.getInstruction(), ArgNo); @@ -2056,7 +2083,7 @@ /// ---------------------------------------------------------------------------- bool Attributor::checkForAllCallSites(Function &F, - std::function &Pred, + const function_ref &Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites) { // We can try to determine information from