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