xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- FunctionAttrs.cpp - Pass which marks functions attributes ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements interprocedural passes which walk the
110b57cec5SDimitry Andric /// call-graph deducing and/or propagating function attributes.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/Transforms/IPO/FunctionAttrs.h"
16e8d8bef9SDimitry Andric #include "llvm/ADT/ArrayRef.h"
17349cc55cSDimitry Andric #include "llvm/ADT/DenseMap.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SCCIterator.h"
190b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
210b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
22349cc55cSDimitry Andric #include "llvm/ADT/SmallSet.h"
230b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
240b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
250b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
260b57cec5SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h"
27e8d8bef9SDimitry Andric #include "llvm/Analysis/CFG.h"
280b57cec5SDimitry Andric #include "llvm/Analysis/CGSCCPassManager.h"
290b57cec5SDimitry Andric #include "llvm/Analysis/CallGraph.h"
300b57cec5SDimitry Andric #include "llvm/Analysis/CallGraphSCCPass.h"
310b57cec5SDimitry Andric #include "llvm/Analysis/CaptureTracking.h"
320b57cec5SDimitry Andric #include "llvm/Analysis/LazyCallGraph.h"
330b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h"
340b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
350b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
360b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
370b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
380b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
390b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
400b57cec5SDimitry Andric #include "llvm/IR/Function.h"
410b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h"
420b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
430b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
440b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
450b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
460b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
4781ad6265SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h"
480b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
490b57cec5SDimitry Andric #include "llvm/IR/Type.h"
500b57cec5SDimitry Andric #include "llvm/IR/Use.h"
510b57cec5SDimitry Andric #include "llvm/IR/User.h"
520b57cec5SDimitry Andric #include "llvm/IR/Value.h"
530b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
540b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
550b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
560b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
570b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
580b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
590b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h"
60fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
610b57cec5SDimitry Andric #include <cassert>
620b57cec5SDimitry Andric #include <iterator>
630b57cec5SDimitry Andric #include <map>
64bdd1243dSDimitry Andric #include <optional>
650b57cec5SDimitry Andric #include <vector>
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric using namespace llvm;
680b57cec5SDimitry Andric 
69e8d8bef9SDimitry Andric #define DEBUG_TYPE "function-attrs"
700b57cec5SDimitry Andric 
71bdd1243dSDimitry Andric STATISTIC(NumMemoryAttr, "Number of functions with improved memory attribute");
720b57cec5SDimitry Andric STATISTIC(NumNoCapture, "Number of arguments marked nocapture");
730b57cec5SDimitry Andric STATISTIC(NumReturned, "Number of arguments marked returned");
740b57cec5SDimitry Andric STATISTIC(NumReadNoneArg, "Number of arguments marked readnone");
750b57cec5SDimitry Andric STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly");
760eae32dcSDimitry Andric STATISTIC(NumWriteOnlyArg, "Number of arguments marked writeonly");
770b57cec5SDimitry Andric STATISTIC(NumNoAlias, "Number of function returns marked noalias");
780b57cec5SDimitry Andric STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
79647cbc5dSDimitry Andric STATISTIC(NumNoUndefReturn, "Number of function returns marked noundef");
800b57cec5SDimitry Andric STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
810b57cec5SDimitry Andric STATISTIC(NumNoUnwind, "Number of functions marked as nounwind");
820b57cec5SDimitry Andric STATISTIC(NumNoFree, "Number of functions marked as nofree");
83e8d8bef9SDimitry Andric STATISTIC(NumWillReturn, "Number of functions marked as willreturn");
84fe6060f1SDimitry Andric STATISTIC(NumNoSync, "Number of functions marked as nosync");
850b57cec5SDimitry Andric 
86349cc55cSDimitry Andric STATISTIC(NumThinLinkNoRecurse,
87349cc55cSDimitry Andric           "Number of functions marked as norecurse during thinlink");
88349cc55cSDimitry Andric STATISTIC(NumThinLinkNoUnwind,
89349cc55cSDimitry Andric           "Number of functions marked as nounwind during thinlink");
90349cc55cSDimitry Andric 
910b57cec5SDimitry Andric static cl::opt<bool> EnableNonnullArgPropagation(
928bcb0991SDimitry Andric     "enable-nonnull-arg-prop", cl::init(true), cl::Hidden,
930b57cec5SDimitry Andric     cl::desc("Try to propagate nonnull argument attributes from callsites to "
940b57cec5SDimitry Andric              "caller functions."));
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric static cl::opt<bool> DisableNoUnwindInference(
970b57cec5SDimitry Andric     "disable-nounwind-inference", cl::Hidden,
980b57cec5SDimitry Andric     cl::desc("Stop inferring nounwind attribute during function-attrs pass"));
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric static cl::opt<bool> DisableNoFreeInference(
1010b57cec5SDimitry Andric     "disable-nofree-inference", cl::Hidden,
1020b57cec5SDimitry Andric     cl::desc("Stop inferring nofree attribute during function-attrs pass"));
1030b57cec5SDimitry Andric 
104349cc55cSDimitry Andric static cl::opt<bool> DisableThinLTOPropagation(
105349cc55cSDimitry Andric     "disable-thinlto-funcattrs", cl::init(true), cl::Hidden,
106349cc55cSDimitry Andric     cl::desc("Don't propagate function-attrs in thinLTO"));
107349cc55cSDimitry Andric 
1080b57cec5SDimitry Andric namespace {
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric using SCCNodeSet = SmallSetVector<Function *, 8>;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric } // end anonymous namespace
1130b57cec5SDimitry Andric 
1145f757f3fSDimitry Andric static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc,
1155f757f3fSDimitry Andric                          ModRefInfo MR, AAResults &AAR) {
116bdd1243dSDimitry Andric   // Ignore accesses to known-invariant or local memory.
117bdd1243dSDimitry Andric   MR &= AAR.getModRefInfoMask(Loc, /*IgnoreLocal=*/true);
118bdd1243dSDimitry Andric   if (isNoModRef(MR))
119bdd1243dSDimitry Andric     return;
120bdd1243dSDimitry Andric 
121bdd1243dSDimitry Andric   const Value *UO = getUnderlyingObject(Loc.Ptr);
122bdd1243dSDimitry Andric   assert(!isa<AllocaInst>(UO) &&
123bdd1243dSDimitry Andric          "Should have been handled by getModRefInfoMask()");
124bdd1243dSDimitry Andric   if (isa<Argument>(UO)) {
125bdd1243dSDimitry Andric     ME |= MemoryEffects::argMemOnly(MR);
126bdd1243dSDimitry Andric     return;
127bdd1243dSDimitry Andric   }
128bdd1243dSDimitry Andric 
129bdd1243dSDimitry Andric   // If it's not an identified object, it might be an argument.
130bdd1243dSDimitry Andric   if (!isIdentifiedObject(UO))
131bdd1243dSDimitry Andric     ME |= MemoryEffects::argMemOnly(MR);
13206c3fb27SDimitry Andric   ME |= MemoryEffects(IRMemLocation::Other, MR);
1335f757f3fSDimitry Andric }
1345f757f3fSDimitry Andric 
1355f757f3fSDimitry Andric static void addArgLocs(MemoryEffects &ME, const CallBase *Call,
1365f757f3fSDimitry Andric                        ModRefInfo ArgMR, AAResults &AAR) {
1375f757f3fSDimitry Andric   for (const Value *Arg : Call->args()) {
1385f757f3fSDimitry Andric     if (!Arg->getType()->isPtrOrPtrVectorTy())
1395f757f3fSDimitry Andric       continue;
1405f757f3fSDimitry Andric 
1415f757f3fSDimitry Andric     addLocAccess(ME,
1425f757f3fSDimitry Andric                  MemoryLocation::getBeforeOrAfter(Arg, Call->getAAMetadata()),
1435f757f3fSDimitry Andric                  ArgMR, AAR);
1445f757f3fSDimitry Andric   }
1455f757f3fSDimitry Andric }
1465f757f3fSDimitry Andric 
1475f757f3fSDimitry Andric /// Returns the memory access attribute for function F using AAR for AA results,
1485f757f3fSDimitry Andric /// where SCCNodes is the current SCC.
1495f757f3fSDimitry Andric ///
1505f757f3fSDimitry Andric /// If ThisBody is true, this function may examine the function body and will
1515f757f3fSDimitry Andric /// return a result pertaining to this copy of the function. If it is false, the
1525f757f3fSDimitry Andric /// result will be based only on AA results for the function declaration; it
1535f757f3fSDimitry Andric /// will be assumed that some other (perhaps less optimized) version of the
1545f757f3fSDimitry Andric /// function may be selected at link time.
1555f757f3fSDimitry Andric ///
1565f757f3fSDimitry Andric /// The return value is split into two parts: Memory effects that always apply,
1575f757f3fSDimitry Andric /// and additional memory effects that apply if any of the functions in the SCC
1585f757f3fSDimitry Andric /// can access argmem.
1595f757f3fSDimitry Andric static std::pair<MemoryEffects, MemoryEffects>
1605f757f3fSDimitry Andric checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR,
1615f757f3fSDimitry Andric                           const SCCNodeSet &SCCNodes) {
1625f757f3fSDimitry Andric   MemoryEffects OrigME = AAR.getMemoryEffects(&F);
1635f757f3fSDimitry Andric   if (OrigME.doesNotAccessMemory())
1645f757f3fSDimitry Andric     // Already perfect!
1655f757f3fSDimitry Andric     return {OrigME, MemoryEffects::none()};
1665f757f3fSDimitry Andric 
1675f757f3fSDimitry Andric   if (!ThisBody)
1685f757f3fSDimitry Andric     return {OrigME, MemoryEffects::none()};
1695f757f3fSDimitry Andric 
1705f757f3fSDimitry Andric   MemoryEffects ME = MemoryEffects::none();
1715f757f3fSDimitry Andric   // Additional locations accessed if the SCC accesses argmem.
1725f757f3fSDimitry Andric   MemoryEffects RecursiveArgME = MemoryEffects::none();
1735f757f3fSDimitry Andric 
1745f757f3fSDimitry Andric   // Inalloca and preallocated arguments are always clobbered by the call.
1755f757f3fSDimitry Andric   if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
1765f757f3fSDimitry Andric       F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
1775f757f3fSDimitry Andric     ME |= MemoryEffects::argMemOnly(ModRefInfo::ModRef);
1785f757f3fSDimitry Andric 
179bdd1243dSDimitry Andric   // Scan the function body for instructions that may read or write memory.
180349cc55cSDimitry Andric   for (Instruction &I : instructions(F)) {
1810b57cec5SDimitry Andric     // Some instructions can be ignored even if they read or write memory.
1820b57cec5SDimitry Andric     // Detect these now, skipping to the next instruction if one is found.
183349cc55cSDimitry Andric     if (auto *Call = dyn_cast<CallBase>(&I)) {
1845f757f3fSDimitry Andric       // We can optimistically ignore calls to functions in the same SCC, with
1855f757f3fSDimitry Andric       // two caveats:
1865f757f3fSDimitry Andric       //  * Calls with operand bundles may have additional effects.
1875f757f3fSDimitry Andric       //  * Argument memory accesses may imply additional effects depending on
1885f757f3fSDimitry Andric       //    what the argument location is.
1890b57cec5SDimitry Andric       if (!Call->hasOperandBundles() && Call->getCalledFunction() &&
1905f757f3fSDimitry Andric           SCCNodes.count(Call->getCalledFunction())) {
1915f757f3fSDimitry Andric         // Keep track of which additional locations are accessed if the SCC
1925f757f3fSDimitry Andric         // turns out to access argmem.
1935f757f3fSDimitry Andric         addArgLocs(RecursiveArgME, Call, ModRefInfo::ModRef, AAR);
1940b57cec5SDimitry Andric         continue;
1955f757f3fSDimitry Andric       }
1965f757f3fSDimitry Andric 
197bdd1243dSDimitry Andric       MemoryEffects CallME = AAR.getMemoryEffects(Call);
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric       // If the call doesn't access memory, we're done.
200bdd1243dSDimitry Andric       if (CallME.doesNotAccessMemory())
2010b57cec5SDimitry Andric         continue;
2020b57cec5SDimitry Andric 
203d409305fSDimitry Andric       // A pseudo probe call shouldn't change any function attribute since it
204d409305fSDimitry Andric       // doesn't translate to a real instruction. It comes with a memory access
205d409305fSDimitry Andric       // tag to prevent itself being removed by optimizations and not block
206d409305fSDimitry Andric       // other instructions being optimized.
207d409305fSDimitry Andric       if (isa<PseudoProbeInst>(I))
208d409305fSDimitry Andric         continue;
209d409305fSDimitry Andric 
21006c3fb27SDimitry Andric       ME |= CallME.getWithoutLoc(IRMemLocation::ArgMem);
211bdd1243dSDimitry Andric 
212bdd1243dSDimitry Andric       // If the call accesses captured memory (currently part of "other") and
213bdd1243dSDimitry Andric       // an argument is captured (currently not tracked), then it may also
214bdd1243dSDimitry Andric       // access argument memory.
21506c3fb27SDimitry Andric       ModRefInfo OtherMR = CallME.getModRef(IRMemLocation::Other);
216bdd1243dSDimitry Andric       ME |= MemoryEffects::argMemOnly(OtherMR);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric       // Check whether all pointer arguments point to local memory, and
2190b57cec5SDimitry Andric       // ignore calls that only access local memory.
22006c3fb27SDimitry Andric       ModRefInfo ArgMR = CallME.getModRef(IRMemLocation::ArgMem);
2215f757f3fSDimitry Andric       if (ArgMR != ModRefInfo::NoModRef)
2225f757f3fSDimitry Andric         addArgLocs(ME, Call, ArgMR, AAR);
2230b57cec5SDimitry Andric       continue;
2240b57cec5SDimitry Andric     }
2250b57cec5SDimitry Andric 
226bdd1243dSDimitry Andric     ModRefInfo MR = ModRefInfo::NoModRef;
227bdd1243dSDimitry Andric     if (I.mayWriteToMemory())
228bdd1243dSDimitry Andric       MR |= ModRefInfo::Mod;
229bdd1243dSDimitry Andric     if (I.mayReadFromMemory())
230bdd1243dSDimitry Andric       MR |= ModRefInfo::Ref;
231bdd1243dSDimitry Andric     if (MR == ModRefInfo::NoModRef)
232bdd1243dSDimitry Andric       continue;
2330b57cec5SDimitry Andric 
234bdd1243dSDimitry Andric     std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(&I);
235bdd1243dSDimitry Andric     if (!Loc) {
236bdd1243dSDimitry Andric       // If no location is known, conservatively assume anything can be
237bdd1243dSDimitry Andric       // accessed.
238bdd1243dSDimitry Andric       ME |= MemoryEffects(MR);
239bdd1243dSDimitry Andric       continue;
2400b57cec5SDimitry Andric     }
2410b57cec5SDimitry Andric 
242bdd1243dSDimitry Andric     // Volatile operations may access inaccessible memory.
243bdd1243dSDimitry Andric     if (I.isVolatile())
244bdd1243dSDimitry Andric       ME |= MemoryEffects::inaccessibleMemOnly(MR);
24581ad6265SDimitry Andric 
2465f757f3fSDimitry Andric     addLocAccess(ME, *Loc, MR, AAR);
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric 
2495f757f3fSDimitry Andric   return {OrigME & ME, RecursiveArgME};
250bdd1243dSDimitry Andric }
251bdd1243dSDimitry Andric 
252bdd1243dSDimitry Andric MemoryEffects llvm::computeFunctionBodyMemoryAccess(Function &F,
2530b57cec5SDimitry Andric                                                     AAResults &AAR) {
2545f757f3fSDimitry Andric   return checkFunctionMemoryAccess(F, /*ThisBody=*/true, AAR, {}).first;
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
25781ad6265SDimitry Andric /// Deduce readonly/readnone/writeonly attributes for the SCC.
2580b57cec5SDimitry Andric template <typename AARGetterT>
25981ad6265SDimitry Andric static void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
260349cc55cSDimitry Andric                            SmallSet<Function *, 8> &Changed) {
261bdd1243dSDimitry Andric   MemoryEffects ME = MemoryEffects::none();
2625f757f3fSDimitry Andric   MemoryEffects RecursiveArgME = MemoryEffects::none();
2630b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
2640b57cec5SDimitry Andric     // Call the callable parameter to look up AA results for this function.
2650b57cec5SDimitry Andric     AAResults &AAR = AARGetter(*F);
2660b57cec5SDimitry Andric     // Non-exact function definitions may not be selected at link time, and an
2670b57cec5SDimitry Andric     // alternative version that writes to memory may be selected.  See the
2680b57cec5SDimitry Andric     // comment on GlobalValue::isDefinitionExact for more details.
2695f757f3fSDimitry Andric     auto [FnME, FnRecursiveArgME] =
2705f757f3fSDimitry Andric         checkFunctionMemoryAccess(*F, F->hasExactDefinition(), AAR, SCCNodes);
2715f757f3fSDimitry Andric     ME |= FnME;
2725f757f3fSDimitry Andric     RecursiveArgME |= FnRecursiveArgME;
273bdd1243dSDimitry Andric     // Reached bottom of the lattice, we will not be able to improve the result.
274bdd1243dSDimitry Andric     if (ME == MemoryEffects::unknown())
275349cc55cSDimitry Andric       return;
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric 
2785f757f3fSDimitry Andric   // If the SCC accesses argmem, add recursive accesses resulting from that.
2795f757f3fSDimitry Andric   ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
2805f757f3fSDimitry Andric   if (ArgMR != ModRefInfo::NoModRef)
2815f757f3fSDimitry Andric     ME |= RecursiveArgME & MemoryEffects(ArgMR);
2825f757f3fSDimitry Andric 
2830b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
284bdd1243dSDimitry Andric     MemoryEffects OldME = F->getMemoryEffects();
285bdd1243dSDimitry Andric     MemoryEffects NewME = ME & OldME;
286bdd1243dSDimitry Andric     if (NewME != OldME) {
287bdd1243dSDimitry Andric       ++NumMemoryAttr;
288bdd1243dSDimitry Andric       F->setMemoryEffects(NewME);
2895f757f3fSDimitry Andric       // Remove conflicting writable attributes.
2905f757f3fSDimitry Andric       if (!isModSet(NewME.getModRef(IRMemLocation::ArgMem)))
2915f757f3fSDimitry Andric         for (Argument &A : F->args())
2925f757f3fSDimitry Andric           A.removeAttr(Attribute::Writable);
29381ad6265SDimitry Andric       Changed.insert(F);
29481ad6265SDimitry Andric     }
2950b57cec5SDimitry Andric   }
296349cc55cSDimitry Andric }
2970b57cec5SDimitry Andric 
298349cc55cSDimitry Andric // Compute definitive function attributes for a function taking into account
299349cc55cSDimitry Andric // prevailing definitions and linkage types
300349cc55cSDimitry Andric static FunctionSummary *calculatePrevailingSummary(
301349cc55cSDimitry Andric     ValueInfo VI,
302349cc55cSDimitry Andric     DenseMap<ValueInfo, FunctionSummary *> &CachedPrevailingSummary,
303349cc55cSDimitry Andric     function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
304349cc55cSDimitry Andric         IsPrevailing) {
305349cc55cSDimitry Andric 
306349cc55cSDimitry Andric   if (CachedPrevailingSummary.count(VI))
307349cc55cSDimitry Andric     return CachedPrevailingSummary[VI];
308349cc55cSDimitry Andric 
309349cc55cSDimitry Andric   /// At this point, prevailing symbols have been resolved. The following leads
310349cc55cSDimitry Andric   /// to returning a conservative result:
311349cc55cSDimitry Andric   /// - Multiple instances with local linkage. Normally local linkage would be
312349cc55cSDimitry Andric   ///   unique per module
313349cc55cSDimitry Andric   ///   as the GUID includes the module path. We could have a guid alias if
314349cc55cSDimitry Andric   ///   there wasn't any distinguishing path when each file was compiled, but
315349cc55cSDimitry Andric   ///   that should be rare so we'll punt on those.
316349cc55cSDimitry Andric 
317349cc55cSDimitry Andric   /// These next 2 cases should not happen and will assert:
318349cc55cSDimitry Andric   /// - Multiple instances with external linkage. This should be caught in
319349cc55cSDimitry Andric   ///   symbol resolution
320349cc55cSDimitry Andric   /// - Non-existent FunctionSummary for Aliasee. This presents a hole in our
321349cc55cSDimitry Andric   ///   knowledge meaning we have to go conservative.
322349cc55cSDimitry Andric 
323349cc55cSDimitry Andric   /// Otherwise, we calculate attributes for a function as:
324349cc55cSDimitry Andric   ///   1. If we have a local linkage, take its attributes. If there's somehow
325349cc55cSDimitry Andric   ///      multiple, bail and go conservative.
326349cc55cSDimitry Andric   ///   2. If we have an external/WeakODR/LinkOnceODR linkage check that it is
327349cc55cSDimitry Andric   ///      prevailing, take its attributes.
328349cc55cSDimitry Andric   ///   3. If we have a Weak/LinkOnce linkage the copies can have semantic
329349cc55cSDimitry Andric   ///      differences. However, if the prevailing copy is known it will be used
330349cc55cSDimitry Andric   ///      so take its attributes. If the prevailing copy is in a native file
331349cc55cSDimitry Andric   ///      all IR copies will be dead and propagation will go conservative.
332349cc55cSDimitry Andric   ///   4. AvailableExternally summaries without a prevailing copy are known to
333349cc55cSDimitry Andric   ///      occur in a couple of circumstances:
334349cc55cSDimitry Andric   ///      a. An internal function gets imported due to its caller getting
335349cc55cSDimitry Andric   ///         imported, it becomes AvailableExternally but no prevailing
336349cc55cSDimitry Andric   ///         definition exists. Because it has to get imported along with its
337349cc55cSDimitry Andric   ///         caller the attributes will be captured by propagating on its
338349cc55cSDimitry Andric   ///         caller.
339349cc55cSDimitry Andric   ///      b. C++11 [temp.explicit]p10 can generate AvailableExternally
340349cc55cSDimitry Andric   ///         definitions of explicitly instanced template declarations
341349cc55cSDimitry Andric   ///         for inlining which are ultimately dropped from the TU. Since this
342349cc55cSDimitry Andric   ///         is localized to the TU the attributes will have already made it to
343349cc55cSDimitry Andric   ///         the callers.
344349cc55cSDimitry Andric   ///      These are edge cases and already captured by their callers so we
345349cc55cSDimitry Andric   ///      ignore these for now. If they become relevant to optimize in the
346349cc55cSDimitry Andric   ///      future this can be revisited.
347349cc55cSDimitry Andric   ///   5. Otherwise, go conservative.
348349cc55cSDimitry Andric 
349349cc55cSDimitry Andric   CachedPrevailingSummary[VI] = nullptr;
350349cc55cSDimitry Andric   FunctionSummary *Local = nullptr;
351349cc55cSDimitry Andric   FunctionSummary *Prevailing = nullptr;
352349cc55cSDimitry Andric 
353349cc55cSDimitry Andric   for (const auto &GVS : VI.getSummaryList()) {
354349cc55cSDimitry Andric     if (!GVS->isLive())
355349cc55cSDimitry Andric       continue;
356349cc55cSDimitry Andric 
357349cc55cSDimitry Andric     FunctionSummary *FS = dyn_cast<FunctionSummary>(GVS->getBaseObject());
358349cc55cSDimitry Andric     // Virtual and Unknown (e.g. indirect) calls require going conservative
359349cc55cSDimitry Andric     if (!FS || FS->fflags().HasUnknownCall)
360349cc55cSDimitry Andric       return nullptr;
361349cc55cSDimitry Andric 
362349cc55cSDimitry Andric     const auto &Linkage = GVS->linkage();
363349cc55cSDimitry Andric     if (GlobalValue::isLocalLinkage(Linkage)) {
364349cc55cSDimitry Andric       if (Local) {
365349cc55cSDimitry Andric         LLVM_DEBUG(
366349cc55cSDimitry Andric             dbgs()
367349cc55cSDimitry Andric             << "ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
368349cc55cSDimitry Andric                "function "
369349cc55cSDimitry Andric             << VI.name() << " from " << FS->modulePath() << ". Previous module "
370349cc55cSDimitry Andric             << Local->modulePath() << "\n");
371349cc55cSDimitry Andric         return nullptr;
372349cc55cSDimitry Andric       }
373349cc55cSDimitry Andric       Local = FS;
374349cc55cSDimitry Andric     } else if (GlobalValue::isExternalLinkage(Linkage)) {
375349cc55cSDimitry Andric       assert(IsPrevailing(VI.getGUID(), GVS.get()));
376349cc55cSDimitry Andric       Prevailing = FS;
377349cc55cSDimitry Andric       break;
378349cc55cSDimitry Andric     } else if (GlobalValue::isWeakODRLinkage(Linkage) ||
379349cc55cSDimitry Andric                GlobalValue::isLinkOnceODRLinkage(Linkage) ||
380349cc55cSDimitry Andric                GlobalValue::isWeakAnyLinkage(Linkage) ||
381349cc55cSDimitry Andric                GlobalValue::isLinkOnceAnyLinkage(Linkage)) {
382349cc55cSDimitry Andric       if (IsPrevailing(VI.getGUID(), GVS.get())) {
383349cc55cSDimitry Andric         Prevailing = FS;
384349cc55cSDimitry Andric         break;
385349cc55cSDimitry Andric       }
386349cc55cSDimitry Andric     } else if (GlobalValue::isAvailableExternallyLinkage(Linkage)) {
387349cc55cSDimitry Andric       // TODO: Handle these cases if they become meaningful
388349cc55cSDimitry Andric       continue;
389349cc55cSDimitry Andric     }
390349cc55cSDimitry Andric   }
391349cc55cSDimitry Andric 
392349cc55cSDimitry Andric   if (Local) {
393349cc55cSDimitry Andric     assert(!Prevailing);
394349cc55cSDimitry Andric     CachedPrevailingSummary[VI] = Local;
395349cc55cSDimitry Andric   } else if (Prevailing) {
396349cc55cSDimitry Andric     assert(!Local);
397349cc55cSDimitry Andric     CachedPrevailingSummary[VI] = Prevailing;
398349cc55cSDimitry Andric   }
399349cc55cSDimitry Andric 
400349cc55cSDimitry Andric   return CachedPrevailingSummary[VI];
401349cc55cSDimitry Andric }
402349cc55cSDimitry Andric 
403349cc55cSDimitry Andric bool llvm::thinLTOPropagateFunctionAttrs(
404349cc55cSDimitry Andric     ModuleSummaryIndex &Index,
405349cc55cSDimitry Andric     function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
406349cc55cSDimitry Andric         IsPrevailing) {
407349cc55cSDimitry Andric   // TODO: implement addNoAliasAttrs once
408349cc55cSDimitry Andric   // there's more information about the return type in the summary
409349cc55cSDimitry Andric   if (DisableThinLTOPropagation)
410349cc55cSDimitry Andric     return false;
411349cc55cSDimitry Andric 
412349cc55cSDimitry Andric   DenseMap<ValueInfo, FunctionSummary *> CachedPrevailingSummary;
413349cc55cSDimitry Andric   bool Changed = false;
414349cc55cSDimitry Andric 
415349cc55cSDimitry Andric   auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
416349cc55cSDimitry Andric     // Assume we can propagate unless we discover otherwise
417349cc55cSDimitry Andric     FunctionSummary::FFlags InferredFlags;
418349cc55cSDimitry Andric     InferredFlags.NoRecurse = (SCCNodes.size() == 1);
419349cc55cSDimitry Andric     InferredFlags.NoUnwind = true;
420349cc55cSDimitry Andric 
421349cc55cSDimitry Andric     for (auto &V : SCCNodes) {
422349cc55cSDimitry Andric       FunctionSummary *CallerSummary =
423349cc55cSDimitry Andric           calculatePrevailingSummary(V, CachedPrevailingSummary, IsPrevailing);
424349cc55cSDimitry Andric 
425349cc55cSDimitry Andric       // Function summaries can fail to contain information such as declarations
426349cc55cSDimitry Andric       if (!CallerSummary)
427349cc55cSDimitry Andric         return;
428349cc55cSDimitry Andric 
429349cc55cSDimitry Andric       if (CallerSummary->fflags().MayThrow)
430349cc55cSDimitry Andric         InferredFlags.NoUnwind = false;
431349cc55cSDimitry Andric 
432349cc55cSDimitry Andric       for (const auto &Callee : CallerSummary->calls()) {
433349cc55cSDimitry Andric         FunctionSummary *CalleeSummary = calculatePrevailingSummary(
434349cc55cSDimitry Andric             Callee.first, CachedPrevailingSummary, IsPrevailing);
435349cc55cSDimitry Andric 
436349cc55cSDimitry Andric         if (!CalleeSummary)
437349cc55cSDimitry Andric           return;
438349cc55cSDimitry Andric 
439349cc55cSDimitry Andric         if (!CalleeSummary->fflags().NoRecurse)
440349cc55cSDimitry Andric           InferredFlags.NoRecurse = false;
441349cc55cSDimitry Andric 
442349cc55cSDimitry Andric         if (!CalleeSummary->fflags().NoUnwind)
443349cc55cSDimitry Andric           InferredFlags.NoUnwind = false;
444349cc55cSDimitry Andric 
445349cc55cSDimitry Andric         if (!InferredFlags.NoUnwind && !InferredFlags.NoRecurse)
446349cc55cSDimitry Andric           break;
447349cc55cSDimitry Andric       }
448349cc55cSDimitry Andric     }
449349cc55cSDimitry Andric 
450349cc55cSDimitry Andric     if (InferredFlags.NoUnwind || InferredFlags.NoRecurse) {
451349cc55cSDimitry Andric       Changed = true;
452349cc55cSDimitry Andric       for (auto &V : SCCNodes) {
453349cc55cSDimitry Andric         if (InferredFlags.NoRecurse) {
454349cc55cSDimitry Andric           LLVM_DEBUG(dbgs() << "ThinLTO FunctionAttrs: Propagated NoRecurse to "
455349cc55cSDimitry Andric                             << V.name() << "\n");
456349cc55cSDimitry Andric           ++NumThinLinkNoRecurse;
457349cc55cSDimitry Andric         }
458349cc55cSDimitry Andric 
459349cc55cSDimitry Andric         if (InferredFlags.NoUnwind) {
460349cc55cSDimitry Andric           LLVM_DEBUG(dbgs() << "ThinLTO FunctionAttrs: Propagated NoUnwind to "
461349cc55cSDimitry Andric                             << V.name() << "\n");
462349cc55cSDimitry Andric           ++NumThinLinkNoUnwind;
463349cc55cSDimitry Andric         }
464349cc55cSDimitry Andric 
465bdd1243dSDimitry Andric         for (const auto &S : V.getSummaryList()) {
466349cc55cSDimitry Andric           if (auto *FS = dyn_cast<FunctionSummary>(S.get())) {
467349cc55cSDimitry Andric             if (InferredFlags.NoRecurse)
468349cc55cSDimitry Andric               FS->setNoRecurse();
469349cc55cSDimitry Andric 
470349cc55cSDimitry Andric             if (InferredFlags.NoUnwind)
471349cc55cSDimitry Andric               FS->setNoUnwind();
472349cc55cSDimitry Andric           }
473349cc55cSDimitry Andric         }
474349cc55cSDimitry Andric       }
475349cc55cSDimitry Andric     }
476349cc55cSDimitry Andric   };
477349cc55cSDimitry Andric 
478349cc55cSDimitry Andric   // Call propagation functions on each SCC in the Index
479349cc55cSDimitry Andric   for (scc_iterator<ModuleSummaryIndex *> I = scc_begin(&Index); !I.isAtEnd();
480349cc55cSDimitry Andric        ++I) {
481349cc55cSDimitry Andric     std::vector<ValueInfo> Nodes(*I);
482349cc55cSDimitry Andric     PropagateAttributes(Nodes);
483349cc55cSDimitry Andric   }
484349cc55cSDimitry Andric   return Changed;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric namespace {
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric /// For a given pointer Argument, this retains a list of Arguments of functions
4900b57cec5SDimitry Andric /// in the same SCC that the pointer data flows into. We use this to build an
4910b57cec5SDimitry Andric /// SCC of the arguments.
4920b57cec5SDimitry Andric struct ArgumentGraphNode {
4930b57cec5SDimitry Andric   Argument *Definition;
4940b57cec5SDimitry Andric   SmallVector<ArgumentGraphNode *, 4> Uses;
4950b57cec5SDimitry Andric };
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric class ArgumentGraph {
4980b57cec5SDimitry Andric   // We store pointers to ArgumentGraphNode objects, so it's important that
4990b57cec5SDimitry Andric   // that they not move around upon insert.
5000b57cec5SDimitry Andric   using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   ArgumentMapTy ArgumentMap;
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   // There is no root node for the argument graph, in fact:
5050b57cec5SDimitry Andric   //   void f(int *x, int *y) { if (...) f(x, y); }
5060b57cec5SDimitry Andric   // is an example where the graph is disconnected. The SCCIterator requires a
5070b57cec5SDimitry Andric   // single entry point, so we maintain a fake ("synthetic") root node that
5080b57cec5SDimitry Andric   // uses every node. Because the graph is directed and nothing points into
5090b57cec5SDimitry Andric   // the root, it will not participate in any SCCs (except for its own).
5100b57cec5SDimitry Andric   ArgumentGraphNode SyntheticRoot;
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric public:
5130b57cec5SDimitry Andric   ArgumentGraph() { SyntheticRoot.Definition = nullptr; }
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   using iterator = SmallVectorImpl<ArgumentGraphNode *>::iterator;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   iterator begin() { return SyntheticRoot.Uses.begin(); }
5180b57cec5SDimitry Andric   iterator end() { return SyntheticRoot.Uses.end(); }
5190b57cec5SDimitry Andric   ArgumentGraphNode *getEntryNode() { return &SyntheticRoot; }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   ArgumentGraphNode *operator[](Argument *A) {
5220b57cec5SDimitry Andric     ArgumentGraphNode &Node = ArgumentMap[A];
5230b57cec5SDimitry Andric     Node.Definition = A;
5240b57cec5SDimitry Andric     SyntheticRoot.Uses.push_back(&Node);
5250b57cec5SDimitry Andric     return &Node;
5260b57cec5SDimitry Andric   }
5270b57cec5SDimitry Andric };
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric /// This tracker checks whether callees are in the SCC, and if so it does not
5300b57cec5SDimitry Andric /// consider that a capture, instead adding it to the "Uses" list and
5310b57cec5SDimitry Andric /// continuing with the analysis.
5320b57cec5SDimitry Andric struct ArgumentUsesTracker : public CaptureTracker {
5330b57cec5SDimitry Andric   ArgumentUsesTracker(const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   void tooManyUses() override { Captured = true; }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   bool captured(const Use *U) override {
5385ffd83dbSDimitry Andric     CallBase *CB = dyn_cast<CallBase>(U->getUser());
5395ffd83dbSDimitry Andric     if (!CB) {
5400b57cec5SDimitry Andric       Captured = true;
5410b57cec5SDimitry Andric       return true;
5420b57cec5SDimitry Andric     }
5430b57cec5SDimitry Andric 
5445ffd83dbSDimitry Andric     Function *F = CB->getCalledFunction();
5450b57cec5SDimitry Andric     if (!F || !F->hasExactDefinition() || !SCCNodes.count(F)) {
5460b57cec5SDimitry Andric       Captured = true;
5470b57cec5SDimitry Andric       return true;
5480b57cec5SDimitry Andric     }
5490b57cec5SDimitry Andric 
5500eae32dcSDimitry Andric     assert(!CB->isCallee(U) && "callee operand reported captured?");
5510eae32dcSDimitry Andric     const unsigned UseIndex = CB->getDataOperandNo(U);
552349cc55cSDimitry Andric     if (UseIndex >= CB->arg_size()) {
5530b57cec5SDimitry Andric       // Data operand, but not a argument operand -- must be a bundle operand
5545ffd83dbSDimitry Andric       assert(CB->hasOperandBundles() && "Must be!");
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric       // CaptureTracking told us that we're being captured by an operand bundle
5570b57cec5SDimitry Andric       // use.  In this case it does not matter if the callee is within our SCC
5580b57cec5SDimitry Andric       // or not -- we've been captured in some unknown way, and we have to be
5590b57cec5SDimitry Andric       // conservative.
5600b57cec5SDimitry Andric       Captured = true;
5610b57cec5SDimitry Andric       return true;
5620b57cec5SDimitry Andric     }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric     if (UseIndex >= F->arg_size()) {
5650b57cec5SDimitry Andric       assert(F->isVarArg() && "More params than args in non-varargs call");
5660b57cec5SDimitry Andric       Captured = true;
5670b57cec5SDimitry Andric       return true;
5680b57cec5SDimitry Andric     }
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric     Uses.push_back(&*std::next(F->arg_begin(), UseIndex));
5710b57cec5SDimitry Andric     return false;
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   // True only if certainly captured (used outside our SCC).
5750b57cec5SDimitry Andric   bool Captured = false;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   // Uses within our SCC.
5780b57cec5SDimitry Andric   SmallVector<Argument *, 4> Uses;
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   const SCCNodeSet &SCCNodes;
5810b57cec5SDimitry Andric };
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric } // end anonymous namespace
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric namespace llvm {
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric template <> struct GraphTraits<ArgumentGraphNode *> {
5880b57cec5SDimitry Andric   using NodeRef = ArgumentGraphNode *;
5890b57cec5SDimitry Andric   using ChildIteratorType = SmallVectorImpl<ArgumentGraphNode *>::iterator;
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   static NodeRef getEntryNode(NodeRef A) { return A; }
5920b57cec5SDimitry Andric   static ChildIteratorType child_begin(NodeRef N) { return N->Uses.begin(); }
5930b57cec5SDimitry Andric   static ChildIteratorType child_end(NodeRef N) { return N->Uses.end(); }
5940b57cec5SDimitry Andric };
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric template <>
5970b57cec5SDimitry Andric struct GraphTraits<ArgumentGraph *> : public GraphTraits<ArgumentGraphNode *> {
5980b57cec5SDimitry Andric   static NodeRef getEntryNode(ArgumentGraph *AG) { return AG->getEntryNode(); }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   static ChildIteratorType nodes_begin(ArgumentGraph *AG) {
6010b57cec5SDimitry Andric     return AG->begin();
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   static ChildIteratorType nodes_end(ArgumentGraph *AG) { return AG->end(); }
6050b57cec5SDimitry Andric };
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric } // end namespace llvm
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric /// Returns Attribute::None, Attribute::ReadOnly or Attribute::ReadNone.
6100b57cec5SDimitry Andric static Attribute::AttrKind
6110eae32dcSDimitry Andric determinePointerAccessAttrs(Argument *A,
6120b57cec5SDimitry Andric                             const SmallPtrSet<Argument *, 8> &SCCNodes) {
6130b57cec5SDimitry Andric   SmallVector<Use *, 32> Worklist;
6140b57cec5SDimitry Andric   SmallPtrSet<Use *, 32> Visited;
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   // inalloca arguments are always clobbered by the call.
6175ffd83dbSDimitry Andric   if (A->hasInAllocaAttr() || A->hasPreallocatedAttr())
6180b57cec5SDimitry Andric     return Attribute::None;
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   bool IsRead = false;
6210eae32dcSDimitry Andric   bool IsWrite = false;
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   for (Use &U : A->uses()) {
6240b57cec5SDimitry Andric     Visited.insert(&U);
6250b57cec5SDimitry Andric     Worklist.push_back(&U);
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   while (!Worklist.empty()) {
6290eae32dcSDimitry Andric     if (IsWrite && IsRead)
6300eae32dcSDimitry Andric       // No point in searching further..
6310eae32dcSDimitry Andric       return Attribute::None;
6320eae32dcSDimitry Andric 
6330b57cec5SDimitry Andric     Use *U = Worklist.pop_back_val();
6340b57cec5SDimitry Andric     Instruction *I = cast<Instruction>(U->getUser());
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric     switch (I->getOpcode()) {
6370b57cec5SDimitry Andric     case Instruction::BitCast:
6380b57cec5SDimitry Andric     case Instruction::GetElementPtr:
6390b57cec5SDimitry Andric     case Instruction::PHI:
6400b57cec5SDimitry Andric     case Instruction::Select:
6410b57cec5SDimitry Andric     case Instruction::AddrSpaceCast:
6420b57cec5SDimitry Andric       // The original value is not read/written via this if the new value isn't.
6430b57cec5SDimitry Andric       for (Use &UU : I->uses())
6440b57cec5SDimitry Andric         if (Visited.insert(&UU).second)
6450b57cec5SDimitry Andric           Worklist.push_back(&UU);
6460b57cec5SDimitry Andric       break;
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric     case Instruction::Call:
6490b57cec5SDimitry Andric     case Instruction::Invoke: {
6500eae32dcSDimitry Andric       CallBase &CB = cast<CallBase>(*I);
6510eae32dcSDimitry Andric       if (CB.isCallee(U)) {
6520eae32dcSDimitry Andric         IsRead = true;
6530eae32dcSDimitry Andric         // Note that indirect calls do not capture, see comment in
6540eae32dcSDimitry Andric         // CaptureTracking for context
6550eae32dcSDimitry Andric         continue;
6560eae32dcSDimitry Andric       }
6570b57cec5SDimitry Andric 
6580eae32dcSDimitry Andric       // Given we've explictily handled the callee operand above, what's left
6590eae32dcSDimitry Andric       // must be a data operand (e.g. argument or operand bundle)
6600eae32dcSDimitry Andric       const unsigned UseIndex = CB.getDataOperandNo(U);
6610b57cec5SDimitry Andric 
6625f757f3fSDimitry Andric       // Some intrinsics (for instance ptrmask) do not capture their results,
6635f757f3fSDimitry Andric       // but return results thas alias their pointer argument, and thus should
6645f757f3fSDimitry Andric       // be handled like GEP or addrspacecast above.
6655f757f3fSDimitry Andric       if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
6665f757f3fSDimitry Andric               &CB, /*MustPreserveNullness=*/false)) {
6675f757f3fSDimitry Andric         for (Use &UU : CB.uses())
6685f757f3fSDimitry Andric           if (Visited.insert(&UU).second)
6695f757f3fSDimitry Andric             Worklist.push_back(&UU);
6705f757f3fSDimitry Andric       } else if (!CB.doesNotCapture(UseIndex)) {
6710eae32dcSDimitry Andric         if (!CB.onlyReadsMemory())
6720eae32dcSDimitry Andric           // If the callee can save a copy into other memory, then simply
6730eae32dcSDimitry Andric           // scanning uses of the call is insufficient.  We have no way
6740eae32dcSDimitry Andric           // of tracking copies of the pointer through memory to see
6750eae32dcSDimitry Andric           // if a reloaded copy is written to, thus we must give up.
6760eae32dcSDimitry Andric           return Attribute::None;
6770eae32dcSDimitry Andric         // Push users for processing once we finish this one
6780eae32dcSDimitry Andric         if (!I->getType()->isVoidTy())
6790b57cec5SDimitry Andric           for (Use &UU : I->uses())
6800b57cec5SDimitry Andric             if (Visited.insert(&UU).second)
6810b57cec5SDimitry Andric               Worklist.push_back(&UU);
6820eae32dcSDimitry Andric       }
6830b57cec5SDimitry Andric 
6845f757f3fSDimitry Andric       ModRefInfo ArgMR = CB.getMemoryEffects().getModRef(IRMemLocation::ArgMem);
6855f757f3fSDimitry Andric       if (isNoModRef(ArgMR))
6860b57cec5SDimitry Andric         continue;
6870b57cec5SDimitry Andric 
6880eae32dcSDimitry Andric       if (Function *F = CB.getCalledFunction())
6890eae32dcSDimitry Andric         if (CB.isArgOperand(U) && UseIndex < F->arg_size() &&
6900eae32dcSDimitry Andric             SCCNodes.count(F->getArg(UseIndex)))
6910eae32dcSDimitry Andric           // This is an argument which is part of the speculative SCC.  Note
6920eae32dcSDimitry Andric           // that only operands corresponding to formal arguments of the callee
6930eae32dcSDimitry Andric           // can participate in the speculation.
6940eae32dcSDimitry Andric           break;
6950b57cec5SDimitry Andric 
6965ffd83dbSDimitry Andric       // The accessors used on call site here do the right thing for calls and
6970b57cec5SDimitry Andric       // invokes with operand bundles.
69804eeddc0SDimitry Andric       if (CB.doesNotAccessMemory(UseIndex)) {
69904eeddc0SDimitry Andric         /* nop */
7005f757f3fSDimitry Andric       } else if (!isModSet(ArgMR) || CB.onlyReadsMemory(UseIndex)) {
7010b57cec5SDimitry Andric         IsRead = true;
7025f757f3fSDimitry Andric       } else if (!isRefSet(ArgMR) ||
70304eeddc0SDimitry Andric                  CB.dataOperandHasImpliedAttr(UseIndex, Attribute::WriteOnly)) {
70404eeddc0SDimitry Andric         IsWrite = true;
70504eeddc0SDimitry Andric       } else {
70604eeddc0SDimitry Andric         return Attribute::None;
70704eeddc0SDimitry Andric       }
7080b57cec5SDimitry Andric       break;
7090b57cec5SDimitry Andric     }
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric     case Instruction::Load:
7120b57cec5SDimitry Andric       // A volatile load has side effects beyond what readonly can be relied
7130b57cec5SDimitry Andric       // upon.
7140b57cec5SDimitry Andric       if (cast<LoadInst>(I)->isVolatile())
7150b57cec5SDimitry Andric         return Attribute::None;
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric       IsRead = true;
7180b57cec5SDimitry Andric       break;
7190b57cec5SDimitry Andric 
7200eae32dcSDimitry Andric     case Instruction::Store:
7210eae32dcSDimitry Andric       if (cast<StoreInst>(I)->getValueOperand() == *U)
7220eae32dcSDimitry Andric         // untrackable capture
7230eae32dcSDimitry Andric         return Attribute::None;
7240eae32dcSDimitry Andric 
7250eae32dcSDimitry Andric       // A volatile store has side effects beyond what writeonly can be relied
7260eae32dcSDimitry Andric       // upon.
7270eae32dcSDimitry Andric       if (cast<StoreInst>(I)->isVolatile())
7280eae32dcSDimitry Andric         return Attribute::None;
7290eae32dcSDimitry Andric 
7300eae32dcSDimitry Andric       IsWrite = true;
7310eae32dcSDimitry Andric       break;
7320eae32dcSDimitry Andric 
7330b57cec5SDimitry Andric     case Instruction::ICmp:
7340b57cec5SDimitry Andric     case Instruction::Ret:
7350b57cec5SDimitry Andric       break;
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric     default:
7380b57cec5SDimitry Andric       return Attribute::None;
7390b57cec5SDimitry Andric     }
7400b57cec5SDimitry Andric   }
7410b57cec5SDimitry Andric 
7420eae32dcSDimitry Andric   if (IsWrite && IsRead)
7430eae32dcSDimitry Andric     return Attribute::None;
7440eae32dcSDimitry Andric   else if (IsRead)
7450eae32dcSDimitry Andric     return Attribute::ReadOnly;
7460eae32dcSDimitry Andric   else if (IsWrite)
7470eae32dcSDimitry Andric     return Attribute::WriteOnly;
7480eae32dcSDimitry Andric   else
7490eae32dcSDimitry Andric     return Attribute::ReadNone;
7500b57cec5SDimitry Andric }
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric /// Deduce returned attributes for the SCC.
753349cc55cSDimitry Andric static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes,
754349cc55cSDimitry Andric                                      SmallSet<Function *, 8> &Changed) {
7550b57cec5SDimitry Andric   // Check each function in turn, determining if an argument is always returned.
7560b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
7570b57cec5SDimitry Andric     // We can infer and propagate function attributes only when we know that the
7580b57cec5SDimitry Andric     // definition we'll get at link time is *exactly* the definition we see now.
7590b57cec5SDimitry Andric     // For more details, see GlobalValue::mayBeDerefined.
7600b57cec5SDimitry Andric     if (!F->hasExactDefinition())
7610b57cec5SDimitry Andric       continue;
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric     if (F->getReturnType()->isVoidTy())
7640b57cec5SDimitry Andric       continue;
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric     // There is nothing to do if an argument is already marked as 'returned'.
76706c3fb27SDimitry Andric     if (F->getAttributes().hasAttrSomewhere(Attribute::Returned))
7680b57cec5SDimitry Andric       continue;
7690b57cec5SDimitry Andric 
77006c3fb27SDimitry Andric     auto FindRetArg = [&]() -> Argument * {
77106c3fb27SDimitry Andric       Argument *RetArg = nullptr;
7720b57cec5SDimitry Andric       for (BasicBlock &BB : *F)
7730b57cec5SDimitry Andric         if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
7740b57cec5SDimitry Andric           // Note that stripPointerCasts should look through functions with
7750b57cec5SDimitry Andric           // returned arguments.
77606c3fb27SDimitry Andric           auto *RetVal =
77706c3fb27SDimitry Andric               dyn_cast<Argument>(Ret->getReturnValue()->stripPointerCasts());
77806c3fb27SDimitry Andric           if (!RetVal || RetVal->getType() != F->getReturnType())
7790b57cec5SDimitry Andric             return nullptr;
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric           if (!RetArg)
7820b57cec5SDimitry Andric             RetArg = RetVal;
7830b57cec5SDimitry Andric           else if (RetArg != RetVal)
7840b57cec5SDimitry Andric             return nullptr;
7850b57cec5SDimitry Andric         }
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric       return RetArg;
7880b57cec5SDimitry Andric     };
7890b57cec5SDimitry Andric 
79006c3fb27SDimitry Andric     if (Argument *RetArg = FindRetArg()) {
79106c3fb27SDimitry Andric       RetArg->addAttr(Attribute::Returned);
7920b57cec5SDimitry Andric       ++NumReturned;
793349cc55cSDimitry Andric       Changed.insert(F);
7940b57cec5SDimitry Andric     }
7950b57cec5SDimitry Andric   }
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric /// If a callsite has arguments that are also arguments to the parent function,
7990b57cec5SDimitry Andric /// try to propagate attributes from the callsite's arguments to the parent's
8000b57cec5SDimitry Andric /// arguments. This may be important because inlining can cause information loss
8010b57cec5SDimitry Andric /// when attribute knowledge disappears with the inlined call.
8020b57cec5SDimitry Andric static bool addArgumentAttrsFromCallsites(Function &F) {
8030b57cec5SDimitry Andric   if (!EnableNonnullArgPropagation)
8040b57cec5SDimitry Andric     return false;
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   bool Changed = false;
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric   // For an argument attribute to transfer from a callsite to the parent, the
8090b57cec5SDimitry Andric   // call must be guaranteed to execute every time the parent is called.
8100b57cec5SDimitry Andric   // Conservatively, just check for calls in the entry block that are guaranteed
8110b57cec5SDimitry Andric   // to execute.
8120b57cec5SDimitry Andric   // TODO: This could be enhanced by testing if the callsite post-dominates the
8130b57cec5SDimitry Andric   // entry block or by doing simple forward walks or backward walks to the
8140b57cec5SDimitry Andric   // callsite.
8150b57cec5SDimitry Andric   BasicBlock &Entry = F.getEntryBlock();
8160b57cec5SDimitry Andric   for (Instruction &I : Entry) {
8175ffd83dbSDimitry Andric     if (auto *CB = dyn_cast<CallBase>(&I)) {
8185ffd83dbSDimitry Andric       if (auto *CalledFunc = CB->getCalledFunction()) {
8190b57cec5SDimitry Andric         for (auto &CSArg : CalledFunc->args()) {
820e8d8bef9SDimitry Andric           if (!CSArg.hasNonNullAttr(/* AllowUndefOrPoison */ false))
8210b57cec5SDimitry Andric             continue;
8220b57cec5SDimitry Andric 
8230b57cec5SDimitry Andric           // If the non-null callsite argument operand is an argument to 'F'
8240b57cec5SDimitry Andric           // (the caller) and the call is guaranteed to execute, then the value
8250b57cec5SDimitry Andric           // must be non-null throughout 'F'.
8265ffd83dbSDimitry Andric           auto *FArg = dyn_cast<Argument>(CB->getArgOperand(CSArg.getArgNo()));
8270b57cec5SDimitry Andric           if (FArg && !FArg->hasNonNullAttr()) {
8280b57cec5SDimitry Andric             FArg->addAttr(Attribute::NonNull);
8290b57cec5SDimitry Andric             Changed = true;
8300b57cec5SDimitry Andric           }
8310b57cec5SDimitry Andric         }
8320b57cec5SDimitry Andric       }
8330b57cec5SDimitry Andric     }
8340b57cec5SDimitry Andric     if (!isGuaranteedToTransferExecutionToSuccessor(&I))
8350b57cec5SDimitry Andric       break;
8360b57cec5SDimitry Andric   }
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   return Changed;
8390b57cec5SDimitry Andric }
8400b57cec5SDimitry Andric 
8410eae32dcSDimitry Andric static bool addAccessAttr(Argument *A, Attribute::AttrKind R) {
8420eae32dcSDimitry Andric   assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
8430eae32dcSDimitry Andric           R == Attribute::WriteOnly)
8440eae32dcSDimitry Andric          && "Must be an access attribute.");
8458bcb0991SDimitry Andric   assert(A && "Argument must not be null.");
8468bcb0991SDimitry Andric 
8478bcb0991SDimitry Andric   // If the argument already has the attribute, nothing needs to be done.
8488bcb0991SDimitry Andric   if (A->hasAttribute(R))
8498bcb0991SDimitry Andric       return false;
8508bcb0991SDimitry Andric 
8518bcb0991SDimitry Andric   // Otherwise, remove potentially conflicting attribute, add the new one,
8528bcb0991SDimitry Andric   // and update statistics.
8538bcb0991SDimitry Andric   A->removeAttr(Attribute::WriteOnly);
8548bcb0991SDimitry Andric   A->removeAttr(Attribute::ReadOnly);
8558bcb0991SDimitry Andric   A->removeAttr(Attribute::ReadNone);
8565f757f3fSDimitry Andric   // Remove conflicting writable attribute.
8575f757f3fSDimitry Andric   if (R == Attribute::ReadNone || R == Attribute::ReadOnly)
8585f757f3fSDimitry Andric     A->removeAttr(Attribute::Writable);
8598bcb0991SDimitry Andric   A->addAttr(R);
8600eae32dcSDimitry Andric   if (R == Attribute::ReadOnly)
8610eae32dcSDimitry Andric     ++NumReadOnlyArg;
8620eae32dcSDimitry Andric   else if (R == Attribute::WriteOnly)
8630eae32dcSDimitry Andric     ++NumWriteOnlyArg;
8640eae32dcSDimitry Andric   else
8650eae32dcSDimitry Andric     ++NumReadNoneArg;
8668bcb0991SDimitry Andric   return true;
8678bcb0991SDimitry Andric }
8688bcb0991SDimitry Andric 
8690b57cec5SDimitry Andric /// Deduce nocapture attributes for the SCC.
870349cc55cSDimitry Andric static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
871349cc55cSDimitry Andric                              SmallSet<Function *, 8> &Changed) {
8720b57cec5SDimitry Andric   ArgumentGraph AG;
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric   // Check each function in turn, determining which pointer arguments are not
8750b57cec5SDimitry Andric   // captured.
8760b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
8770b57cec5SDimitry Andric     // We can infer and propagate function attributes only when we know that the
8780b57cec5SDimitry Andric     // definition we'll get at link time is *exactly* the definition we see now.
8790b57cec5SDimitry Andric     // For more details, see GlobalValue::mayBeDerefined.
8800b57cec5SDimitry Andric     if (!F->hasExactDefinition())
8810b57cec5SDimitry Andric       continue;
8820b57cec5SDimitry Andric 
883349cc55cSDimitry Andric     if (addArgumentAttrsFromCallsites(*F))
884349cc55cSDimitry Andric       Changed.insert(F);
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric     // Functions that are readonly (or readnone) and nounwind and don't return
8870b57cec5SDimitry Andric     // a value can't capture arguments. Don't analyze them.
8880b57cec5SDimitry Andric     if (F->onlyReadsMemory() && F->doesNotThrow() &&
8890b57cec5SDimitry Andric         F->getReturnType()->isVoidTy()) {
890972a253aSDimitry Andric       for (Argument &A : F->args()) {
891972a253aSDimitry Andric         if (A.getType()->isPointerTy() && !A.hasNoCaptureAttr()) {
892972a253aSDimitry Andric           A.addAttr(Attribute::NoCapture);
8930b57cec5SDimitry Andric           ++NumNoCapture;
894349cc55cSDimitry Andric           Changed.insert(F);
8950b57cec5SDimitry Andric         }
8960b57cec5SDimitry Andric       }
8970b57cec5SDimitry Andric       continue;
8980b57cec5SDimitry Andric     }
8990b57cec5SDimitry Andric 
900972a253aSDimitry Andric     for (Argument &A : F->args()) {
901972a253aSDimitry Andric       if (!A.getType()->isPointerTy())
9020b57cec5SDimitry Andric         continue;
9030b57cec5SDimitry Andric       bool HasNonLocalUses = false;
904972a253aSDimitry Andric       if (!A.hasNoCaptureAttr()) {
9050b57cec5SDimitry Andric         ArgumentUsesTracker Tracker(SCCNodes);
906972a253aSDimitry Andric         PointerMayBeCaptured(&A, &Tracker);
9070b57cec5SDimitry Andric         if (!Tracker.Captured) {
9080b57cec5SDimitry Andric           if (Tracker.Uses.empty()) {
9090b57cec5SDimitry Andric             // If it's trivially not captured, mark it nocapture now.
910972a253aSDimitry Andric             A.addAttr(Attribute::NoCapture);
9110b57cec5SDimitry Andric             ++NumNoCapture;
912349cc55cSDimitry Andric             Changed.insert(F);
9130b57cec5SDimitry Andric           } else {
9140b57cec5SDimitry Andric             // If it's not trivially captured and not trivially not captured,
9150b57cec5SDimitry Andric             // then it must be calling into another function in our SCC. Save
9160b57cec5SDimitry Andric             // its particulars for Argument-SCC analysis later.
917972a253aSDimitry Andric             ArgumentGraphNode *Node = AG[&A];
9180b57cec5SDimitry Andric             for (Argument *Use : Tracker.Uses) {
9190b57cec5SDimitry Andric               Node->Uses.push_back(AG[Use]);
920972a253aSDimitry Andric               if (Use != &A)
9210b57cec5SDimitry Andric                 HasNonLocalUses = true;
9220b57cec5SDimitry Andric             }
9230b57cec5SDimitry Andric           }
9240b57cec5SDimitry Andric         }
9250b57cec5SDimitry Andric         // Otherwise, it's captured. Don't bother doing SCC analysis on it.
9260b57cec5SDimitry Andric       }
927972a253aSDimitry Andric       if (!HasNonLocalUses && !A.onlyReadsMemory()) {
9280eae32dcSDimitry Andric         // Can we determine that it's readonly/readnone/writeonly without doing
9290eae32dcSDimitry Andric         // an SCC? Note that we don't allow any calls at all here, or else our
9300eae32dcSDimitry Andric         // result will be dependent on the iteration order through the
9310eae32dcSDimitry Andric         // functions in the SCC.
9320b57cec5SDimitry Andric         SmallPtrSet<Argument *, 8> Self;
933972a253aSDimitry Andric         Self.insert(&A);
934972a253aSDimitry Andric         Attribute::AttrKind R = determinePointerAccessAttrs(&A, Self);
9358bcb0991SDimitry Andric         if (R != Attribute::None)
936972a253aSDimitry Andric           if (addAccessAttr(&A, R))
937349cc55cSDimitry Andric             Changed.insert(F);
9380b57cec5SDimitry Andric       }
9390b57cec5SDimitry Andric     }
9400b57cec5SDimitry Andric   }
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   // The graph we've collected is partial because we stopped scanning for
9430b57cec5SDimitry Andric   // argument uses once we solved the argument trivially. These partial nodes
9440b57cec5SDimitry Andric   // show up as ArgumentGraphNode objects with an empty Uses list, and for
9450b57cec5SDimitry Andric   // these nodes the final decision about whether they capture has already been
9460b57cec5SDimitry Andric   // made.  If the definition doesn't have a 'nocapture' attribute by now, it
9470b57cec5SDimitry Andric   // captures.
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric   for (scc_iterator<ArgumentGraph *> I = scc_begin(&AG); !I.isAtEnd(); ++I) {
9500b57cec5SDimitry Andric     const std::vector<ArgumentGraphNode *> &ArgumentSCC = *I;
9510b57cec5SDimitry Andric     if (ArgumentSCC.size() == 1) {
9520b57cec5SDimitry Andric       if (!ArgumentSCC[0]->Definition)
9530b57cec5SDimitry Andric         continue; // synthetic root node
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric       // eg. "void f(int* x) { if (...) f(x); }"
9560b57cec5SDimitry Andric       if (ArgumentSCC[0]->Uses.size() == 1 &&
9570b57cec5SDimitry Andric           ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
9580b57cec5SDimitry Andric         Argument *A = ArgumentSCC[0]->Definition;
9590b57cec5SDimitry Andric         A->addAttr(Attribute::NoCapture);
9600b57cec5SDimitry Andric         ++NumNoCapture;
961349cc55cSDimitry Andric         Changed.insert(A->getParent());
9620eae32dcSDimitry Andric 
9630eae32dcSDimitry Andric         // Infer the access attributes given the new nocapture one
9640eae32dcSDimitry Andric         SmallPtrSet<Argument *, 8> Self;
9650eae32dcSDimitry Andric         Self.insert(&*A);
9660eae32dcSDimitry Andric         Attribute::AttrKind R = determinePointerAccessAttrs(&*A, Self);
9670eae32dcSDimitry Andric         if (R != Attribute::None)
9680eae32dcSDimitry Andric           addAccessAttr(A, R);
9690b57cec5SDimitry Andric       }
9700b57cec5SDimitry Andric       continue;
9710b57cec5SDimitry Andric     }
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric     bool SCCCaptured = false;
974972a253aSDimitry Andric     for (ArgumentGraphNode *Node : ArgumentSCC) {
975972a253aSDimitry Andric       if (Node->Uses.empty() && !Node->Definition->hasNoCaptureAttr()) {
9760b57cec5SDimitry Andric         SCCCaptured = true;
977972a253aSDimitry Andric         break;
9780b57cec5SDimitry Andric       }
9790b57cec5SDimitry Andric     }
9800b57cec5SDimitry Andric     if (SCCCaptured)
9810b57cec5SDimitry Andric       continue;
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric     SmallPtrSet<Argument *, 8> ArgumentSCCNodes;
9840b57cec5SDimitry Andric     // Fill ArgumentSCCNodes with the elements of the ArgumentSCC.  Used for
9850b57cec5SDimitry Andric     // quickly looking up whether a given Argument is in this ArgumentSCC.
9860b57cec5SDimitry Andric     for (ArgumentGraphNode *I : ArgumentSCC) {
9870b57cec5SDimitry Andric       ArgumentSCCNodes.insert(I->Definition);
9880b57cec5SDimitry Andric     }
9890b57cec5SDimitry Andric 
990972a253aSDimitry Andric     for (ArgumentGraphNode *N : ArgumentSCC) {
9910b57cec5SDimitry Andric       for (ArgumentGraphNode *Use : N->Uses) {
9920b57cec5SDimitry Andric         Argument *A = Use->Definition;
9930b57cec5SDimitry Andric         if (A->hasNoCaptureAttr() || ArgumentSCCNodes.count(A))
9940b57cec5SDimitry Andric           continue;
9950b57cec5SDimitry Andric         SCCCaptured = true;
9960b57cec5SDimitry Andric         break;
9970b57cec5SDimitry Andric       }
998972a253aSDimitry Andric       if (SCCCaptured)
999972a253aSDimitry Andric         break;
10000b57cec5SDimitry Andric     }
10010b57cec5SDimitry Andric     if (SCCCaptured)
10020b57cec5SDimitry Andric       continue;
10030b57cec5SDimitry Andric 
1004972a253aSDimitry Andric     for (ArgumentGraphNode *N : ArgumentSCC) {
1005972a253aSDimitry Andric       Argument *A = N->Definition;
10060b57cec5SDimitry Andric       A->addAttr(Attribute::NoCapture);
10070b57cec5SDimitry Andric       ++NumNoCapture;
1008349cc55cSDimitry Andric       Changed.insert(A->getParent());
10090b57cec5SDimitry Andric     }
10100b57cec5SDimitry Andric 
10110eae32dcSDimitry Andric     // We also want to compute readonly/readnone/writeonly. With a small number
10120eae32dcSDimitry Andric     // of false negatives, we can assume that any pointer which is captured
10130eae32dcSDimitry Andric     // isn't going to be provably readonly or readnone, since by definition
10140eae32dcSDimitry Andric     // we can't analyze all uses of a captured pointer.
10150b57cec5SDimitry Andric     //
10160b57cec5SDimitry Andric     // The false negatives happen when the pointer is captured by a function
10170b57cec5SDimitry Andric     // that promises readonly/readnone behaviour on the pointer, then the
10180b57cec5SDimitry Andric     // pointer's lifetime ends before anything that writes to arbitrary memory.
10190b57cec5SDimitry Andric     // Also, a readonly/readnone pointer may be returned, but returning a
10200b57cec5SDimitry Andric     // pointer is capturing it.
10210b57cec5SDimitry Andric 
10220eae32dcSDimitry Andric     auto meetAccessAttr = [](Attribute::AttrKind A, Attribute::AttrKind B) {
10230eae32dcSDimitry Andric       if (A == B)
10240eae32dcSDimitry Andric         return A;
10250eae32dcSDimitry Andric       if (A == Attribute::ReadNone)
10260eae32dcSDimitry Andric         return B;
10270eae32dcSDimitry Andric       if (B == Attribute::ReadNone)
10280eae32dcSDimitry Andric         return A;
10290eae32dcSDimitry Andric       return Attribute::None;
10300eae32dcSDimitry Andric     };
10310eae32dcSDimitry Andric 
10320eae32dcSDimitry Andric     Attribute::AttrKind AccessAttr = Attribute::ReadNone;
1033972a253aSDimitry Andric     for (ArgumentGraphNode *N : ArgumentSCC) {
1034972a253aSDimitry Andric       Argument *A = N->Definition;
10350eae32dcSDimitry Andric       Attribute::AttrKind K = determinePointerAccessAttrs(A, ArgumentSCCNodes);
10360eae32dcSDimitry Andric       AccessAttr = meetAccessAttr(AccessAttr, K);
1037972a253aSDimitry Andric       if (AccessAttr == Attribute::None)
1038972a253aSDimitry Andric         break;
10390b57cec5SDimitry Andric     }
10400b57cec5SDimitry Andric 
10410eae32dcSDimitry Andric     if (AccessAttr != Attribute::None) {
1042972a253aSDimitry Andric       for (ArgumentGraphNode *N : ArgumentSCC) {
1043972a253aSDimitry Andric         Argument *A = N->Definition;
10440eae32dcSDimitry Andric         if (addAccessAttr(A, AccessAttr))
1045349cc55cSDimitry Andric           Changed.insert(A->getParent());
10460b57cec5SDimitry Andric       }
10470b57cec5SDimitry Andric     }
10480b57cec5SDimitry Andric   }
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric /// Tests whether a function is "malloc-like".
10520b57cec5SDimitry Andric ///
10530b57cec5SDimitry Andric /// A function is "malloc-like" if it returns either null or a pointer that
10540b57cec5SDimitry Andric /// doesn't alias any other pointer visible to the caller.
10550b57cec5SDimitry Andric static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes) {
10560b57cec5SDimitry Andric   SmallSetVector<Value *, 8> FlowsToReturn;
10570b57cec5SDimitry Andric   for (BasicBlock &BB : *F)
10580b57cec5SDimitry Andric     if (ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
10590b57cec5SDimitry Andric       FlowsToReturn.insert(Ret->getReturnValue());
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric   for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
10620b57cec5SDimitry Andric     Value *RetVal = FlowsToReturn[i];
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric     if (Constant *C = dyn_cast<Constant>(RetVal)) {
10650b57cec5SDimitry Andric       if (!C->isNullValue() && !isa<UndefValue>(C))
10660b57cec5SDimitry Andric         return false;
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric       continue;
10690b57cec5SDimitry Andric     }
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric     if (isa<Argument>(RetVal))
10720b57cec5SDimitry Andric       return false;
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric     if (Instruction *RVI = dyn_cast<Instruction>(RetVal))
10750b57cec5SDimitry Andric       switch (RVI->getOpcode()) {
10760b57cec5SDimitry Andric       // Extend the analysis by looking upwards.
10770b57cec5SDimitry Andric       case Instruction::BitCast:
10780b57cec5SDimitry Andric       case Instruction::GetElementPtr:
10790b57cec5SDimitry Andric       case Instruction::AddrSpaceCast:
10800b57cec5SDimitry Andric         FlowsToReturn.insert(RVI->getOperand(0));
10810b57cec5SDimitry Andric         continue;
10820b57cec5SDimitry Andric       case Instruction::Select: {
10830b57cec5SDimitry Andric         SelectInst *SI = cast<SelectInst>(RVI);
10840b57cec5SDimitry Andric         FlowsToReturn.insert(SI->getTrueValue());
10850b57cec5SDimitry Andric         FlowsToReturn.insert(SI->getFalseValue());
10860b57cec5SDimitry Andric         continue;
10870b57cec5SDimitry Andric       }
10880b57cec5SDimitry Andric       case Instruction::PHI: {
10890b57cec5SDimitry Andric         PHINode *PN = cast<PHINode>(RVI);
10900b57cec5SDimitry Andric         for (Value *IncValue : PN->incoming_values())
10910b57cec5SDimitry Andric           FlowsToReturn.insert(IncValue);
10920b57cec5SDimitry Andric         continue;
10930b57cec5SDimitry Andric       }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric       // Check whether the pointer came from an allocation.
10960b57cec5SDimitry Andric       case Instruction::Alloca:
10970b57cec5SDimitry Andric         break;
10980b57cec5SDimitry Andric       case Instruction::Call:
10990b57cec5SDimitry Andric       case Instruction::Invoke: {
11005ffd83dbSDimitry Andric         CallBase &CB = cast<CallBase>(*RVI);
11015ffd83dbSDimitry Andric         if (CB.hasRetAttr(Attribute::NoAlias))
11020b57cec5SDimitry Andric           break;
11035ffd83dbSDimitry Andric         if (CB.getCalledFunction() && SCCNodes.count(CB.getCalledFunction()))
11040b57cec5SDimitry Andric           break;
1105bdd1243dSDimitry Andric         [[fallthrough]];
11060b57cec5SDimitry Andric       }
11070b57cec5SDimitry Andric       default:
11080b57cec5SDimitry Andric         return false; // Did not come from an allocation.
11090b57cec5SDimitry Andric       }
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric     if (PointerMayBeCaptured(RetVal, false, /*StoreCaptures=*/false))
11120b57cec5SDimitry Andric       return false;
11130b57cec5SDimitry Andric   }
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   return true;
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric /// Deduce noalias attributes for the SCC.
1119349cc55cSDimitry Andric static void addNoAliasAttrs(const SCCNodeSet &SCCNodes,
1120349cc55cSDimitry Andric                             SmallSet<Function *, 8> &Changed) {
11210b57cec5SDimitry Andric   // Check each function in turn, determining which functions return noalias
11220b57cec5SDimitry Andric   // pointers.
11230b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
11240b57cec5SDimitry Andric     // Already noalias.
11250b57cec5SDimitry Andric     if (F->returnDoesNotAlias())
11260b57cec5SDimitry Andric       continue;
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric     // We can infer and propagate function attributes only when we know that the
11290b57cec5SDimitry Andric     // definition we'll get at link time is *exactly* the definition we see now.
11300b57cec5SDimitry Andric     // For more details, see GlobalValue::mayBeDerefined.
11310b57cec5SDimitry Andric     if (!F->hasExactDefinition())
1132349cc55cSDimitry Andric       return;
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric     // We annotate noalias return values, which are only applicable to
11350b57cec5SDimitry Andric     // pointer types.
11360b57cec5SDimitry Andric     if (!F->getReturnType()->isPointerTy())
11370b57cec5SDimitry Andric       continue;
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric     if (!isFunctionMallocLike(F, SCCNodes))
1140349cc55cSDimitry Andric       return;
11410b57cec5SDimitry Andric   }
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
11440b57cec5SDimitry Andric     if (F->returnDoesNotAlias() ||
11450b57cec5SDimitry Andric         !F->getReturnType()->isPointerTy())
11460b57cec5SDimitry Andric       continue;
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric     F->setReturnDoesNotAlias();
11490b57cec5SDimitry Andric     ++NumNoAlias;
1150349cc55cSDimitry Andric     Changed.insert(F);
11510b57cec5SDimitry Andric   }
11520b57cec5SDimitry Andric }
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric /// Tests whether this function is known to not return null.
11550b57cec5SDimitry Andric ///
11560b57cec5SDimitry Andric /// Requires that the function returns a pointer.
11570b57cec5SDimitry Andric ///
11580b57cec5SDimitry Andric /// Returns true if it believes the function will not return a null, and sets
11590b57cec5SDimitry Andric /// \p Speculative based on whether the returned conclusion is a speculative
11600b57cec5SDimitry Andric /// conclusion due to SCC calls.
11610b57cec5SDimitry Andric static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes,
11620b57cec5SDimitry Andric                             bool &Speculative) {
11630b57cec5SDimitry Andric   assert(F->getReturnType()->isPointerTy() &&
11640b57cec5SDimitry Andric          "nonnull only meaningful on pointer types");
11650b57cec5SDimitry Andric   Speculative = false;
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   SmallSetVector<Value *, 8> FlowsToReturn;
11680b57cec5SDimitry Andric   for (BasicBlock &BB : *F)
11690b57cec5SDimitry Andric     if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
11700b57cec5SDimitry Andric       FlowsToReturn.insert(Ret->getReturnValue());
11710b57cec5SDimitry Andric 
1172*0fca6ea1SDimitry Andric   auto &DL = F->getDataLayout();
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
11750b57cec5SDimitry Andric     Value *RetVal = FlowsToReturn[i];
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric     // If this value is locally known to be non-null, we're good
11780b57cec5SDimitry Andric     if (isKnownNonZero(RetVal, DL))
11790b57cec5SDimitry Andric       continue;
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric     // Otherwise, we need to look upwards since we can't make any local
11820b57cec5SDimitry Andric     // conclusions.
11830b57cec5SDimitry Andric     Instruction *RVI = dyn_cast<Instruction>(RetVal);
11840b57cec5SDimitry Andric     if (!RVI)
11850b57cec5SDimitry Andric       return false;
11860b57cec5SDimitry Andric     switch (RVI->getOpcode()) {
11870b57cec5SDimitry Andric     // Extend the analysis by looking upwards.
11880b57cec5SDimitry Andric     case Instruction::BitCast:
11890b57cec5SDimitry Andric     case Instruction::AddrSpaceCast:
11900b57cec5SDimitry Andric       FlowsToReturn.insert(RVI->getOperand(0));
11910b57cec5SDimitry Andric       continue;
11923a079333SDimitry Andric     case Instruction::GetElementPtr:
11933a079333SDimitry Andric       if (cast<GEPOperator>(RVI)->isInBounds()) {
11943a079333SDimitry Andric         FlowsToReturn.insert(RVI->getOperand(0));
11953a079333SDimitry Andric         continue;
11963a079333SDimitry Andric       }
11973a079333SDimitry Andric       return false;
11980b57cec5SDimitry Andric     case Instruction::Select: {
11990b57cec5SDimitry Andric       SelectInst *SI = cast<SelectInst>(RVI);
12000b57cec5SDimitry Andric       FlowsToReturn.insert(SI->getTrueValue());
12010b57cec5SDimitry Andric       FlowsToReturn.insert(SI->getFalseValue());
12020b57cec5SDimitry Andric       continue;
12030b57cec5SDimitry Andric     }
12040b57cec5SDimitry Andric     case Instruction::PHI: {
12050b57cec5SDimitry Andric       PHINode *PN = cast<PHINode>(RVI);
12060b57cec5SDimitry Andric       for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
12070b57cec5SDimitry Andric         FlowsToReturn.insert(PN->getIncomingValue(i));
12080b57cec5SDimitry Andric       continue;
12090b57cec5SDimitry Andric     }
12100b57cec5SDimitry Andric     case Instruction::Call:
12110b57cec5SDimitry Andric     case Instruction::Invoke: {
12125ffd83dbSDimitry Andric       CallBase &CB = cast<CallBase>(*RVI);
12135ffd83dbSDimitry Andric       Function *Callee = CB.getCalledFunction();
12140b57cec5SDimitry Andric       // A call to a node within the SCC is assumed to return null until
12150b57cec5SDimitry Andric       // proven otherwise
12160b57cec5SDimitry Andric       if (Callee && SCCNodes.count(Callee)) {
12170b57cec5SDimitry Andric         Speculative = true;
12180b57cec5SDimitry Andric         continue;
12190b57cec5SDimitry Andric       }
12200b57cec5SDimitry Andric       return false;
12210b57cec5SDimitry Andric     }
12220b57cec5SDimitry Andric     default:
12230b57cec5SDimitry Andric       return false; // Unknown source, may be null
12240b57cec5SDimitry Andric     };
12250b57cec5SDimitry Andric     llvm_unreachable("should have either continued or returned");
12260b57cec5SDimitry Andric   }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric   return true;
12290b57cec5SDimitry Andric }
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric /// Deduce nonnull attributes for the SCC.
1232349cc55cSDimitry Andric static void addNonNullAttrs(const SCCNodeSet &SCCNodes,
1233349cc55cSDimitry Andric                             SmallSet<Function *, 8> &Changed) {
12340b57cec5SDimitry Andric   // Speculative that all functions in the SCC return only nonnull
12350b57cec5SDimitry Andric   // pointers.  We may refute this as we analyze functions.
12360b57cec5SDimitry Andric   bool SCCReturnsNonNull = true;
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric   // Check each function in turn, determining which functions return nonnull
12390b57cec5SDimitry Andric   // pointers.
12400b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
12410b57cec5SDimitry Andric     // Already nonnull.
1242349cc55cSDimitry Andric     if (F->getAttributes().hasRetAttr(Attribute::NonNull))
12430b57cec5SDimitry Andric       continue;
12440b57cec5SDimitry Andric 
12450b57cec5SDimitry Andric     // We can infer and propagate function attributes only when we know that the
12460b57cec5SDimitry Andric     // definition we'll get at link time is *exactly* the definition we see now.
12470b57cec5SDimitry Andric     // For more details, see GlobalValue::mayBeDerefined.
12480b57cec5SDimitry Andric     if (!F->hasExactDefinition())
1249349cc55cSDimitry Andric       return;
12500b57cec5SDimitry Andric 
12510b57cec5SDimitry Andric     // We annotate nonnull return values, which are only applicable to
12520b57cec5SDimitry Andric     // pointer types.
12530b57cec5SDimitry Andric     if (!F->getReturnType()->isPointerTy())
12540b57cec5SDimitry Andric       continue;
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric     bool Speculative = false;
12570b57cec5SDimitry Andric     if (isReturnNonNull(F, SCCNodes, Speculative)) {
12580b57cec5SDimitry Andric       if (!Speculative) {
12590b57cec5SDimitry Andric         // Mark the function eagerly since we may discover a function
12600b57cec5SDimitry Andric         // which prevents us from speculating about the entire SCC
12610b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Eagerly marking " << F->getName()
12620b57cec5SDimitry Andric                           << " as nonnull\n");
1263349cc55cSDimitry Andric         F->addRetAttr(Attribute::NonNull);
12640b57cec5SDimitry Andric         ++NumNonNullReturn;
1265349cc55cSDimitry Andric         Changed.insert(F);
12660b57cec5SDimitry Andric       }
12670b57cec5SDimitry Andric       continue;
12680b57cec5SDimitry Andric     }
12690b57cec5SDimitry Andric     // At least one function returns something which could be null, can't
12700b57cec5SDimitry Andric     // speculate any more.
12710b57cec5SDimitry Andric     SCCReturnsNonNull = false;
12720b57cec5SDimitry Andric   }
12730b57cec5SDimitry Andric 
12740b57cec5SDimitry Andric   if (SCCReturnsNonNull) {
12750b57cec5SDimitry Andric     for (Function *F : SCCNodes) {
1276349cc55cSDimitry Andric       if (F->getAttributes().hasRetAttr(Attribute::NonNull) ||
12770b57cec5SDimitry Andric           !F->getReturnType()->isPointerTy())
12780b57cec5SDimitry Andric         continue;
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "SCC marking " << F->getName() << " as nonnull\n");
1281349cc55cSDimitry Andric       F->addRetAttr(Attribute::NonNull);
12820b57cec5SDimitry Andric       ++NumNonNullReturn;
1283349cc55cSDimitry Andric       Changed.insert(F);
12840b57cec5SDimitry Andric     }
12850b57cec5SDimitry Andric   }
12860b57cec5SDimitry Andric }
12870b57cec5SDimitry Andric 
1288647cbc5dSDimitry Andric /// Deduce noundef attributes for the SCC.
1289647cbc5dSDimitry Andric static void addNoUndefAttrs(const SCCNodeSet &SCCNodes,
1290647cbc5dSDimitry Andric                             SmallSet<Function *, 8> &Changed) {
1291647cbc5dSDimitry Andric   // Check each function in turn, determining which functions return noundef
1292647cbc5dSDimitry Andric   // values.
1293647cbc5dSDimitry Andric   for (Function *F : SCCNodes) {
1294647cbc5dSDimitry Andric     // Already noundef.
1295*0fca6ea1SDimitry Andric     AttributeList Attrs = F->getAttributes();
1296*0fca6ea1SDimitry Andric     if (Attrs.hasRetAttr(Attribute::NoUndef))
1297647cbc5dSDimitry Andric       continue;
1298647cbc5dSDimitry Andric 
1299647cbc5dSDimitry Andric     // We can infer and propagate function attributes only when we know that the
1300647cbc5dSDimitry Andric     // definition we'll get at link time is *exactly* the definition we see now.
1301647cbc5dSDimitry Andric     // For more details, see GlobalValue::mayBeDerefined.
1302647cbc5dSDimitry Andric     if (!F->hasExactDefinition())
1303647cbc5dSDimitry Andric       return;
1304647cbc5dSDimitry Andric 
1305647cbc5dSDimitry Andric     // MemorySanitizer assumes that the definition and declaration of a
1306647cbc5dSDimitry Andric     // function will be consistent. A function with sanitize_memory attribute
1307647cbc5dSDimitry Andric     // should be skipped from inference.
1308647cbc5dSDimitry Andric     if (F->hasFnAttribute(Attribute::SanitizeMemory))
1309647cbc5dSDimitry Andric       continue;
1310647cbc5dSDimitry Andric 
1311647cbc5dSDimitry Andric     if (F->getReturnType()->isVoidTy())
1312647cbc5dSDimitry Andric       continue;
1313647cbc5dSDimitry Andric 
1314*0fca6ea1SDimitry Andric     const DataLayout &DL = F->getDataLayout();
1315*0fca6ea1SDimitry Andric     if (all_of(*F, [&](BasicBlock &BB) {
1316647cbc5dSDimitry Andric           if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
1317647cbc5dSDimitry Andric             // TODO: perform context-sensitive analysis?
1318*0fca6ea1SDimitry Andric             Value *RetVal = Ret->getReturnValue();
1319*0fca6ea1SDimitry Andric             if (!isGuaranteedNotToBeUndefOrPoison(RetVal))
1320*0fca6ea1SDimitry Andric               return false;
1321*0fca6ea1SDimitry Andric 
1322*0fca6ea1SDimitry Andric             // We know the original return value is not poison now, but it
1323*0fca6ea1SDimitry Andric             // could still be converted to poison by another return attribute.
1324*0fca6ea1SDimitry Andric             // Try to explicitly re-prove the relevant attributes.
1325*0fca6ea1SDimitry Andric             if (Attrs.hasRetAttr(Attribute::NonNull) &&
1326*0fca6ea1SDimitry Andric                 !isKnownNonZero(RetVal, DL))
1327*0fca6ea1SDimitry Andric               return false;
1328*0fca6ea1SDimitry Andric 
1329*0fca6ea1SDimitry Andric             if (MaybeAlign Align = Attrs.getRetAlignment())
1330*0fca6ea1SDimitry Andric               if (RetVal->getPointerAlignment(DL) < *Align)
1331*0fca6ea1SDimitry Andric                 return false;
1332*0fca6ea1SDimitry Andric 
1333*0fca6ea1SDimitry Andric             Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1334*0fca6ea1SDimitry Andric             if (Attr.isValid() &&
1335*0fca6ea1SDimitry Andric                 !Attr.getRange().contains(
1336*0fca6ea1SDimitry Andric                     computeConstantRange(RetVal, /*ForSigned=*/false)))
1337*0fca6ea1SDimitry Andric               return false;
1338647cbc5dSDimitry Andric           }
1339647cbc5dSDimitry Andric           return true;
1340647cbc5dSDimitry Andric         })) {
1341647cbc5dSDimitry Andric       F->addRetAttr(Attribute::NoUndef);
1342647cbc5dSDimitry Andric       ++NumNoUndefReturn;
1343647cbc5dSDimitry Andric       Changed.insert(F);
1344647cbc5dSDimitry Andric     }
1345647cbc5dSDimitry Andric   }
1346647cbc5dSDimitry Andric }
1347647cbc5dSDimitry Andric 
13480b57cec5SDimitry Andric namespace {
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric /// Collects a set of attribute inference requests and performs them all in one
13510b57cec5SDimitry Andric /// go on a single SCC Node. Inference involves scanning function bodies
13520b57cec5SDimitry Andric /// looking for instructions that violate attribute assumptions.
13530b57cec5SDimitry Andric /// As soon as all the bodies are fine we are free to set the attribute.
13540b57cec5SDimitry Andric /// Customization of inference for individual attributes is performed by
13550b57cec5SDimitry Andric /// providing a handful of predicates for each attribute.
13560b57cec5SDimitry Andric class AttributeInferer {
13570b57cec5SDimitry Andric public:
13580b57cec5SDimitry Andric   /// Describes a request for inference of a single attribute.
13590b57cec5SDimitry Andric   struct InferenceDescriptor {
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric     /// Returns true if this function does not have to be handled.
13620b57cec5SDimitry Andric     /// General intent for this predicate is to provide an optimization
13630b57cec5SDimitry Andric     /// for functions that do not need this attribute inference at all
13640b57cec5SDimitry Andric     /// (say, for functions that already have the attribute).
13650b57cec5SDimitry Andric     std::function<bool(const Function &)> SkipFunction;
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric     /// Returns true if this instruction violates attribute assumptions.
13680b57cec5SDimitry Andric     std::function<bool(Instruction &)> InstrBreaksAttribute;
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric     /// Sets the inferred attribute for this function.
13710b57cec5SDimitry Andric     std::function<void(Function &)> SetAttribute;
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric     /// Attribute we derive.
13740b57cec5SDimitry Andric     Attribute::AttrKind AKind;
13750b57cec5SDimitry Andric 
13760b57cec5SDimitry Andric     /// If true, only "exact" definitions can be used to infer this attribute.
13770b57cec5SDimitry Andric     /// See GlobalValue::isDefinitionExact.
13780b57cec5SDimitry Andric     bool RequiresExactDefinition;
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric     InferenceDescriptor(Attribute::AttrKind AK,
13810b57cec5SDimitry Andric                         std::function<bool(const Function &)> SkipFunc,
13820b57cec5SDimitry Andric                         std::function<bool(Instruction &)> InstrScan,
13830b57cec5SDimitry Andric                         std::function<void(Function &)> SetAttr,
13840b57cec5SDimitry Andric                         bool ReqExactDef)
13850b57cec5SDimitry Andric         : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
13860b57cec5SDimitry Andric           SetAttribute(SetAttr), AKind(AK),
13870b57cec5SDimitry Andric           RequiresExactDefinition(ReqExactDef) {}
13880b57cec5SDimitry Andric   };
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric private:
13910b57cec5SDimitry Andric   SmallVector<InferenceDescriptor, 4> InferenceDescriptors;
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric public:
13940b57cec5SDimitry Andric   void registerAttrInference(InferenceDescriptor AttrInference) {
13950b57cec5SDimitry Andric     InferenceDescriptors.push_back(AttrInference);
13960b57cec5SDimitry Andric   }
13970b57cec5SDimitry Andric 
1398349cc55cSDimitry Andric   void run(const SCCNodeSet &SCCNodes, SmallSet<Function *, 8> &Changed);
13990b57cec5SDimitry Andric };
14000b57cec5SDimitry Andric 
14010b57cec5SDimitry Andric /// Perform all the requested attribute inference actions according to the
14020b57cec5SDimitry Andric /// attribute predicates stored before.
1403349cc55cSDimitry Andric void AttributeInferer::run(const SCCNodeSet &SCCNodes,
1404349cc55cSDimitry Andric                            SmallSet<Function *, 8> &Changed) {
14050b57cec5SDimitry Andric   SmallVector<InferenceDescriptor, 4> InferInSCC = InferenceDescriptors;
14060b57cec5SDimitry Andric   // Go through all the functions in SCC and check corresponding attribute
14070b57cec5SDimitry Andric   // assumptions for each of them. Attributes that are invalid for this SCC
14080b57cec5SDimitry Andric   // will be removed from InferInSCC.
14090b57cec5SDimitry Andric   for (Function *F : SCCNodes) {
14100b57cec5SDimitry Andric 
14110b57cec5SDimitry Andric     // No attributes whose assumptions are still valid - done.
14120b57cec5SDimitry Andric     if (InferInSCC.empty())
1413349cc55cSDimitry Andric       return;
14140b57cec5SDimitry Andric 
14150b57cec5SDimitry Andric     // Check if our attributes ever need scanning/can be scanned.
14160b57cec5SDimitry Andric     llvm::erase_if(InferInSCC, [F](const InferenceDescriptor &ID) {
14170b57cec5SDimitry Andric       if (ID.SkipFunction(*F))
14180b57cec5SDimitry Andric         return false;
14190b57cec5SDimitry Andric 
14200b57cec5SDimitry Andric       // Remove from further inference (invalidate) when visiting a function
14210b57cec5SDimitry Andric       // that has no instructions to scan/has an unsuitable definition.
14220b57cec5SDimitry Andric       return F->isDeclaration() ||
14230b57cec5SDimitry Andric              (ID.RequiresExactDefinition && !F->hasExactDefinition());
14240b57cec5SDimitry Andric     });
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric     // For each attribute still in InferInSCC that doesn't explicitly skip F,
14270b57cec5SDimitry Andric     // set up the F instructions scan to verify assumptions of the attribute.
14280b57cec5SDimitry Andric     SmallVector<InferenceDescriptor, 4> InferInThisFunc;
14290b57cec5SDimitry Andric     llvm::copy_if(
14300b57cec5SDimitry Andric         InferInSCC, std::back_inserter(InferInThisFunc),
14310b57cec5SDimitry Andric         [F](const InferenceDescriptor &ID) { return !ID.SkipFunction(*F); });
14320b57cec5SDimitry Andric 
14330b57cec5SDimitry Andric     if (InferInThisFunc.empty())
14340b57cec5SDimitry Andric       continue;
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric     // Start instruction scan.
14370b57cec5SDimitry Andric     for (Instruction &I : instructions(*F)) {
14380b57cec5SDimitry Andric       llvm::erase_if(InferInThisFunc, [&](const InferenceDescriptor &ID) {
14390b57cec5SDimitry Andric         if (!ID.InstrBreaksAttribute(I))
14400b57cec5SDimitry Andric           return false;
14410b57cec5SDimitry Andric         // Remove attribute from further inference on any other functions
14420b57cec5SDimitry Andric         // because attribute assumptions have just been violated.
14430b57cec5SDimitry Andric         llvm::erase_if(InferInSCC, [&ID](const InferenceDescriptor &D) {
14440b57cec5SDimitry Andric           return D.AKind == ID.AKind;
14450b57cec5SDimitry Andric         });
14460b57cec5SDimitry Andric         // Remove attribute from the rest of current instruction scan.
14470b57cec5SDimitry Andric         return true;
14480b57cec5SDimitry Andric       });
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric       if (InferInThisFunc.empty())
14510b57cec5SDimitry Andric         break;
14520b57cec5SDimitry Andric     }
14530b57cec5SDimitry Andric   }
14540b57cec5SDimitry Andric 
14550b57cec5SDimitry Andric   if (InferInSCC.empty())
1456349cc55cSDimitry Andric     return;
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric   for (Function *F : SCCNodes)
14590b57cec5SDimitry Andric     // At this point InferInSCC contains only functions that were either:
14600b57cec5SDimitry Andric     //   - explicitly skipped from scan/inference, or
14610b57cec5SDimitry Andric     //   - verified to have no instructions that break attribute assumptions.
14620b57cec5SDimitry Andric     // Hence we just go and force the attribute for all non-skipped functions.
14630b57cec5SDimitry Andric     for (auto &ID : InferInSCC) {
14640b57cec5SDimitry Andric       if (ID.SkipFunction(*F))
14650b57cec5SDimitry Andric         continue;
1466349cc55cSDimitry Andric       Changed.insert(F);
14670b57cec5SDimitry Andric       ID.SetAttribute(*F);
14680b57cec5SDimitry Andric     }
14690b57cec5SDimitry Andric }
14700b57cec5SDimitry Andric 
1471e8d8bef9SDimitry Andric struct SCCNodesResult {
1472e8d8bef9SDimitry Andric   SCCNodeSet SCCNodes;
1473e8d8bef9SDimitry Andric   bool HasUnknownCall;
1474e8d8bef9SDimitry Andric };
1475e8d8bef9SDimitry Andric 
14760b57cec5SDimitry Andric } // end anonymous namespace
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric /// Helper for non-Convergent inference predicate InstrBreaksAttribute.
14790b57cec5SDimitry Andric static bool InstrBreaksNonConvergent(Instruction &I,
14800b57cec5SDimitry Andric                                      const SCCNodeSet &SCCNodes) {
14815ffd83dbSDimitry Andric   const CallBase *CB = dyn_cast<CallBase>(&I);
14820b57cec5SDimitry Andric   // Breaks non-convergent assumption if CS is a convergent call to a function
14830b57cec5SDimitry Andric   // not in the SCC.
14845ffd83dbSDimitry Andric   return CB && CB->isConvergent() &&
1485349cc55cSDimitry Andric          !SCCNodes.contains(CB->getCalledFunction());
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric /// Helper for NoUnwind inference predicate InstrBreaksAttribute.
14890b57cec5SDimitry Andric static bool InstrBreaksNonThrowing(Instruction &I, const SCCNodeSet &SCCNodes) {
149006c3fb27SDimitry Andric   if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
14910b57cec5SDimitry Andric     return false;
14920b57cec5SDimitry Andric   if (const auto *CI = dyn_cast<CallInst>(&I)) {
14930b57cec5SDimitry Andric     if (Function *Callee = CI->getCalledFunction()) {
14940b57cec5SDimitry Andric       // I is a may-throw call to a function inside our SCC. This doesn't
14950b57cec5SDimitry Andric       // invalidate our current working assumption that the SCC is no-throw; we
14960b57cec5SDimitry Andric       // just have to scan that other function.
1497e8d8bef9SDimitry Andric       if (SCCNodes.contains(Callee))
14980b57cec5SDimitry Andric         return false;
14990b57cec5SDimitry Andric     }
15000b57cec5SDimitry Andric   }
15010b57cec5SDimitry Andric   return true;
15020b57cec5SDimitry Andric }
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric /// Helper for NoFree inference predicate InstrBreaksAttribute.
15050b57cec5SDimitry Andric static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes) {
15065ffd83dbSDimitry Andric   CallBase *CB = dyn_cast<CallBase>(&I);
15075ffd83dbSDimitry Andric   if (!CB)
15080b57cec5SDimitry Andric     return false;
15090b57cec5SDimitry Andric 
1510fe6060f1SDimitry Andric   if (CB->hasFnAttr(Attribute::NoFree))
15110b57cec5SDimitry Andric     return false;
15120b57cec5SDimitry Andric 
1513fe6060f1SDimitry Andric   // Speculatively assume in SCC.
1514fe6060f1SDimitry Andric   if (Function *Callee = CB->getCalledFunction())
1515e8d8bef9SDimitry Andric     if (SCCNodes.contains(Callee))
15160b57cec5SDimitry Andric       return false;
15170b57cec5SDimitry Andric 
15180b57cec5SDimitry Andric   return true;
15190b57cec5SDimitry Andric }
15200b57cec5SDimitry Andric 
152106c3fb27SDimitry Andric // Return true if this is an atomic which has an ordering stronger than
152206c3fb27SDimitry Andric // unordered.  Note that this is different than the predicate we use in
152306c3fb27SDimitry Andric // Attributor.  Here we chose to be conservative and consider monotonic
152406c3fb27SDimitry Andric // operations potentially synchronizing.  We generally don't do much with
152506c3fb27SDimitry Andric // monotonic operations, so this is simply risk reduction.
152606c3fb27SDimitry Andric static bool isOrderedAtomic(Instruction *I) {
152706c3fb27SDimitry Andric   if (!I->isAtomic())
152806c3fb27SDimitry Andric     return false;
152906c3fb27SDimitry Andric 
153006c3fb27SDimitry Andric   if (auto *FI = dyn_cast<FenceInst>(I))
153106c3fb27SDimitry Andric     // All legal orderings for fence are stronger than monotonic.
153206c3fb27SDimitry Andric     return FI->getSyncScopeID() != SyncScope::SingleThread;
153306c3fb27SDimitry Andric   else if (isa<AtomicCmpXchgInst>(I) || isa<AtomicRMWInst>(I))
153406c3fb27SDimitry Andric     return true;
153506c3fb27SDimitry Andric   else if (auto *SI = dyn_cast<StoreInst>(I))
153606c3fb27SDimitry Andric     return !SI->isUnordered();
153706c3fb27SDimitry Andric   else if (auto *LI = dyn_cast<LoadInst>(I))
153806c3fb27SDimitry Andric     return !LI->isUnordered();
153906c3fb27SDimitry Andric   else {
154006c3fb27SDimitry Andric     llvm_unreachable("unknown atomic instruction?");
154106c3fb27SDimitry Andric   }
154206c3fb27SDimitry Andric }
154306c3fb27SDimitry Andric 
154406c3fb27SDimitry Andric static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes) {
154506c3fb27SDimitry Andric   // Volatile may synchronize
154606c3fb27SDimitry Andric   if (I.isVolatile())
154706c3fb27SDimitry Andric     return true;
154806c3fb27SDimitry Andric 
154906c3fb27SDimitry Andric   // An ordered atomic may synchronize.  (See comment about on monotonic.)
155006c3fb27SDimitry Andric   if (isOrderedAtomic(&I))
155106c3fb27SDimitry Andric     return true;
155206c3fb27SDimitry Andric 
155306c3fb27SDimitry Andric   auto *CB = dyn_cast<CallBase>(&I);
155406c3fb27SDimitry Andric   if (!CB)
155506c3fb27SDimitry Andric     // Non call site cases covered by the two checks above
155606c3fb27SDimitry Andric     return false;
155706c3fb27SDimitry Andric 
155806c3fb27SDimitry Andric   if (CB->hasFnAttr(Attribute::NoSync))
155906c3fb27SDimitry Andric     return false;
156006c3fb27SDimitry Andric 
156106c3fb27SDimitry Andric   // Non volatile memset/memcpy/memmoves are nosync
156206c3fb27SDimitry Andric   // NOTE: Only intrinsics with volatile flags should be handled here.  All
156306c3fb27SDimitry Andric   // others should be marked in Intrinsics.td.
156406c3fb27SDimitry Andric   if (auto *MI = dyn_cast<MemIntrinsic>(&I))
156506c3fb27SDimitry Andric     if (!MI->isVolatile())
156606c3fb27SDimitry Andric       return false;
156706c3fb27SDimitry Andric 
156806c3fb27SDimitry Andric   // Speculatively assume in SCC.
156906c3fb27SDimitry Andric   if (Function *Callee = CB->getCalledFunction())
157006c3fb27SDimitry Andric     if (SCCNodes.contains(Callee))
157106c3fb27SDimitry Andric       return false;
157206c3fb27SDimitry Andric 
157306c3fb27SDimitry Andric   return true;
157406c3fb27SDimitry Andric }
157506c3fb27SDimitry Andric 
1576e8d8bef9SDimitry Andric /// Attempt to remove convergent function attribute when possible.
15770b57cec5SDimitry Andric ///
15780b57cec5SDimitry Andric /// Returns true if any changes to function attributes were made.
1579349cc55cSDimitry Andric static void inferConvergent(const SCCNodeSet &SCCNodes,
1580349cc55cSDimitry Andric                             SmallSet<Function *, 8> &Changed) {
15810b57cec5SDimitry Andric   AttributeInferer AI;
15820b57cec5SDimitry Andric 
15830b57cec5SDimitry Andric   // Request to remove the convergent attribute from all functions in the SCC
15840b57cec5SDimitry Andric   // if every callsite within the SCC is not convergent (except for calls
15850b57cec5SDimitry Andric   // to functions within the SCC).
15860b57cec5SDimitry Andric   // Note: Removal of the attr from the callsites will happen in
15870b57cec5SDimitry Andric   // InstCombineCalls separately.
15880b57cec5SDimitry Andric   AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
15890b57cec5SDimitry Andric       Attribute::Convergent,
15900b57cec5SDimitry Andric       // Skip non-convergent functions.
15910b57cec5SDimitry Andric       [](const Function &F) { return !F.isConvergent(); },
15920b57cec5SDimitry Andric       // Instructions that break non-convergent assumption.
15930b57cec5SDimitry Andric       [SCCNodes](Instruction &I) {
15940b57cec5SDimitry Andric         return InstrBreaksNonConvergent(I, SCCNodes);
15950b57cec5SDimitry Andric       },
15960b57cec5SDimitry Andric       [](Function &F) {
15970b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Removing convergent attr from fn " << F.getName()
15980b57cec5SDimitry Andric                           << "\n");
15990b57cec5SDimitry Andric         F.setNotConvergent();
16000b57cec5SDimitry Andric       },
16010b57cec5SDimitry Andric       /* RequiresExactDefinition= */ false});
1602e8d8bef9SDimitry Andric   // Perform all the requested attribute inference actions.
1603349cc55cSDimitry Andric   AI.run(SCCNodes, Changed);
1604e8d8bef9SDimitry Andric }
1605e8d8bef9SDimitry Andric 
1606e8d8bef9SDimitry Andric /// Infer attributes from all functions in the SCC by scanning every
160706c3fb27SDimitry Andric /// instruction for compliance to the attribute assumptions.
1608e8d8bef9SDimitry Andric ///
1609e8d8bef9SDimitry Andric /// Returns true if any changes to function attributes were made.
1610349cc55cSDimitry Andric static void inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes,
1611349cc55cSDimitry Andric                                          SmallSet<Function *, 8> &Changed) {
1612e8d8bef9SDimitry Andric   AttributeInferer AI;
16130b57cec5SDimitry Andric 
16140b57cec5SDimitry Andric   if (!DisableNoUnwindInference)
16150b57cec5SDimitry Andric     // Request to infer nounwind attribute for all the functions in the SCC if
16160b57cec5SDimitry Andric     // every callsite within the SCC is not throwing (except for calls to
16170b57cec5SDimitry Andric     // functions within the SCC). Note that nounwind attribute suffers from
16180b57cec5SDimitry Andric     // derefinement - results may change depending on how functions are
16190b57cec5SDimitry Andric     // optimized. Thus it can be inferred only from exact definitions.
16200b57cec5SDimitry Andric     AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
16210b57cec5SDimitry Andric         Attribute::NoUnwind,
16220b57cec5SDimitry Andric         // Skip non-throwing functions.
16230b57cec5SDimitry Andric         [](const Function &F) { return F.doesNotThrow(); },
16240b57cec5SDimitry Andric         // Instructions that break non-throwing assumption.
16255ffd83dbSDimitry Andric         [&SCCNodes](Instruction &I) {
16260b57cec5SDimitry Andric           return InstrBreaksNonThrowing(I, SCCNodes);
16270b57cec5SDimitry Andric         },
16280b57cec5SDimitry Andric         [](Function &F) {
16290b57cec5SDimitry Andric           LLVM_DEBUG(dbgs()
16300b57cec5SDimitry Andric                      << "Adding nounwind attr to fn " << F.getName() << "\n");
16310b57cec5SDimitry Andric           F.setDoesNotThrow();
16320b57cec5SDimitry Andric           ++NumNoUnwind;
16330b57cec5SDimitry Andric         },
16340b57cec5SDimitry Andric         /* RequiresExactDefinition= */ true});
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric   if (!DisableNoFreeInference)
16370b57cec5SDimitry Andric     // Request to infer nofree attribute for all the functions in the SCC if
16380b57cec5SDimitry Andric     // every callsite within the SCC does not directly or indirectly free
16390b57cec5SDimitry Andric     // memory (except for calls to functions within the SCC). Note that nofree
16400b57cec5SDimitry Andric     // attribute suffers from derefinement - results may change depending on
16410b57cec5SDimitry Andric     // how functions are optimized. Thus it can be inferred only from exact
16420b57cec5SDimitry Andric     // definitions.
16430b57cec5SDimitry Andric     AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
16440b57cec5SDimitry Andric         Attribute::NoFree,
16450b57cec5SDimitry Andric         // Skip functions known not to free memory.
16460b57cec5SDimitry Andric         [](const Function &F) { return F.doesNotFreeMemory(); },
16470b57cec5SDimitry Andric         // Instructions that break non-deallocating assumption.
16485ffd83dbSDimitry Andric         [&SCCNodes](Instruction &I) {
16490b57cec5SDimitry Andric           return InstrBreaksNoFree(I, SCCNodes);
16500b57cec5SDimitry Andric         },
16510b57cec5SDimitry Andric         [](Function &F) {
16520b57cec5SDimitry Andric           LLVM_DEBUG(dbgs()
16530b57cec5SDimitry Andric                      << "Adding nofree attr to fn " << F.getName() << "\n");
16540b57cec5SDimitry Andric           F.setDoesNotFreeMemory();
16550b57cec5SDimitry Andric           ++NumNoFree;
16560b57cec5SDimitry Andric         },
16570b57cec5SDimitry Andric         /* RequiresExactDefinition= */ true});
16580b57cec5SDimitry Andric 
165906c3fb27SDimitry Andric   AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
166006c3fb27SDimitry Andric       Attribute::NoSync,
166106c3fb27SDimitry Andric       // Skip already marked functions.
166206c3fb27SDimitry Andric       [](const Function &F) { return F.hasNoSync(); },
166306c3fb27SDimitry Andric       // Instructions that break nosync assumption.
166406c3fb27SDimitry Andric       [&SCCNodes](Instruction &I) {
166506c3fb27SDimitry Andric         return InstrBreaksNoSync(I, SCCNodes);
166606c3fb27SDimitry Andric       },
166706c3fb27SDimitry Andric       [](Function &F) {
166806c3fb27SDimitry Andric         LLVM_DEBUG(dbgs()
166906c3fb27SDimitry Andric                    << "Adding nosync attr to fn " << F.getName() << "\n");
167006c3fb27SDimitry Andric         F.setNoSync();
167106c3fb27SDimitry Andric         ++NumNoSync;
167206c3fb27SDimitry Andric       },
167306c3fb27SDimitry Andric       /* RequiresExactDefinition= */ true});
167406c3fb27SDimitry Andric 
16750b57cec5SDimitry Andric   // Perform all the requested attribute inference actions.
1676349cc55cSDimitry Andric   AI.run(SCCNodes, Changed);
16770b57cec5SDimitry Andric }
16780b57cec5SDimitry Andric 
1679349cc55cSDimitry Andric static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
1680349cc55cSDimitry Andric                               SmallSet<Function *, 8> &Changed) {
16810b57cec5SDimitry Andric   // Try and identify functions that do not recurse.
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric   // If the SCC contains multiple nodes we know for sure there is recursion.
16840b57cec5SDimitry Andric   if (SCCNodes.size() != 1)
1685349cc55cSDimitry Andric     return;
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric   Function *F = *SCCNodes.begin();
16880b57cec5SDimitry Andric   if (!F || !F->hasExactDefinition() || F->doesNotRecurse())
1689349cc55cSDimitry Andric     return;
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric   // If all of the calls in F are identifiable and are to norecurse functions, F
16920b57cec5SDimitry Andric   // is norecurse. This check also detects self-recursion as F is not currently
16930b57cec5SDimitry Andric   // marked norecurse, so any called from F to F will not be marked norecurse.
16940b57cec5SDimitry Andric   for (auto &BB : *F)
16950b57cec5SDimitry Andric     for (auto &I : BB.instructionsWithoutDebug())
16965ffd83dbSDimitry Andric       if (auto *CB = dyn_cast<CallBase>(&I)) {
16975ffd83dbSDimitry Andric         Function *Callee = CB->getCalledFunction();
1698647cbc5dSDimitry Andric         if (!Callee || Callee == F ||
1699647cbc5dSDimitry Andric             (!Callee->doesNotRecurse() &&
1700647cbc5dSDimitry Andric              !(Callee->isDeclaration() &&
1701647cbc5dSDimitry Andric                Callee->hasFnAttribute(Attribute::NoCallback))))
17020b57cec5SDimitry Andric           // Function calls a potentially recursive function.
1703349cc55cSDimitry Andric           return;
17040b57cec5SDimitry Andric       }
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   // Every call was to a non-recursive function other than this function, and
17070b57cec5SDimitry Andric   // we have no indirect recursion as the SCC size is one. This function cannot
17080b57cec5SDimitry Andric   // recurse.
1709e8d8bef9SDimitry Andric   F->setDoesNotRecurse();
1710e8d8bef9SDimitry Andric   ++NumNoRecurse;
1711349cc55cSDimitry Andric   Changed.insert(F);
1712e8d8bef9SDimitry Andric }
1713e8d8bef9SDimitry Andric 
1714e8d8bef9SDimitry Andric static bool instructionDoesNotReturn(Instruction &I) {
1715fe6060f1SDimitry Andric   if (auto *CB = dyn_cast<CallBase>(&I))
1716fe6060f1SDimitry Andric     return CB->hasFnAttr(Attribute::NoReturn);
1717e8d8bef9SDimitry Andric   return false;
1718e8d8bef9SDimitry Andric }
1719e8d8bef9SDimitry Andric 
1720e8d8bef9SDimitry Andric // A basic block can only return if it terminates with a ReturnInst and does not
1721e8d8bef9SDimitry Andric // contain calls to noreturn functions.
1722e8d8bef9SDimitry Andric static bool basicBlockCanReturn(BasicBlock &BB) {
1723e8d8bef9SDimitry Andric   if (!isa<ReturnInst>(BB.getTerminator()))
1724e8d8bef9SDimitry Andric     return false;
1725e8d8bef9SDimitry Andric   return none_of(BB, instructionDoesNotReturn);
1726e8d8bef9SDimitry Andric }
1727e8d8bef9SDimitry Andric 
1728d781ede6SDimitry Andric // FIXME: this doesn't handle recursion.
1729d781ede6SDimitry Andric static bool canReturn(Function &F) {
1730d781ede6SDimitry Andric   SmallVector<BasicBlock *, 16> Worklist;
1731d781ede6SDimitry Andric   SmallPtrSet<BasicBlock *, 16> Visited;
1732d781ede6SDimitry Andric 
1733d781ede6SDimitry Andric   Visited.insert(&F.front());
1734d781ede6SDimitry Andric   Worklist.push_back(&F.front());
1735d781ede6SDimitry Andric 
1736d781ede6SDimitry Andric   do {
1737d781ede6SDimitry Andric     BasicBlock *BB = Worklist.pop_back_val();
1738d781ede6SDimitry Andric     if (basicBlockCanReturn(*BB))
1739d781ede6SDimitry Andric       return true;
1740d781ede6SDimitry Andric     for (BasicBlock *Succ : successors(BB))
1741d781ede6SDimitry Andric       if (Visited.insert(Succ).second)
1742d781ede6SDimitry Andric         Worklist.push_back(Succ);
1743d781ede6SDimitry Andric   } while (!Worklist.empty());
1744d781ede6SDimitry Andric 
1745d781ede6SDimitry Andric   return false;
1746d781ede6SDimitry Andric }
1747d781ede6SDimitry Andric 
1748e8d8bef9SDimitry Andric // Set the noreturn function attribute if possible.
1749349cc55cSDimitry Andric static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
1750349cc55cSDimitry Andric                              SmallSet<Function *, 8> &Changed) {
1751e8d8bef9SDimitry Andric   for (Function *F : SCCNodes) {
1752e8d8bef9SDimitry Andric     if (!F || !F->hasExactDefinition() || F->hasFnAttribute(Attribute::Naked) ||
1753e8d8bef9SDimitry Andric         F->doesNotReturn())
1754e8d8bef9SDimitry Andric       continue;
1755e8d8bef9SDimitry Andric 
1756d781ede6SDimitry Andric     if (!canReturn(*F)) {
1757e8d8bef9SDimitry Andric       F->setDoesNotReturn();
1758349cc55cSDimitry Andric       Changed.insert(F);
1759e8d8bef9SDimitry Andric     }
1760e8d8bef9SDimitry Andric   }
1761e8d8bef9SDimitry Andric }
1762e8d8bef9SDimitry Andric 
1763e8d8bef9SDimitry Andric static bool functionWillReturn(const Function &F) {
1764fe6060f1SDimitry Andric   // We can infer and propagate function attributes only when we know that the
1765fe6060f1SDimitry Andric   // definition we'll get at link time is *exactly* the definition we see now.
1766fe6060f1SDimitry Andric   // For more details, see GlobalValue::mayBeDerefined.
1767fe6060f1SDimitry Andric   if (!F.hasExactDefinition())
1768fe6060f1SDimitry Andric     return false;
1769fe6060f1SDimitry Andric 
1770e8d8bef9SDimitry Andric   // Must-progress function without side-effects must return.
1771e8d8bef9SDimitry Andric   if (F.mustProgress() && F.onlyReadsMemory())
1772e8d8bef9SDimitry Andric     return true;
1773e8d8bef9SDimitry Andric 
1774e8d8bef9SDimitry Andric   // Can only analyze functions with a definition.
1775e8d8bef9SDimitry Andric   if (F.isDeclaration())
1776e8d8bef9SDimitry Andric     return false;
1777e8d8bef9SDimitry Andric 
1778e8d8bef9SDimitry Andric   // Functions with loops require more sophisticated analysis, as the loop
1779e8d8bef9SDimitry Andric   // may be infinite. For now, don't try to handle them.
1780e8d8bef9SDimitry Andric   SmallVector<std::pair<const BasicBlock *, const BasicBlock *>> Backedges;
1781e8d8bef9SDimitry Andric   FindFunctionBackedges(F, Backedges);
1782e8d8bef9SDimitry Andric   if (!Backedges.empty())
1783e8d8bef9SDimitry Andric     return false;
1784e8d8bef9SDimitry Andric 
1785e8d8bef9SDimitry Andric   // If there are no loops, then the function is willreturn if all calls in
1786e8d8bef9SDimitry Andric   // it are willreturn.
1787e8d8bef9SDimitry Andric   return all_of(instructions(F), [](const Instruction &I) {
1788d409305fSDimitry Andric     return I.willReturn();
1789e8d8bef9SDimitry Andric   });
1790e8d8bef9SDimitry Andric }
1791e8d8bef9SDimitry Andric 
1792e8d8bef9SDimitry Andric // Set the willreturn function attribute if possible.
1793349cc55cSDimitry Andric static void addWillReturn(const SCCNodeSet &SCCNodes,
1794349cc55cSDimitry Andric                           SmallSet<Function *, 8> &Changed) {
1795e8d8bef9SDimitry Andric   for (Function *F : SCCNodes) {
1796e8d8bef9SDimitry Andric     if (!F || F->willReturn() || !functionWillReturn(*F))
1797e8d8bef9SDimitry Andric       continue;
1798e8d8bef9SDimitry Andric 
1799e8d8bef9SDimitry Andric     F->setWillReturn();
1800e8d8bef9SDimitry Andric     NumWillReturn++;
1801349cc55cSDimitry Andric     Changed.insert(F);
1802e8d8bef9SDimitry Andric   }
1803e8d8bef9SDimitry Andric }
1804e8d8bef9SDimitry Andric 
1805e8d8bef9SDimitry Andric static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
1806e8d8bef9SDimitry Andric   SCCNodesResult Res;
1807e8d8bef9SDimitry Andric   Res.HasUnknownCall = false;
1808e8d8bef9SDimitry Andric   for (Function *F : Functions) {
1809349cc55cSDimitry Andric     if (!F || F->hasOptNone() || F->hasFnAttribute(Attribute::Naked) ||
1810349cc55cSDimitry Andric         F->isPresplitCoroutine()) {
1811e8d8bef9SDimitry Andric       // Treat any function we're trying not to optimize as if it were an
1812e8d8bef9SDimitry Andric       // indirect call and omit it from the node set used below.
1813e8d8bef9SDimitry Andric       Res.HasUnknownCall = true;
1814e8d8bef9SDimitry Andric       continue;
1815e8d8bef9SDimitry Andric     }
1816e8d8bef9SDimitry Andric     // Track whether any functions in this SCC have an unknown call edge.
1817e8d8bef9SDimitry Andric     // Note: if this is ever a performance hit, we can common it with
1818e8d8bef9SDimitry Andric     // subsequent routines which also do scans over the instructions of the
1819e8d8bef9SDimitry Andric     // function.
1820e8d8bef9SDimitry Andric     if (!Res.HasUnknownCall) {
1821e8d8bef9SDimitry Andric       for (Instruction &I : instructions(*F)) {
1822e8d8bef9SDimitry Andric         if (auto *CB = dyn_cast<CallBase>(&I)) {
1823e8d8bef9SDimitry Andric           if (!CB->getCalledFunction()) {
1824e8d8bef9SDimitry Andric             Res.HasUnknownCall = true;
1825e8d8bef9SDimitry Andric             break;
1826e8d8bef9SDimitry Andric           }
1827e8d8bef9SDimitry Andric         }
1828e8d8bef9SDimitry Andric       }
1829e8d8bef9SDimitry Andric     }
1830e8d8bef9SDimitry Andric     Res.SCCNodes.insert(F);
1831e8d8bef9SDimitry Andric   }
1832e8d8bef9SDimitry Andric   return Res;
18330b57cec5SDimitry Andric }
18340b57cec5SDimitry Andric 
18350b57cec5SDimitry Andric template <typename AARGetterT>
1836349cc55cSDimitry Andric static SmallSet<Function *, 8>
18375f757f3fSDimitry Andric deriveAttrsInPostOrder(ArrayRef<Function *> Functions, AARGetterT &&AARGetter,
18385f757f3fSDimitry Andric                        bool ArgAttrsOnly) {
1839e8d8bef9SDimitry Andric   SCCNodesResult Nodes = createSCCNodeSet(Functions);
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric   // Bail if the SCC only contains optnone functions.
1842e8d8bef9SDimitry Andric   if (Nodes.SCCNodes.empty())
1843349cc55cSDimitry Andric     return {};
18440b57cec5SDimitry Andric 
1845349cc55cSDimitry Andric   SmallSet<Function *, 8> Changed;
18465f757f3fSDimitry Andric   if (ArgAttrsOnly) {
18475f757f3fSDimitry Andric     addArgumentAttrs(Nodes.SCCNodes, Changed);
18485f757f3fSDimitry Andric     return Changed;
18495f757f3fSDimitry Andric   }
1850349cc55cSDimitry Andric 
1851349cc55cSDimitry Andric   addArgumentReturnedAttrs(Nodes.SCCNodes, Changed);
185281ad6265SDimitry Andric   addMemoryAttrs(Nodes.SCCNodes, AARGetter, Changed);
1853349cc55cSDimitry Andric   addArgumentAttrs(Nodes.SCCNodes, Changed);
1854349cc55cSDimitry Andric   inferConvergent(Nodes.SCCNodes, Changed);
1855349cc55cSDimitry Andric   addNoReturnAttrs(Nodes.SCCNodes, Changed);
1856349cc55cSDimitry Andric   addWillReturn(Nodes.SCCNodes, Changed);
1857647cbc5dSDimitry Andric   addNoUndefAttrs(Nodes.SCCNodes, Changed);
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   // If we have no external nodes participating in the SCC, we can deduce some
18600b57cec5SDimitry Andric   // more precise attributes as well.
1861e8d8bef9SDimitry Andric   if (!Nodes.HasUnknownCall) {
1862349cc55cSDimitry Andric     addNoAliasAttrs(Nodes.SCCNodes, Changed);
1863349cc55cSDimitry Andric     addNonNullAttrs(Nodes.SCCNodes, Changed);
1864349cc55cSDimitry Andric     inferAttrsFromFunctionBodies(Nodes.SCCNodes, Changed);
1865349cc55cSDimitry Andric     addNoRecurseAttrs(Nodes.SCCNodes, Changed);
18660b57cec5SDimitry Andric   }
18670b57cec5SDimitry Andric 
1868fe6060f1SDimitry Andric   // Finally, infer the maximal set of attributes from the ones we've inferred
1869fe6060f1SDimitry Andric   // above.  This is handling the cases where one attribute on a signature
1870fe6060f1SDimitry Andric   // implies another, but for implementation reasons the inference rule for
1871fe6060f1SDimitry Andric   // the later is missing (or simply less sophisticated).
1872fe6060f1SDimitry Andric   for (Function *F : Nodes.SCCNodes)
1873fe6060f1SDimitry Andric     if (F)
1874349cc55cSDimitry Andric       if (inferAttributesFromOthers(*F))
1875349cc55cSDimitry Andric         Changed.insert(F);
1876fe6060f1SDimitry Andric 
18770b57cec5SDimitry Andric   return Changed;
18780b57cec5SDimitry Andric }
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
18810b57cec5SDimitry Andric                                                   CGSCCAnalysisManager &AM,
18820b57cec5SDimitry Andric                                                   LazyCallGraph &CG,
18830b57cec5SDimitry Andric                                                   CGSCCUpdateResult &) {
188406c3fb27SDimitry Andric   // Skip non-recursive functions if requested.
18855f757f3fSDimitry Andric   // Only infer argument attributes for non-recursive functions, because
18865f757f3fSDimitry Andric   // it can affect optimization behavior in conjunction with noalias.
18875f757f3fSDimitry Andric   bool ArgAttrsOnly = false;
188806c3fb27SDimitry Andric   if (C.size() == 1 && SkipNonRecursive) {
188906c3fb27SDimitry Andric     LazyCallGraph::Node &N = *C.begin();
189006c3fb27SDimitry Andric     if (!N->lookup(N))
18915f757f3fSDimitry Andric       ArgAttrsOnly = true;
189206c3fb27SDimitry Andric   }
189306c3fb27SDimitry Andric 
18940b57cec5SDimitry Andric   FunctionAnalysisManager &FAM =
18950b57cec5SDimitry Andric       AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
18960b57cec5SDimitry Andric 
18970b57cec5SDimitry Andric   // We pass a lambda into functions to wire them up to the analysis manager
18980b57cec5SDimitry Andric   // for getting function analyses.
18990b57cec5SDimitry Andric   auto AARGetter = [&](Function &F) -> AAResults & {
19000b57cec5SDimitry Andric     return FAM.getResult<AAManager>(F);
19010b57cec5SDimitry Andric   };
19020b57cec5SDimitry Andric 
1903e8d8bef9SDimitry Andric   SmallVector<Function *, 8> Functions;
19040b57cec5SDimitry Andric   for (LazyCallGraph::Node &N : C) {
1905e8d8bef9SDimitry Andric     Functions.push_back(&N.getFunction());
19060b57cec5SDimitry Andric   }
19070b57cec5SDimitry Andric 
19085f757f3fSDimitry Andric   auto ChangedFunctions =
19095f757f3fSDimitry Andric       deriveAttrsInPostOrder(Functions, AARGetter, ArgAttrsOnly);
1910349cc55cSDimitry Andric   if (ChangedFunctions.empty())
1911349cc55cSDimitry Andric     return PreservedAnalyses::all();
1912349cc55cSDimitry Andric 
1913349cc55cSDimitry Andric   // Invalidate analyses for modified functions so that we don't have to
1914349cc55cSDimitry Andric   // invalidate all analyses for all functions in this SCC.
1915349cc55cSDimitry Andric   PreservedAnalyses FuncPA;
1916349cc55cSDimitry Andric   // We haven't changed the CFG for modified functions.
1917349cc55cSDimitry Andric   FuncPA.preserveSet<CFGAnalyses>();
1918349cc55cSDimitry Andric   for (Function *Changed : ChangedFunctions) {
1919349cc55cSDimitry Andric     FAM.invalidate(*Changed, FuncPA);
1920349cc55cSDimitry Andric     // Also invalidate any direct callers of changed functions since analyses
1921349cc55cSDimitry Andric     // may care about attributes of direct callees. For example, MemorySSA cares
1922349cc55cSDimitry Andric     // about whether or not a call's callee modifies memory and queries that
1923349cc55cSDimitry Andric     // through function attributes.
1924349cc55cSDimitry Andric     for (auto *U : Changed->users()) {
1925349cc55cSDimitry Andric       if (auto *Call = dyn_cast<CallBase>(U)) {
1926349cc55cSDimitry Andric         if (Call->getCalledFunction() == Changed)
1927349cc55cSDimitry Andric           FAM.invalidate(*Call->getFunction(), FuncPA);
1928349cc55cSDimitry Andric       }
1929349cc55cSDimitry Andric     }
1930fe6060f1SDimitry Andric   }
19310b57cec5SDimitry Andric 
1932349cc55cSDimitry Andric   PreservedAnalyses PA;
1933349cc55cSDimitry Andric   // We have not added or removed functions.
1934349cc55cSDimitry Andric   PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1935349cc55cSDimitry Andric   // We already invalidated all relevant function analyses above.
1936349cc55cSDimitry Andric   PA.preserveSet<AllAnalysesOn<Function>>();
1937349cc55cSDimitry Andric   return PA;
19380b57cec5SDimitry Andric }
19390b57cec5SDimitry Andric 
194006c3fb27SDimitry Andric void PostOrderFunctionAttrsPass::printPipeline(
194106c3fb27SDimitry Andric     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
194206c3fb27SDimitry Andric   static_cast<PassInfoMixin<PostOrderFunctionAttrsPass> *>(this)->printPipeline(
194306c3fb27SDimitry Andric       OS, MapClassName2PassName);
194406c3fb27SDimitry Andric   if (SkipNonRecursive)
19455f757f3fSDimitry Andric     OS << "<skip-non-recursive-function-attrs>";
19460b57cec5SDimitry Andric }
19470b57cec5SDimitry Andric 
19480b57cec5SDimitry Andric template <typename AARGetterT>
19490b57cec5SDimitry Andric static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter) {
1950e8d8bef9SDimitry Andric   SmallVector<Function *, 8> Functions;
19510b57cec5SDimitry Andric   for (CallGraphNode *I : SCC) {
1952e8d8bef9SDimitry Andric     Functions.push_back(I->getFunction());
19530b57cec5SDimitry Andric   }
19540b57cec5SDimitry Andric 
1955349cc55cSDimitry Andric   return !deriveAttrsInPostOrder(Functions, AARGetter).empty();
19560b57cec5SDimitry Andric }
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric static bool addNoRecurseAttrsTopDown(Function &F) {
19590b57cec5SDimitry Andric   // We check the preconditions for the function prior to calling this to avoid
19600b57cec5SDimitry Andric   // the cost of building up a reversible post-order list. We assert them here
19610b57cec5SDimitry Andric   // to make sure none of the invariants this relies on were violated.
19620b57cec5SDimitry Andric   assert(!F.isDeclaration() && "Cannot deduce norecurse without a definition!");
19630b57cec5SDimitry Andric   assert(!F.doesNotRecurse() &&
19640b57cec5SDimitry Andric          "This function has already been deduced as norecurs!");
19650b57cec5SDimitry Andric   assert(F.hasInternalLinkage() &&
19660b57cec5SDimitry Andric          "Can only do top-down deduction for internal linkage functions!");
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric   // If F is internal and all of its uses are calls from a non-recursive
19690b57cec5SDimitry Andric   // functions, then none of its calls could in fact recurse without going
19700b57cec5SDimitry Andric   // through a function marked norecurse, and so we can mark this function too
19710b57cec5SDimitry Andric   // as norecurse. Note that the uses must actually be calls -- otherwise
19720b57cec5SDimitry Andric   // a pointer to this function could be returned from a norecurse function but
19730b57cec5SDimitry Andric   // this function could be recursively (indirectly) called. Note that this
19740b57cec5SDimitry Andric   // also detects if F is directly recursive as F is not yet marked as
19750b57cec5SDimitry Andric   // a norecurse function.
197681ad6265SDimitry Andric   for (auto &U : F.uses()) {
197781ad6265SDimitry Andric     auto *I = dyn_cast<Instruction>(U.getUser());
19780b57cec5SDimitry Andric     if (!I)
19790b57cec5SDimitry Andric       return false;
19805ffd83dbSDimitry Andric     CallBase *CB = dyn_cast<CallBase>(I);
198181ad6265SDimitry Andric     if (!CB || !CB->isCallee(&U) ||
198281ad6265SDimitry Andric         !CB->getParent()->getParent()->doesNotRecurse())
19830b57cec5SDimitry Andric       return false;
19840b57cec5SDimitry Andric   }
1985e8d8bef9SDimitry Andric   F.setDoesNotRecurse();
1986e8d8bef9SDimitry Andric   ++NumNoRecurse;
1987e8d8bef9SDimitry Andric   return true;
19880b57cec5SDimitry Andric }
19890b57cec5SDimitry Andric 
199006c3fb27SDimitry Andric static bool deduceFunctionAttributeInRPO(Module &M, LazyCallGraph &CG) {
19910b57cec5SDimitry Andric   // We only have a post-order SCC traversal (because SCCs are inherently
19920b57cec5SDimitry Andric   // discovered in post-order), so we accumulate them in a vector and then walk
19930b57cec5SDimitry Andric   // it in reverse. This is simpler than using the RPO iterator infrastructure
19940b57cec5SDimitry Andric   // because we need to combine SCC detection and the PO walk of the call
19950b57cec5SDimitry Andric   // graph. We can also cheat egregiously because we're primarily interested in
19960b57cec5SDimitry Andric   // synthesizing norecurse and so we can only save the singular SCCs as SCCs
19970b57cec5SDimitry Andric   // with multiple functions in them will clearly be recursive.
199806c3fb27SDimitry Andric 
19990b57cec5SDimitry Andric   SmallVector<Function *, 16> Worklist;
200006c3fb27SDimitry Andric   CG.buildRefSCCs();
200106c3fb27SDimitry Andric   for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
200206c3fb27SDimitry Andric     for (LazyCallGraph::SCC &SCC : RC) {
200306c3fb27SDimitry Andric       if (SCC.size() != 1)
20040b57cec5SDimitry Andric         continue;
200506c3fb27SDimitry Andric       Function &F = SCC.begin()->getFunction();
200606c3fb27SDimitry Andric       if (!F.isDeclaration() && !F.doesNotRecurse() && F.hasInternalLinkage())
200706c3fb27SDimitry Andric         Worklist.push_back(&F);
20080b57cec5SDimitry Andric     }
200906c3fb27SDimitry Andric   }
20100b57cec5SDimitry Andric   bool Changed = false;
20110b57cec5SDimitry Andric   for (auto *F : llvm::reverse(Worklist))
20120b57cec5SDimitry Andric     Changed |= addNoRecurseAttrsTopDown(*F);
20130b57cec5SDimitry Andric 
20140b57cec5SDimitry Andric   return Changed;
20150b57cec5SDimitry Andric }
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric PreservedAnalyses
20180b57cec5SDimitry Andric ReversePostOrderFunctionAttrsPass::run(Module &M, ModuleAnalysisManager &AM) {
201906c3fb27SDimitry Andric   auto &CG = AM.getResult<LazyCallGraphAnalysis>(M);
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric   if (!deduceFunctionAttributeInRPO(M, CG))
20220b57cec5SDimitry Andric     return PreservedAnalyses::all();
20230b57cec5SDimitry Andric 
20240b57cec5SDimitry Andric   PreservedAnalyses PA;
202506c3fb27SDimitry Andric   PA.preserve<LazyCallGraphAnalysis>();
20260b57cec5SDimitry Andric   return PA;
20270b57cec5SDimitry Andric }
2028