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,8 +1245,16 @@ void initialize(Attributor &A) override { const Function &F = getAnchorScope(); + if (F.hasInternalLinkage()) + return; + + exploreFromEntry(A, F); + } + + void exploreFromEntry(Attributor &A, const Function &F) { 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])) @@ -1467,10 +1475,25 @@ } 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)) + return ChangeStatus::UNCHANGED; + + // There exists at least one live call site, so we explore the function. + Status = ChangeStatus::CHANGED; + + exploreFromEntry(A, F); + } + // 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 +1797,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 +1973,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 +2079,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 diff --git a/llvm/test/Transforms/FunctionAttrs/align.ll b/llvm/test/Transforms/FunctionAttrs/align.ll --- a/llvm/test/Transforms/FunctionAttrs/align.ll +++ b/llvm/test/Transforms/FunctionAttrs/align.ll @@ -83,12 +83,12 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { -; ATTRIBUTOR: define internal nonnull align 8 i8* @f1(i8* nonnull readnone align 8 %0) +; ATTRIBUTOR: define internal i8* @f1(i8* readnone %0) %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 ;