10b57cec5SDimitry Andric //===- Attributor.cpp - Module-wide attribute deduction -------------------===// 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 // 95ffd83dbSDimitry Andric // This file implements an interprocedural pass that deduces and/or propagates 100b57cec5SDimitry Andric // attributes. This is done in an abstract interpretation style fixpoint 110b57cec5SDimitry Andric // iteration. See the Attributor.h file comment and the class descriptions in 120b57cec5SDimitry Andric // that file for more information. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/Transforms/IPO/Attributor.h" 170b57cec5SDimitry Andric 1806c3fb27SDimitry Andric #include "llvm/ADT/ArrayRef.h" 19e8d8bef9SDimitry Andric #include "llvm/ADT/PointerIntPair.h" 20fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h" 215f757f3fSDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 220b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 2381ad6265SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 2481ad6265SDimitry Andric #include "llvm/Analysis/CallGraph.h" 2581ad6265SDimitry Andric #include "llvm/Analysis/CallGraphSCCPass.h" 26e8d8bef9SDimitry Andric #include "llvm/Analysis/InlineCost.h" 2704eeddc0SDimitry Andric #include "llvm/Analysis/MemoryBuiltins.h" 285ffd83dbSDimitry Andric #include "llvm/Analysis/MustExecute.h" 2906c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h" 30fe6060f1SDimitry Andric #include "llvm/IR/Attributes.h" 31fe6060f1SDimitry Andric #include "llvm/IR/Constant.h" 32bdd1243dSDimitry Andric #include "llvm/IR/ConstantFold.h" 33fe6060f1SDimitry Andric #include "llvm/IR/Constants.h" 34bdd1243dSDimitry Andric #include "llvm/IR/DataLayout.h" 35e8d8bef9SDimitry Andric #include "llvm/IR/GlobalValue.h" 36fe6060f1SDimitry Andric #include "llvm/IR/GlobalVariable.h" 37fe6060f1SDimitry Andric #include "llvm/IR/Instruction.h" 386e75b2fbSDimitry Andric #include "llvm/IR/Instructions.h" 39fe6060f1SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 4006c3fb27SDimitry Andric #include "llvm/IR/LLVMContext.h" 41fe6060f1SDimitry Andric #include "llvm/IR/ValueHandle.h" 425ffd83dbSDimitry Andric #include "llvm/Support/Casting.h" 430b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 44e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h" 45e8d8bef9SDimitry Andric #include "llvm/Support/DebugCounter.h" 46e8d8bef9SDimitry Andric #include "llvm/Support/FileSystem.h" 47e8d8bef9SDimitry Andric #include "llvm/Support/GraphWriter.h" 4806c3fb27SDimitry Andric #include "llvm/Support/ModRef.h" 49e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h" 508bcb0991SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 51e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 528bcb0991SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 53bdd1243dSDimitry Andric #include <cstdint> 545f757f3fSDimitry Andric #include <memory> 558bcb0991SDimitry Andric 5681ad6265SDimitry Andric #ifdef EXPENSIVE_CHECKS 5781ad6265SDimitry Andric #include "llvm/IR/Verifier.h" 5881ad6265SDimitry Andric #endif 5981ad6265SDimitry Andric 600b57cec5SDimitry Andric #include <cassert> 61bdd1243dSDimitry Andric #include <optional> 62e8d8bef9SDimitry Andric #include <string> 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric using namespace llvm; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric #define DEBUG_TYPE "attributor" 67bdd1243dSDimitry Andric #define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose" 680b57cec5SDimitry Andric 69e8d8bef9SDimitry Andric DEBUG_COUNTER(ManifestDBGCounter, "attributor-manifest", 70e8d8bef9SDimitry Andric "Determine what attributes are manifested in the IR"); 71e8d8bef9SDimitry Andric 725ffd83dbSDimitry Andric STATISTIC(NumFnDeleted, "Number of function deleted"); 730b57cec5SDimitry Andric STATISTIC(NumFnWithExactDefinition, 745ffd83dbSDimitry Andric "Number of functions with exact definitions"); 750b57cec5SDimitry Andric STATISTIC(NumFnWithoutExactDefinition, 765ffd83dbSDimitry Andric "Number of functions without exact definitions"); 77e8d8bef9SDimitry Andric STATISTIC(NumFnShallowWrappersCreated, "Number of shallow wrappers created"); 780b57cec5SDimitry Andric STATISTIC(NumAttributesTimedOut, 790b57cec5SDimitry Andric "Number of abstract attributes timed out before fixpoint"); 800b57cec5SDimitry Andric STATISTIC(NumAttributesValidFixpoint, 810b57cec5SDimitry Andric "Number of abstract attributes in a valid fixpoint state"); 820b57cec5SDimitry Andric STATISTIC(NumAttributesManifested, 830b57cec5SDimitry Andric "Number of abstract attributes manifested in IR"); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric // TODO: Determine a good default value. 860b57cec5SDimitry Andric // 870b57cec5SDimitry Andric // In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads 880b57cec5SDimitry Andric // (when run with the first 5 abstract attributes). The results also indicate 890b57cec5SDimitry Andric // that we never reach 32 iterations but always find a fixpoint sooner. 900b57cec5SDimitry Andric // 910b57cec5SDimitry Andric // This will become more evolved once we perform two interleaved fixpoint 920b57cec5SDimitry Andric // iterations: bottom-up and top-down. 930b57cec5SDimitry Andric static cl::opt<unsigned> 94fe6060f1SDimitry Andric SetFixpointIterations("attributor-max-iterations", cl::Hidden, 950b57cec5SDimitry Andric cl::desc("Maximal number of fixpoint iterations."), 960b57cec5SDimitry Andric cl::init(32)); 97e8d8bef9SDimitry Andric 985f757f3fSDimitry Andric static cl::opt<unsigned> 995f757f3fSDimitry Andric MaxSpecializationPerCB("attributor-max-specializations-per-call-base", 1005f757f3fSDimitry Andric cl::Hidden, 1015f757f3fSDimitry Andric cl::desc("Maximal number of callees specialized for " 1025f757f3fSDimitry Andric "a call base"), 1035f757f3fSDimitry Andric cl::init(UINT32_MAX)); 1045f757f3fSDimitry Andric 105e8d8bef9SDimitry Andric static cl::opt<unsigned, true> MaxInitializationChainLengthX( 106e8d8bef9SDimitry Andric "attributor-max-initialization-chain-length", cl::Hidden, 107e8d8bef9SDimitry Andric cl::desc( 108e8d8bef9SDimitry Andric "Maximal number of chained initializations (to avoid stack overflows)"), 109e8d8bef9SDimitry Andric cl::location(MaxInitializationChainLength), cl::init(1024)); 110e8d8bef9SDimitry Andric unsigned llvm::MaxInitializationChainLength; 111e8d8bef9SDimitry Andric 112480093f4SDimitry Andric static cl::opt<bool> AnnotateDeclarationCallSites( 113480093f4SDimitry Andric "attributor-annotate-decl-cs", cl::Hidden, 114480093f4SDimitry Andric cl::desc("Annotate call sites of function declarations."), cl::init(false)); 115480093f4SDimitry Andric 1168bcb0991SDimitry Andric static cl::opt<bool> EnableHeapToStack("enable-heap-to-stack-conversion", 1178bcb0991SDimitry Andric cl::init(true), cl::Hidden); 1188bcb0991SDimitry Andric 1195ffd83dbSDimitry Andric static cl::opt<bool> 1205ffd83dbSDimitry Andric AllowShallowWrappers("attributor-allow-shallow-wrappers", cl::Hidden, 1215ffd83dbSDimitry Andric cl::desc("Allow the Attributor to create shallow " 1225ffd83dbSDimitry Andric "wrappers for non-exact definitions."), 1235ffd83dbSDimitry Andric cl::init(false)); 1245ffd83dbSDimitry Andric 125e8d8bef9SDimitry Andric static cl::opt<bool> 126e8d8bef9SDimitry Andric AllowDeepWrapper("attributor-allow-deep-wrappers", cl::Hidden, 127e8d8bef9SDimitry Andric cl::desc("Allow the Attributor to use IP information " 128e8d8bef9SDimitry Andric "derived from non-exact functions via cloning"), 129e8d8bef9SDimitry Andric cl::init(false)); 130e8d8bef9SDimitry Andric 131e8d8bef9SDimitry Andric // These options can only used for debug builds. 132e8d8bef9SDimitry Andric #ifndef NDEBUG 1335ffd83dbSDimitry Andric static cl::list<std::string> 1345ffd83dbSDimitry Andric SeedAllowList("attributor-seed-allow-list", cl::Hidden, 135*0fca6ea1SDimitry Andric cl::desc("Comma separated list of attribute names that are " 1365ffd83dbSDimitry Andric "allowed to be seeded."), 13781ad6265SDimitry Andric cl::CommaSeparated); 1388bcb0991SDimitry Andric 139e8d8bef9SDimitry Andric static cl::list<std::string> FunctionSeedAllowList( 140e8d8bef9SDimitry Andric "attributor-function-seed-allow-list", cl::Hidden, 141*0fca6ea1SDimitry Andric cl::desc("Comma separated list of function names that are " 142e8d8bef9SDimitry Andric "allowed to be seeded."), 14381ad6265SDimitry Andric cl::CommaSeparated); 144e8d8bef9SDimitry Andric #endif 145e8d8bef9SDimitry Andric 146e8d8bef9SDimitry Andric static cl::opt<bool> 147e8d8bef9SDimitry Andric DumpDepGraph("attributor-dump-dep-graph", cl::Hidden, 148e8d8bef9SDimitry Andric cl::desc("Dump the dependency graph to dot files."), 149e8d8bef9SDimitry Andric cl::init(false)); 150e8d8bef9SDimitry Andric 151e8d8bef9SDimitry Andric static cl::opt<std::string> DepGraphDotFileNamePrefix( 152e8d8bef9SDimitry Andric "attributor-depgraph-dot-filename-prefix", cl::Hidden, 153e8d8bef9SDimitry Andric cl::desc("The prefix used for the CallGraph dot file names.")); 154e8d8bef9SDimitry Andric 155e8d8bef9SDimitry Andric static cl::opt<bool> ViewDepGraph("attributor-view-dep-graph", cl::Hidden, 156e8d8bef9SDimitry Andric cl::desc("View the dependency graph."), 157e8d8bef9SDimitry Andric cl::init(false)); 158e8d8bef9SDimitry Andric 159e8d8bef9SDimitry Andric static cl::opt<bool> PrintDependencies("attributor-print-dep", cl::Hidden, 160e8d8bef9SDimitry Andric cl::desc("Print attribute dependencies"), 161e8d8bef9SDimitry Andric cl::init(false)); 162e8d8bef9SDimitry Andric 163fe6060f1SDimitry Andric static cl::opt<bool> EnableCallSiteSpecific( 164fe6060f1SDimitry Andric "attributor-enable-call-site-specific-deduction", cl::Hidden, 165fe6060f1SDimitry Andric cl::desc("Allow the Attributor to do call site specific analysis"), 166fe6060f1SDimitry Andric cl::init(false)); 167fe6060f1SDimitry Andric 168fe6060f1SDimitry Andric static cl::opt<bool> 169fe6060f1SDimitry Andric PrintCallGraph("attributor-print-call-graph", cl::Hidden, 170fe6060f1SDimitry Andric cl::desc("Print Attributor's internal call graph"), 171fe6060f1SDimitry Andric cl::init(false)); 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric static cl::opt<bool> SimplifyAllLoads("attributor-simplify-all-loads", 174fe6060f1SDimitry Andric cl::Hidden, 175fe6060f1SDimitry Andric cl::desc("Try to simplify all loads."), 176fe6060f1SDimitry Andric cl::init(true)); 177fe6060f1SDimitry Andric 1785f757f3fSDimitry Andric static cl::opt<bool> CloseWorldAssumption( 1795f757f3fSDimitry Andric "attributor-assume-closed-world", cl::Hidden, 1805f757f3fSDimitry Andric cl::desc("Should a closed world be assumed, or not. Default if not set.")); 1815f757f3fSDimitry Andric 1820b57cec5SDimitry Andric /// Logic operators for the change status enum class. 1830b57cec5SDimitry Andric /// 1840b57cec5SDimitry Andric ///{ 185e8d8bef9SDimitry Andric ChangeStatus llvm::operator|(ChangeStatus L, ChangeStatus R) { 186e8d8bef9SDimitry Andric return L == ChangeStatus::CHANGED ? L : R; 1870b57cec5SDimitry Andric } 188fe6060f1SDimitry Andric ChangeStatus &llvm::operator|=(ChangeStatus &L, ChangeStatus R) { 189fe6060f1SDimitry Andric L = L | R; 190fe6060f1SDimitry Andric return L; 191fe6060f1SDimitry Andric } 192e8d8bef9SDimitry Andric ChangeStatus llvm::operator&(ChangeStatus L, ChangeStatus R) { 193e8d8bef9SDimitry Andric return L == ChangeStatus::UNCHANGED ? L : R; 1940b57cec5SDimitry Andric } 195fe6060f1SDimitry Andric ChangeStatus &llvm::operator&=(ChangeStatus &L, ChangeStatus R) { 196fe6060f1SDimitry Andric L = L & R; 197fe6060f1SDimitry Andric return L; 198fe6060f1SDimitry Andric } 1990b57cec5SDimitry Andric ///} 2000b57cec5SDimitry Andric 20106c3fb27SDimitry Andric bool AA::isGPU(const Module &M) { 20206c3fb27SDimitry Andric Triple T(M.getTargetTriple()); 20306c3fb27SDimitry Andric return T.isAMDGPU() || T.isNVPTX(); 20406c3fb27SDimitry Andric } 20506c3fb27SDimitry Andric 2061fd87a68SDimitry Andric bool AA::isNoSyncInst(Attributor &A, const Instruction &I, 2071fd87a68SDimitry Andric const AbstractAttribute &QueryingAA) { 2081fd87a68SDimitry Andric // We are looking for volatile instructions or non-relaxed atomics. 2091fd87a68SDimitry Andric if (const auto *CB = dyn_cast<CallBase>(&I)) { 2101fd87a68SDimitry Andric if (CB->hasFnAttr(Attribute::NoSync)) 2111fd87a68SDimitry Andric return true; 2121fd87a68SDimitry Andric 2131fd87a68SDimitry Andric // Non-convergent and readnone imply nosync. 2141fd87a68SDimitry Andric if (!CB->isConvergent() && !CB->mayReadOrWriteMemory()) 2151fd87a68SDimitry Andric return true; 2161fd87a68SDimitry Andric 2171fd87a68SDimitry Andric if (AANoSync::isNoSyncIntrinsic(&I)) 2181fd87a68SDimitry Andric return true; 2191fd87a68SDimitry Andric 22006c3fb27SDimitry Andric bool IsKnownNoSync; 22106c3fb27SDimitry Andric return AA::hasAssumedIRAttr<Attribute::NoSync>( 22206c3fb27SDimitry Andric A, &QueryingAA, IRPosition::callsite_function(*CB), 22306c3fb27SDimitry Andric DepClassTy::OPTIONAL, IsKnownNoSync); 2241fd87a68SDimitry Andric } 2251fd87a68SDimitry Andric 2261fd87a68SDimitry Andric if (!I.mayReadOrWriteMemory()) 2271fd87a68SDimitry Andric return true; 2281fd87a68SDimitry Andric 2291fd87a68SDimitry Andric return !I.isVolatile() && !AANoSync::isNonRelaxedAtomic(&I); 2301fd87a68SDimitry Andric } 2311fd87a68SDimitry Andric 232fe6060f1SDimitry Andric bool AA::isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA, 23381ad6265SDimitry Andric const Value &V, bool ForAnalysisOnly) { 23481ad6265SDimitry Andric // TODO: See the AAInstanceInfo class comment. 23581ad6265SDimitry Andric if (!ForAnalysisOnly) 236fe6060f1SDimitry Andric return false; 23706c3fb27SDimitry Andric auto *InstanceInfoAA = A.getAAFor<AAInstanceInfo>( 23881ad6265SDimitry Andric QueryingAA, IRPosition::value(V), DepClassTy::OPTIONAL); 23906c3fb27SDimitry Andric return InstanceInfoAA && InstanceInfoAA->isAssumedUniqueForAnalysis(); 240fe6060f1SDimitry Andric } 241fe6060f1SDimitry Andric 2425f757f3fSDimitry Andric Constant * 2435f757f3fSDimitry Andric AA::getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA, 2445f757f3fSDimitry Andric Value &Obj, Type &Ty, const TargetLibraryInfo *TLI, 2455f757f3fSDimitry Andric const DataLayout &DL, AA::RangeTy *RangePtr) { 246fe6060f1SDimitry Andric if (isa<AllocaInst>(Obj)) 247fe6060f1SDimitry Andric return UndefValue::get(&Ty); 24881ad6265SDimitry Andric if (Constant *Init = getInitialValueOfAllocation(&Obj, TLI, &Ty)) 24981ad6265SDimitry Andric return Init; 250fe6060f1SDimitry Andric auto *GV = dyn_cast<GlobalVariable>(&Obj); 25181ad6265SDimitry Andric if (!GV) 25281ad6265SDimitry Andric return nullptr; 25306c3fb27SDimitry Andric 25406c3fb27SDimitry Andric bool UsedAssumedInformation = false; 25506c3fb27SDimitry Andric Constant *Initializer = nullptr; 25606c3fb27SDimitry Andric if (A.hasGlobalVariableSimplificationCallback(*GV)) { 25706c3fb27SDimitry Andric auto AssumedGV = A.getAssumedInitializerFromCallBack( 2585f757f3fSDimitry Andric *GV, &QueryingAA, UsedAssumedInformation); 25906c3fb27SDimitry Andric Initializer = *AssumedGV; 26006c3fb27SDimitry Andric if (!Initializer) 26106c3fb27SDimitry Andric return nullptr; 26206c3fb27SDimitry Andric } else { 2635f757f3fSDimitry Andric if (!GV->hasLocalLinkage() && 2645f757f3fSDimitry Andric (GV->isInterposable() || !(GV->isConstant() && GV->hasInitializer()))) 265fe6060f1SDimitry Andric return nullptr; 266fe6060f1SDimitry Andric if (!GV->hasInitializer()) 267fe6060f1SDimitry Andric return UndefValue::get(&Ty); 268bdd1243dSDimitry Andric 26906c3fb27SDimitry Andric if (!Initializer) 27006c3fb27SDimitry Andric Initializer = GV->getInitializer(); 271bdd1243dSDimitry Andric } 272bdd1243dSDimitry Andric 27306c3fb27SDimitry Andric if (RangePtr && !RangePtr->offsetOrSizeAreUnknown()) { 27406c3fb27SDimitry Andric APInt Offset = APInt(64, RangePtr->Offset); 27506c3fb27SDimitry Andric return ConstantFoldLoadFromConst(Initializer, &Ty, Offset, DL); 27606c3fb27SDimitry Andric } 27706c3fb27SDimitry Andric 278*0fca6ea1SDimitry Andric return ConstantFoldLoadFromUniformValue(Initializer, &Ty, DL); 279fe6060f1SDimitry Andric } 280fe6060f1SDimitry Andric 281fe6060f1SDimitry Andric bool AA::isValidInScope(const Value &V, const Function *Scope) { 282fe6060f1SDimitry Andric if (isa<Constant>(V)) 283fe6060f1SDimitry Andric return true; 284fe6060f1SDimitry Andric if (auto *I = dyn_cast<Instruction>(&V)) 285fe6060f1SDimitry Andric return I->getFunction() == Scope; 286fe6060f1SDimitry Andric if (auto *A = dyn_cast<Argument>(&V)) 287fe6060f1SDimitry Andric return A->getParent() == Scope; 288fe6060f1SDimitry Andric return false; 289fe6060f1SDimitry Andric } 290fe6060f1SDimitry Andric 29181ad6265SDimitry Andric bool AA::isValidAtPosition(const AA::ValueAndContext &VAC, 292fe6060f1SDimitry Andric InformationCache &InfoCache) { 29381ad6265SDimitry Andric if (isa<Constant>(VAC.getValue()) || VAC.getValue() == VAC.getCtxI()) 294fe6060f1SDimitry Andric return true; 29581ad6265SDimitry Andric const Function *Scope = nullptr; 29681ad6265SDimitry Andric const Instruction *CtxI = VAC.getCtxI(); 29781ad6265SDimitry Andric if (CtxI) 29881ad6265SDimitry Andric Scope = CtxI->getFunction(); 29981ad6265SDimitry Andric if (auto *A = dyn_cast<Argument>(VAC.getValue())) 300fe6060f1SDimitry Andric return A->getParent() == Scope; 30181ad6265SDimitry Andric if (auto *I = dyn_cast<Instruction>(VAC.getValue())) { 302fe6060f1SDimitry Andric if (I->getFunction() == Scope) { 30381ad6265SDimitry Andric if (const DominatorTree *DT = 30481ad6265SDimitry Andric InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>( 30581ad6265SDimitry Andric *Scope)) 30681ad6265SDimitry Andric return DT->dominates(I, CtxI); 30781ad6265SDimitry Andric // Local dominance check mostly for the old PM passes. 30881ad6265SDimitry Andric if (CtxI && I->getParent() == CtxI->getParent()) 30981ad6265SDimitry Andric return llvm::any_of( 31081ad6265SDimitry Andric make_range(I->getIterator(), I->getParent()->end()), 31181ad6265SDimitry Andric [&](const Instruction &AfterI) { return &AfterI == CtxI; }); 31281ad6265SDimitry Andric } 313fe6060f1SDimitry Andric } 314fe6060f1SDimitry Andric return false; 315fe6060f1SDimitry Andric } 316fe6060f1SDimitry Andric 317fe6060f1SDimitry Andric Value *AA::getWithType(Value &V, Type &Ty) { 318fe6060f1SDimitry Andric if (V.getType() == &Ty) 319fe6060f1SDimitry Andric return &V; 320fe6060f1SDimitry Andric if (isa<PoisonValue>(V)) 321fe6060f1SDimitry Andric return PoisonValue::get(&Ty); 322fe6060f1SDimitry Andric if (isa<UndefValue>(V)) 323fe6060f1SDimitry Andric return UndefValue::get(&Ty); 324fe6060f1SDimitry Andric if (auto *C = dyn_cast<Constant>(&V)) { 325fe6060f1SDimitry Andric if (C->isNullValue()) 326fe6060f1SDimitry Andric return Constant::getNullValue(&Ty); 327fe6060f1SDimitry Andric if (C->getType()->isPointerTy() && Ty.isPointerTy()) 328fe6060f1SDimitry Andric return ConstantExpr::getPointerCast(C, &Ty); 3296e75b2fbSDimitry Andric if (C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) { 330fe6060f1SDimitry Andric if (C->getType()->isIntegerTy() && Ty.isIntegerTy()) 331fe6060f1SDimitry Andric return ConstantExpr::getTrunc(C, &Ty, /* OnlyIfReduced */ true); 332fe6060f1SDimitry Andric if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy()) 3335f757f3fSDimitry Andric return ConstantFoldCastInstruction(Instruction::FPTrunc, C, &Ty); 334fe6060f1SDimitry Andric } 3356e75b2fbSDimitry Andric } 336fe6060f1SDimitry Andric return nullptr; 337fe6060f1SDimitry Andric } 338fe6060f1SDimitry Andric 339bdd1243dSDimitry Andric std::optional<Value *> 340bdd1243dSDimitry Andric AA::combineOptionalValuesInAAValueLatice(const std::optional<Value *> &A, 341bdd1243dSDimitry Andric const std::optional<Value *> &B, 342bdd1243dSDimitry Andric Type *Ty) { 343fe6060f1SDimitry Andric if (A == B) 344fe6060f1SDimitry Andric return A; 34581ad6265SDimitry Andric if (!B) 346fe6060f1SDimitry Andric return A; 347fe6060f1SDimitry Andric if (*B == nullptr) 348fe6060f1SDimitry Andric return nullptr; 34981ad6265SDimitry Andric if (!A) 350fe6060f1SDimitry Andric return Ty ? getWithType(**B, *Ty) : nullptr; 351fe6060f1SDimitry Andric if (*A == nullptr) 352fe6060f1SDimitry Andric return nullptr; 353fe6060f1SDimitry Andric if (!Ty) 354fe6060f1SDimitry Andric Ty = (*A)->getType(); 355fe6060f1SDimitry Andric if (isa_and_nonnull<UndefValue>(*A)) 356fe6060f1SDimitry Andric return getWithType(**B, *Ty); 357fe6060f1SDimitry Andric if (isa<UndefValue>(*B)) 358fe6060f1SDimitry Andric return A; 359fe6060f1SDimitry Andric if (*A && *B && *A == getWithType(**B, *Ty)) 360fe6060f1SDimitry Andric return A; 361fe6060f1SDimitry Andric return nullptr; 362fe6060f1SDimitry Andric } 363fe6060f1SDimitry Andric 36481ad6265SDimitry Andric template <bool IsLoad, typename Ty> 36581ad6265SDimitry Andric static bool getPotentialCopiesOfMemoryValue( 36681ad6265SDimitry Andric Attributor &A, Ty &I, SmallSetVector<Value *, 4> &PotentialCopies, 3675f757f3fSDimitry Andric SmallSetVector<Instruction *, 4> *PotentialValueOrigins, 36881ad6265SDimitry Andric const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, 36981ad6265SDimitry Andric bool OnlyExact) { 37081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Trying to determine the potential copies of " << I 37181ad6265SDimitry Andric << " (only exact: " << OnlyExact << ")\n";); 372fe6060f1SDimitry Andric 37381ad6265SDimitry Andric Value &Ptr = *I.getPointerOperand(); 37481ad6265SDimitry Andric // Containers to remember the pointer infos and new copies while we are not 37581ad6265SDimitry Andric // sure that we can find all of them. If we abort we want to avoid spurious 37681ad6265SDimitry Andric // dependences and potential copies in the provided container. 377fe6060f1SDimitry Andric SmallVector<const AAPointerInfo *> PIs; 3785f757f3fSDimitry Andric SmallSetVector<Value *, 8> NewCopies; 3795f757f3fSDimitry Andric SmallSetVector<Instruction *, 8> NewCopyOrigins; 380fe6060f1SDimitry Andric 38181ad6265SDimitry Andric const auto *TLI = 38281ad6265SDimitry Andric A.getInfoCache().getTargetLibraryInfoForFunction(*I.getFunction()); 383bdd1243dSDimitry Andric 384bdd1243dSDimitry Andric auto Pred = [&](Value &Obj) { 385bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Visit underlying object " << Obj << "\n"); 386bdd1243dSDimitry Andric if (isa<UndefValue>(&Obj)) 387bdd1243dSDimitry Andric return true; 388bdd1243dSDimitry Andric if (isa<ConstantPointerNull>(&Obj)) { 389fe6060f1SDimitry Andric // A null pointer access can be undefined but any offset from null may 390fe6060f1SDimitry Andric // be OK. We do not try to optimize the latter. 39181ad6265SDimitry Andric if (!NullPointerIsDefined(I.getFunction(), 392fe6060f1SDimitry Andric Ptr.getType()->getPointerAddressSpace()) && 393fcaf7f86SDimitry Andric A.getAssumedSimplified(Ptr, QueryingAA, UsedAssumedInformation, 394bdd1243dSDimitry Andric AA::Interprocedural) == &Obj) 395bdd1243dSDimitry Andric return true; 396fe6060f1SDimitry Andric LLVM_DEBUG( 397fe6060f1SDimitry Andric dbgs() << "Underlying object is a valid nullptr, giving up.\n";); 398fe6060f1SDimitry Andric return false; 399fe6060f1SDimitry Andric } 40081ad6265SDimitry Andric // TODO: Use assumed noalias return. 401bdd1243dSDimitry Andric if (!isa<AllocaInst>(&Obj) && !isa<GlobalVariable>(&Obj) && 402bdd1243dSDimitry Andric !(IsLoad ? isAllocationFn(&Obj, TLI) : isNoAliasCall(&Obj))) { 403bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Underlying object is not supported yet: " << Obj 404fe6060f1SDimitry Andric << "\n";); 405fe6060f1SDimitry Andric return false; 406fe6060f1SDimitry Andric } 407bdd1243dSDimitry Andric if (auto *GV = dyn_cast<GlobalVariable>(&Obj)) 40881ad6265SDimitry Andric if (!GV->hasLocalLinkage() && 40981ad6265SDimitry Andric !(GV->isConstant() && GV->hasInitializer())) { 410fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Underlying object is global with external " 411fe6060f1SDimitry Andric "linkage, not supported yet: " 412bdd1243dSDimitry Andric << Obj << "\n";); 413fe6060f1SDimitry Andric return false; 414fe6060f1SDimitry Andric } 415fe6060f1SDimitry Andric 416fcaf7f86SDimitry Andric bool NullOnly = true; 417fcaf7f86SDimitry Andric bool NullRequired = false; 418bdd1243dSDimitry Andric auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V, 419bdd1243dSDimitry Andric bool IsExact) { 420fcaf7f86SDimitry Andric if (!V || *V == nullptr) 421fcaf7f86SDimitry Andric NullOnly = false; 422fcaf7f86SDimitry Andric else if (isa<UndefValue>(*V)) 423fcaf7f86SDimitry Andric /* No op */; 424fcaf7f86SDimitry Andric else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue()) 425fcaf7f86SDimitry Andric NullRequired = !IsExact; 426fcaf7f86SDimitry Andric else 427fcaf7f86SDimitry Andric NullOnly = false; 428fcaf7f86SDimitry Andric }; 42981ad6265SDimitry Andric 4301ac55f4cSDimitry Andric auto AdjustWrittenValueType = [&](const AAPointerInfo::Access &Acc, 4311ac55f4cSDimitry Andric Value &V) { 4321ac55f4cSDimitry Andric Value *AdjV = AA::getWithType(V, *I.getType()); 4331ac55f4cSDimitry Andric if (!AdjV) { 4341ac55f4cSDimitry Andric LLVM_DEBUG(dbgs() << "Underlying object written but stored value " 4351ac55f4cSDimitry Andric "cannot be converted to read type: " 4361ac55f4cSDimitry Andric << *Acc.getRemoteInst() << " : " << *I.getType() 4371ac55f4cSDimitry Andric << "\n";); 4381ac55f4cSDimitry Andric } 4391ac55f4cSDimitry Andric return AdjV; 4401ac55f4cSDimitry Andric }; 4411ac55f4cSDimitry Andric 4425f757f3fSDimitry Andric auto SkipCB = [&](const AAPointerInfo::Access &Acc) { 4435f757f3fSDimitry Andric if ((IsLoad && !Acc.isWriteOrAssumption()) || (!IsLoad && !Acc.isRead())) 4445f757f3fSDimitry Andric return true; 4455f757f3fSDimitry Andric if (IsLoad) { 4465f757f3fSDimitry Andric if (Acc.isWrittenValueYetUndetermined()) 4475f757f3fSDimitry Andric return true; 4485f757f3fSDimitry Andric if (PotentialValueOrigins && !isa<AssumeInst>(Acc.getRemoteInst())) 4495f757f3fSDimitry Andric return false; 4505f757f3fSDimitry Andric if (!Acc.isWrittenValueUnknown()) 4515f757f3fSDimitry Andric if (Value *V = AdjustWrittenValueType(Acc, *Acc.getWrittenValue())) 4525f757f3fSDimitry Andric if (NewCopies.count(V)) { 4535f757f3fSDimitry Andric NewCopyOrigins.insert(Acc.getRemoteInst()); 4545f757f3fSDimitry Andric return true; 4555f757f3fSDimitry Andric } 4565f757f3fSDimitry Andric if (auto *SI = dyn_cast<StoreInst>(Acc.getRemoteInst())) 4575f757f3fSDimitry Andric if (Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand())) 4585f757f3fSDimitry Andric if (NewCopies.count(V)) { 4595f757f3fSDimitry Andric NewCopyOrigins.insert(Acc.getRemoteInst()); 4605f757f3fSDimitry Andric return true; 4615f757f3fSDimitry Andric } 4625f757f3fSDimitry Andric } 4635f757f3fSDimitry Andric return false; 4645f757f3fSDimitry Andric }; 4655f757f3fSDimitry Andric 466fe6060f1SDimitry Andric auto CheckAccess = [&](const AAPointerInfo::Access &Acc, bool IsExact) { 467bdd1243dSDimitry Andric if ((IsLoad && !Acc.isWriteOrAssumption()) || (!IsLoad && !Acc.isRead())) 468fe6060f1SDimitry Andric return true; 46981ad6265SDimitry Andric if (IsLoad && Acc.isWrittenValueYetUndetermined()) 47081ad6265SDimitry Andric return true; 471fcaf7f86SDimitry Andric CheckForNullOnlyAndUndef(Acc.getContent(), IsExact); 472fcaf7f86SDimitry Andric if (OnlyExact && !IsExact && !NullOnly && 47381ad6265SDimitry Andric !isa_and_nonnull<UndefValue>(Acc.getWrittenValue())) { 47481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Non exact access " << *Acc.getRemoteInst() 47581ad6265SDimitry Andric << ", abort!\n"); 47681ad6265SDimitry Andric return false; 47781ad6265SDimitry Andric } 478fcaf7f86SDimitry Andric if (NullRequired && !NullOnly) { 479fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "Required all `null` accesses due to non exact " 480fcaf7f86SDimitry Andric "one, however found non-null one: " 481fcaf7f86SDimitry Andric << *Acc.getRemoteInst() << ", abort!\n"); 482fcaf7f86SDimitry Andric return false; 483fcaf7f86SDimitry Andric } 48481ad6265SDimitry Andric if (IsLoad) { 48581ad6265SDimitry Andric assert(isa<LoadInst>(I) && "Expected load or store instruction only!"); 48681ad6265SDimitry Andric if (!Acc.isWrittenValueUnknown()) { 4871ac55f4cSDimitry Andric Value *V = AdjustWrittenValueType(Acc, *Acc.getWrittenValue()); 4881ac55f4cSDimitry Andric if (!V) 4891ac55f4cSDimitry Andric return false; 4905f757f3fSDimitry Andric NewCopies.insert(V); 4915f757f3fSDimitry Andric if (PotentialValueOrigins) 4925f757f3fSDimitry Andric NewCopyOrigins.insert(Acc.getRemoteInst()); 49381ad6265SDimitry Andric return true; 49481ad6265SDimitry Andric } 49581ad6265SDimitry Andric auto *SI = dyn_cast<StoreInst>(Acc.getRemoteInst()); 49681ad6265SDimitry Andric if (!SI) { 49781ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Underlying object written through a non-store " 49881ad6265SDimitry Andric "instruction not supported yet: " 49981ad6265SDimitry Andric << *Acc.getRemoteInst() << "\n";); 50081ad6265SDimitry Andric return false; 50181ad6265SDimitry Andric } 5021ac55f4cSDimitry Andric Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand()); 5031ac55f4cSDimitry Andric if (!V) 5041ac55f4cSDimitry Andric return false; 5055f757f3fSDimitry Andric NewCopies.insert(V); 5065f757f3fSDimitry Andric if (PotentialValueOrigins) 5075f757f3fSDimitry Andric NewCopyOrigins.insert(SI); 50881ad6265SDimitry Andric } else { 50981ad6265SDimitry Andric assert(isa<StoreInst>(I) && "Expected load or store instruction only!"); 510fe6060f1SDimitry Andric auto *LI = dyn_cast<LoadInst>(Acc.getRemoteInst()); 51181ad6265SDimitry Andric if (!LI && OnlyExact) { 512fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Underlying object read through a non-load " 513fe6060f1SDimitry Andric "instruction not supported yet: " 514fe6060f1SDimitry Andric << *Acc.getRemoteInst() << "\n";); 515fe6060f1SDimitry Andric return false; 516fe6060f1SDimitry Andric } 5175f757f3fSDimitry Andric NewCopies.insert(Acc.getRemoteInst()); 51881ad6265SDimitry Andric } 519fe6060f1SDimitry Andric return true; 520fe6060f1SDimitry Andric }; 521fe6060f1SDimitry Andric 522fcaf7f86SDimitry Andric // If the value has been written to we don't need the initial value of the 523fcaf7f86SDimitry Andric // object. 524fcaf7f86SDimitry Andric bool HasBeenWrittenTo = false; 525fcaf7f86SDimitry Andric 526bdd1243dSDimitry Andric AA::RangeTy Range; 52706c3fb27SDimitry Andric auto *PI = A.getAAFor<AAPointerInfo>(QueryingAA, IRPosition::value(Obj), 528fe6060f1SDimitry Andric DepClassTy::NONE); 5295f757f3fSDimitry Andric if (!PI || !PI->forallInterferingAccesses( 5305f757f3fSDimitry Andric A, QueryingAA, I, 53106c3fb27SDimitry Andric /* FindInterferingWrites */ IsLoad, 5325f757f3fSDimitry Andric /* FindInterferingReads */ !IsLoad, CheckAccess, 5335f757f3fSDimitry Andric HasBeenWrittenTo, Range, SkipCB)) { 534fe6060f1SDimitry Andric LLVM_DEBUG( 535fe6060f1SDimitry Andric dbgs() 536fe6060f1SDimitry Andric << "Failed to verify all interfering accesses for underlying object: " 537bdd1243dSDimitry Andric << Obj << "\n"); 538fe6060f1SDimitry Andric return false; 539fe6060f1SDimitry Andric } 540fcaf7f86SDimitry Andric 541bdd1243dSDimitry Andric if (IsLoad && !HasBeenWrittenTo && !Range.isUnassigned()) { 542bdd1243dSDimitry Andric const DataLayout &DL = A.getDataLayout(); 5435f757f3fSDimitry Andric Value *InitialValue = AA::getInitialValueForObj( 5445f757f3fSDimitry Andric A, QueryingAA, Obj, *I.getType(), TLI, DL, &Range); 545bdd1243dSDimitry Andric if (!InitialValue) { 546bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Could not determine required initial value of " 547bdd1243dSDimitry Andric "underlying object, abort!\n"); 548fcaf7f86SDimitry Andric return false; 549bdd1243dSDimitry Andric } 550fcaf7f86SDimitry Andric CheckForNullOnlyAndUndef(InitialValue, /* IsExact */ true); 551fcaf7f86SDimitry Andric if (NullRequired && !NullOnly) { 552fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "Non exact access but initial value that is not " 553fcaf7f86SDimitry Andric "null or undef, abort!\n"); 554fcaf7f86SDimitry Andric return false; 555fcaf7f86SDimitry Andric } 556fcaf7f86SDimitry Andric 5575f757f3fSDimitry Andric NewCopies.insert(InitialValue); 5585f757f3fSDimitry Andric if (PotentialValueOrigins) 5595f757f3fSDimitry Andric NewCopyOrigins.insert(nullptr); 560fcaf7f86SDimitry Andric } 561fcaf7f86SDimitry Andric 56206c3fb27SDimitry Andric PIs.push_back(PI); 563bdd1243dSDimitry Andric 564bdd1243dSDimitry Andric return true; 565bdd1243dSDimitry Andric }; 566bdd1243dSDimitry Andric 56706c3fb27SDimitry Andric const auto *AAUO = A.getAAFor<AAUnderlyingObjects>( 568bdd1243dSDimitry Andric QueryingAA, IRPosition::value(Ptr), DepClassTy::OPTIONAL); 56906c3fb27SDimitry Andric if (!AAUO || !AAUO->forallUnderlyingObjects(Pred)) { 570bdd1243dSDimitry Andric LLVM_DEBUG( 571bdd1243dSDimitry Andric dbgs() << "Underlying objects stored into could not be determined\n";); 572bdd1243dSDimitry Andric return false; 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric 57581ad6265SDimitry Andric // Only if we were successful collection all potential copies we record 57681ad6265SDimitry Andric // dependences (on non-fix AAPointerInfo AAs). We also only then modify the 57781ad6265SDimitry Andric // given PotentialCopies container. 578bdd1243dSDimitry Andric for (const auto *PI : PIs) { 579fe6060f1SDimitry Andric if (!PI->getState().isAtFixpoint()) 580fe6060f1SDimitry Andric UsedAssumedInformation = true; 581fe6060f1SDimitry Andric A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL); 582fe6060f1SDimitry Andric } 583fe6060f1SDimitry Andric PotentialCopies.insert(NewCopies.begin(), NewCopies.end()); 5845f757f3fSDimitry Andric if (PotentialValueOrigins) 5855f757f3fSDimitry Andric PotentialValueOrigins->insert(NewCopyOrigins.begin(), NewCopyOrigins.end()); 586fe6060f1SDimitry Andric 587fe6060f1SDimitry Andric return true; 588fe6060f1SDimitry Andric } 589fe6060f1SDimitry Andric 59081ad6265SDimitry Andric bool AA::getPotentiallyLoadedValues( 59181ad6265SDimitry Andric Attributor &A, LoadInst &LI, SmallSetVector<Value *, 4> &PotentialValues, 59281ad6265SDimitry Andric SmallSetVector<Instruction *, 4> &PotentialValueOrigins, 59381ad6265SDimitry Andric const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, 59481ad6265SDimitry Andric bool OnlyExact) { 59581ad6265SDimitry Andric return getPotentialCopiesOfMemoryValue</* IsLoad */ true>( 5965f757f3fSDimitry Andric A, LI, PotentialValues, &PotentialValueOrigins, QueryingAA, 59781ad6265SDimitry Andric UsedAssumedInformation, OnlyExact); 59881ad6265SDimitry Andric } 59981ad6265SDimitry Andric 60081ad6265SDimitry Andric bool AA::getPotentialCopiesOfStoredValue( 60181ad6265SDimitry Andric Attributor &A, StoreInst &SI, SmallSetVector<Value *, 4> &PotentialCopies, 60281ad6265SDimitry Andric const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, 60381ad6265SDimitry Andric bool OnlyExact) { 60481ad6265SDimitry Andric return getPotentialCopiesOfMemoryValue</* IsLoad */ false>( 6055f757f3fSDimitry Andric A, SI, PotentialCopies, nullptr, QueryingAA, UsedAssumedInformation, 6065f757f3fSDimitry Andric OnlyExact); 60781ad6265SDimitry Andric } 60881ad6265SDimitry Andric 6091fd87a68SDimitry Andric static bool isAssumedReadOnlyOrReadNone(Attributor &A, const IRPosition &IRP, 6101fd87a68SDimitry Andric const AbstractAttribute &QueryingAA, 6111fd87a68SDimitry Andric bool RequireReadNone, bool &IsKnown) { 61206c3fb27SDimitry Andric if (RequireReadNone) { 61306c3fb27SDimitry Andric if (AA::hasAssumedIRAttr<Attribute::ReadNone>( 61406c3fb27SDimitry Andric A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown, 61506c3fb27SDimitry Andric /* IgnoreSubsumingPositions */ true)) 61606c3fb27SDimitry Andric return true; 61706c3fb27SDimitry Andric } else if (AA::hasAssumedIRAttr<Attribute::ReadOnly>( 61806c3fb27SDimitry Andric A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown, 61906c3fb27SDimitry Andric /* IgnoreSubsumingPositions */ true)) 62006c3fb27SDimitry Andric return true; 6211fd87a68SDimitry Andric 6221fd87a68SDimitry Andric IRPosition::Kind Kind = IRP.getPositionKind(); 6231fd87a68SDimitry Andric if (Kind == IRPosition::IRP_FUNCTION || Kind == IRPosition::IRP_CALL_SITE) { 62406c3fb27SDimitry Andric const auto *MemLocAA = 6251fd87a68SDimitry Andric A.getAAFor<AAMemoryLocation>(QueryingAA, IRP, DepClassTy::NONE); 62606c3fb27SDimitry Andric if (MemLocAA && MemLocAA->isAssumedReadNone()) { 62706c3fb27SDimitry Andric IsKnown = MemLocAA->isKnownReadNone(); 6281fd87a68SDimitry Andric if (!IsKnown) 62906c3fb27SDimitry Andric A.recordDependence(*MemLocAA, QueryingAA, DepClassTy::OPTIONAL); 6301fd87a68SDimitry Andric return true; 6311fd87a68SDimitry Andric } 6321fd87a68SDimitry Andric } 6331fd87a68SDimitry Andric 63406c3fb27SDimitry Andric const auto *MemBehaviorAA = 6351fd87a68SDimitry Andric A.getAAFor<AAMemoryBehavior>(QueryingAA, IRP, DepClassTy::NONE); 63606c3fb27SDimitry Andric if (MemBehaviorAA && 63706c3fb27SDimitry Andric (MemBehaviorAA->isAssumedReadNone() || 63806c3fb27SDimitry Andric (!RequireReadNone && MemBehaviorAA->isAssumedReadOnly()))) { 63906c3fb27SDimitry Andric IsKnown = RequireReadNone ? MemBehaviorAA->isKnownReadNone() 64006c3fb27SDimitry Andric : MemBehaviorAA->isKnownReadOnly(); 6411fd87a68SDimitry Andric if (!IsKnown) 64206c3fb27SDimitry Andric A.recordDependence(*MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL); 6431fd87a68SDimitry Andric return true; 6441fd87a68SDimitry Andric } 6451fd87a68SDimitry Andric 6461fd87a68SDimitry Andric return false; 6471fd87a68SDimitry Andric } 6481fd87a68SDimitry Andric 6491fd87a68SDimitry Andric bool AA::isAssumedReadOnly(Attributor &A, const IRPosition &IRP, 6501fd87a68SDimitry Andric const AbstractAttribute &QueryingAA, bool &IsKnown) { 6511fd87a68SDimitry Andric return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA, 6521fd87a68SDimitry Andric /* RequireReadNone */ false, IsKnown); 6531fd87a68SDimitry Andric } 6541fd87a68SDimitry Andric bool AA::isAssumedReadNone(Attributor &A, const IRPosition &IRP, 6551fd87a68SDimitry Andric const AbstractAttribute &QueryingAA, bool &IsKnown) { 6561fd87a68SDimitry Andric return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA, 6571fd87a68SDimitry Andric /* RequireReadNone */ true, IsKnown); 6581fd87a68SDimitry Andric } 6591fd87a68SDimitry Andric 6601fd87a68SDimitry Andric static bool 6611fd87a68SDimitry Andric isPotentiallyReachable(Attributor &A, const Instruction &FromI, 6621fd87a68SDimitry Andric const Instruction *ToI, const Function &ToFn, 6631fd87a68SDimitry Andric const AbstractAttribute &QueryingAA, 664bdd1243dSDimitry Andric const AA::InstExclusionSetTy *ExclusionSet, 6651fd87a68SDimitry Andric std::function<bool(const Function &F)> GoBackwardsCB) { 66606c3fb27SDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, { 667bdd1243dSDimitry Andric dbgs() << "[AA] isPotentiallyReachable @" << ToFn.getName() << " from " 668bdd1243dSDimitry Andric << FromI << " [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " 669bdd1243dSDimitry Andric << (ExclusionSet ? std::to_string(ExclusionSet->size()) : "none") 670bdd1243dSDimitry Andric << "]\n"; 671bdd1243dSDimitry Andric if (ExclusionSet) 672bdd1243dSDimitry Andric for (auto *ES : *ExclusionSet) 673bdd1243dSDimitry Andric dbgs() << *ES << "\n"; 674bdd1243dSDimitry Andric }); 6751fd87a68SDimitry Andric 67606c3fb27SDimitry Andric // We know kernels (generally) cannot be called from within the module. Thus, 67706c3fb27SDimitry Andric // for reachability we would need to step back from a kernel which would allow 67806c3fb27SDimitry Andric // us to reach anything anyway. Even if a kernel is invoked from another 67906c3fb27SDimitry Andric // kernel, values like allocas and shared memory are not accessible. We 68006c3fb27SDimitry Andric // implicitly check for this situation to avoid costly lookups. 68106c3fb27SDimitry Andric if (GoBackwardsCB && &ToFn != FromI.getFunction() && 68206c3fb27SDimitry Andric !GoBackwardsCB(*FromI.getFunction()) && ToFn.hasFnAttribute("kernel") && 68306c3fb27SDimitry Andric FromI.getFunction()->hasFnAttribute("kernel")) { 68406c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "[AA] assume kernel cannot be reached from within the " 68506c3fb27SDimitry Andric "module; success\n";); 68606c3fb27SDimitry Andric return false; 68706c3fb27SDimitry Andric } 68806c3fb27SDimitry Andric 689bdd1243dSDimitry Andric // If we can go arbitrarily backwards we will eventually reach an entry point 690bdd1243dSDimitry Andric // that can reach ToI. Only if a set of blocks through which we cannot go is 691bdd1243dSDimitry Andric // provided, or once we track internal functions not accessible from the 692bdd1243dSDimitry Andric // outside, it makes sense to perform backwards analysis in the absence of a 693bdd1243dSDimitry Andric // GoBackwardsCB. 694bdd1243dSDimitry Andric if (!GoBackwardsCB && !ExclusionSet) { 695fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "[AA] check @" << ToFn.getName() << " from " << FromI 696bdd1243dSDimitry Andric << " is not checked backwards and does not have an " 697bdd1243dSDimitry Andric "exclusion set, abort\n"); 698fcaf7f86SDimitry Andric return true; 699fcaf7f86SDimitry Andric } 700fcaf7f86SDimitry Andric 7011fd87a68SDimitry Andric SmallPtrSet<const Instruction *, 8> Visited; 7021fd87a68SDimitry Andric SmallVector<const Instruction *> Worklist; 7031fd87a68SDimitry Andric Worklist.push_back(&FromI); 7041fd87a68SDimitry Andric 7051fd87a68SDimitry Andric while (!Worklist.empty()) { 7061fd87a68SDimitry Andric const Instruction *CurFromI = Worklist.pop_back_val(); 7071fd87a68SDimitry Andric if (!Visited.insert(CurFromI).second) 7081fd87a68SDimitry Andric continue; 7091fd87a68SDimitry Andric 7101fd87a68SDimitry Andric const Function *FromFn = CurFromI->getFunction(); 7111fd87a68SDimitry Andric if (FromFn == &ToFn) { 7121fd87a68SDimitry Andric if (!ToI) 7131fd87a68SDimitry Andric return true; 7141fd87a68SDimitry Andric LLVM_DEBUG(dbgs() << "[AA] check " << *ToI << " from " << *CurFromI 7151fd87a68SDimitry Andric << " intraprocedurally\n"); 71606c3fb27SDimitry Andric const auto *ReachabilityAA = A.getAAFor<AAIntraFnReachability>( 7171fd87a68SDimitry Andric QueryingAA, IRPosition::function(ToFn), DepClassTy::OPTIONAL); 71806c3fb27SDimitry Andric bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable( 71906c3fb27SDimitry Andric A, *CurFromI, *ToI, ExclusionSet); 7201fd87a68SDimitry Andric LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " " 7211fd87a68SDimitry Andric << (Result ? "can potentially " : "cannot ") << "reach " 7221fd87a68SDimitry Andric << *ToI << " [Intra]\n"); 7231fd87a68SDimitry Andric if (Result) 7241fd87a68SDimitry Andric return true; 7251fd87a68SDimitry Andric } 7261fd87a68SDimitry Andric 727bdd1243dSDimitry Andric bool Result = true; 728bdd1243dSDimitry Andric if (!ToFn.isDeclaration() && ToI) { 72906c3fb27SDimitry Andric const auto *ToReachabilityAA = A.getAAFor<AAIntraFnReachability>( 730bdd1243dSDimitry Andric QueryingAA, IRPosition::function(ToFn), DepClassTy::OPTIONAL); 731bdd1243dSDimitry Andric const Instruction &EntryI = ToFn.getEntryBlock().front(); 73206c3fb27SDimitry Andric Result = !ToReachabilityAA || ToReachabilityAA->isAssumedReachable( 73306c3fb27SDimitry Andric A, EntryI, *ToI, ExclusionSet); 734bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Entry " << EntryI << " of @" << ToFn.getName() 735bdd1243dSDimitry Andric << " " << (Result ? "can potentially " : "cannot ") 736bdd1243dSDimitry Andric << "reach @" << *ToI << " [ToFn]\n"); 737bdd1243dSDimitry Andric } 738bdd1243dSDimitry Andric 739bdd1243dSDimitry Andric if (Result) { 740bdd1243dSDimitry Andric // The entry of the ToFn can reach the instruction ToI. If the current 741bdd1243dSDimitry Andric // instruction is already known to reach the ToFn. 74206c3fb27SDimitry Andric const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>( 7431fd87a68SDimitry Andric QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL); 74406c3fb27SDimitry Andric Result = !FnReachabilityAA || FnReachabilityAA->instructionCanReach( 74506c3fb27SDimitry Andric A, *CurFromI, ToFn, ExclusionSet); 7461fd87a68SDimitry Andric LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " in @" << FromFn->getName() 7471fd87a68SDimitry Andric << " " << (Result ? "can potentially " : "cannot ") 7481fd87a68SDimitry Andric << "reach @" << ToFn.getName() << " [FromFn]\n"); 7491fd87a68SDimitry Andric if (Result) 7501fd87a68SDimitry Andric return true; 751bdd1243dSDimitry Andric } 752bdd1243dSDimitry Andric 753bdd1243dSDimitry Andric // TODO: Check assumed nounwind. 75406c3fb27SDimitry Andric const auto *ReachabilityAA = A.getAAFor<AAIntraFnReachability>( 755bdd1243dSDimitry Andric QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL); 756bdd1243dSDimitry Andric auto ReturnInstCB = [&](Instruction &Ret) { 75706c3fb27SDimitry Andric bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable( 75806c3fb27SDimitry Andric A, *CurFromI, Ret, ExclusionSet); 759bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA][Ret] " << *CurFromI << " " 760bdd1243dSDimitry Andric << (Result ? "can potentially " : "cannot ") << "reach " 761bdd1243dSDimitry Andric << Ret << " [Intra]\n"); 762bdd1243dSDimitry Andric return !Result; 763bdd1243dSDimitry Andric }; 764bdd1243dSDimitry Andric 765bdd1243dSDimitry Andric // Check if we can reach returns. 766bdd1243dSDimitry Andric bool UsedAssumedInformation = false; 7675f757f3fSDimitry Andric if (A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA, 768bdd1243dSDimitry Andric {Instruction::Ret}, UsedAssumedInformation)) { 769bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] No return is reachable, done\n"); 770bdd1243dSDimitry Andric continue; 771bdd1243dSDimitry Andric } 772bdd1243dSDimitry Andric 773bdd1243dSDimitry Andric if (!GoBackwardsCB) { 774bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] check @" << ToFn.getName() << " from " << FromI 775bdd1243dSDimitry Andric << " is not checked backwards, abort\n"); 776bdd1243dSDimitry Andric return true; 777bdd1243dSDimitry Andric } 7781fd87a68SDimitry Andric 7791fd87a68SDimitry Andric // If we do not go backwards from the FromFn we are done here and so far we 7801fd87a68SDimitry Andric // could not find a way to reach ToFn/ToI. 7811fd87a68SDimitry Andric if (!GoBackwardsCB(*FromFn)) 7821fd87a68SDimitry Andric continue; 7831fd87a68SDimitry Andric 7841fd87a68SDimitry Andric LLVM_DEBUG(dbgs() << "Stepping backwards to the call sites of @" 7851fd87a68SDimitry Andric << FromFn->getName() << "\n"); 7861fd87a68SDimitry Andric 7871fd87a68SDimitry Andric auto CheckCallSite = [&](AbstractCallSite ACS) { 7881fd87a68SDimitry Andric CallBase *CB = ACS.getInstruction(); 7891fd87a68SDimitry Andric if (!CB) 7901fd87a68SDimitry Andric return false; 7911fd87a68SDimitry Andric 7921fd87a68SDimitry Andric if (isa<InvokeInst>(CB)) 7931fd87a68SDimitry Andric return false; 7941fd87a68SDimitry Andric 7951fd87a68SDimitry Andric Instruction *Inst = CB->getNextNonDebugInstruction(); 7961fd87a68SDimitry Andric Worklist.push_back(Inst); 7971fd87a68SDimitry Andric return true; 7981fd87a68SDimitry Andric }; 7991fd87a68SDimitry Andric 8001fd87a68SDimitry Andric Result = !A.checkForAllCallSites(CheckCallSite, *FromFn, 8011fd87a68SDimitry Andric /* RequireAllCallSites */ true, 802d781ede6SDimitry Andric &QueryingAA, UsedAssumedInformation); 8031fd87a68SDimitry Andric if (Result) { 8041fd87a68SDimitry Andric LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromI 8051fd87a68SDimitry Andric << " in @" << FromFn->getName() 8061fd87a68SDimitry Andric << " failed, give up\n"); 8071fd87a68SDimitry Andric return true; 8081fd87a68SDimitry Andric } 8091fd87a68SDimitry Andric 8101fd87a68SDimitry Andric LLVM_DEBUG(dbgs() << "[AA] stepped back to call sites from " << *CurFromI 8111fd87a68SDimitry Andric << " in @" << FromFn->getName() 8121fd87a68SDimitry Andric << " worklist size is: " << Worklist.size() << "\n"); 8131fd87a68SDimitry Andric } 8141fd87a68SDimitry Andric return false; 8151fd87a68SDimitry Andric } 8161fd87a68SDimitry Andric 8171fd87a68SDimitry Andric bool AA::isPotentiallyReachable( 8181fd87a68SDimitry Andric Attributor &A, const Instruction &FromI, const Instruction &ToI, 8191fd87a68SDimitry Andric const AbstractAttribute &QueryingAA, 820bdd1243dSDimitry Andric const AA::InstExclusionSetTy *ExclusionSet, 8211fd87a68SDimitry Andric std::function<bool(const Function &F)> GoBackwardsCB) { 8221fd87a68SDimitry Andric const Function *ToFn = ToI.getFunction(); 8231fd87a68SDimitry Andric return ::isPotentiallyReachable(A, FromI, &ToI, *ToFn, QueryingAA, 824bdd1243dSDimitry Andric ExclusionSet, GoBackwardsCB); 8251fd87a68SDimitry Andric } 8261fd87a68SDimitry Andric 8271fd87a68SDimitry Andric bool AA::isPotentiallyReachable( 8281fd87a68SDimitry Andric Attributor &A, const Instruction &FromI, const Function &ToFn, 8291fd87a68SDimitry Andric const AbstractAttribute &QueryingAA, 830bdd1243dSDimitry Andric const AA::InstExclusionSetTy *ExclusionSet, 8311fd87a68SDimitry Andric std::function<bool(const Function &F)> GoBackwardsCB) { 8321fd87a68SDimitry Andric return ::isPotentiallyReachable(A, FromI, /* ToI */ nullptr, ToFn, QueryingAA, 833bdd1243dSDimitry Andric ExclusionSet, GoBackwardsCB); 834bdd1243dSDimitry Andric } 835bdd1243dSDimitry Andric 836bdd1243dSDimitry Andric bool AA::isAssumedThreadLocalObject(Attributor &A, Value &Obj, 837bdd1243dSDimitry Andric const AbstractAttribute &QueryingAA) { 838bdd1243dSDimitry Andric if (isa<UndefValue>(Obj)) 839bdd1243dSDimitry Andric return true; 840bdd1243dSDimitry Andric if (isa<AllocaInst>(Obj)) { 841bdd1243dSDimitry Andric InformationCache &InfoCache = A.getInfoCache(); 842bdd1243dSDimitry Andric if (!InfoCache.stackIsAccessibleByOtherThreads()) { 843bdd1243dSDimitry Andric LLVM_DEBUG( 844bdd1243dSDimitry Andric dbgs() << "[AA] Object '" << Obj 845bdd1243dSDimitry Andric << "' is thread local; stack objects are thread local.\n"); 846bdd1243dSDimitry Andric return true; 847bdd1243dSDimitry Andric } 84806c3fb27SDimitry Andric bool IsKnownNoCapture; 84906c3fb27SDimitry Andric bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>( 85006c3fb27SDimitry Andric A, &QueryingAA, IRPosition::value(Obj), DepClassTy::OPTIONAL, 85106c3fb27SDimitry Andric IsKnownNoCapture); 852bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is " 85306c3fb27SDimitry Andric << (IsAssumedNoCapture ? "" : "not") << " thread local; " 85406c3fb27SDimitry Andric << (IsAssumedNoCapture ? "non-" : "") 855bdd1243dSDimitry Andric << "captured stack object.\n"); 85606c3fb27SDimitry Andric return IsAssumedNoCapture; 857bdd1243dSDimitry Andric } 858bdd1243dSDimitry Andric if (auto *GV = dyn_cast<GlobalVariable>(&Obj)) { 859bdd1243dSDimitry Andric if (GV->isConstant()) { 860bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj 861bdd1243dSDimitry Andric << "' is thread local; constant global\n"); 862bdd1243dSDimitry Andric return true; 863bdd1243dSDimitry Andric } 864bdd1243dSDimitry Andric if (GV->isThreadLocal()) { 865bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj 866bdd1243dSDimitry Andric << "' is thread local; thread local global\n"); 867bdd1243dSDimitry Andric return true; 868bdd1243dSDimitry Andric } 869bdd1243dSDimitry Andric } 870bdd1243dSDimitry Andric 871bdd1243dSDimitry Andric if (A.getInfoCache().targetIsGPU()) { 872bdd1243dSDimitry Andric if (Obj.getType()->getPointerAddressSpace() == 873bdd1243dSDimitry Andric (int)AA::GPUAddressSpace::Local) { 874bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj 875bdd1243dSDimitry Andric << "' is thread local; GPU local memory\n"); 876bdd1243dSDimitry Andric return true; 877bdd1243dSDimitry Andric } 878bdd1243dSDimitry Andric if (Obj.getType()->getPointerAddressSpace() == 879bdd1243dSDimitry Andric (int)AA::GPUAddressSpace::Constant) { 880bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj 881bdd1243dSDimitry Andric << "' is thread local; GPU constant memory\n"); 882bdd1243dSDimitry Andric return true; 883bdd1243dSDimitry Andric } 884bdd1243dSDimitry Andric } 885bdd1243dSDimitry Andric 886bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is not thread local\n"); 887bdd1243dSDimitry Andric return false; 888bdd1243dSDimitry Andric } 889bdd1243dSDimitry Andric 890bdd1243dSDimitry Andric bool AA::isPotentiallyAffectedByBarrier(Attributor &A, const Instruction &I, 891bdd1243dSDimitry Andric const AbstractAttribute &QueryingAA) { 892bdd1243dSDimitry Andric if (!I.mayHaveSideEffects() && !I.mayReadFromMemory()) 893bdd1243dSDimitry Andric return false; 894bdd1243dSDimitry Andric 895bdd1243dSDimitry Andric SmallSetVector<const Value *, 8> Ptrs; 896bdd1243dSDimitry Andric 897bdd1243dSDimitry Andric auto AddLocationPtr = [&](std::optional<MemoryLocation> Loc) { 898bdd1243dSDimitry Andric if (!Loc || !Loc->Ptr) { 899bdd1243dSDimitry Andric LLVM_DEBUG( 900bdd1243dSDimitry Andric dbgs() << "[AA] Access to unknown location; -> requires barriers\n"); 901bdd1243dSDimitry Andric return false; 902bdd1243dSDimitry Andric } 903bdd1243dSDimitry Andric Ptrs.insert(Loc->Ptr); 904bdd1243dSDimitry Andric return true; 905bdd1243dSDimitry Andric }; 906bdd1243dSDimitry Andric 907bdd1243dSDimitry Andric if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&I)) { 908bdd1243dSDimitry Andric if (!AddLocationPtr(MemoryLocation::getForDest(MI))) 909bdd1243dSDimitry Andric return true; 910bdd1243dSDimitry Andric if (const MemTransferInst *MTI = dyn_cast<MemTransferInst>(&I)) 911bdd1243dSDimitry Andric if (!AddLocationPtr(MemoryLocation::getForSource(MTI))) 912bdd1243dSDimitry Andric return true; 913bdd1243dSDimitry Andric } else if (!AddLocationPtr(MemoryLocation::getOrNone(&I))) 914bdd1243dSDimitry Andric return true; 915bdd1243dSDimitry Andric 916bdd1243dSDimitry Andric return isPotentiallyAffectedByBarrier(A, Ptrs.getArrayRef(), QueryingAA, &I); 917bdd1243dSDimitry Andric } 918bdd1243dSDimitry Andric 919bdd1243dSDimitry Andric bool AA::isPotentiallyAffectedByBarrier(Attributor &A, 920bdd1243dSDimitry Andric ArrayRef<const Value *> Ptrs, 921bdd1243dSDimitry Andric const AbstractAttribute &QueryingAA, 922bdd1243dSDimitry Andric const Instruction *CtxI) { 923bdd1243dSDimitry Andric for (const Value *Ptr : Ptrs) { 924bdd1243dSDimitry Andric if (!Ptr) { 925bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] nullptr; -> requires barriers\n"); 926bdd1243dSDimitry Andric return true; 927bdd1243dSDimitry Andric } 928bdd1243dSDimitry Andric 929bdd1243dSDimitry Andric auto Pred = [&](Value &Obj) { 930bdd1243dSDimitry Andric if (AA::isAssumedThreadLocalObject(A, Obj, QueryingAA)) 931bdd1243dSDimitry Andric return true; 932bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "[AA] Access to '" << Obj << "' via '" << *Ptr 933bdd1243dSDimitry Andric << "'; -> requires barrier\n"); 934bdd1243dSDimitry Andric return false; 935bdd1243dSDimitry Andric }; 936bdd1243dSDimitry Andric 93706c3fb27SDimitry Andric const auto *UnderlyingObjsAA = A.getAAFor<AAUnderlyingObjects>( 938bdd1243dSDimitry Andric QueryingAA, IRPosition::value(*Ptr), DepClassTy::OPTIONAL); 93906c3fb27SDimitry Andric if (!UnderlyingObjsAA || !UnderlyingObjsAA->forallUnderlyingObjects(Pred)) 940bdd1243dSDimitry Andric return true; 941bdd1243dSDimitry Andric } 942bdd1243dSDimitry Andric return false; 9431fd87a68SDimitry Andric } 9441fd87a68SDimitry Andric 9450b57cec5SDimitry Andric /// Return true if \p New is equal or worse than \p Old. 9460b57cec5SDimitry Andric static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) { 9470b57cec5SDimitry Andric if (!Old.isIntAttribute()) 9480b57cec5SDimitry Andric return true; 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric return Old.getValueAsInt() >= New.getValueAsInt(); 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric /// Return true if the information provided by \p Attr was added to the 95406c3fb27SDimitry Andric /// attribute set \p AttrSet. This is only the case if it was not already 95506c3fb27SDimitry Andric /// present in \p AttrSet. 9560b57cec5SDimitry Andric static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, 95706c3fb27SDimitry Andric AttributeSet AttrSet, bool ForceReplace, 95806c3fb27SDimitry Andric AttrBuilder &AB) { 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric if (Attr.isEnumAttribute()) { 9610b57cec5SDimitry Andric Attribute::AttrKind Kind = Attr.getKindAsEnum(); 96206c3fb27SDimitry Andric if (AttrSet.hasAttribute(Kind)) 9630b57cec5SDimitry Andric return false; 96406c3fb27SDimitry Andric AB.addAttribute(Kind); 9650b57cec5SDimitry Andric return true; 9660b57cec5SDimitry Andric } 9670b57cec5SDimitry Andric if (Attr.isStringAttribute()) { 9680b57cec5SDimitry Andric StringRef Kind = Attr.getKindAsString(); 96906c3fb27SDimitry Andric if (AttrSet.hasAttribute(Kind)) { 97006c3fb27SDimitry Andric if (!ForceReplace) 9710b57cec5SDimitry Andric return false; 97206c3fb27SDimitry Andric } 97306c3fb27SDimitry Andric AB.addAttribute(Kind, Attr.getValueAsString()); 9740b57cec5SDimitry Andric return true; 9750b57cec5SDimitry Andric } 9768bcb0991SDimitry Andric if (Attr.isIntAttribute()) { 9778bcb0991SDimitry Andric Attribute::AttrKind Kind = Attr.getKindAsEnum(); 97806c3fb27SDimitry Andric if (!ForceReplace && Kind == Attribute::Memory) { 97906c3fb27SDimitry Andric MemoryEffects ME = Attr.getMemoryEffects() & AttrSet.getMemoryEffects(); 98006c3fb27SDimitry Andric if (ME == AttrSet.getMemoryEffects()) 9818bcb0991SDimitry Andric return false; 98206c3fb27SDimitry Andric AB.addMemoryAttr(ME); 98306c3fb27SDimitry Andric return true; 98406c3fb27SDimitry Andric } 98506c3fb27SDimitry Andric if (AttrSet.hasAttribute(Kind)) { 98606c3fb27SDimitry Andric if (!ForceReplace && isEqualOrWorse(Attr, AttrSet.getAttribute(Kind))) 98706c3fb27SDimitry Andric return false; 98806c3fb27SDimitry Andric } 98906c3fb27SDimitry Andric AB.addAttribute(Attr); 9908bcb0991SDimitry Andric return true; 9918bcb0991SDimitry Andric } 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric llvm_unreachable("Expected enum or string attribute!"); 9940b57cec5SDimitry Andric } 9958bcb0991SDimitry Andric 9965ffd83dbSDimitry Andric Argument *IRPosition::getAssociatedArgument() const { 9975ffd83dbSDimitry Andric if (getPositionKind() == IRP_ARGUMENT) 9985ffd83dbSDimitry Andric return cast<Argument>(&getAnchorValue()); 9995ffd83dbSDimitry Andric 10005ffd83dbSDimitry Andric // Not an Argument and no argument number means this is not a call site 10015ffd83dbSDimitry Andric // argument, thus we cannot find a callback argument to return. 1002e8d8bef9SDimitry Andric int ArgNo = getCallSiteArgNo(); 10035ffd83dbSDimitry Andric if (ArgNo < 0) 10048bcb0991SDimitry Andric return nullptr; 10058bcb0991SDimitry Andric 10065ffd83dbSDimitry Andric // Use abstract call sites to make the connection between the call site 10075ffd83dbSDimitry Andric // values and the ones in callbacks. If a callback was found that makes use 10085ffd83dbSDimitry Andric // of the underlying call site operand, we want the corresponding callback 10095ffd83dbSDimitry Andric // callee argument and not the direct callee argument. 1010bdd1243dSDimitry Andric std::optional<Argument *> CBCandidateArg; 10115ffd83dbSDimitry Andric SmallVector<const Use *, 4> CallbackUses; 10125ffd83dbSDimitry Andric const auto &CB = cast<CallBase>(getAnchorValue()); 10135ffd83dbSDimitry Andric AbstractCallSite::getCallbackUses(CB, CallbackUses); 10145ffd83dbSDimitry Andric for (const Use *U : CallbackUses) { 10155ffd83dbSDimitry Andric AbstractCallSite ACS(U); 10165ffd83dbSDimitry Andric assert(ACS && ACS.isCallbackCall()); 10175ffd83dbSDimitry Andric if (!ACS.getCalledFunction()) 10185ffd83dbSDimitry Andric continue; 10195ffd83dbSDimitry Andric 10205ffd83dbSDimitry Andric for (unsigned u = 0, e = ACS.getNumArgOperands(); u < e; u++) { 10215ffd83dbSDimitry Andric 10225ffd83dbSDimitry Andric // Test if the underlying call site operand is argument number u of the 10235ffd83dbSDimitry Andric // callback callee. 10245ffd83dbSDimitry Andric if (ACS.getCallArgOperandNo(u) != ArgNo) 10255ffd83dbSDimitry Andric continue; 10265ffd83dbSDimitry Andric 10275ffd83dbSDimitry Andric assert(ACS.getCalledFunction()->arg_size() > u && 10285ffd83dbSDimitry Andric "ACS mapped into var-args arguments!"); 102981ad6265SDimitry Andric if (CBCandidateArg) { 10305ffd83dbSDimitry Andric CBCandidateArg = nullptr; 10315ffd83dbSDimitry Andric break; 10325ffd83dbSDimitry Andric } 10335ffd83dbSDimitry Andric CBCandidateArg = ACS.getCalledFunction()->getArg(u); 10345ffd83dbSDimitry Andric } 10355ffd83dbSDimitry Andric } 10365ffd83dbSDimitry Andric 10375ffd83dbSDimitry Andric // If we found a unique callback candidate argument, return it. 1038bdd1243dSDimitry Andric if (CBCandidateArg && *CBCandidateArg) 1039bdd1243dSDimitry Andric return *CBCandidateArg; 10405ffd83dbSDimitry Andric 10415ffd83dbSDimitry Andric // If no callbacks were found, or none used the underlying call site operand 10425ffd83dbSDimitry Andric // exclusively, use the direct callee argument if available. 104306c3fb27SDimitry Andric auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand()); 10445ffd83dbSDimitry Andric if (Callee && Callee->arg_size() > unsigned(ArgNo)) 10455ffd83dbSDimitry Andric return Callee->getArg(ArgNo); 10465ffd83dbSDimitry Andric 10475ffd83dbSDimitry Andric return nullptr; 10488bcb0991SDimitry Andric } 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric ChangeStatus AbstractAttribute::update(Attributor &A) { 10510b57cec5SDimitry Andric ChangeStatus HasChanged = ChangeStatus::UNCHANGED; 10520b57cec5SDimitry Andric if (getState().isAtFixpoint()) 10530b57cec5SDimitry Andric return HasChanged; 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n"); 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric HasChanged = updateImpl(A); 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this 10600b57cec5SDimitry Andric << "\n"); 10610b57cec5SDimitry Andric 10620b57cec5SDimitry Andric return HasChanged; 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric 10655f757f3fSDimitry Andric Attributor::Attributor(SetVector<Function *> &Functions, 10665f757f3fSDimitry Andric InformationCache &InfoCache, 10675f757f3fSDimitry Andric AttributorConfig Configuration) 10685f757f3fSDimitry Andric : Allocator(InfoCache.Allocator), Functions(Functions), 10695f757f3fSDimitry Andric InfoCache(InfoCache), Configuration(Configuration) { 10705f757f3fSDimitry Andric if (!isClosedWorldModule()) 10715f757f3fSDimitry Andric return; 10725f757f3fSDimitry Andric for (Function *Fn : Functions) 10735f757f3fSDimitry Andric if (Fn->hasAddressTaken(/*PutOffender=*/nullptr, 10745f757f3fSDimitry Andric /*IgnoreCallbackUses=*/false, 10755f757f3fSDimitry Andric /*IgnoreAssumeLikeCalls=*/true, 10765f757f3fSDimitry Andric /*IgnoreLLVMUsed=*/true, 10775f757f3fSDimitry Andric /*IgnoreARCAttachedCall=*/false, 10785f757f3fSDimitry Andric /*IgnoreCastedDirectCall=*/true)) 10795f757f3fSDimitry Andric InfoCache.IndirectlyCallableFunctions.push_back(Fn); 10805f757f3fSDimitry Andric } 10815f757f3fSDimitry Andric 108206c3fb27SDimitry Andric bool Attributor::getAttrsFromAssumes(const IRPosition &IRP, 108306c3fb27SDimitry Andric Attribute::AttrKind AK, 108406c3fb27SDimitry Andric SmallVectorImpl<Attribute> &Attrs) { 108506c3fb27SDimitry Andric assert(IRP.getPositionKind() != IRPosition::IRP_INVALID && 108606c3fb27SDimitry Andric "Did expect a valid position!"); 108706c3fb27SDimitry Andric MustBeExecutedContextExplorer *Explorer = 108806c3fb27SDimitry Andric getInfoCache().getMustBeExecutedContextExplorer(); 108906c3fb27SDimitry Andric if (!Explorer) 109006c3fb27SDimitry Andric return false; 10910b57cec5SDimitry Andric 109206c3fb27SDimitry Andric Value &AssociatedValue = IRP.getAssociatedValue(); 10930b57cec5SDimitry Andric 109406c3fb27SDimitry Andric const Assume2KnowledgeMap &A2K = 109506c3fb27SDimitry Andric getInfoCache().getKnowledgeMap().lookup({&AssociatedValue, AK}); 109606c3fb27SDimitry Andric 109706c3fb27SDimitry Andric // Check if we found any potential assume use, if not we don't need to create 109806c3fb27SDimitry Andric // explorer iterators. 109906c3fb27SDimitry Andric if (A2K.empty()) 110006c3fb27SDimitry Andric return false; 110106c3fb27SDimitry Andric 110206c3fb27SDimitry Andric LLVMContext &Ctx = AssociatedValue.getContext(); 110306c3fb27SDimitry Andric unsigned AttrsSize = Attrs.size(); 110406c3fb27SDimitry Andric auto EIt = Explorer->begin(IRP.getCtxI()), 110506c3fb27SDimitry Andric EEnd = Explorer->end(IRP.getCtxI()); 110606c3fb27SDimitry Andric for (const auto &It : A2K) 110706c3fb27SDimitry Andric if (Explorer->findInContextOf(It.first, EIt, EEnd)) 110806c3fb27SDimitry Andric Attrs.push_back(Attribute::get(Ctx, AK, It.second.Max)); 110906c3fb27SDimitry Andric return AttrsSize != Attrs.size(); 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 111206c3fb27SDimitry Andric template <typename DescTy> 111306c3fb27SDimitry Andric ChangeStatus 11145f757f3fSDimitry Andric Attributor::updateAttrMap(const IRPosition &IRP, ArrayRef<DescTy> AttrDescs, 111506c3fb27SDimitry Andric function_ref<bool(const DescTy &, AttributeSet, 111606c3fb27SDimitry Andric AttributeMask &, AttrBuilder &)> 111706c3fb27SDimitry Andric CB) { 111806c3fb27SDimitry Andric if (AttrDescs.empty()) 111906c3fb27SDimitry Andric return ChangeStatus::UNCHANGED; 112006c3fb27SDimitry Andric switch (IRP.getPositionKind()) { 112106c3fb27SDimitry Andric case IRPosition::IRP_FLOAT: 112206c3fb27SDimitry Andric case IRPosition::IRP_INVALID: 112306c3fb27SDimitry Andric return ChangeStatus::UNCHANGED; 112406c3fb27SDimitry Andric default: 112506c3fb27SDimitry Andric break; 112606c3fb27SDimitry Andric }; 112706c3fb27SDimitry Andric 112806c3fb27SDimitry Andric AttributeList AL; 112906c3fb27SDimitry Andric Value *AttrListAnchor = IRP.getAttrListAnchor(); 113006c3fb27SDimitry Andric auto It = AttrsMap.find(AttrListAnchor); 113106c3fb27SDimitry Andric if (It == AttrsMap.end()) 113206c3fb27SDimitry Andric AL = IRP.getAttrList(); 113306c3fb27SDimitry Andric else 113406c3fb27SDimitry Andric AL = It->getSecond(); 113506c3fb27SDimitry Andric 113606c3fb27SDimitry Andric LLVMContext &Ctx = IRP.getAnchorValue().getContext(); 113706c3fb27SDimitry Andric auto AttrIdx = IRP.getAttrIdx(); 113806c3fb27SDimitry Andric AttributeSet AS = AL.getAttributes(AttrIdx); 113906c3fb27SDimitry Andric AttributeMask AM; 114006c3fb27SDimitry Andric AttrBuilder AB(Ctx); 114106c3fb27SDimitry Andric 11428bcb0991SDimitry Andric ChangeStatus HasChanged = ChangeStatus::UNCHANGED; 114306c3fb27SDimitry Andric for (const DescTy &AttrDesc : AttrDescs) 114406c3fb27SDimitry Andric if (CB(AttrDesc, AS, AM, AB)) 11450b57cec5SDimitry Andric HasChanged = ChangeStatus::CHANGED; 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric if (HasChanged == ChangeStatus::UNCHANGED) 114806c3fb27SDimitry Andric return ChangeStatus::UNCHANGED; 11490b57cec5SDimitry Andric 115006c3fb27SDimitry Andric AL = AL.removeAttributesAtIndex(Ctx, AttrIdx, AM); 115106c3fb27SDimitry Andric AL = AL.addAttributesAtIndex(Ctx, AttrIdx, AB); 115206c3fb27SDimitry Andric AttrsMap[AttrListAnchor] = AL; 115306c3fb27SDimitry Andric return ChangeStatus::CHANGED; 11540b57cec5SDimitry Andric } 11550b57cec5SDimitry Andric 115606c3fb27SDimitry Andric bool Attributor::hasAttr(const IRPosition &IRP, 115706c3fb27SDimitry Andric ArrayRef<Attribute::AttrKind> AttrKinds, 115806c3fb27SDimitry Andric bool IgnoreSubsumingPositions, 115906c3fb27SDimitry Andric Attribute::AttrKind ImpliedAttributeKind) { 116006c3fb27SDimitry Andric bool Implied = false; 116106c3fb27SDimitry Andric bool HasAttr = false; 116206c3fb27SDimitry Andric auto HasAttrCB = [&](const Attribute::AttrKind &Kind, AttributeSet AttrSet, 116306c3fb27SDimitry Andric AttributeMask &, AttrBuilder &) { 116406c3fb27SDimitry Andric if (AttrSet.hasAttribute(Kind)) { 116506c3fb27SDimitry Andric Implied |= Kind != ImpliedAttributeKind; 116606c3fb27SDimitry Andric HasAttr = true; 116706c3fb27SDimitry Andric } 116806c3fb27SDimitry Andric return false; 116906c3fb27SDimitry Andric }; 117006c3fb27SDimitry Andric for (const IRPosition &EquivIRP : SubsumingPositionIterator(IRP)) { 117106c3fb27SDimitry Andric updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, HasAttrCB); 117206c3fb27SDimitry Andric if (HasAttr) 117306c3fb27SDimitry Andric break; 117406c3fb27SDimitry Andric // The first position returned by the SubsumingPositionIterator is 117506c3fb27SDimitry Andric // always the position itself. If we ignore subsuming positions we 117606c3fb27SDimitry Andric // are done after the first iteration. 117706c3fb27SDimitry Andric if (IgnoreSubsumingPositions) 117806c3fb27SDimitry Andric break; 117906c3fb27SDimitry Andric Implied = true; 118006c3fb27SDimitry Andric } 118106c3fb27SDimitry Andric if (!HasAttr) { 118206c3fb27SDimitry Andric Implied = true; 118306c3fb27SDimitry Andric SmallVector<Attribute> Attrs; 118406c3fb27SDimitry Andric for (Attribute::AttrKind AK : AttrKinds) 118506c3fb27SDimitry Andric if (getAttrsFromAssumes(IRP, AK, Attrs)) { 118606c3fb27SDimitry Andric HasAttr = true; 118706c3fb27SDimitry Andric break; 118806c3fb27SDimitry Andric } 118906c3fb27SDimitry Andric } 119006c3fb27SDimitry Andric 119106c3fb27SDimitry Andric // Check if we should manifest the implied attribute kind at the IRP. 119206c3fb27SDimitry Andric if (ImpliedAttributeKind != Attribute::None && HasAttr && Implied) 119306c3fb27SDimitry Andric manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(), 119406c3fb27SDimitry Andric ImpliedAttributeKind)}); 119506c3fb27SDimitry Andric return HasAttr; 119606c3fb27SDimitry Andric } 119706c3fb27SDimitry Andric 119806c3fb27SDimitry Andric void Attributor::getAttrs(const IRPosition &IRP, 119906c3fb27SDimitry Andric ArrayRef<Attribute::AttrKind> AttrKinds, 120006c3fb27SDimitry Andric SmallVectorImpl<Attribute> &Attrs, 120106c3fb27SDimitry Andric bool IgnoreSubsumingPositions) { 120206c3fb27SDimitry Andric auto CollectAttrCB = [&](const Attribute::AttrKind &Kind, 120306c3fb27SDimitry Andric AttributeSet AttrSet, AttributeMask &, 120406c3fb27SDimitry Andric AttrBuilder &) { 120506c3fb27SDimitry Andric if (AttrSet.hasAttribute(Kind)) 120606c3fb27SDimitry Andric Attrs.push_back(AttrSet.getAttribute(Kind)); 120706c3fb27SDimitry Andric return false; 120806c3fb27SDimitry Andric }; 120906c3fb27SDimitry Andric for (const IRPosition &EquivIRP : SubsumingPositionIterator(IRP)) { 121006c3fb27SDimitry Andric updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, CollectAttrCB); 121106c3fb27SDimitry Andric // The first position returned by the SubsumingPositionIterator is 121206c3fb27SDimitry Andric // always the position itself. If we ignore subsuming positions we 121306c3fb27SDimitry Andric // are done after the first iteration. 121406c3fb27SDimitry Andric if (IgnoreSubsumingPositions) 121506c3fb27SDimitry Andric break; 121606c3fb27SDimitry Andric } 121706c3fb27SDimitry Andric for (Attribute::AttrKind AK : AttrKinds) 121806c3fb27SDimitry Andric getAttrsFromAssumes(IRP, AK, Attrs); 121906c3fb27SDimitry Andric } 122006c3fb27SDimitry Andric 12215f757f3fSDimitry Andric ChangeStatus Attributor::removeAttrs(const IRPosition &IRP, 12225f757f3fSDimitry Andric ArrayRef<Attribute::AttrKind> AttrKinds) { 122306c3fb27SDimitry Andric auto RemoveAttrCB = [&](const Attribute::AttrKind &Kind, AttributeSet AttrSet, 122406c3fb27SDimitry Andric AttributeMask &AM, AttrBuilder &) { 122506c3fb27SDimitry Andric if (!AttrSet.hasAttribute(Kind)) 122606c3fb27SDimitry Andric return false; 122706c3fb27SDimitry Andric AM.addAttribute(Kind); 122806c3fb27SDimitry Andric return true; 122906c3fb27SDimitry Andric }; 123006c3fb27SDimitry Andric return updateAttrMap<Attribute::AttrKind>(IRP, AttrKinds, RemoveAttrCB); 123106c3fb27SDimitry Andric } 123206c3fb27SDimitry Andric 12335f757f3fSDimitry Andric ChangeStatus Attributor::removeAttrs(const IRPosition &IRP, 12345f757f3fSDimitry Andric ArrayRef<StringRef> Attrs) { 12355f757f3fSDimitry Andric auto RemoveAttrCB = [&](StringRef Attr, AttributeSet AttrSet, 12365f757f3fSDimitry Andric AttributeMask &AM, AttrBuilder &) -> bool { 12375f757f3fSDimitry Andric if (!AttrSet.hasAttribute(Attr)) 12385f757f3fSDimitry Andric return false; 12395f757f3fSDimitry Andric AM.addAttribute(Attr); 12405f757f3fSDimitry Andric return true; 12415f757f3fSDimitry Andric }; 12425f757f3fSDimitry Andric 12435f757f3fSDimitry Andric return updateAttrMap<StringRef>(IRP, Attrs, RemoveAttrCB); 12445f757f3fSDimitry Andric } 12455f757f3fSDimitry Andric 124606c3fb27SDimitry Andric ChangeStatus Attributor::manifestAttrs(const IRPosition &IRP, 12475f757f3fSDimitry Andric ArrayRef<Attribute> Attrs, 124806c3fb27SDimitry Andric bool ForceReplace) { 124906c3fb27SDimitry Andric LLVMContext &Ctx = IRP.getAnchorValue().getContext(); 125006c3fb27SDimitry Andric auto AddAttrCB = [&](const Attribute &Attr, AttributeSet AttrSet, 125106c3fb27SDimitry Andric AttributeMask &, AttrBuilder &AB) { 125206c3fb27SDimitry Andric return addIfNotExistent(Ctx, Attr, AttrSet, ForceReplace, AB); 125306c3fb27SDimitry Andric }; 125406c3fb27SDimitry Andric return updateAttrMap<Attribute>(IRP, Attrs, AddAttrCB); 12550b57cec5SDimitry Andric } 12560b57cec5SDimitry Andric 12575ffd83dbSDimitry Andric const IRPosition IRPosition::EmptyKey(DenseMapInfo<void *>::getEmptyKey()); 12585ffd83dbSDimitry Andric const IRPosition 12595ffd83dbSDimitry Andric IRPosition::TombstoneKey(DenseMapInfo<void *>::getTombstoneKey()); 12608bcb0991SDimitry Andric 12618bcb0991SDimitry Andric SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) { 12628bcb0991SDimitry Andric IRPositions.emplace_back(IRP); 12638bcb0991SDimitry Andric 126406c3fb27SDimitry Andric // Helper to determine if operand bundles on a call site are benign or 1265e8d8bef9SDimitry Andric // potentially problematic. We handle only llvm.assume for now. 1266e8d8bef9SDimitry Andric auto CanIgnoreOperandBundles = [](const CallBase &CB) { 1267e8d8bef9SDimitry Andric return (isa<IntrinsicInst>(CB) && 1268e8d8bef9SDimitry Andric cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume); 1269e8d8bef9SDimitry Andric }; 1270e8d8bef9SDimitry Andric 12715ffd83dbSDimitry Andric const auto *CB = dyn_cast<CallBase>(&IRP.getAnchorValue()); 12728bcb0991SDimitry Andric switch (IRP.getPositionKind()) { 12738bcb0991SDimitry Andric case IRPosition::IRP_INVALID: 12748bcb0991SDimitry Andric case IRPosition::IRP_FLOAT: 12758bcb0991SDimitry Andric case IRPosition::IRP_FUNCTION: 12768bcb0991SDimitry Andric return; 12778bcb0991SDimitry Andric case IRPosition::IRP_ARGUMENT: 12788bcb0991SDimitry Andric case IRPosition::IRP_RETURNED: 12795ffd83dbSDimitry Andric IRPositions.emplace_back(IRPosition::function(*IRP.getAnchorScope())); 12808bcb0991SDimitry Andric return; 12818bcb0991SDimitry Andric case IRPosition::IRP_CALL_SITE: 12825ffd83dbSDimitry Andric assert(CB && "Expected call site!"); 12838bcb0991SDimitry Andric // TODO: We need to look at the operand bundles similar to the redirection 12848bcb0991SDimitry Andric // in CallBase. 1285e8d8bef9SDimitry Andric if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) 128606c3fb27SDimitry Andric if (auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand())) 12878bcb0991SDimitry Andric IRPositions.emplace_back(IRPosition::function(*Callee)); 12888bcb0991SDimitry Andric return; 12898bcb0991SDimitry Andric case IRPosition::IRP_CALL_SITE_RETURNED: 12905ffd83dbSDimitry Andric assert(CB && "Expected call site!"); 12918bcb0991SDimitry Andric // TODO: We need to look at the operand bundles similar to the redirection 12928bcb0991SDimitry Andric // in CallBase. 1293e8d8bef9SDimitry Andric if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) { 129406c3fb27SDimitry Andric if (auto *Callee = 129506c3fb27SDimitry Andric dyn_cast_if_present<Function>(CB->getCalledOperand())) { 12968bcb0991SDimitry Andric IRPositions.emplace_back(IRPosition::returned(*Callee)); 12978bcb0991SDimitry Andric IRPositions.emplace_back(IRPosition::function(*Callee)); 12985ffd83dbSDimitry Andric for (const Argument &Arg : Callee->args()) 12995ffd83dbSDimitry Andric if (Arg.hasReturnedAttr()) { 13008bcb0991SDimitry Andric IRPositions.emplace_back( 13015ffd83dbSDimitry Andric IRPosition::callsite_argument(*CB, Arg.getArgNo())); 13025ffd83dbSDimitry Andric IRPositions.emplace_back( 13035ffd83dbSDimitry Andric IRPosition::value(*CB->getArgOperand(Arg.getArgNo()))); 13045ffd83dbSDimitry Andric IRPositions.emplace_back(IRPosition::argument(Arg)); 13055ffd83dbSDimitry Andric } 13065ffd83dbSDimitry Andric } 13075ffd83dbSDimitry Andric } 13085ffd83dbSDimitry Andric IRPositions.emplace_back(IRPosition::callsite_function(*CB)); 13098bcb0991SDimitry Andric return; 13108bcb0991SDimitry Andric case IRPosition::IRP_CALL_SITE_ARGUMENT: { 1311e8d8bef9SDimitry Andric assert(CB && "Expected call site!"); 13128bcb0991SDimitry Andric // TODO: We need to look at the operand bundles similar to the redirection 13138bcb0991SDimitry Andric // in CallBase. 1314e8d8bef9SDimitry Andric if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) { 131506c3fb27SDimitry Andric auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand()); 1316e8d8bef9SDimitry Andric if (Callee) { 1317e8d8bef9SDimitry Andric if (Argument *Arg = IRP.getAssociatedArgument()) 1318e8d8bef9SDimitry Andric IRPositions.emplace_back(IRPosition::argument(*Arg)); 13198bcb0991SDimitry Andric IRPositions.emplace_back(IRPosition::function(*Callee)); 13208bcb0991SDimitry Andric } 1321e8d8bef9SDimitry Andric } 13228bcb0991SDimitry Andric IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue())); 13238bcb0991SDimitry Andric return; 13248bcb0991SDimitry Andric } 13258bcb0991SDimitry Andric } 13260b57cec5SDimitry Andric } 13270b57cec5SDimitry Andric 13288bcb0991SDimitry Andric void IRPosition::verify() { 13295ffd83dbSDimitry Andric #ifdef EXPENSIVE_CHECKS 13305ffd83dbSDimitry Andric switch (getPositionKind()) { 13318bcb0991SDimitry Andric case IRP_INVALID: 1332fe6060f1SDimitry Andric assert((CBContext == nullptr) && 1333fe6060f1SDimitry Andric "Invalid position must not have CallBaseContext!"); 13345ffd83dbSDimitry Andric assert(!Enc.getOpaqueValue() && 13355ffd83dbSDimitry Andric "Expected a nullptr for an invalid position!"); 13365ffd83dbSDimitry Andric return; 13378bcb0991SDimitry Andric case IRP_FLOAT: 13381fd87a68SDimitry Andric assert((!isa<Argument>(&getAssociatedValue())) && 13391fd87a68SDimitry Andric "Expected specialized kind for argument values!"); 13405ffd83dbSDimitry Andric return; 13418bcb0991SDimitry Andric case IRP_RETURNED: 13425ffd83dbSDimitry Andric assert(isa<Function>(getAsValuePtr()) && 13438bcb0991SDimitry Andric "Expected function for a 'returned' position!"); 13445ffd83dbSDimitry Andric assert(getAsValuePtr() == &getAssociatedValue() && 13455ffd83dbSDimitry Andric "Associated value mismatch!"); 13465ffd83dbSDimitry Andric return; 13478bcb0991SDimitry Andric case IRP_CALL_SITE_RETURNED: 1348fe6060f1SDimitry Andric assert((CBContext == nullptr) && 1349fe6060f1SDimitry Andric "'call site returned' position must not have CallBaseContext!"); 13505ffd83dbSDimitry Andric assert((isa<CallBase>(getAsValuePtr())) && 13518bcb0991SDimitry Andric "Expected call base for 'call site returned' position!"); 13525ffd83dbSDimitry Andric assert(getAsValuePtr() == &getAssociatedValue() && 13535ffd83dbSDimitry Andric "Associated value mismatch!"); 13545ffd83dbSDimitry Andric return; 13558bcb0991SDimitry Andric case IRP_CALL_SITE: 1356fe6060f1SDimitry Andric assert((CBContext == nullptr) && 1357fe6060f1SDimitry Andric "'call site function' position must not have CallBaseContext!"); 13585ffd83dbSDimitry Andric assert((isa<CallBase>(getAsValuePtr())) && 13598bcb0991SDimitry Andric "Expected call base for 'call site function' position!"); 13605ffd83dbSDimitry Andric assert(getAsValuePtr() == &getAssociatedValue() && 13615ffd83dbSDimitry Andric "Associated value mismatch!"); 13625ffd83dbSDimitry Andric return; 13638bcb0991SDimitry Andric case IRP_FUNCTION: 13645ffd83dbSDimitry Andric assert(isa<Function>(getAsValuePtr()) && 13658bcb0991SDimitry Andric "Expected function for a 'function' position!"); 13665ffd83dbSDimitry Andric assert(getAsValuePtr() == &getAssociatedValue() && 13675ffd83dbSDimitry Andric "Associated value mismatch!"); 13688bcb0991SDimitry Andric return; 13695ffd83dbSDimitry Andric case IRP_ARGUMENT: 13705ffd83dbSDimitry Andric assert(isa<Argument>(getAsValuePtr()) && 13715ffd83dbSDimitry Andric "Expected argument for a 'argument' position!"); 13725ffd83dbSDimitry Andric assert(getAsValuePtr() == &getAssociatedValue() && 13735ffd83dbSDimitry Andric "Associated value mismatch!"); 13748bcb0991SDimitry Andric return; 13755ffd83dbSDimitry Andric case IRP_CALL_SITE_ARGUMENT: { 1376fe6060f1SDimitry Andric assert((CBContext == nullptr) && 1377fe6060f1SDimitry Andric "'call site argument' position must not have CallBaseContext!"); 13785ffd83dbSDimitry Andric Use *U = getAsUsePtr(); 137904eeddc0SDimitry Andric (void)U; // Silence unused variable warning. 13805ffd83dbSDimitry Andric assert(U && "Expected use for a 'call site argument' position!"); 13815ffd83dbSDimitry Andric assert(isa<CallBase>(U->getUser()) && 13825ffd83dbSDimitry Andric "Expected call base user for a 'call site argument' position!"); 13835ffd83dbSDimitry Andric assert(cast<CallBase>(U->getUser())->isArgOperand(U) && 13845ffd83dbSDimitry Andric "Expected call base argument operand for a 'call site argument' " 13855ffd83dbSDimitry Andric "position"); 13865ffd83dbSDimitry Andric assert(cast<CallBase>(U->getUser())->getArgOperandNo(U) == 1387e8d8bef9SDimitry Andric unsigned(getCallSiteArgNo()) && 13885ffd83dbSDimitry Andric "Argument number mismatch!"); 13895ffd83dbSDimitry Andric assert(U->get() == &getAssociatedValue() && "Associated value mismatch!"); 13900b57cec5SDimitry Andric return; 13910b57cec5SDimitry Andric } 13920b57cec5SDimitry Andric } 13935ffd83dbSDimitry Andric #endif 13940b57cec5SDimitry Andric } 13950b57cec5SDimitry Andric 1396bdd1243dSDimitry Andric std::optional<Constant *> 1397fe6060f1SDimitry Andric Attributor::getAssumedConstant(const IRPosition &IRP, 1398fe6060f1SDimitry Andric const AbstractAttribute &AA, 1399480093f4SDimitry Andric bool &UsedAssumedInformation) { 1400fe6060f1SDimitry Andric // First check all callbacks provided by outside AAs. If any of them returns 1401bdd1243dSDimitry Andric // a non-null value that is different from the associated value, or 1402bdd1243dSDimitry Andric // std::nullopt, we assume it's simplified. 1403fe6060f1SDimitry Andric for (auto &CB : SimplificationCallbacks.lookup(IRP)) { 1404bdd1243dSDimitry Andric std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation); 140581ad6265SDimitry Andric if (!SimplifiedV) 1406bdd1243dSDimitry Andric return std::nullopt; 1407fe6060f1SDimitry Andric if (isa_and_nonnull<Constant>(*SimplifiedV)) 1408fe6060f1SDimitry Andric return cast<Constant>(*SimplifiedV); 1409fe6060f1SDimitry Andric return nullptr; 1410fe6060f1SDimitry Andric } 141181ad6265SDimitry Andric if (auto *C = dyn_cast<Constant>(&IRP.getAssociatedValue())) 141281ad6265SDimitry Andric return C; 1413fcaf7f86SDimitry Andric SmallVector<AA::ValueAndContext> Values; 1414fcaf7f86SDimitry Andric if (getAssumedSimplifiedValues(IRP, &AA, Values, 1415fcaf7f86SDimitry Andric AA::ValueScope::Interprocedural, 1416fcaf7f86SDimitry Andric UsedAssumedInformation)) { 1417fcaf7f86SDimitry Andric if (Values.empty()) 1418bdd1243dSDimitry Andric return std::nullopt; 1419fcaf7f86SDimitry Andric if (auto *C = dyn_cast_or_null<Constant>( 1420fcaf7f86SDimitry Andric AAPotentialValues::getSingleValue(*this, AA, IRP, Values))) 1421fcaf7f86SDimitry Andric return C; 14225ffd83dbSDimitry Andric } 1423fcaf7f86SDimitry Andric return nullptr; 1424480093f4SDimitry Andric } 1425480093f4SDimitry Andric 1426bdd1243dSDimitry Andric std::optional<Value *> Attributor::getAssumedSimplified( 1427bdd1243dSDimitry Andric const IRPosition &IRP, const AbstractAttribute *AA, 1428bdd1243dSDimitry Andric bool &UsedAssumedInformation, AA::ValueScope S) { 1429fe6060f1SDimitry Andric // First check all callbacks provided by outside AAs. If any of them returns 1430bdd1243dSDimitry Andric // a non-null value that is different from the associated value, or 1431bdd1243dSDimitry Andric // std::nullopt, we assume it's simplified. 1432fe6060f1SDimitry Andric for (auto &CB : SimplificationCallbacks.lookup(IRP)) 1433fe6060f1SDimitry Andric return CB(IRP, AA, UsedAssumedInformation); 1434fe6060f1SDimitry Andric 1435fcaf7f86SDimitry Andric SmallVector<AA::ValueAndContext> Values; 1436fcaf7f86SDimitry Andric if (!getAssumedSimplifiedValues(IRP, AA, Values, S, UsedAssumedInformation)) 1437fcaf7f86SDimitry Andric return &IRP.getAssociatedValue(); 1438fcaf7f86SDimitry Andric if (Values.empty()) 1439bdd1243dSDimitry Andric return std::nullopt; 1440fe6060f1SDimitry Andric if (AA) 1441fcaf7f86SDimitry Andric if (Value *V = AAPotentialValues::getSingleValue(*this, *AA, IRP, Values)) 1442fcaf7f86SDimitry Andric return V; 1443fcaf7f86SDimitry Andric if (IRP.getPositionKind() == IRPosition::IRP_RETURNED || 1444fcaf7f86SDimitry Andric IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) 1445fcaf7f86SDimitry Andric return nullptr; 1446fcaf7f86SDimitry Andric return &IRP.getAssociatedValue(); 1447fe6060f1SDimitry Andric } 1448fcaf7f86SDimitry Andric 1449fcaf7f86SDimitry Andric bool Attributor::getAssumedSimplifiedValues( 145006c3fb27SDimitry Andric const IRPosition &InitialIRP, const AbstractAttribute *AA, 1451fcaf7f86SDimitry Andric SmallVectorImpl<AA::ValueAndContext> &Values, AA::ValueScope S, 145206c3fb27SDimitry Andric bool &UsedAssumedInformation, bool RecurseForSelectAndPHI) { 145306c3fb27SDimitry Andric SmallPtrSet<Value *, 8> Seen; 145406c3fb27SDimitry Andric SmallVector<IRPosition, 8> Worklist; 145506c3fb27SDimitry Andric Worklist.push_back(InitialIRP); 145606c3fb27SDimitry Andric while (!Worklist.empty()) { 145706c3fb27SDimitry Andric const IRPosition &IRP = Worklist.pop_back_val(); 145806c3fb27SDimitry Andric 1459fcaf7f86SDimitry Andric // First check all callbacks provided by outside AAs. If any of them returns 1460bdd1243dSDimitry Andric // a non-null value that is different from the associated value, or 1461bdd1243dSDimitry Andric // std::nullopt, we assume it's simplified. 146206c3fb27SDimitry Andric int NV = Values.size(); 1463fcaf7f86SDimitry Andric const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP); 1464bdd1243dSDimitry Andric for (const auto &CB : SimplificationCBs) { 1465bdd1243dSDimitry Andric std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation); 1466fcaf7f86SDimitry Andric if (!CBResult.has_value()) 1467fcaf7f86SDimitry Andric continue; 1468bdd1243dSDimitry Andric Value *V = *CBResult; 1469fcaf7f86SDimitry Andric if (!V) 1470fcaf7f86SDimitry Andric return false; 1471fcaf7f86SDimitry Andric if ((S & AA::ValueScope::Interprocedural) || 1472fcaf7f86SDimitry Andric AA::isValidInScope(*V, IRP.getAnchorScope())) 1473fcaf7f86SDimitry Andric Values.push_back(AA::ValueAndContext{*V, nullptr}); 1474fcaf7f86SDimitry Andric else 1475fcaf7f86SDimitry Andric return false; 1476fcaf7f86SDimitry Andric } 147706c3fb27SDimitry Andric if (SimplificationCBs.empty()) { 147806c3fb27SDimitry Andric // If no high-level/outside simplification occurred, use 147906c3fb27SDimitry Andric // AAPotentialValues. 148006c3fb27SDimitry Andric const auto *PotentialValuesAA = 1481fcaf7f86SDimitry Andric getOrCreateAAFor<AAPotentialValues>(IRP, AA, DepClassTy::OPTIONAL); 148206c3fb27SDimitry Andric if (PotentialValuesAA && PotentialValuesAA->getAssumedSimplifiedValues(*this, Values, S)) { 148306c3fb27SDimitry Andric UsedAssumedInformation |= !PotentialValuesAA->isAtFixpoint(); 148406c3fb27SDimitry Andric } else if (IRP.getPositionKind() != IRPosition::IRP_RETURNED) { 148506c3fb27SDimitry Andric Values.push_back({IRP.getAssociatedValue(), IRP.getCtxI()}); 148606c3fb27SDimitry Andric } else { 148706c3fb27SDimitry Andric // TODO: We could visit all returns and add the operands. 1488fcaf7f86SDimitry Andric return false; 148906c3fb27SDimitry Andric } 149006c3fb27SDimitry Andric } 149106c3fb27SDimitry Andric 149206c3fb27SDimitry Andric if (!RecurseForSelectAndPHI) 149306c3fb27SDimitry Andric break; 149406c3fb27SDimitry Andric 149506c3fb27SDimitry Andric for (int I = NV, E = Values.size(); I < E; ++I) { 149606c3fb27SDimitry Andric Value *V = Values[I].getValue(); 149706c3fb27SDimitry Andric if (!isa<PHINode>(V) && !isa<SelectInst>(V)) 149806c3fb27SDimitry Andric continue; 149906c3fb27SDimitry Andric if (!Seen.insert(V).second) 150006c3fb27SDimitry Andric continue; 150106c3fb27SDimitry Andric // Move the last element to this slot. 150206c3fb27SDimitry Andric Values[I] = Values[E - 1]; 150306c3fb27SDimitry Andric // Eliminate the last slot, adjust the indices. 150406c3fb27SDimitry Andric Values.pop_back(); 150506c3fb27SDimitry Andric --E; 150606c3fb27SDimitry Andric --I; 150706c3fb27SDimitry Andric // Add a new value (select or phi) to the worklist. 150806c3fb27SDimitry Andric Worklist.push_back(IRPosition::value(*V)); 150906c3fb27SDimitry Andric } 151006c3fb27SDimitry Andric } 1511fcaf7f86SDimitry Andric return true; 1512fe6060f1SDimitry Andric } 1513fe6060f1SDimitry Andric 1514bdd1243dSDimitry Andric std::optional<Value *> Attributor::translateArgumentToCallSiteContent( 1515bdd1243dSDimitry Andric std::optional<Value *> V, CallBase &CB, const AbstractAttribute &AA, 1516fe6060f1SDimitry Andric bool &UsedAssumedInformation) { 151781ad6265SDimitry Andric if (!V) 1518fe6060f1SDimitry Andric return V; 1519fe6060f1SDimitry Andric if (*V == nullptr || isa<Constant>(*V)) 1520fe6060f1SDimitry Andric return V; 1521fe6060f1SDimitry Andric if (auto *Arg = dyn_cast<Argument>(*V)) 152206c3fb27SDimitry Andric if (CB.getCalledOperand() == Arg->getParent() && 152306c3fb27SDimitry Andric CB.arg_size() > Arg->getArgNo()) 1524fe6060f1SDimitry Andric if (!Arg->hasPointeeInMemoryValueAttr()) 1525fe6060f1SDimitry Andric return getAssumedSimplified( 1526fe6060f1SDimitry Andric IRPosition::callsite_argument(CB, Arg->getArgNo()), AA, 1527fcaf7f86SDimitry Andric UsedAssumedInformation, AA::Intraprocedural); 1528fe6060f1SDimitry Andric return nullptr; 1529fe6060f1SDimitry Andric } 1530fe6060f1SDimitry Andric 15315ffd83dbSDimitry Andric Attributor::~Attributor() { 15325ffd83dbSDimitry Andric // The abstract attributes are allocated via the BumpPtrAllocator Allocator, 15335ffd83dbSDimitry Andric // thus we cannot delete them. We can, and want to, destruct them though. 1534bdd1243dSDimitry Andric for (auto &It : AAMap) { 1535bdd1243dSDimitry Andric AbstractAttribute *AA = It.getSecond(); 15365ffd83dbSDimitry Andric AA->~AbstractAttribute(); 1537480093f4SDimitry Andric } 1538e8d8bef9SDimitry Andric } 1539480093f4SDimitry Andric 15408bcb0991SDimitry Andric bool Attributor::isAssumedDead(const AbstractAttribute &AA, 15415ffd83dbSDimitry Andric const AAIsDead *FnLivenessAA, 1542fe6060f1SDimitry Andric bool &UsedAssumedInformation, 15435ffd83dbSDimitry Andric bool CheckBBLivenessOnly, DepClassTy DepClass) { 154406c3fb27SDimitry Andric if (!Configuration.UseLiveness) 154506c3fb27SDimitry Andric return false; 15465ffd83dbSDimitry Andric const IRPosition &IRP = AA.getIRPosition(); 15475ffd83dbSDimitry Andric if (!Functions.count(IRP.getAnchorScope())) 15488bcb0991SDimitry Andric return false; 1549fe6060f1SDimitry Andric return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation, 1550fe6060f1SDimitry Andric CheckBBLivenessOnly, DepClass); 15515ffd83dbSDimitry Andric } 15528bcb0991SDimitry Andric 15535ffd83dbSDimitry Andric bool Attributor::isAssumedDead(const Use &U, 15545ffd83dbSDimitry Andric const AbstractAttribute *QueryingAA, 15555ffd83dbSDimitry Andric const AAIsDead *FnLivenessAA, 1556fe6060f1SDimitry Andric bool &UsedAssumedInformation, 15575ffd83dbSDimitry Andric bool CheckBBLivenessOnly, DepClassTy DepClass) { 155806c3fb27SDimitry Andric if (!Configuration.UseLiveness) 155906c3fb27SDimitry Andric return false; 15605ffd83dbSDimitry Andric Instruction *UserI = dyn_cast<Instruction>(U.getUser()); 15615ffd83dbSDimitry Andric if (!UserI) 15625ffd83dbSDimitry Andric return isAssumedDead(IRPosition::value(*U.get()), QueryingAA, FnLivenessAA, 1563fe6060f1SDimitry Andric UsedAssumedInformation, CheckBBLivenessOnly, DepClass); 15645ffd83dbSDimitry Andric 15655ffd83dbSDimitry Andric if (auto *CB = dyn_cast<CallBase>(UserI)) { 15665ffd83dbSDimitry Andric // For call site argument uses we can check if the argument is 15675ffd83dbSDimitry Andric // unused/dead. 15685ffd83dbSDimitry Andric if (CB->isArgOperand(&U)) { 15695ffd83dbSDimitry Andric const IRPosition &CSArgPos = 15705ffd83dbSDimitry Andric IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U)); 15715ffd83dbSDimitry Andric return isAssumedDead(CSArgPos, QueryingAA, FnLivenessAA, 1572fe6060f1SDimitry Andric UsedAssumedInformation, CheckBBLivenessOnly, 1573fe6060f1SDimitry Andric DepClass); 15745ffd83dbSDimitry Andric } 15755ffd83dbSDimitry Andric } else if (ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) { 15765ffd83dbSDimitry Andric const IRPosition &RetPos = IRPosition::returned(*RI->getFunction()); 1577fe6060f1SDimitry Andric return isAssumedDead(RetPos, QueryingAA, FnLivenessAA, 1578fe6060f1SDimitry Andric UsedAssumedInformation, CheckBBLivenessOnly, DepClass); 15795ffd83dbSDimitry Andric } else if (PHINode *PHI = dyn_cast<PHINode>(UserI)) { 15805ffd83dbSDimitry Andric BasicBlock *IncomingBB = PHI->getIncomingBlock(U); 15815ffd83dbSDimitry Andric return isAssumedDead(*IncomingBB->getTerminator(), QueryingAA, FnLivenessAA, 1582fe6060f1SDimitry Andric UsedAssumedInformation, CheckBBLivenessOnly, DepClass); 158381ad6265SDimitry Andric } else if (StoreInst *SI = dyn_cast<StoreInst>(UserI)) { 158481ad6265SDimitry Andric if (!CheckBBLivenessOnly && SI->getPointerOperand() != U.get()) { 158581ad6265SDimitry Andric const IRPosition IRP = IRPosition::inst(*SI); 158606c3fb27SDimitry Andric const AAIsDead *IsDeadAA = 158781ad6265SDimitry Andric getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE); 158806c3fb27SDimitry Andric if (IsDeadAA && IsDeadAA->isRemovableStore()) { 158981ad6265SDimitry Andric if (QueryingAA) 159006c3fb27SDimitry Andric recordDependence(*IsDeadAA, *QueryingAA, DepClass); 159106c3fb27SDimitry Andric if (!IsDeadAA->isKnown(AAIsDead::IS_REMOVABLE)) 159281ad6265SDimitry Andric UsedAssumedInformation = true; 159381ad6265SDimitry Andric return true; 159481ad6265SDimitry Andric } 159581ad6265SDimitry Andric } 15965ffd83dbSDimitry Andric } 15975ffd83dbSDimitry Andric 15981fd87a68SDimitry Andric return isAssumedDead(IRPosition::inst(*UserI), QueryingAA, FnLivenessAA, 1599fe6060f1SDimitry Andric UsedAssumedInformation, CheckBBLivenessOnly, DepClass); 16005ffd83dbSDimitry Andric } 16015ffd83dbSDimitry Andric 16025ffd83dbSDimitry Andric bool Attributor::isAssumedDead(const Instruction &I, 16035ffd83dbSDimitry Andric const AbstractAttribute *QueryingAA, 16045ffd83dbSDimitry Andric const AAIsDead *FnLivenessAA, 1605fe6060f1SDimitry Andric bool &UsedAssumedInformation, 1606bdd1243dSDimitry Andric bool CheckBBLivenessOnly, DepClassTy DepClass, 1607bdd1243dSDimitry Andric bool CheckForDeadStore) { 160806c3fb27SDimitry Andric if (!Configuration.UseLiveness) 160906c3fb27SDimitry Andric return false; 1610fe6060f1SDimitry Andric const IRPosition::CallBaseContext *CBCtx = 1611fe6060f1SDimitry Andric QueryingAA ? QueryingAA->getCallBaseContext() : nullptr; 1612fe6060f1SDimitry Andric 1613fe6060f1SDimitry Andric if (ManifestAddedBlocks.contains(I.getParent())) 1614fe6060f1SDimitry Andric return false; 1615fe6060f1SDimitry Andric 1616bdd1243dSDimitry Andric const Function &F = *I.getFunction(); 1617bdd1243dSDimitry Andric if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F) 161806c3fb27SDimitry Andric FnLivenessAA = getOrCreateAAFor<AAIsDead>(IRPosition::function(F, CBCtx), 1619fe6060f1SDimitry Andric QueryingAA, DepClassTy::NONE); 16208bcb0991SDimitry Andric 1621bdd1243dSDimitry Andric // Don't use recursive reasoning. 162206c3fb27SDimitry Andric if (!FnLivenessAA || QueryingAA == FnLivenessAA) 1623bdd1243dSDimitry Andric return false; 1624bdd1243dSDimitry Andric 16255ffd83dbSDimitry Andric // If we have a context instruction and a liveness AA we use it. 1626bdd1243dSDimitry Andric if (CheckBBLivenessOnly ? FnLivenessAA->isAssumedDead(I.getParent()) 1627bdd1243dSDimitry Andric : FnLivenessAA->isAssumedDead(&I)) { 16285ffd83dbSDimitry Andric if (QueryingAA) 16295ffd83dbSDimitry Andric recordDependence(*FnLivenessAA, *QueryingAA, DepClass); 1630fe6060f1SDimitry Andric if (!FnLivenessAA->isKnownDead(&I)) 1631fe6060f1SDimitry Andric UsedAssumedInformation = true; 1632480093f4SDimitry Andric return true; 1633480093f4SDimitry Andric } 1634480093f4SDimitry Andric 16355ffd83dbSDimitry Andric if (CheckBBLivenessOnly) 16365ffd83dbSDimitry Andric return false; 16375ffd83dbSDimitry Andric 16381fd87a68SDimitry Andric const IRPosition IRP = IRPosition::inst(I, CBCtx); 163906c3fb27SDimitry Andric const AAIsDead *IsDeadAA = 16401fd87a68SDimitry Andric getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE); 1641bdd1243dSDimitry Andric 1642bdd1243dSDimitry Andric // Don't use recursive reasoning. 164306c3fb27SDimitry Andric if (!IsDeadAA || QueryingAA == IsDeadAA) 16445ffd83dbSDimitry Andric return false; 16455ffd83dbSDimitry Andric 164606c3fb27SDimitry Andric if (IsDeadAA->isAssumedDead()) { 16475ffd83dbSDimitry Andric if (QueryingAA) 164806c3fb27SDimitry Andric recordDependence(*IsDeadAA, *QueryingAA, DepClass); 164906c3fb27SDimitry Andric if (!IsDeadAA->isKnownDead()) 1650fe6060f1SDimitry Andric UsedAssumedInformation = true; 16515ffd83dbSDimitry Andric return true; 16525ffd83dbSDimitry Andric } 16535ffd83dbSDimitry Andric 165406c3fb27SDimitry Andric if (CheckForDeadStore && isa<StoreInst>(I) && IsDeadAA->isRemovableStore()) { 1655bdd1243dSDimitry Andric if (QueryingAA) 165606c3fb27SDimitry Andric recordDependence(*IsDeadAA, *QueryingAA, DepClass); 165706c3fb27SDimitry Andric if (!IsDeadAA->isKnownDead()) 1658bdd1243dSDimitry Andric UsedAssumedInformation = true; 1659bdd1243dSDimitry Andric return true; 1660bdd1243dSDimitry Andric } 1661bdd1243dSDimitry Andric 16625ffd83dbSDimitry Andric return false; 16635ffd83dbSDimitry Andric } 16645ffd83dbSDimitry Andric 16655ffd83dbSDimitry Andric bool Attributor::isAssumedDead(const IRPosition &IRP, 16665ffd83dbSDimitry Andric const AbstractAttribute *QueryingAA, 16675ffd83dbSDimitry Andric const AAIsDead *FnLivenessAA, 1668fe6060f1SDimitry Andric bool &UsedAssumedInformation, 16695ffd83dbSDimitry Andric bool CheckBBLivenessOnly, DepClassTy DepClass) { 167006c3fb27SDimitry Andric if (!Configuration.UseLiveness) 167106c3fb27SDimitry Andric return false; 1672bdd1243dSDimitry Andric // Don't check liveness for constants, e.g. functions, used as (floating) 1673bdd1243dSDimitry Andric // values since the context instruction and such is here meaningless. 1674bdd1243dSDimitry Andric if (IRP.getPositionKind() == IRPosition::IRP_FLOAT && 1675bdd1243dSDimitry Andric isa<Constant>(IRP.getAssociatedValue())) { 1676bdd1243dSDimitry Andric return false; 1677bdd1243dSDimitry Andric } 1678bdd1243dSDimitry Andric 16795ffd83dbSDimitry Andric Instruction *CtxI = IRP.getCtxI(); 16805ffd83dbSDimitry Andric if (CtxI && 1681fe6060f1SDimitry Andric isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation, 16825ffd83dbSDimitry Andric /* CheckBBLivenessOnly */ true, 16835ffd83dbSDimitry Andric CheckBBLivenessOnly ? DepClass : DepClassTy::OPTIONAL)) 16845ffd83dbSDimitry Andric return true; 16855ffd83dbSDimitry Andric 16865ffd83dbSDimitry Andric if (CheckBBLivenessOnly) 16875ffd83dbSDimitry Andric return false; 16885ffd83dbSDimitry Andric 16895ffd83dbSDimitry Andric // If we haven't succeeded we query the specific liveness info for the IRP. 16905ffd83dbSDimitry Andric const AAIsDead *IsDeadAA; 16915ffd83dbSDimitry Andric if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE) 169206c3fb27SDimitry Andric IsDeadAA = getOrCreateAAFor<AAIsDead>( 16935ffd83dbSDimitry Andric IRPosition::callsite_returned(cast<CallBase>(IRP.getAssociatedValue())), 1694fe6060f1SDimitry Andric QueryingAA, DepClassTy::NONE); 16955ffd83dbSDimitry Andric else 169606c3fb27SDimitry Andric IsDeadAA = getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE); 1697bdd1243dSDimitry Andric 1698bdd1243dSDimitry Andric // Don't use recursive reasoning. 169906c3fb27SDimitry Andric if (!IsDeadAA || QueryingAA == IsDeadAA) 17005ffd83dbSDimitry Andric return false; 17015ffd83dbSDimitry Andric 17025ffd83dbSDimitry Andric if (IsDeadAA->isAssumedDead()) { 17035ffd83dbSDimitry Andric if (QueryingAA) 17045ffd83dbSDimitry Andric recordDependence(*IsDeadAA, *QueryingAA, DepClass); 1705fe6060f1SDimitry Andric if (!IsDeadAA->isKnownDead()) 1706fe6060f1SDimitry Andric UsedAssumedInformation = true; 1707fe6060f1SDimitry Andric return true; 1708fe6060f1SDimitry Andric } 1709fe6060f1SDimitry Andric 1710fe6060f1SDimitry Andric return false; 1711fe6060f1SDimitry Andric } 1712fe6060f1SDimitry Andric 1713fe6060f1SDimitry Andric bool Attributor::isAssumedDead(const BasicBlock &BB, 1714fe6060f1SDimitry Andric const AbstractAttribute *QueryingAA, 1715fe6060f1SDimitry Andric const AAIsDead *FnLivenessAA, 1716fe6060f1SDimitry Andric DepClassTy DepClass) { 171706c3fb27SDimitry Andric if (!Configuration.UseLiveness) 171806c3fb27SDimitry Andric return false; 1719bdd1243dSDimitry Andric const Function &F = *BB.getParent(); 1720bdd1243dSDimitry Andric if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F) 172106c3fb27SDimitry Andric FnLivenessAA = getOrCreateAAFor<AAIsDead>(IRPosition::function(F), 1722fe6060f1SDimitry Andric QueryingAA, DepClassTy::NONE); 1723bdd1243dSDimitry Andric 1724bdd1243dSDimitry Andric // Don't use recursive reasoning. 172506c3fb27SDimitry Andric if (!FnLivenessAA || QueryingAA == FnLivenessAA) 1726bdd1243dSDimitry Andric return false; 1727bdd1243dSDimitry Andric 1728fe6060f1SDimitry Andric if (FnLivenessAA->isAssumedDead(&BB)) { 1729fe6060f1SDimitry Andric if (QueryingAA) 1730fe6060f1SDimitry Andric recordDependence(*FnLivenessAA, *QueryingAA, DepClass); 17315ffd83dbSDimitry Andric return true; 17325ffd83dbSDimitry Andric } 17335ffd83dbSDimitry Andric 17345ffd83dbSDimitry Andric return false; 17355ffd83dbSDimitry Andric } 17365ffd83dbSDimitry Andric 17375f757f3fSDimitry Andric bool Attributor::checkForAllCallees( 17385f757f3fSDimitry Andric function_ref<bool(ArrayRef<const Function *>)> Pred, 17395f757f3fSDimitry Andric const AbstractAttribute &QueryingAA, const CallBase &CB) { 17405f757f3fSDimitry Andric if (const Function *Callee = dyn_cast<Function>(CB.getCalledOperand())) 17415f757f3fSDimitry Andric return Pred(Callee); 17425f757f3fSDimitry Andric 17435f757f3fSDimitry Andric const auto *CallEdgesAA = getAAFor<AACallEdges>( 17445f757f3fSDimitry Andric QueryingAA, IRPosition::callsite_function(CB), DepClassTy::OPTIONAL); 17455f757f3fSDimitry Andric if (!CallEdgesAA || CallEdgesAA->hasUnknownCallee()) 17465f757f3fSDimitry Andric return false; 17475f757f3fSDimitry Andric 17485f757f3fSDimitry Andric const auto &Callees = CallEdgesAA->getOptimisticEdges(); 17495f757f3fSDimitry Andric return Pred(Callees.getArrayRef()); 17505f757f3fSDimitry Andric } 17515f757f3fSDimitry Andric 1752*0fca6ea1SDimitry Andric bool canMarkAsVisited(const User *Usr) { 1753*0fca6ea1SDimitry Andric return isa<PHINode>(Usr) || !isa<Instruction>(Usr); 1754*0fca6ea1SDimitry Andric } 1755*0fca6ea1SDimitry Andric 175604eeddc0SDimitry Andric bool Attributor::checkForAllUses( 175704eeddc0SDimitry Andric function_ref<bool(const Use &, bool &)> Pred, 175804eeddc0SDimitry Andric const AbstractAttribute &QueryingAA, const Value &V, 175904eeddc0SDimitry Andric bool CheckBBLivenessOnly, DepClassTy LivenessDepClass, 176081ad6265SDimitry Andric bool IgnoreDroppableUses, 176104eeddc0SDimitry Andric function_ref<bool(const Use &OldU, const Use &NewU)> EquivalentUseCB) { 17625ffd83dbSDimitry Andric 1763bdd1243dSDimitry Andric // Check virtual uses first. 1764bdd1243dSDimitry Andric for (VirtualUseCallbackTy &CB : VirtualUseCallbacks.lookup(&V)) 1765bdd1243dSDimitry Andric if (!CB(*this, &QueryingAA)) 1766bdd1243dSDimitry Andric return false; 1767bdd1243dSDimitry Andric 17685ffd83dbSDimitry Andric // Check the trivial case first as it catches void values. 17695ffd83dbSDimitry Andric if (V.use_empty()) 17705ffd83dbSDimitry Andric return true; 17715ffd83dbSDimitry Andric 1772480093f4SDimitry Andric const IRPosition &IRP = QueryingAA.getIRPosition(); 1773480093f4SDimitry Andric SmallVector<const Use *, 16> Worklist; 1774480093f4SDimitry Andric SmallPtrSet<const Use *, 16> Visited; 1775480093f4SDimitry Andric 1776fcaf7f86SDimitry Andric auto AddUsers = [&](const Value &V, const Use *OldUse) { 1777fcaf7f86SDimitry Andric for (const Use &UU : V.uses()) { 1778fcaf7f86SDimitry Andric if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) { 1779fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Potential copy was " 1780fcaf7f86SDimitry Andric "rejected by the equivalence call back: " 1781fcaf7f86SDimitry Andric << *UU << "!\n"); 1782fcaf7f86SDimitry Andric return false; 1783fcaf7f86SDimitry Andric } 1784fcaf7f86SDimitry Andric 1785fcaf7f86SDimitry Andric Worklist.push_back(&UU); 1786fcaf7f86SDimitry Andric } 1787fcaf7f86SDimitry Andric return true; 1788fcaf7f86SDimitry Andric }; 1789fcaf7f86SDimitry Andric 1790fcaf7f86SDimitry Andric AddUsers(V, /* OldUse */ nullptr); 1791480093f4SDimitry Andric 1792480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Got " << Worklist.size() 1793480093f4SDimitry Andric << " initial uses to check\n"); 1794480093f4SDimitry Andric 1795480093f4SDimitry Andric const Function *ScopeFn = IRP.getAnchorScope(); 1796480093f4SDimitry Andric const auto *LivenessAA = 179706c3fb27SDimitry Andric ScopeFn ? getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*ScopeFn), 1798fe6060f1SDimitry Andric DepClassTy::NONE) 1799480093f4SDimitry Andric : nullptr; 1800480093f4SDimitry Andric 1801480093f4SDimitry Andric while (!Worklist.empty()) { 1802480093f4SDimitry Andric const Use *U = Worklist.pop_back_val(); 1803*0fca6ea1SDimitry Andric if (canMarkAsVisited(U->getUser()) && !Visited.insert(U).second) 1804480093f4SDimitry Andric continue; 1805bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, { 18061fd87a68SDimitry Andric if (auto *Fn = dyn_cast<Function>(U->getUser())) 18071fd87a68SDimitry Andric dbgs() << "[Attributor] Check use: " << **U << " in " << Fn->getName() 18081fd87a68SDimitry Andric << "\n"; 18091fd87a68SDimitry Andric else 18101fd87a68SDimitry Andric dbgs() << "[Attributor] Check use: " << **U << " in " << *U->getUser() 18111fd87a68SDimitry Andric << "\n"; 18121fd87a68SDimitry Andric }); 1813fe6060f1SDimitry Andric bool UsedAssumedInformation = false; 1814fe6060f1SDimitry Andric if (isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation, 1815fe6060f1SDimitry Andric CheckBBLivenessOnly, LivenessDepClass)) { 1816bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, 1817bdd1243dSDimitry Andric dbgs() << "[Attributor] Dead use, skip!\n"); 18185ffd83dbSDimitry Andric continue; 18195ffd83dbSDimitry Andric } 182081ad6265SDimitry Andric if (IgnoreDroppableUses && U->getUser()->isDroppable()) { 1821bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, 1822bdd1243dSDimitry Andric dbgs() << "[Attributor] Droppable user, skip!\n"); 1823480093f4SDimitry Andric continue; 1824480093f4SDimitry Andric } 1825480093f4SDimitry Andric 1826fe6060f1SDimitry Andric if (auto *SI = dyn_cast<StoreInst>(U->getUser())) { 1827fe6060f1SDimitry Andric if (&SI->getOperandUse(0) == U) { 1828349cc55cSDimitry Andric if (!Visited.insert(U).second) 1829349cc55cSDimitry Andric continue; 1830fe6060f1SDimitry Andric SmallSetVector<Value *, 4> PotentialCopies; 183181ad6265SDimitry Andric if (AA::getPotentialCopiesOfStoredValue( 183281ad6265SDimitry Andric *this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation, 183381ad6265SDimitry Andric /* OnlyExact */ true)) { 1834bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, 1835bdd1243dSDimitry Andric dbgs() 1836bdd1243dSDimitry Andric << "[Attributor] Value is stored, continue with " 1837fe6060f1SDimitry Andric << PotentialCopies.size() 1838fe6060f1SDimitry Andric << " potential copies instead!\n"); 1839fe6060f1SDimitry Andric for (Value *PotentialCopy : PotentialCopies) 1840fcaf7f86SDimitry Andric if (!AddUsers(*PotentialCopy, U)) 184104eeddc0SDimitry Andric return false; 1842fe6060f1SDimitry Andric continue; 1843fe6060f1SDimitry Andric } 1844fe6060f1SDimitry Andric } 1845fe6060f1SDimitry Andric } 1846fe6060f1SDimitry Andric 1847480093f4SDimitry Andric bool Follow = false; 1848480093f4SDimitry Andric if (!Pred(*U, Follow)) 1849480093f4SDimitry Andric return false; 1850480093f4SDimitry Andric if (!Follow) 1851480093f4SDimitry Andric continue; 1852fcaf7f86SDimitry Andric 1853fcaf7f86SDimitry Andric User &Usr = *U->getUser(); 1854fcaf7f86SDimitry Andric AddUsers(Usr, /* OldUse */ nullptr); 1855fcaf7f86SDimitry Andric 1856fcaf7f86SDimitry Andric auto *RI = dyn_cast<ReturnInst>(&Usr); 1857fcaf7f86SDimitry Andric if (!RI) 1858fcaf7f86SDimitry Andric continue; 1859fcaf7f86SDimitry Andric 1860fcaf7f86SDimitry Andric Function &F = *RI->getFunction(); 1861fcaf7f86SDimitry Andric auto CallSitePred = [&](AbstractCallSite ACS) { 1862fcaf7f86SDimitry Andric return AddUsers(*ACS.getInstruction(), U); 1863fcaf7f86SDimitry Andric }; 1864fcaf7f86SDimitry Andric if (!checkForAllCallSites(CallSitePred, F, /* RequireAllCallSites */ true, 1865fcaf7f86SDimitry Andric &QueryingAA, UsedAssumedInformation)) { 1866fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Could not follow return instruction " 1867fcaf7f86SDimitry Andric "to all call sites: " 1868fcaf7f86SDimitry Andric << *RI << "\n"); 1869fcaf7f86SDimitry Andric return false; 1870fcaf7f86SDimitry Andric } 1871480093f4SDimitry Andric } 1872480093f4SDimitry Andric 18738bcb0991SDimitry Andric return true; 18748bcb0991SDimitry Andric } 18758bcb0991SDimitry Andric 18765ffd83dbSDimitry Andric bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, 18775ffd83dbSDimitry Andric const AbstractAttribute &QueryingAA, 18785ffd83dbSDimitry Andric bool RequireAllCallSites, 1879d781ede6SDimitry Andric bool &UsedAssumedInformation) { 18800b57cec5SDimitry Andric // We can try to determine information from 18810b57cec5SDimitry Andric // the call sites. However, this is only possible all call sites are known, 18820b57cec5SDimitry Andric // hence the function has internal linkage. 18838bcb0991SDimitry Andric const IRPosition &IRP = QueryingAA.getIRPosition(); 18848bcb0991SDimitry Andric const Function *AssociatedFunction = IRP.getAssociatedFunction(); 18858bcb0991SDimitry Andric if (!AssociatedFunction) { 18868bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRP 18878bcb0991SDimitry Andric << "\n"); 18888bcb0991SDimitry Andric return false; 18898bcb0991SDimitry Andric } 18908bcb0991SDimitry Andric 18918bcb0991SDimitry Andric return checkForAllCallSites(Pred, *AssociatedFunction, RequireAllCallSites, 1892d781ede6SDimitry Andric &QueryingAA, UsedAssumedInformation); 18938bcb0991SDimitry Andric } 18948bcb0991SDimitry Andric 18955ffd83dbSDimitry Andric bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, 18965ffd83dbSDimitry Andric const Function &Fn, 18975ffd83dbSDimitry Andric bool RequireAllCallSites, 18985ffd83dbSDimitry Andric const AbstractAttribute *QueryingAA, 1899bdd1243dSDimitry Andric bool &UsedAssumedInformation, 1900bdd1243dSDimitry Andric bool CheckPotentiallyDead) { 19018bcb0991SDimitry Andric if (RequireAllCallSites && !Fn.hasLocalLinkage()) { 19020b57cec5SDimitry Andric LLVM_DEBUG( 19030b57cec5SDimitry Andric dbgs() 19048bcb0991SDimitry Andric << "[Attributor] Function " << Fn.getName() 19050b57cec5SDimitry Andric << " has no internal linkage, hence not all call sites are known\n"); 19060b57cec5SDimitry Andric return false; 19070b57cec5SDimitry Andric } 1908bdd1243dSDimitry Andric // Check virtual uses first. 1909bdd1243dSDimitry Andric for (VirtualUseCallbackTy &CB : VirtualUseCallbacks.lookup(&Fn)) 1910bdd1243dSDimitry Andric if (!CB(*this, QueryingAA)) 1911bdd1243dSDimitry Andric return false; 19120b57cec5SDimitry Andric 19135ffd83dbSDimitry Andric SmallVector<const Use *, 8> Uses(make_pointer_range(Fn.uses())); 19145ffd83dbSDimitry Andric for (unsigned u = 0; u < Uses.size(); ++u) { 19155ffd83dbSDimitry Andric const Use &U = *Uses[u]; 1916bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, { 19171fd87a68SDimitry Andric if (auto *Fn = dyn_cast<Function>(U)) 19181fd87a68SDimitry Andric dbgs() << "[Attributor] Check use: " << Fn->getName() << " in " 19191fd87a68SDimitry Andric << *U.getUser() << "\n"; 19201fd87a68SDimitry Andric else 19211fd87a68SDimitry Andric dbgs() << "[Attributor] Check use: " << *U << " in " << *U.getUser() 19221fd87a68SDimitry Andric << "\n"; 19231fd87a68SDimitry Andric }); 1924bdd1243dSDimitry Andric if (!CheckPotentiallyDead && 1925bdd1243dSDimitry Andric isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation, 1926fe6060f1SDimitry Andric /* CheckBBLivenessOnly */ true)) { 1927bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, 1928bdd1243dSDimitry Andric dbgs() << "[Attributor] Dead use, skip!\n"); 19295ffd83dbSDimitry Andric continue; 19305ffd83dbSDimitry Andric } 19315ffd83dbSDimitry Andric if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) { 193281ad6265SDimitry Andric if (CE->isCast() && CE->getType()->isPointerTy()) { 1933bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, { 1934349cc55cSDimitry Andric dbgs() << "[Attributor] Use, is constant cast expression, add " 1935bdd1243dSDimitry Andric << CE->getNumUses() << " uses of that expression instead!\n"; 1936bdd1243dSDimitry Andric }); 19375ffd83dbSDimitry Andric for (const Use &CEU : CE->uses()) 19385ffd83dbSDimitry Andric Uses.push_back(&CEU); 19395ffd83dbSDimitry Andric continue; 19405ffd83dbSDimitry Andric } 19415ffd83dbSDimitry Andric } 19425ffd83dbSDimitry Andric 19438bcb0991SDimitry Andric AbstractCallSite ACS(&U); 19448bcb0991SDimitry Andric if (!ACS) { 1945480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Function " << Fn.getName() 19468bcb0991SDimitry Andric << " has non call site use " << *U.get() << " in " 19478bcb0991SDimitry Andric << *U.getUser() << "\n"); 1948480093f4SDimitry Andric // BlockAddress users are allowed. 1949480093f4SDimitry Andric if (isa<BlockAddress>(U.getUser())) 1950480093f4SDimitry Andric continue; 19510b57cec5SDimitry Andric return false; 19520b57cec5SDimitry Andric } 19530b57cec5SDimitry Andric 19548bcb0991SDimitry Andric const Use *EffectiveUse = 19558bcb0991SDimitry Andric ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U; 19568bcb0991SDimitry Andric if (!ACS.isCallee(EffectiveUse)) { 1957349cc55cSDimitry Andric if (!RequireAllCallSites) { 1958349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser() 1959349cc55cSDimitry Andric << " is not a call of " << Fn.getName() 1960349cc55cSDimitry Andric << ", skip use\n"); 19618bcb0991SDimitry Andric continue; 1962349cc55cSDimitry Andric } 1963349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser() 1964480093f4SDimitry Andric << " is an invalid use of " << Fn.getName() << "\n"); 19658bcb0991SDimitry Andric return false; 19668bcb0991SDimitry Andric } 19678bcb0991SDimitry Andric 19685ffd83dbSDimitry Andric // Make sure the arguments that can be matched between the call site and the 19695ffd83dbSDimitry Andric // callee argee on their type. It is unlikely they do not and it doesn't 19705ffd83dbSDimitry Andric // make sense for all attributes to know/care about this. 19715ffd83dbSDimitry Andric assert(&Fn == ACS.getCalledFunction() && "Expected known callee"); 19725ffd83dbSDimitry Andric unsigned MinArgsParams = 19735ffd83dbSDimitry Andric std::min(size_t(ACS.getNumArgOperands()), Fn.arg_size()); 19745ffd83dbSDimitry Andric for (unsigned u = 0; u < MinArgsParams; ++u) { 19755ffd83dbSDimitry Andric Value *CSArgOp = ACS.getCallArgOperand(u); 19765ffd83dbSDimitry Andric if (CSArgOp && Fn.getArg(u)->getType() != CSArgOp->getType()) { 19775ffd83dbSDimitry Andric LLVM_DEBUG( 19785ffd83dbSDimitry Andric dbgs() << "[Attributor] Call site / callee argument type mismatch [" 19795ffd83dbSDimitry Andric << u << "@" << Fn.getName() << ": " 19805ffd83dbSDimitry Andric << *Fn.getArg(u)->getType() << " vs. " 19815ffd83dbSDimitry Andric << *ACS.getCallArgOperand(u)->getType() << "\n"); 19825ffd83dbSDimitry Andric return false; 19835ffd83dbSDimitry Andric } 19845ffd83dbSDimitry Andric } 19855ffd83dbSDimitry Andric 19868bcb0991SDimitry Andric if (Pred(ACS)) 19870b57cec5SDimitry Andric continue; 19880b57cec5SDimitry Andric 19898bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for " 19908bcb0991SDimitry Andric << *ACS.getInstruction() << "\n"); 19910b57cec5SDimitry Andric return false; 19920b57cec5SDimitry Andric } 19930b57cec5SDimitry Andric 19940b57cec5SDimitry Andric return true; 19950b57cec5SDimitry Andric } 19960b57cec5SDimitry Andric 1997fe6060f1SDimitry Andric bool Attributor::shouldPropagateCallBaseContext(const IRPosition &IRP) { 1998fe6060f1SDimitry Andric // TODO: Maintain a cache of Values that are 1999fe6060f1SDimitry Andric // on the pathway from a Argument to a Instruction that would effect the 2000fe6060f1SDimitry Andric // liveness/return state etc. 2001fe6060f1SDimitry Andric return EnableCallSiteSpecific; 2002fe6060f1SDimitry Andric } 2003fe6060f1SDimitry Andric 200406c3fb27SDimitry Andric bool Attributor::checkForAllReturnedValues(function_ref<bool(Value &)> Pred, 200506c3fb27SDimitry Andric const AbstractAttribute &QueryingAA, 200606c3fb27SDimitry Andric AA::ValueScope S, 200706c3fb27SDimitry Andric bool RecurseForSelectAndPHI) { 20088bcb0991SDimitry Andric 20098bcb0991SDimitry Andric const IRPosition &IRP = QueryingAA.getIRPosition(); 20108bcb0991SDimitry Andric const Function *AssociatedFunction = IRP.getAssociatedFunction(); 20118bcb0991SDimitry Andric if (!AssociatedFunction) 20128bcb0991SDimitry Andric return false; 20138bcb0991SDimitry Andric 201406c3fb27SDimitry Andric bool UsedAssumedInformation = false; 201506c3fb27SDimitry Andric SmallVector<AA::ValueAndContext> Values; 201606c3fb27SDimitry Andric if (!getAssumedSimplifiedValues( 201706c3fb27SDimitry Andric IRPosition::returned(*AssociatedFunction), &QueryingAA, Values, S, 201806c3fb27SDimitry Andric UsedAssumedInformation, RecurseForSelectAndPHI)) 20198bcb0991SDimitry Andric return false; 20208bcb0991SDimitry Andric 202106c3fb27SDimitry Andric return llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) { 202206c3fb27SDimitry Andric return Pred(*VAC.getValue()); 20238bcb0991SDimitry Andric }); 20248bcb0991SDimitry Andric } 20258bcb0991SDimitry Andric 20265ffd83dbSDimitry Andric static bool checkForAllInstructionsImpl( 20275ffd83dbSDimitry Andric Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap, 20285ffd83dbSDimitry Andric function_ref<bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA, 20295f757f3fSDimitry Andric const AAIsDead *LivenessAA, ArrayRef<unsigned> Opcodes, 2030fe6060f1SDimitry Andric bool &UsedAssumedInformation, bool CheckBBLivenessOnly = false, 2031fe6060f1SDimitry Andric bool CheckPotentiallyDead = false) { 20328bcb0991SDimitry Andric for (unsigned Opcode : Opcodes) { 20335ffd83dbSDimitry Andric // Check if we have instructions with this opcode at all first. 20345ffd83dbSDimitry Andric auto *Insts = OpcodeInstMap.lookup(Opcode); 20355ffd83dbSDimitry Andric if (!Insts) 20368bcb0991SDimitry Andric continue; 20375ffd83dbSDimitry Andric 20385ffd83dbSDimitry Andric for (Instruction *I : *Insts) { 20395ffd83dbSDimitry Andric // Skip dead instructions. 2040fe6060f1SDimitry Andric if (A && !CheckPotentiallyDead && 20411fd87a68SDimitry Andric A->isAssumedDead(IRPosition::inst(*I), QueryingAA, LivenessAA, 20421fd87a68SDimitry Andric UsedAssumedInformation, CheckBBLivenessOnly)) { 2043bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, 2044bdd1243dSDimitry Andric dbgs() << "[Attributor] Instruction " << *I 20451fd87a68SDimitry Andric << " is potentially dead, skip!\n";); 20465ffd83dbSDimitry Andric continue; 20471fd87a68SDimitry Andric } 20488bcb0991SDimitry Andric 20498bcb0991SDimitry Andric if (!Pred(*I)) 20508bcb0991SDimitry Andric return false; 20518bcb0991SDimitry Andric } 20528bcb0991SDimitry Andric } 20538bcb0991SDimitry Andric return true; 20548bcb0991SDimitry Andric } 20558bcb0991SDimitry Andric 20565ffd83dbSDimitry Andric bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred, 205781ad6265SDimitry Andric const Function *Fn, 20585f757f3fSDimitry Andric const AbstractAttribute *QueryingAA, 20595f757f3fSDimitry Andric ArrayRef<unsigned> Opcodes, 2060fe6060f1SDimitry Andric bool &UsedAssumedInformation, 2061fe6060f1SDimitry Andric bool CheckBBLivenessOnly, 2062fe6060f1SDimitry Andric bool CheckPotentiallyDead) { 20638bcb0991SDimitry Andric // Since we need to provide instructions we have to have an exact definition. 206481ad6265SDimitry Andric if (!Fn || Fn->isDeclaration()) 2065fe6060f1SDimitry Andric return false; 2066fe6060f1SDimitry Andric 206781ad6265SDimitry Andric const IRPosition &QueryIRP = IRPosition::function(*Fn); 2068e8d8bef9SDimitry Andric const auto *LivenessAA = 20695f757f3fSDimitry Andric CheckPotentiallyDead && QueryingAA 20705f757f3fSDimitry Andric ? (getAAFor<AAIsDead>(*QueryingAA, QueryIRP, DepClassTy::NONE)) 20715f757f3fSDimitry Andric : nullptr; 20728bcb0991SDimitry Andric 207381ad6265SDimitry Andric auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn); 20745f757f3fSDimitry Andric if (!checkForAllInstructionsImpl(this, OpcodeInstMap, Pred, QueryingAA, 2075fe6060f1SDimitry Andric LivenessAA, Opcodes, UsedAssumedInformation, 2076fe6060f1SDimitry Andric CheckBBLivenessOnly, CheckPotentiallyDead)) 20778bcb0991SDimitry Andric return false; 20788bcb0991SDimitry Andric 20798bcb0991SDimitry Andric return true; 20808bcb0991SDimitry Andric } 20818bcb0991SDimitry Andric 208281ad6265SDimitry Andric bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred, 208381ad6265SDimitry Andric const AbstractAttribute &QueryingAA, 20845f757f3fSDimitry Andric ArrayRef<unsigned> Opcodes, 208581ad6265SDimitry Andric bool &UsedAssumedInformation, 208681ad6265SDimitry Andric bool CheckBBLivenessOnly, 208781ad6265SDimitry Andric bool CheckPotentiallyDead) { 208881ad6265SDimitry Andric const IRPosition &IRP = QueryingAA.getIRPosition(); 208981ad6265SDimitry Andric const Function *AssociatedFunction = IRP.getAssociatedFunction(); 20905f757f3fSDimitry Andric return checkForAllInstructions(Pred, AssociatedFunction, &QueryingAA, Opcodes, 209181ad6265SDimitry Andric UsedAssumedInformation, CheckBBLivenessOnly, 209281ad6265SDimitry Andric CheckPotentiallyDead); 209381ad6265SDimitry Andric } 209481ad6265SDimitry Andric 20958bcb0991SDimitry Andric bool Attributor::checkForAllReadWriteInstructions( 2096fe6060f1SDimitry Andric function_ref<bool(Instruction &)> Pred, AbstractAttribute &QueryingAA, 2097fe6060f1SDimitry Andric bool &UsedAssumedInformation) { 209806c3fb27SDimitry Andric TimeTraceScope TS("checkForAllReadWriteInstructions"); 20998bcb0991SDimitry Andric 21008bcb0991SDimitry Andric const Function *AssociatedFunction = 21018bcb0991SDimitry Andric QueryingAA.getIRPosition().getAssociatedFunction(); 21028bcb0991SDimitry Andric if (!AssociatedFunction) 21038bcb0991SDimitry Andric return false; 21048bcb0991SDimitry Andric 21058bcb0991SDimitry Andric const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction); 210606c3fb27SDimitry Andric const auto *LivenessAA = 2107fe6060f1SDimitry Andric getAAFor<AAIsDead>(QueryingAA, QueryIRP, DepClassTy::NONE); 21088bcb0991SDimitry Andric 21098bcb0991SDimitry Andric for (Instruction *I : 21108bcb0991SDimitry Andric InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) { 21118bcb0991SDimitry Andric // Skip dead instructions. 211206c3fb27SDimitry Andric if (isAssumedDead(IRPosition::inst(*I), &QueryingAA, LivenessAA, 2113fe6060f1SDimitry Andric UsedAssumedInformation)) 21148bcb0991SDimitry Andric continue; 21158bcb0991SDimitry Andric 21168bcb0991SDimitry Andric if (!Pred(*I)) 21178bcb0991SDimitry Andric return false; 21188bcb0991SDimitry Andric } 21198bcb0991SDimitry Andric 21208bcb0991SDimitry Andric return true; 21218bcb0991SDimitry Andric } 21228bcb0991SDimitry Andric 21235ffd83dbSDimitry Andric void Attributor::runTillFixpoint() { 2124e8d8bef9SDimitry Andric TimeTraceScope TimeScope("Attributor::runTillFixpoint"); 21250b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized " 2126e8d8bef9SDimitry Andric << DG.SyntheticRoot.Deps.size() 21270b57cec5SDimitry Andric << " abstract attributes.\n"); 21280b57cec5SDimitry Andric 21290b57cec5SDimitry Andric // Now that all abstract attributes are collected and initialized we start 21300b57cec5SDimitry Andric // the abstract analysis. 21310b57cec5SDimitry Andric 21320b57cec5SDimitry Andric unsigned IterationCounter = 1; 213381ad6265SDimitry Andric unsigned MaxIterations = 213481ad6265SDimitry Andric Configuration.MaxFixpointIterations.value_or(SetFixpointIterations); 21350b57cec5SDimitry Andric 21365ffd83dbSDimitry Andric SmallVector<AbstractAttribute *, 32> ChangedAAs; 2137480093f4SDimitry Andric SetVector<AbstractAttribute *> Worklist, InvalidAAs; 2138e8d8bef9SDimitry Andric Worklist.insert(DG.SyntheticRoot.begin(), DG.SyntheticRoot.end()); 21390b57cec5SDimitry Andric 21400b57cec5SDimitry Andric do { 21418bcb0991SDimitry Andric // Remember the size to determine new attributes. 2142e8d8bef9SDimitry Andric size_t NumAAs = DG.SyntheticRoot.Deps.size(); 21430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter 21440b57cec5SDimitry Andric << ", Worklist size: " << Worklist.size() << "\n"); 21450b57cec5SDimitry Andric 2146480093f4SDimitry Andric // For invalid AAs we can fix dependent AAs that have a required dependence, 2147480093f4SDimitry Andric // thereby folding long dependence chains in a single step without the need 2148480093f4SDimitry Andric // to run updates. 2149480093f4SDimitry Andric for (unsigned u = 0; u < InvalidAAs.size(); ++u) { 2150480093f4SDimitry Andric AbstractAttribute *InvalidAA = InvalidAAs[u]; 2151480093f4SDimitry Andric 21525ffd83dbSDimitry Andric // Check the dependences to fast track invalidation. 2153bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, 2154bdd1243dSDimitry Andric dbgs() << "[Attributor] InvalidAA: " << *InvalidAA 2155bdd1243dSDimitry Andric << " has " << InvalidAA->Deps.size() 21565ffd83dbSDimitry Andric << " required & optional dependences\n"); 215706c3fb27SDimitry Andric for (auto &DepIt : InvalidAA->Deps) { 215806c3fb27SDimitry Andric AbstractAttribute *DepAA = cast<AbstractAttribute>(DepIt.getPointer()); 215906c3fb27SDimitry Andric if (DepIt.getInt() == unsigned(DepClassTy::OPTIONAL)) { 2160bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, 2161bdd1243dSDimitry Andric dbgs() << " - recompute: " << *DepAA); 21625ffd83dbSDimitry Andric Worklist.insert(DepAA); 21635ffd83dbSDimitry Andric continue; 21645ffd83dbSDimitry Andric } 2165bdd1243dSDimitry Andric DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, dbgs() 2166bdd1243dSDimitry Andric << " - invalidate: " << *DepAA); 21675ffd83dbSDimitry Andric DepAA->getState().indicatePessimisticFixpoint(); 21685ffd83dbSDimitry Andric assert(DepAA->getState().isAtFixpoint() && "Expected fixpoint state!"); 21695ffd83dbSDimitry Andric if (!DepAA->getState().isValidState()) 21705ffd83dbSDimitry Andric InvalidAAs.insert(DepAA); 21715ffd83dbSDimitry Andric else 21725ffd83dbSDimitry Andric ChangedAAs.push_back(DepAA); 21735ffd83dbSDimitry Andric } 217406c3fb27SDimitry Andric InvalidAA->Deps.clear(); 21758bcb0991SDimitry Andric } 21768bcb0991SDimitry Andric 21770b57cec5SDimitry Andric // Add all abstract attributes that are potentially dependent on one that 21780b57cec5SDimitry Andric // changed to the work list. 217906c3fb27SDimitry Andric for (AbstractAttribute *ChangedAA : ChangedAAs) { 218006c3fb27SDimitry Andric for (auto &DepIt : ChangedAA->Deps) 218106c3fb27SDimitry Andric Worklist.insert(cast<AbstractAttribute>(DepIt.getPointer())); 218206c3fb27SDimitry Andric ChangedAA->Deps.clear(); 21830b57cec5SDimitry Andric } 21840b57cec5SDimitry Andric 21858bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] #Iteration: " << IterationCounter 21868bcb0991SDimitry Andric << ", Worklist+Dependent size: " << Worklist.size() 21878bcb0991SDimitry Andric << "\n"); 21888bcb0991SDimitry Andric 2189480093f4SDimitry Andric // Reset the changed and invalid set. 21900b57cec5SDimitry Andric ChangedAAs.clear(); 2191480093f4SDimitry Andric InvalidAAs.clear(); 21920b57cec5SDimitry Andric 21930b57cec5SDimitry Andric // Update all abstract attribute in the work list and record the ones that 21940b57cec5SDimitry Andric // changed. 21955ffd83dbSDimitry Andric for (AbstractAttribute *AA : Worklist) { 21965ffd83dbSDimitry Andric const auto &AAState = AA->getState(); 21975ffd83dbSDimitry Andric if (!AAState.isAtFixpoint()) 21985ffd83dbSDimitry Andric if (updateAA(*AA) == ChangeStatus::CHANGED) 21990b57cec5SDimitry Andric ChangedAAs.push_back(AA); 22000b57cec5SDimitry Andric 22015ffd83dbSDimitry Andric // Use the InvalidAAs vector to propagate invalid states fast transitively 22025ffd83dbSDimitry Andric // without requiring updates. 22035ffd83dbSDimitry Andric if (!AAState.isValidState()) 22045ffd83dbSDimitry Andric InvalidAAs.insert(AA); 22055ffd83dbSDimitry Andric } 22068bcb0991SDimitry Andric 22078bcb0991SDimitry Andric // Add attributes to the changed set if they have been created in the last 22088bcb0991SDimitry Andric // iteration. 2209e8d8bef9SDimitry Andric ChangedAAs.append(DG.SyntheticRoot.begin() + NumAAs, 2210e8d8bef9SDimitry Andric DG.SyntheticRoot.end()); 22118bcb0991SDimitry Andric 22120b57cec5SDimitry Andric // Reset the work list and repopulate with the changed abstract attributes. 22130b57cec5SDimitry Andric // Note that dependent ones are added above. 22140b57cec5SDimitry Andric Worklist.clear(); 22150b57cec5SDimitry Andric Worklist.insert(ChangedAAs.begin(), ChangedAAs.end()); 22161fd87a68SDimitry Andric Worklist.insert(QueryAAsAwaitingUpdate.begin(), 22171fd87a68SDimitry Andric QueryAAsAwaitingUpdate.end()); 22181fd87a68SDimitry Andric QueryAAsAwaitingUpdate.clear(); 22190b57cec5SDimitry Andric 222006c3fb27SDimitry Andric } while (!Worklist.empty() && (IterationCounter++ < MaxIterations)); 22210b57cec5SDimitry Andric 222281ad6265SDimitry Andric if (IterationCounter > MaxIterations && !Functions.empty()) { 2223349cc55cSDimitry Andric auto Remark = [&](OptimizationRemarkMissed ORM) { 2224349cc55cSDimitry Andric return ORM << "Attributor did not reach a fixpoint after " 222581ad6265SDimitry Andric << ore::NV("Iterations", MaxIterations) << " iterations."; 2226349cc55cSDimitry Andric }; 222781ad6265SDimitry Andric Function *F = Functions.front(); 2228349cc55cSDimitry Andric emitRemark<OptimizationRemarkMissed>(F, "FixedPoint", Remark); 2229349cc55cSDimitry Andric } 2230349cc55cSDimitry Andric 22310b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: " 223281ad6265SDimitry Andric << IterationCounter << "/" << MaxIterations 22330b57cec5SDimitry Andric << " iterations\n"); 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric // Reset abstract arguments not settled in a sound fixpoint by now. This 22360b57cec5SDimitry Andric // happens when we stopped the fixpoint iteration early. Note that only the 22370b57cec5SDimitry Andric // ones marked as "changed" *and* the ones transitively depending on them 22380b57cec5SDimitry Andric // need to be reverted to a pessimistic state. Others might not be in a 22390b57cec5SDimitry Andric // fixpoint state but we can use the optimistic results for them anyway. 22400b57cec5SDimitry Andric SmallPtrSet<AbstractAttribute *, 32> Visited; 22410b57cec5SDimitry Andric for (unsigned u = 0; u < ChangedAAs.size(); u++) { 22420b57cec5SDimitry Andric AbstractAttribute *ChangedAA = ChangedAAs[u]; 22430b57cec5SDimitry Andric if (!Visited.insert(ChangedAA).second) 22440b57cec5SDimitry Andric continue; 22450b57cec5SDimitry Andric 22460b57cec5SDimitry Andric AbstractState &State = ChangedAA->getState(); 22470b57cec5SDimitry Andric if (!State.isAtFixpoint()) { 22480b57cec5SDimitry Andric State.indicatePessimisticFixpoint(); 22490b57cec5SDimitry Andric 22500b57cec5SDimitry Andric NumAttributesTimedOut++; 22510b57cec5SDimitry Andric } 22520b57cec5SDimitry Andric 225306c3fb27SDimitry Andric for (auto &DepIt : ChangedAA->Deps) 225406c3fb27SDimitry Andric ChangedAAs.push_back(cast<AbstractAttribute>(DepIt.getPointer())); 225506c3fb27SDimitry Andric ChangedAA->Deps.clear(); 22560b57cec5SDimitry Andric } 22570b57cec5SDimitry Andric 22580b57cec5SDimitry Andric LLVM_DEBUG({ 22590b57cec5SDimitry Andric if (!Visited.empty()) 22600b57cec5SDimitry Andric dbgs() << "\n[Attributor] Finalized " << Visited.size() 22610b57cec5SDimitry Andric << " abstract attributes.\n"; 22620b57cec5SDimitry Andric }); 22635ffd83dbSDimitry Andric } 22645ffd83dbSDimitry Andric 22651fd87a68SDimitry Andric void Attributor::registerForUpdate(AbstractAttribute &AA) { 22661fd87a68SDimitry Andric assert(AA.isQueryAA() && 22671fd87a68SDimitry Andric "Non-query AAs should not be required to register for updates!"); 22681fd87a68SDimitry Andric QueryAAsAwaitingUpdate.insert(&AA); 22691fd87a68SDimitry Andric } 22701fd87a68SDimitry Andric 22715ffd83dbSDimitry Andric ChangeStatus Attributor::manifestAttributes() { 2272e8d8bef9SDimitry Andric TimeTraceScope TimeScope("Attributor::manifestAttributes"); 2273e8d8bef9SDimitry Andric size_t NumFinalAAs = DG.SyntheticRoot.Deps.size(); 22745ffd83dbSDimitry Andric 22750b57cec5SDimitry Andric unsigned NumManifested = 0; 22760b57cec5SDimitry Andric unsigned NumAtFixpoint = 0; 22770b57cec5SDimitry Andric ChangeStatus ManifestChange = ChangeStatus::UNCHANGED; 2278e8d8bef9SDimitry Andric for (auto &DepAA : DG.SyntheticRoot.Deps) { 2279e8d8bef9SDimitry Andric AbstractAttribute *AA = cast<AbstractAttribute>(DepAA.getPointer()); 22800b57cec5SDimitry Andric AbstractState &State = AA->getState(); 22810b57cec5SDimitry Andric 22820b57cec5SDimitry Andric // If there is not already a fixpoint reached, we can now take the 22830b57cec5SDimitry Andric // optimistic state. This is correct because we enforced a pessimistic one 22840b57cec5SDimitry Andric // on abstract attributes that were transitively dependent on a changed one 22850b57cec5SDimitry Andric // already above. 22860b57cec5SDimitry Andric if (!State.isAtFixpoint()) 22870b57cec5SDimitry Andric State.indicateOptimisticFixpoint(); 22880b57cec5SDimitry Andric 2289fe6060f1SDimitry Andric // We must not manifest Attributes that use Callbase info. 2290fe6060f1SDimitry Andric if (AA->hasCallBaseContext()) 2291fe6060f1SDimitry Andric continue; 22920b57cec5SDimitry Andric // If the state is invalid, we do not try to manifest it. 22930b57cec5SDimitry Andric if (!State.isValidState()) 22940b57cec5SDimitry Andric continue; 22950b57cec5SDimitry Andric 229681ad6265SDimitry Andric if (AA->getCtxI() && !isRunOn(*AA->getAnchorScope())) 229781ad6265SDimitry Andric continue; 229881ad6265SDimitry Andric 22998bcb0991SDimitry Andric // Skip dead code. 2300fe6060f1SDimitry Andric bool UsedAssumedInformation = false; 2301fe6060f1SDimitry Andric if (isAssumedDead(*AA, nullptr, UsedAssumedInformation, 2302fe6060f1SDimitry Andric /* CheckBBLivenessOnly */ true)) 23038bcb0991SDimitry Andric continue; 2304e8d8bef9SDimitry Andric // Check if the manifest debug counter that allows skipping manifestation of 2305e8d8bef9SDimitry Andric // AAs 2306e8d8bef9SDimitry Andric if (!DebugCounter::shouldExecute(ManifestDBGCounter)) 2307e8d8bef9SDimitry Andric continue; 23080b57cec5SDimitry Andric // Manifest the state and record if we changed the IR. 23090b57cec5SDimitry Andric ChangeStatus LocalChange = AA->manifest(*this); 23108bcb0991SDimitry Andric if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled()) 23118bcb0991SDimitry Andric AA->trackStatistics(); 23125ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Manifest " << LocalChange << " : " << *AA 23135ffd83dbSDimitry Andric << "\n"); 23148bcb0991SDimitry Andric 23150b57cec5SDimitry Andric ManifestChange = ManifestChange | LocalChange; 23160b57cec5SDimitry Andric 23170b57cec5SDimitry Andric NumAtFixpoint++; 23180b57cec5SDimitry Andric NumManifested += (LocalChange == ChangeStatus::CHANGED); 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric (void)NumManifested; 23220b57cec5SDimitry Andric (void)NumAtFixpoint; 23230b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested 23240b57cec5SDimitry Andric << " arguments while " << NumAtFixpoint 23250b57cec5SDimitry Andric << " were in a valid fixpoint state\n"); 23260b57cec5SDimitry Andric 23270b57cec5SDimitry Andric NumAttributesManifested += NumManifested; 23280b57cec5SDimitry Andric NumAttributesValidFixpoint += NumAtFixpoint; 23290b57cec5SDimitry Andric 23308bcb0991SDimitry Andric (void)NumFinalAAs; 2331e8d8bef9SDimitry Andric if (NumFinalAAs != DG.SyntheticRoot.Deps.size()) { 233206c3fb27SDimitry Andric auto DepIt = DG.SyntheticRoot.Deps.begin(); 233306c3fb27SDimitry Andric for (unsigned u = 0; u < NumFinalAAs; ++u) 233406c3fb27SDimitry Andric ++DepIt; 233506c3fb27SDimitry Andric for (unsigned u = NumFinalAAs; u < DG.SyntheticRoot.Deps.size(); 233606c3fb27SDimitry Andric ++u, ++DepIt) { 2337e8d8bef9SDimitry Andric errs() << "Unexpected abstract attribute: " 233806c3fb27SDimitry Andric << cast<AbstractAttribute>(DepIt->getPointer()) << " :: " 233906c3fb27SDimitry Andric << cast<AbstractAttribute>(DepIt->getPointer()) 2340e8d8bef9SDimitry Andric ->getIRPosition() 2341e8d8bef9SDimitry Andric .getAssociatedValue() 23425ffd83dbSDimitry Andric << "\n"; 234306c3fb27SDimitry Andric } 23445ffd83dbSDimitry Andric llvm_unreachable("Expected the final number of abstract attributes to " 23455ffd83dbSDimitry Andric "remain unchanged!"); 23465ffd83dbSDimitry Andric } 234706c3fb27SDimitry Andric 234806c3fb27SDimitry Andric for (auto &It : AttrsMap) { 234906c3fb27SDimitry Andric AttributeList &AL = It.getSecond(); 235006c3fb27SDimitry Andric const IRPosition &IRP = 235106c3fb27SDimitry Andric isa<Function>(It.getFirst()) 235206c3fb27SDimitry Andric ? IRPosition::function(*cast<Function>(It.getFirst())) 235306c3fb27SDimitry Andric : IRPosition::callsite_function(*cast<CallBase>(It.getFirst())); 235406c3fb27SDimitry Andric IRP.setAttrList(AL); 235506c3fb27SDimitry Andric } 235606c3fb27SDimitry Andric 23575ffd83dbSDimitry Andric return ManifestChange; 23585ffd83dbSDimitry Andric } 23598bcb0991SDimitry Andric 2360e8d8bef9SDimitry Andric void Attributor::identifyDeadInternalFunctions() { 2361fe6060f1SDimitry Andric // Early exit if we don't intend to delete functions. 236281ad6265SDimitry Andric if (!Configuration.DeleteFns) 2363fe6060f1SDimitry Andric return; 2364fe6060f1SDimitry Andric 2365bdd1243dSDimitry Andric // To avoid triggering an assertion in the lazy call graph we will not delete 2366bdd1243dSDimitry Andric // any internal library functions. We should modify the assertion though and 2367bdd1243dSDimitry Andric // allow internals to be deleted. 2368bdd1243dSDimitry Andric const auto *TLI = 2369bdd1243dSDimitry Andric isModulePass() 2370bdd1243dSDimitry Andric ? nullptr 2371bdd1243dSDimitry Andric : getInfoCache().getTargetLibraryInfoForFunction(*Functions.back()); 2372bdd1243dSDimitry Andric LibFunc LF; 2373bdd1243dSDimitry Andric 2374e8d8bef9SDimitry Andric // Identify dead internal functions and delete them. This happens outside 2375e8d8bef9SDimitry Andric // the other fixpoint analysis as we might treat potentially dead functions 2376e8d8bef9SDimitry Andric // as live to lower the number of iterations. If they happen to be dead, the 2377e8d8bef9SDimitry Andric // below fixpoint loop will identify and eliminate them. 2378bdd1243dSDimitry Andric 2379e8d8bef9SDimitry Andric SmallVector<Function *, 8> InternalFns; 2380e8d8bef9SDimitry Andric for (Function *F : Functions) 2381bdd1243dSDimitry Andric if (F->hasLocalLinkage() && (isModulePass() || !TLI->getLibFunc(*F, LF))) 2382e8d8bef9SDimitry Andric InternalFns.push_back(F); 2383e8d8bef9SDimitry Andric 2384e8d8bef9SDimitry Andric SmallPtrSet<Function *, 8> LiveInternalFns; 2385e8d8bef9SDimitry Andric bool FoundLiveInternal = true; 2386e8d8bef9SDimitry Andric while (FoundLiveInternal) { 2387e8d8bef9SDimitry Andric FoundLiveInternal = false; 2388*0fca6ea1SDimitry Andric for (Function *&F : InternalFns) { 2389e8d8bef9SDimitry Andric if (!F) 2390e8d8bef9SDimitry Andric continue; 2391e8d8bef9SDimitry Andric 2392d781ede6SDimitry Andric bool UsedAssumedInformation = false; 2393e8d8bef9SDimitry Andric if (checkForAllCallSites( 2394e8d8bef9SDimitry Andric [&](AbstractCallSite ACS) { 2395e8d8bef9SDimitry Andric Function *Callee = ACS.getInstruction()->getFunction(); 2396e8d8bef9SDimitry Andric return ToBeDeletedFunctions.count(Callee) || 2397e8d8bef9SDimitry Andric (Functions.count(Callee) && Callee->hasLocalLinkage() && 2398e8d8bef9SDimitry Andric !LiveInternalFns.count(Callee)); 2399e8d8bef9SDimitry Andric }, 2400d781ede6SDimitry Andric *F, true, nullptr, UsedAssumedInformation)) { 2401e8d8bef9SDimitry Andric continue; 2402e8d8bef9SDimitry Andric } 2403e8d8bef9SDimitry Andric 2404e8d8bef9SDimitry Andric LiveInternalFns.insert(F); 2405*0fca6ea1SDimitry Andric F = nullptr; 2406e8d8bef9SDimitry Andric FoundLiveInternal = true; 2407e8d8bef9SDimitry Andric } 2408e8d8bef9SDimitry Andric } 2409e8d8bef9SDimitry Andric 2410*0fca6ea1SDimitry Andric for (Function *F : InternalFns) 2411*0fca6ea1SDimitry Andric if (F) 2412e8d8bef9SDimitry Andric ToBeDeletedFunctions.insert(F); 2413e8d8bef9SDimitry Andric } 2414e8d8bef9SDimitry Andric 24155ffd83dbSDimitry Andric ChangeStatus Attributor::cleanupIR() { 2416e8d8bef9SDimitry Andric TimeTraceScope TimeScope("Attributor::cleanupIR"); 24178bcb0991SDimitry Andric // Delete stuff at the end to avoid invalid references and a nice order. 2418fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\n[Attributor] Delete/replace at least " 24198bcb0991SDimitry Andric << ToBeDeletedFunctions.size() << " functions and " 24208bcb0991SDimitry Andric << ToBeDeletedBlocks.size() << " blocks and " 2421480093f4SDimitry Andric << ToBeDeletedInsts.size() << " instructions and " 2422fe6060f1SDimitry Andric << ToBeChangedValues.size() << " values and " 242381ad6265SDimitry Andric << ToBeChangedUses.size() << " uses. To insert " 2424fcaf7f86SDimitry Andric << ToBeChangedToUnreachableInsts.size() 2425fcaf7f86SDimitry Andric << " unreachables.\n" 2426fe6060f1SDimitry Andric << "Preserve manifest added " << ManifestAddedBlocks.size() 2427fe6060f1SDimitry Andric << " blocks\n"); 2428480093f4SDimitry Andric 24295ffd83dbSDimitry Andric SmallVector<WeakTrackingVH, 32> DeadInsts; 2430480093f4SDimitry Andric SmallVector<Instruction *, 32> TerminatorsToFold; 2431480093f4SDimitry Andric 2432fe6060f1SDimitry Andric auto ReplaceUse = [&](Use *U, Value *NewV) { 2433480093f4SDimitry Andric Value *OldV = U->get(); 24345ffd83dbSDimitry Andric 2435fe6060f1SDimitry Andric // If we plan to replace NewV we need to update it at this point. 2436fe6060f1SDimitry Andric do { 2437fe6060f1SDimitry Andric const auto &Entry = ToBeChangedValues.lookup(NewV); 2438bdd1243dSDimitry Andric if (!get<0>(Entry)) 2439fe6060f1SDimitry Andric break; 2440bdd1243dSDimitry Andric NewV = get<0>(Entry); 2441fe6060f1SDimitry Andric } while (true); 2442fe6060f1SDimitry Andric 244381ad6265SDimitry Andric Instruction *I = dyn_cast<Instruction>(U->getUser()); 244481ad6265SDimitry Andric assert((!I || isRunOn(*I->getFunction())) && 244581ad6265SDimitry Andric "Cannot replace an instruction outside the current SCC!"); 244681ad6265SDimitry Andric 24475ffd83dbSDimitry Andric // Do not replace uses in returns if the value is a must-tail call we will 24485ffd83dbSDimitry Andric // not delete. 244981ad6265SDimitry Andric if (auto *RI = dyn_cast_or_null<ReturnInst>(I)) { 24505ffd83dbSDimitry Andric if (auto *CI = dyn_cast<CallInst>(OldV->stripPointerCasts())) 245181ad6265SDimitry Andric if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI)) 2452fe6060f1SDimitry Andric return; 2453fe6060f1SDimitry Andric // If we rewrite a return and the new value is not an argument, strip the 2454fe6060f1SDimitry Andric // `returned` attribute as it is wrong now. 2455fe6060f1SDimitry Andric if (!isa<Argument>(NewV)) 2456fe6060f1SDimitry Andric for (auto &Arg : RI->getFunction()->args()) 2457fe6060f1SDimitry Andric Arg.removeAttr(Attribute::Returned); 2458fe6060f1SDimitry Andric } 2459fe6060f1SDimitry Andric 2460480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "Use " << *NewV << " in " << *U->getUser() 2461480093f4SDimitry Andric << " instead of " << *OldV << "\n"); 2462480093f4SDimitry Andric U->set(NewV); 2463fe6060f1SDimitry Andric 24645ffd83dbSDimitry Andric if (Instruction *I = dyn_cast<Instruction>(OldV)) { 24655ffd83dbSDimitry Andric CGModifiedFunctions.insert(I->getFunction()); 2466480093f4SDimitry Andric if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) && 24675ffd83dbSDimitry Andric isInstructionTriviallyDead(I)) 2468480093f4SDimitry Andric DeadInsts.push_back(I); 2469480093f4SDimitry Andric } 2470fe6060f1SDimitry Andric if (isa<UndefValue>(NewV) && isa<CallBase>(U->getUser())) { 2471fe6060f1SDimitry Andric auto *CB = cast<CallBase>(U->getUser()); 2472fe6060f1SDimitry Andric if (CB->isArgOperand(U)) { 2473fe6060f1SDimitry Andric unsigned Idx = CB->getArgOperandNo(U); 2474fe6060f1SDimitry Andric CB->removeParamAttr(Idx, Attribute::NoUndef); 247506c3fb27SDimitry Andric auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand()); 247606c3fb27SDimitry Andric if (Callee && Callee->arg_size() > Idx) 247706c3fb27SDimitry Andric Callee->removeParamAttr(Idx, Attribute::NoUndef); 2478fe6060f1SDimitry Andric } 2479fe6060f1SDimitry Andric } 2480480093f4SDimitry Andric if (isa<Constant>(NewV) && isa<BranchInst>(U->getUser())) { 2481480093f4SDimitry Andric Instruction *UserI = cast<Instruction>(U->getUser()); 2482480093f4SDimitry Andric if (isa<UndefValue>(NewV)) { 2483480093f4SDimitry Andric ToBeChangedToUnreachableInsts.insert(UserI); 2484480093f4SDimitry Andric } else { 2485480093f4SDimitry Andric TerminatorsToFold.push_back(UserI); 2486480093f4SDimitry Andric } 2487480093f4SDimitry Andric } 2488fe6060f1SDimitry Andric }; 2489fe6060f1SDimitry Andric 2490fe6060f1SDimitry Andric for (auto &It : ToBeChangedUses) { 2491fe6060f1SDimitry Andric Use *U = It.first; 2492fe6060f1SDimitry Andric Value *NewV = It.second; 2493fe6060f1SDimitry Andric ReplaceUse(U, NewV); 2494480093f4SDimitry Andric } 2495fe6060f1SDimitry Andric 2496fe6060f1SDimitry Andric SmallVector<Use *, 4> Uses; 2497fe6060f1SDimitry Andric for (auto &It : ToBeChangedValues) { 2498fe6060f1SDimitry Andric Value *OldV = It.first; 2499bdd1243dSDimitry Andric auto [NewV, Done] = It.second; 2500fe6060f1SDimitry Andric Uses.clear(); 2501fe6060f1SDimitry Andric for (auto &U : OldV->uses()) 2502bdd1243dSDimitry Andric if (Done || !U.getUser()->isDroppable()) 2503fe6060f1SDimitry Andric Uses.push_back(&U); 250481ad6265SDimitry Andric for (Use *U : Uses) { 250581ad6265SDimitry Andric if (auto *I = dyn_cast<Instruction>(U->getUser())) 250681ad6265SDimitry Andric if (!isRunOn(*I->getFunction())) 250781ad6265SDimitry Andric continue; 2508fe6060f1SDimitry Andric ReplaceUse(U, NewV); 2509fe6060f1SDimitry Andric } 251081ad6265SDimitry Andric } 2511fe6060f1SDimitry Andric 2512bdd1243dSDimitry Andric for (const auto &V : InvokeWithDeadSuccessor) 2513480093f4SDimitry Andric if (InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) { 2514fe6060f1SDimitry Andric assert(isRunOn(*II->getFunction()) && 2515fe6060f1SDimitry Andric "Cannot replace an invoke outside the current SCC!"); 2516480093f4SDimitry Andric bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind); 2517480093f4SDimitry Andric bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn); 2518480093f4SDimitry Andric bool Invoke2CallAllowed = 25195ffd83dbSDimitry Andric !AAIsDead::mayCatchAsynchronousExceptions(*II->getFunction()); 2520480093f4SDimitry Andric assert((UnwindBBIsDead || NormalBBIsDead) && 2521480093f4SDimitry Andric "Invoke does not have dead successors!"); 2522480093f4SDimitry Andric BasicBlock *BB = II->getParent(); 2523480093f4SDimitry Andric BasicBlock *NormalDestBB = II->getNormalDest(); 2524480093f4SDimitry Andric if (UnwindBBIsDead) { 2525480093f4SDimitry Andric Instruction *NormalNextIP = &NormalDestBB->front(); 2526480093f4SDimitry Andric if (Invoke2CallAllowed) { 2527480093f4SDimitry Andric changeToCall(II); 2528480093f4SDimitry Andric NormalNextIP = BB->getTerminator(); 2529480093f4SDimitry Andric } 2530480093f4SDimitry Andric if (NormalBBIsDead) 2531480093f4SDimitry Andric ToBeChangedToUnreachableInsts.insert(NormalNextIP); 2532480093f4SDimitry Andric } else { 2533480093f4SDimitry Andric assert(NormalBBIsDead && "Broken invariant!"); 2534480093f4SDimitry Andric if (!NormalDestBB->getUniquePredecessor()) 2535480093f4SDimitry Andric NormalDestBB = SplitBlockPredecessors(NormalDestBB, {BB}, ".dead"); 2536480093f4SDimitry Andric ToBeChangedToUnreachableInsts.insert(&NormalDestBB->front()); 2537480093f4SDimitry Andric } 2538480093f4SDimitry Andric } 25395ffd83dbSDimitry Andric for (Instruction *I : TerminatorsToFold) { 254081ad6265SDimitry Andric assert(isRunOn(*I->getFunction()) && 254181ad6265SDimitry Andric "Cannot replace a terminator outside the current SCC!"); 25425ffd83dbSDimitry Andric CGModifiedFunctions.insert(I->getFunction()); 2543480093f4SDimitry Andric ConstantFoldTerminator(I->getParent()); 25445ffd83dbSDimitry Andric } 2545bdd1243dSDimitry Andric for (const auto &V : ToBeChangedToUnreachableInsts) 25465ffd83dbSDimitry Andric if (Instruction *I = dyn_cast_or_null<Instruction>(V)) { 2547fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Change to unreachable: " << *I 2548fcaf7f86SDimitry Andric << "\n"); 254981ad6265SDimitry Andric assert(isRunOn(*I->getFunction()) && 255081ad6265SDimitry Andric "Cannot replace an instruction outside the current SCC!"); 25515ffd83dbSDimitry Andric CGModifiedFunctions.insert(I->getFunction()); 2552fe6060f1SDimitry Andric changeToUnreachable(I); 25535ffd83dbSDimitry Andric } 2554480093f4SDimitry Andric 2555bdd1243dSDimitry Andric for (const auto &V : ToBeDeletedInsts) { 25565ffd83dbSDimitry Andric if (Instruction *I = dyn_cast_or_null<Instruction>(V)) { 2557*0fca6ea1SDimitry Andric assert((!isa<CallBase>(I) || isa<IntrinsicInst>(I) || 2558*0fca6ea1SDimitry Andric isRunOn(*I->getFunction())) && 255981ad6265SDimitry Andric "Cannot delete an instruction outside the current SCC!"); 25605ffd83dbSDimitry Andric I->dropDroppableUses(); 25615ffd83dbSDimitry Andric CGModifiedFunctions.insert(I->getFunction()); 25625ffd83dbSDimitry Andric if (!I->getType()->isVoidTy()) 25638bcb0991SDimitry Andric I->replaceAllUsesWith(UndefValue::get(I->getType())); 2564480093f4SDimitry Andric if (!isa<PHINode>(I) && isInstructionTriviallyDead(I)) 2565480093f4SDimitry Andric DeadInsts.push_back(I); 2566480093f4SDimitry Andric else 25678bcb0991SDimitry Andric I->eraseFromParent(); 25688bcb0991SDimitry Andric } 25695ffd83dbSDimitry Andric } 25705ffd83dbSDimitry Andric 257181ad6265SDimitry Andric llvm::erase_if(DeadInsts, [&](WeakTrackingVH I) { return !I; }); 2572fe6060f1SDimitry Andric 2573fe6060f1SDimitry Andric LLVM_DEBUG({ 2574fe6060f1SDimitry Andric dbgs() << "[Attributor] DeadInsts size: " << DeadInsts.size() << "\n"; 2575fe6060f1SDimitry Andric for (auto &I : DeadInsts) 2576fe6060f1SDimitry Andric if (I) 2577fe6060f1SDimitry Andric dbgs() << " - " << *I << "\n"; 2578fe6060f1SDimitry Andric }); 25798bcb0991SDimitry Andric 2580480093f4SDimitry Andric RecursivelyDeleteTriviallyDeadInstructions(DeadInsts); 2581480093f4SDimitry Andric 25828bcb0991SDimitry Andric if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) { 25838bcb0991SDimitry Andric SmallVector<BasicBlock *, 8> ToBeDeletedBBs; 25848bcb0991SDimitry Andric ToBeDeletedBBs.reserve(NumDeadBlocks); 25855ffd83dbSDimitry Andric for (BasicBlock *BB : ToBeDeletedBlocks) { 2586fe6060f1SDimitry Andric assert(isRunOn(*BB->getParent()) && 2587fe6060f1SDimitry Andric "Cannot delete a block outside the current SCC!"); 25885ffd83dbSDimitry Andric CGModifiedFunctions.insert(BB->getParent()); 2589fe6060f1SDimitry Andric // Do not delete BBs added during manifests of AAs. 2590fe6060f1SDimitry Andric if (ManifestAddedBlocks.contains(BB)) 2591fe6060f1SDimitry Andric continue; 25925ffd83dbSDimitry Andric ToBeDeletedBBs.push_back(BB); 25935ffd83dbSDimitry Andric } 2594480093f4SDimitry Andric // Actually we do not delete the blocks but squash them into a single 2595480093f4SDimitry Andric // unreachable but untangling branches that jump here is something we need 2596480093f4SDimitry Andric // to do in a more generic way. 25971fd87a68SDimitry Andric detachDeadBlocks(ToBeDeletedBBs, nullptr); 25988bcb0991SDimitry Andric } 25998bcb0991SDimitry Andric 2600e8d8bef9SDimitry Andric identifyDeadInternalFunctions(); 2601480093f4SDimitry Andric 2602480093f4SDimitry Andric // Rewrite the functions as requested during manifest. 26035ffd83dbSDimitry Andric ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions); 2604480093f4SDimitry Andric 26055ffd83dbSDimitry Andric for (Function *Fn : CGModifiedFunctions) 2606fe6060f1SDimitry Andric if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn)) 260781ad6265SDimitry Andric Configuration.CGUpdater.reanalyzeFunction(*Fn); 2608480093f4SDimitry Andric 2609e8d8bef9SDimitry Andric for (Function *Fn : ToBeDeletedFunctions) { 2610e8d8bef9SDimitry Andric if (!Functions.count(Fn)) 2611e8d8bef9SDimitry Andric continue; 261281ad6265SDimitry Andric Configuration.CGUpdater.removeFunction(*Fn); 2613e8d8bef9SDimitry Andric } 2614e8d8bef9SDimitry Andric 2615e8d8bef9SDimitry Andric if (!ToBeChangedUses.empty()) 2616e8d8bef9SDimitry Andric ManifestChange = ChangeStatus::CHANGED; 2617e8d8bef9SDimitry Andric 2618e8d8bef9SDimitry Andric if (!ToBeChangedToUnreachableInsts.empty()) 2619e8d8bef9SDimitry Andric ManifestChange = ChangeStatus::CHANGED; 2620e8d8bef9SDimitry Andric 2621e8d8bef9SDimitry Andric if (!ToBeDeletedFunctions.empty()) 2622e8d8bef9SDimitry Andric ManifestChange = ChangeStatus::CHANGED; 2623e8d8bef9SDimitry Andric 2624e8d8bef9SDimitry Andric if (!ToBeDeletedBlocks.empty()) 2625e8d8bef9SDimitry Andric ManifestChange = ChangeStatus::CHANGED; 2626e8d8bef9SDimitry Andric 2627e8d8bef9SDimitry Andric if (!ToBeDeletedInsts.empty()) 2628e8d8bef9SDimitry Andric ManifestChange = ChangeStatus::CHANGED; 2629e8d8bef9SDimitry Andric 2630e8d8bef9SDimitry Andric if (!InvokeWithDeadSuccessor.empty()) 2631e8d8bef9SDimitry Andric ManifestChange = ChangeStatus::CHANGED; 2632e8d8bef9SDimitry Andric 2633e8d8bef9SDimitry Andric if (!DeadInsts.empty()) 2634e8d8bef9SDimitry Andric ManifestChange = ChangeStatus::CHANGED; 26355ffd83dbSDimitry Andric 26365ffd83dbSDimitry Andric NumFnDeleted += ToBeDeletedFunctions.size(); 26375ffd83dbSDimitry Andric 2638e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Deleted " << ToBeDeletedFunctions.size() 26395ffd83dbSDimitry Andric << " functions after manifest.\n"); 26405ffd83dbSDimitry Andric 26415ffd83dbSDimitry Andric #ifdef EXPENSIVE_CHECKS 26425ffd83dbSDimitry Andric for (Function *F : Functions) { 26435ffd83dbSDimitry Andric if (ToBeDeletedFunctions.count(F)) 26445ffd83dbSDimitry Andric continue; 26455ffd83dbSDimitry Andric assert(!verifyFunction(*F, &errs()) && "Module verification failed!"); 26468bcb0991SDimitry Andric } 26475ffd83dbSDimitry Andric #endif 26488bcb0991SDimitry Andric 26490b57cec5SDimitry Andric return ManifestChange; 26500b57cec5SDimitry Andric } 26510b57cec5SDimitry Andric 26525ffd83dbSDimitry Andric ChangeStatus Attributor::run() { 2653e8d8bef9SDimitry Andric TimeTraceScope TimeScope("Attributor::run"); 2654fe6060f1SDimitry Andric AttributorCallGraph ACallGraph(*this); 2655fe6060f1SDimitry Andric 2656fe6060f1SDimitry Andric if (PrintCallGraph) 2657fe6060f1SDimitry Andric ACallGraph.populateAll(); 2658e8d8bef9SDimitry Andric 2659e8d8bef9SDimitry Andric Phase = AttributorPhase::UPDATE; 26605ffd83dbSDimitry Andric runTillFixpoint(); 2661e8d8bef9SDimitry Andric 2662e8d8bef9SDimitry Andric // dump graphs on demand 2663e8d8bef9SDimitry Andric if (DumpDepGraph) 2664e8d8bef9SDimitry Andric DG.dumpGraph(); 2665e8d8bef9SDimitry Andric 2666e8d8bef9SDimitry Andric if (ViewDepGraph) 2667e8d8bef9SDimitry Andric DG.viewGraph(); 2668e8d8bef9SDimitry Andric 2669e8d8bef9SDimitry Andric if (PrintDependencies) 2670e8d8bef9SDimitry Andric DG.print(); 2671e8d8bef9SDimitry Andric 2672e8d8bef9SDimitry Andric Phase = AttributorPhase::MANIFEST; 26735ffd83dbSDimitry Andric ChangeStatus ManifestChange = manifestAttributes(); 2674e8d8bef9SDimitry Andric 2675e8d8bef9SDimitry Andric Phase = AttributorPhase::CLEANUP; 26765ffd83dbSDimitry Andric ChangeStatus CleanupChange = cleanupIR(); 2677e8d8bef9SDimitry Andric 2678fe6060f1SDimitry Andric if (PrintCallGraph) 2679fe6060f1SDimitry Andric ACallGraph.print(); 2680fe6060f1SDimitry Andric 26815ffd83dbSDimitry Andric return ManifestChange | CleanupChange; 26825ffd83dbSDimitry Andric } 26835ffd83dbSDimitry Andric 26845ffd83dbSDimitry Andric ChangeStatus Attributor::updateAA(AbstractAttribute &AA) { 268506c3fb27SDimitry Andric TimeTraceScope TimeScope("updateAA", [&]() { 268606c3fb27SDimitry Andric return AA.getName() + std::to_string(AA.getIRPosition().getPositionKind()); 268706c3fb27SDimitry Andric }); 2688e8d8bef9SDimitry Andric assert(Phase == AttributorPhase::UPDATE && 2689e8d8bef9SDimitry Andric "We can update AA only in the update stage!"); 2690e8d8bef9SDimitry Andric 26915ffd83dbSDimitry Andric // Use a new dependence vector for this update. 26925ffd83dbSDimitry Andric DependenceVector DV; 26935ffd83dbSDimitry Andric DependenceStack.push_back(&DV); 26945ffd83dbSDimitry Andric 26955ffd83dbSDimitry Andric auto &AAState = AA.getState(); 26965ffd83dbSDimitry Andric ChangeStatus CS = ChangeStatus::UNCHANGED; 2697fe6060f1SDimitry Andric bool UsedAssumedInformation = false; 2698fe6060f1SDimitry Andric if (!isAssumedDead(AA, nullptr, UsedAssumedInformation, 2699fe6060f1SDimitry Andric /* CheckBBLivenessOnly */ true)) 27005ffd83dbSDimitry Andric CS = AA.update(*this); 27015ffd83dbSDimitry Andric 2702bdd1243dSDimitry Andric if (!AA.isQueryAA() && DV.empty() && !AA.getState().isAtFixpoint()) { 2703bdd1243dSDimitry Andric // If the AA did not rely on outside information but changed, we run it 2704bdd1243dSDimitry Andric // again to see if it found a fixpoint. Most AAs do but we don't require 2705bdd1243dSDimitry Andric // them to. Hence, it might take the AA multiple iterations to get to a 2706bdd1243dSDimitry Andric // fixpoint even if it does not rely on outside information, which is fine. 2707bdd1243dSDimitry Andric ChangeStatus RerunCS = ChangeStatus::UNCHANGED; 2708bdd1243dSDimitry Andric if (CS == ChangeStatus::CHANGED) 2709bdd1243dSDimitry Andric RerunCS = AA.update(*this); 2710bdd1243dSDimitry Andric 2711bdd1243dSDimitry Andric // If the attribute did not change during the run or rerun, and it still did 2712bdd1243dSDimitry Andric // not query any non-fix information, the state will not change and we can 2713bdd1243dSDimitry Andric // indicate that right at this point. 2714bdd1243dSDimitry Andric if (RerunCS == ChangeStatus::UNCHANGED && !AA.isQueryAA() && DV.empty()) 27155ffd83dbSDimitry Andric AAState.indicateOptimisticFixpoint(); 27165ffd83dbSDimitry Andric } 27175ffd83dbSDimitry Andric 27185ffd83dbSDimitry Andric if (!AAState.isAtFixpoint()) 27195ffd83dbSDimitry Andric rememberDependences(); 27205ffd83dbSDimitry Andric 27215ffd83dbSDimitry Andric // Verify the stack was used properly, that is we pop the dependence vector we 27225ffd83dbSDimitry Andric // put there earlier. 27235ffd83dbSDimitry Andric DependenceVector *PoppedDV = DependenceStack.pop_back_val(); 27245ffd83dbSDimitry Andric (void)PoppedDV; 27255ffd83dbSDimitry Andric assert(PoppedDV == &DV && "Inconsistent usage of the dependence stack!"); 27265ffd83dbSDimitry Andric 27275ffd83dbSDimitry Andric return CS; 27285ffd83dbSDimitry Andric } 27295ffd83dbSDimitry Andric 2730e8d8bef9SDimitry Andric void Attributor::createShallowWrapper(Function &F) { 27315ffd83dbSDimitry Andric assert(!F.isDeclaration() && "Cannot create a wrapper around a declaration!"); 27325ffd83dbSDimitry Andric 27335ffd83dbSDimitry Andric Module &M = *F.getParent(); 27345ffd83dbSDimitry Andric LLVMContext &Ctx = M.getContext(); 27355ffd83dbSDimitry Andric FunctionType *FnTy = F.getFunctionType(); 27365ffd83dbSDimitry Andric 27375ffd83dbSDimitry Andric Function *Wrapper = 27385ffd83dbSDimitry Andric Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(), F.getName()); 27395ffd83dbSDimitry Andric F.setName(""); // set the inside function anonymous 27405ffd83dbSDimitry Andric M.getFunctionList().insert(F.getIterator(), Wrapper); 2741*0fca6ea1SDimitry Andric // Flag whether the function is using new-debug-info or not. 2742*0fca6ea1SDimitry Andric Wrapper->IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; 27435ffd83dbSDimitry Andric 27445ffd83dbSDimitry Andric F.setLinkage(GlobalValue::InternalLinkage); 27455ffd83dbSDimitry Andric 27465ffd83dbSDimitry Andric F.replaceAllUsesWith(Wrapper); 27475ffd83dbSDimitry Andric assert(F.use_empty() && "Uses remained after wrapper was created!"); 27485ffd83dbSDimitry Andric 27495ffd83dbSDimitry Andric // Move the COMDAT section to the wrapper. 27505ffd83dbSDimitry Andric // TODO: Check if we need to keep it for F as well. 27515ffd83dbSDimitry Andric Wrapper->setComdat(F.getComdat()); 27525ffd83dbSDimitry Andric F.setComdat(nullptr); 27535ffd83dbSDimitry Andric 27545ffd83dbSDimitry Andric // Copy all metadata and attributes but keep them on F as well. 27555ffd83dbSDimitry Andric SmallVector<std::pair<unsigned, MDNode *>, 1> MDs; 27565ffd83dbSDimitry Andric F.getAllMetadata(MDs); 27575ffd83dbSDimitry Andric for (auto MDIt : MDs) 27585ffd83dbSDimitry Andric Wrapper->addMetadata(MDIt.first, *MDIt.second); 27595ffd83dbSDimitry Andric Wrapper->setAttributes(F.getAttributes()); 27605ffd83dbSDimitry Andric 27615ffd83dbSDimitry Andric // Create the call in the wrapper. 27625ffd83dbSDimitry Andric BasicBlock *EntryBB = BasicBlock::Create(Ctx, "entry", Wrapper); 27635ffd83dbSDimitry Andric 27645ffd83dbSDimitry Andric SmallVector<Value *, 8> Args; 2765e8d8bef9SDimitry Andric Argument *FArgIt = F.arg_begin(); 27665ffd83dbSDimitry Andric for (Argument &Arg : Wrapper->args()) { 27675ffd83dbSDimitry Andric Args.push_back(&Arg); 27685ffd83dbSDimitry Andric Arg.setName((FArgIt++)->getName()); 27695ffd83dbSDimitry Andric } 27705ffd83dbSDimitry Andric 27715ffd83dbSDimitry Andric CallInst *CI = CallInst::Create(&F, Args, "", EntryBB); 27725ffd83dbSDimitry Andric CI->setTailCall(true); 2773349cc55cSDimitry Andric CI->addFnAttr(Attribute::NoInline); 27745ffd83dbSDimitry Andric ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI, EntryBB); 27755ffd83dbSDimitry Andric 2776e8d8bef9SDimitry Andric NumFnShallowWrappersCreated++; 2777e8d8bef9SDimitry Andric } 2778e8d8bef9SDimitry Andric 27796e75b2fbSDimitry Andric bool Attributor::isInternalizable(Function &F) { 27806e75b2fbSDimitry Andric if (F.isDeclaration() || F.hasLocalLinkage() || 27816e75b2fbSDimitry Andric GlobalValue::isInterposableLinkage(F.getLinkage())) 27826e75b2fbSDimitry Andric return false; 27836e75b2fbSDimitry Andric return true; 27846e75b2fbSDimitry Andric } 27856e75b2fbSDimitry Andric 2786fe6060f1SDimitry Andric Function *Attributor::internalizeFunction(Function &F, bool Force) { 2787fe6060f1SDimitry Andric if (!AllowDeepWrapper && !Force) 2788fe6060f1SDimitry Andric return nullptr; 27896e75b2fbSDimitry Andric if (!isInternalizable(F)) 2790fe6060f1SDimitry Andric return nullptr; 2791e8d8bef9SDimitry Andric 27926e75b2fbSDimitry Andric SmallPtrSet<Function *, 2> FnSet = {&F}; 27936e75b2fbSDimitry Andric DenseMap<Function *, Function *> InternalizedFns; 27946e75b2fbSDimitry Andric internalizeFunctions(FnSet, InternalizedFns); 2795e8d8bef9SDimitry Andric 27966e75b2fbSDimitry Andric return InternalizedFns[&F]; 27976e75b2fbSDimitry Andric } 27986e75b2fbSDimitry Andric 27996e75b2fbSDimitry Andric bool Attributor::internalizeFunctions(SmallPtrSetImpl<Function *> &FnSet, 28006e75b2fbSDimitry Andric DenseMap<Function *, Function *> &FnMap) { 28016e75b2fbSDimitry Andric for (Function *F : FnSet) 28026e75b2fbSDimitry Andric if (!Attributor::isInternalizable(*F)) 28036e75b2fbSDimitry Andric return false; 28046e75b2fbSDimitry Andric 28056e75b2fbSDimitry Andric FnMap.clear(); 28066e75b2fbSDimitry Andric // Generate the internalized version of each function. 28076e75b2fbSDimitry Andric for (Function *F : FnSet) { 28086e75b2fbSDimitry Andric Module &M = *F->getParent(); 28096e75b2fbSDimitry Andric FunctionType *FnTy = F->getFunctionType(); 28106e75b2fbSDimitry Andric 28116e75b2fbSDimitry Andric // Create a copy of the current function 28126e75b2fbSDimitry Andric Function *Copied = 28136e75b2fbSDimitry Andric Function::Create(FnTy, F->getLinkage(), F->getAddressSpace(), 28146e75b2fbSDimitry Andric F->getName() + ".internalized"); 2815e8d8bef9SDimitry Andric ValueToValueMapTy VMap; 2816e8d8bef9SDimitry Andric auto *NewFArgIt = Copied->arg_begin(); 28176e75b2fbSDimitry Andric for (auto &Arg : F->args()) { 2818e8d8bef9SDimitry Andric auto ArgName = Arg.getName(); 2819e8d8bef9SDimitry Andric NewFArgIt->setName(ArgName); 2820e8d8bef9SDimitry Andric VMap[&Arg] = &(*NewFArgIt++); 2821e8d8bef9SDimitry Andric } 2822e8d8bef9SDimitry Andric SmallVector<ReturnInst *, 8> Returns; 2823*0fca6ea1SDimitry Andric // Flag whether the function is using new-debug-info or not. 2824*0fca6ea1SDimitry Andric Copied->IsNewDbgInfoFormat = F->IsNewDbgInfoFormat; 2825e8d8bef9SDimitry Andric 2826e8d8bef9SDimitry Andric // Copy the body of the original function to the new one 28276e75b2fbSDimitry Andric CloneFunctionInto(Copied, F, VMap, 28286e75b2fbSDimitry Andric CloneFunctionChangeType::LocalChangesOnly, Returns); 2829e8d8bef9SDimitry Andric 28306e75b2fbSDimitry Andric // Set the linakage and visibility late as CloneFunctionInto has some 28316e75b2fbSDimitry Andric // implicit requirements. 2832e8d8bef9SDimitry Andric Copied->setVisibility(GlobalValue::DefaultVisibility); 2833e8d8bef9SDimitry Andric Copied->setLinkage(GlobalValue::PrivateLinkage); 2834e8d8bef9SDimitry Andric 2835e8d8bef9SDimitry Andric // Copy metadata 2836e8d8bef9SDimitry Andric SmallVector<std::pair<unsigned, MDNode *>, 1> MDs; 28376e75b2fbSDimitry Andric F->getAllMetadata(MDs); 2838e8d8bef9SDimitry Andric for (auto MDIt : MDs) 2839fe6060f1SDimitry Andric if (!Copied->hasMetadata()) 2840e8d8bef9SDimitry Andric Copied->addMetadata(MDIt.first, *MDIt.second); 2841e8d8bef9SDimitry Andric 28426e75b2fbSDimitry Andric M.getFunctionList().insert(F->getIterator(), Copied); 2843e8d8bef9SDimitry Andric Copied->setDSOLocal(true); 28446e75b2fbSDimitry Andric FnMap[F] = Copied; 28456e75b2fbSDimitry Andric } 2846e8d8bef9SDimitry Andric 28476e75b2fbSDimitry Andric // Replace all uses of the old function with the new internalized function 28486e75b2fbSDimitry Andric // unless the caller is a function that was just internalized. 28496e75b2fbSDimitry Andric for (Function *F : FnSet) { 28506e75b2fbSDimitry Andric auto &InternalizedFn = FnMap[F]; 28516e75b2fbSDimitry Andric auto IsNotInternalized = [&](Use &U) -> bool { 28526e75b2fbSDimitry Andric if (auto *CB = dyn_cast<CallBase>(U.getUser())) 28536e75b2fbSDimitry Andric return !FnMap.lookup(CB->getCaller()); 28546e75b2fbSDimitry Andric return false; 28556e75b2fbSDimitry Andric }; 28566e75b2fbSDimitry Andric F->replaceUsesWithIf(InternalizedFn, IsNotInternalized); 28576e75b2fbSDimitry Andric } 28586e75b2fbSDimitry Andric 28596e75b2fbSDimitry Andric return true; 28605ffd83dbSDimitry Andric } 28615ffd83dbSDimitry Andric 28625ffd83dbSDimitry Andric bool Attributor::isValidFunctionSignatureRewrite( 28635ffd83dbSDimitry Andric Argument &Arg, ArrayRef<Type *> ReplacementTypes) { 2864480093f4SDimitry Andric 286581ad6265SDimitry Andric if (!Configuration.RewriteSignatures) 2866fe6060f1SDimitry Andric return false; 2867fe6060f1SDimitry Andric 2868349cc55cSDimitry Andric Function *Fn = Arg.getParent(); 2869349cc55cSDimitry Andric auto CallSiteCanBeChanged = [Fn](AbstractCallSite ACS) { 28705ffd83dbSDimitry Andric // Forbid the call site to cast the function return type. If we need to 28715ffd83dbSDimitry Andric // rewrite these functions we need to re-create a cast for the new call site 28725ffd83dbSDimitry Andric // (if the old had uses). 28735ffd83dbSDimitry Andric if (!ACS.getCalledFunction() || 28745ffd83dbSDimitry Andric ACS.getInstruction()->getType() != 28755ffd83dbSDimitry Andric ACS.getCalledFunction()->getReturnType()) 28765ffd83dbSDimitry Andric return false; 287706c3fb27SDimitry Andric if (cast<CallBase>(ACS.getInstruction())->getCalledOperand()->getType() != 287806c3fb27SDimitry Andric Fn->getType()) 287906c3fb27SDimitry Andric return false; 288006c3fb27SDimitry Andric if (ACS.getNumArgOperands() != Fn->arg_size()) 2881349cc55cSDimitry Andric return false; 2882480093f4SDimitry Andric // Forbid must-tail calls for now. 28835ffd83dbSDimitry Andric return !ACS.isCallbackCall() && !ACS.getInstruction()->isMustTailCall(); 2884480093f4SDimitry Andric }; 2885480093f4SDimitry Andric 2886480093f4SDimitry Andric // Avoid var-arg functions for now. 2887480093f4SDimitry Andric if (Fn->isVarArg()) { 2888480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite var-args functions\n"); 2889480093f4SDimitry Andric return false; 2890480093f4SDimitry Andric } 2891480093f4SDimitry Andric 2892480093f4SDimitry Andric // Avoid functions with complicated argument passing semantics. 2893480093f4SDimitry Andric AttributeList FnAttributeList = Fn->getAttributes(); 2894480093f4SDimitry Andric if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) || 2895480093f4SDimitry Andric FnAttributeList.hasAttrSomewhere(Attribute::StructRet) || 28965ffd83dbSDimitry Andric FnAttributeList.hasAttrSomewhere(Attribute::InAlloca) || 28975ffd83dbSDimitry Andric FnAttributeList.hasAttrSomewhere(Attribute::Preallocated)) { 2898480093f4SDimitry Andric LLVM_DEBUG( 2899480093f4SDimitry Andric dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n"); 2900480093f4SDimitry Andric return false; 2901480093f4SDimitry Andric } 2902480093f4SDimitry Andric 2903480093f4SDimitry Andric // Avoid callbacks for now. 2904d781ede6SDimitry Andric bool UsedAssumedInformation = false; 29055ffd83dbSDimitry Andric if (!checkForAllCallSites(CallSiteCanBeChanged, *Fn, true, nullptr, 290606c3fb27SDimitry Andric UsedAssumedInformation, 290706c3fb27SDimitry Andric /* CheckPotentiallyDead */ true)) { 2908480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n"); 2909480093f4SDimitry Andric return false; 2910480093f4SDimitry Andric } 2911480093f4SDimitry Andric 2912480093f4SDimitry Andric auto InstPred = [](Instruction &I) { 2913480093f4SDimitry Andric if (auto *CI = dyn_cast<CallInst>(&I)) 2914480093f4SDimitry Andric return !CI->isMustTailCall(); 2915480093f4SDimitry Andric return true; 2916480093f4SDimitry Andric }; 2917480093f4SDimitry Andric 2918480093f4SDimitry Andric // Forbid must-tail calls for now. 2919480093f4SDimitry Andric // TODO: 2920480093f4SDimitry Andric auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn); 29215ffd83dbSDimitry Andric if (!checkForAllInstructionsImpl(nullptr, OpcodeInstMap, InstPred, nullptr, 2922fe6060f1SDimitry Andric nullptr, {Instruction::Call}, 2923fe6060f1SDimitry Andric UsedAssumedInformation)) { 2924480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite due to instructions\n"); 2925480093f4SDimitry Andric return false; 2926480093f4SDimitry Andric } 2927480093f4SDimitry Andric 29285ffd83dbSDimitry Andric return true; 29295ffd83dbSDimitry Andric } 29305ffd83dbSDimitry Andric 29315ffd83dbSDimitry Andric bool Attributor::registerFunctionSignatureRewrite( 29325ffd83dbSDimitry Andric Argument &Arg, ArrayRef<Type *> ReplacementTypes, 29335ffd83dbSDimitry Andric ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB, 29345ffd83dbSDimitry Andric ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB) { 29355ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in " 29365ffd83dbSDimitry Andric << Arg.getParent()->getName() << " with " 29375ffd83dbSDimitry Andric << ReplacementTypes.size() << " replacements\n"); 29385ffd83dbSDimitry Andric assert(isValidFunctionSignatureRewrite(Arg, ReplacementTypes) && 29395ffd83dbSDimitry Andric "Cannot register an invalid rewrite"); 29405ffd83dbSDimitry Andric 29415ffd83dbSDimitry Andric Function *Fn = Arg.getParent(); 29425ffd83dbSDimitry Andric SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs = 29435ffd83dbSDimitry Andric ArgumentReplacementMap[Fn]; 29445ffd83dbSDimitry Andric if (ARIs.empty()) 2945480093f4SDimitry Andric ARIs.resize(Fn->arg_size()); 2946480093f4SDimitry Andric 2947480093f4SDimitry Andric // If we have a replacement already with less than or equal new arguments, 2948480093f4SDimitry Andric // ignore this request. 29495ffd83dbSDimitry Andric std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.getArgNo()]; 2950480093f4SDimitry Andric if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.size()) { 2951480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Existing rewrite is preferred\n"); 2952480093f4SDimitry Andric return false; 2953480093f4SDimitry Andric } 2954480093f4SDimitry Andric 2955480093f4SDimitry Andric // If we have a replacement already but we like the new one better, delete 2956480093f4SDimitry Andric // the old. 29575ffd83dbSDimitry Andric ARI.reset(); 29585ffd83dbSDimitry Andric 29595ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in " 29605ffd83dbSDimitry Andric << Arg.getParent()->getName() << " with " 29615ffd83dbSDimitry Andric << ReplacementTypes.size() << " replacements\n"); 2962480093f4SDimitry Andric 2963480093f4SDimitry Andric // Remember the replacement. 29645ffd83dbSDimitry Andric ARI.reset(new ArgumentReplacementInfo(*this, Arg, ReplacementTypes, 2965480093f4SDimitry Andric std::move(CalleeRepairCB), 29665ffd83dbSDimitry Andric std::move(ACSRepairCB))); 2967480093f4SDimitry Andric 2968480093f4SDimitry Andric return true; 2969480093f4SDimitry Andric } 2970480093f4SDimitry Andric 29715ffd83dbSDimitry Andric bool Attributor::shouldSeedAttribute(AbstractAttribute &AA) { 2972e8d8bef9SDimitry Andric bool Result = true; 2973e8d8bef9SDimitry Andric #ifndef NDEBUG 2974e8d8bef9SDimitry Andric if (SeedAllowList.size() != 0) 29750eae32dcSDimitry Andric Result = llvm::is_contained(SeedAllowList, AA.getName()); 2976e8d8bef9SDimitry Andric Function *Fn = AA.getAnchorScope(); 2977e8d8bef9SDimitry Andric if (FunctionSeedAllowList.size() != 0 && Fn) 29780eae32dcSDimitry Andric Result &= llvm::is_contained(FunctionSeedAllowList, Fn->getName()); 2979e8d8bef9SDimitry Andric #endif 2980e8d8bef9SDimitry Andric return Result; 29815ffd83dbSDimitry Andric } 29825ffd83dbSDimitry Andric 29835ffd83dbSDimitry Andric ChangeStatus Attributor::rewriteFunctionSignatures( 298481ad6265SDimitry Andric SmallSetVector<Function *, 8> &ModifiedFns) { 2985480093f4SDimitry Andric ChangeStatus Changed = ChangeStatus::UNCHANGED; 2986480093f4SDimitry Andric 2987480093f4SDimitry Andric for (auto &It : ArgumentReplacementMap) { 2988480093f4SDimitry Andric Function *OldFn = It.getFirst(); 2989480093f4SDimitry Andric 2990480093f4SDimitry Andric // Deleted functions do not require rewrites. 2991e8d8bef9SDimitry Andric if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn)) 2992480093f4SDimitry Andric continue; 2993480093f4SDimitry Andric 29945ffd83dbSDimitry Andric const SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs = 29955ffd83dbSDimitry Andric It.getSecond(); 2996480093f4SDimitry Andric assert(ARIs.size() == OldFn->arg_size() && "Inconsistent state!"); 2997480093f4SDimitry Andric 2998480093f4SDimitry Andric SmallVector<Type *, 16> NewArgumentTypes; 2999480093f4SDimitry Andric SmallVector<AttributeSet, 16> NewArgumentAttributes; 3000480093f4SDimitry Andric 3001480093f4SDimitry Andric // Collect replacement argument types and copy over existing attributes. 3002480093f4SDimitry Andric AttributeList OldFnAttributeList = OldFn->getAttributes(); 3003480093f4SDimitry Andric for (Argument &Arg : OldFn->args()) { 30045ffd83dbSDimitry Andric if (const std::unique_ptr<ArgumentReplacementInfo> &ARI = 30055ffd83dbSDimitry Andric ARIs[Arg.getArgNo()]) { 3006480093f4SDimitry Andric NewArgumentTypes.append(ARI->ReplacementTypes.begin(), 3007480093f4SDimitry Andric ARI->ReplacementTypes.end()); 3008480093f4SDimitry Andric NewArgumentAttributes.append(ARI->getNumReplacementArgs(), 3009480093f4SDimitry Andric AttributeSet()); 3010480093f4SDimitry Andric } else { 3011480093f4SDimitry Andric NewArgumentTypes.push_back(Arg.getType()); 3012480093f4SDimitry Andric NewArgumentAttributes.push_back( 3013349cc55cSDimitry Andric OldFnAttributeList.getParamAttrs(Arg.getArgNo())); 3014480093f4SDimitry Andric } 3015480093f4SDimitry Andric } 3016480093f4SDimitry Andric 301781ad6265SDimitry Andric uint64_t LargestVectorWidth = 0; 301881ad6265SDimitry Andric for (auto *I : NewArgumentTypes) 301981ad6265SDimitry Andric if (auto *VT = dyn_cast<llvm::VectorType>(I)) 3020bdd1243dSDimitry Andric LargestVectorWidth = 3021bdd1243dSDimitry Andric std::max(LargestVectorWidth, 3022bdd1243dSDimitry Andric VT->getPrimitiveSizeInBits().getKnownMinValue()); 302381ad6265SDimitry Andric 3024480093f4SDimitry Andric FunctionType *OldFnTy = OldFn->getFunctionType(); 3025480093f4SDimitry Andric Type *RetTy = OldFnTy->getReturnType(); 3026480093f4SDimitry Andric 3027480093f4SDimitry Andric // Construct the new function type using the new arguments types. 3028480093f4SDimitry Andric FunctionType *NewFnTy = 3029480093f4SDimitry Andric FunctionType::get(RetTy, NewArgumentTypes, OldFnTy->isVarArg()); 3030480093f4SDimitry Andric 3031480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Function rewrite '" << OldFn->getName() 3032480093f4SDimitry Andric << "' from " << *OldFn->getFunctionType() << " to " 3033480093f4SDimitry Andric << *NewFnTy << "\n"); 3034480093f4SDimitry Andric 3035480093f4SDimitry Andric // Create the new function body and insert it into the module. 3036480093f4SDimitry Andric Function *NewFn = Function::Create(NewFnTy, OldFn->getLinkage(), 3037480093f4SDimitry Andric OldFn->getAddressSpace(), ""); 3038fe6060f1SDimitry Andric Functions.insert(NewFn); 3039480093f4SDimitry Andric OldFn->getParent()->getFunctionList().insert(OldFn->getIterator(), NewFn); 3040480093f4SDimitry Andric NewFn->takeName(OldFn); 3041480093f4SDimitry Andric NewFn->copyAttributesFrom(OldFn); 3042*0fca6ea1SDimitry Andric // Flag whether the function is using new-debug-info or not. 3043*0fca6ea1SDimitry Andric NewFn->IsNewDbgInfoFormat = OldFn->IsNewDbgInfoFormat; 3044480093f4SDimitry Andric 3045480093f4SDimitry Andric // Patch the pointer to LLVM function in debug info descriptor. 3046480093f4SDimitry Andric NewFn->setSubprogram(OldFn->getSubprogram()); 3047480093f4SDimitry Andric OldFn->setSubprogram(nullptr); 3048480093f4SDimitry Andric 3049480093f4SDimitry Andric // Recompute the parameter attributes list based on the new arguments for 3050480093f4SDimitry Andric // the function. 3051480093f4SDimitry Andric LLVMContext &Ctx = OldFn->getContext(); 3052480093f4SDimitry Andric NewFn->setAttributes(AttributeList::get( 3053349cc55cSDimitry Andric Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(), 3054349cc55cSDimitry Andric NewArgumentAttributes)); 305581ad6265SDimitry Andric AttributeFuncs::updateMinLegalVectorWidthAttr(*NewFn, LargestVectorWidth); 3056480093f4SDimitry Andric 30575f757f3fSDimitry Andric // Remove argmem from the memory effects if we have no more pointer 30585f757f3fSDimitry Andric // arguments, or they are readnone. 30595f757f3fSDimitry Andric MemoryEffects ME = NewFn->getMemoryEffects(); 30605f757f3fSDimitry Andric int ArgNo = -1; 30615f757f3fSDimitry Andric if (ME.doesAccessArgPointees() && all_of(NewArgumentTypes, [&](Type *T) { 30625f757f3fSDimitry Andric ++ArgNo; 30635f757f3fSDimitry Andric return !T->isPtrOrPtrVectorTy() || 30645f757f3fSDimitry Andric NewFn->hasParamAttribute(ArgNo, Attribute::ReadNone); 30655f757f3fSDimitry Andric })) { 30665f757f3fSDimitry Andric NewFn->setMemoryEffects(ME - MemoryEffects::argMemOnly()); 30675f757f3fSDimitry Andric } 30685f757f3fSDimitry Andric 3069480093f4SDimitry Andric // Since we have now created the new function, splice the body of the old 3070480093f4SDimitry Andric // function right into the new function, leaving the old rotting hulk of the 3071480093f4SDimitry Andric // function empty. 3072bdd1243dSDimitry Andric NewFn->splice(NewFn->begin(), OldFn); 3073480093f4SDimitry Andric 30745ffd83dbSDimitry Andric // Fixup block addresses to reference new function. 30755ffd83dbSDimitry Andric SmallVector<BlockAddress *, 8u> BlockAddresses; 30765ffd83dbSDimitry Andric for (User *U : OldFn->users()) 30775ffd83dbSDimitry Andric if (auto *BA = dyn_cast<BlockAddress>(U)) 30785ffd83dbSDimitry Andric BlockAddresses.push_back(BA); 30795ffd83dbSDimitry Andric for (auto *BA : BlockAddresses) 30805ffd83dbSDimitry Andric BA->replaceAllUsesWith(BlockAddress::get(NewFn, BA->getBasicBlock())); 30815ffd83dbSDimitry Andric 3082480093f4SDimitry Andric // Set of all "call-like" instructions that invoke the old function mapped 3083480093f4SDimitry Andric // to their new replacements. 3084480093f4SDimitry Andric SmallVector<std::pair<CallBase *, CallBase *>, 8> CallSitePairs; 3085480093f4SDimitry Andric 3086480093f4SDimitry Andric // Callback to create a new "call-like" instruction for a given one. 3087480093f4SDimitry Andric auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) { 3088480093f4SDimitry Andric CallBase *OldCB = cast<CallBase>(ACS.getInstruction()); 3089480093f4SDimitry Andric const AttributeList &OldCallAttributeList = OldCB->getAttributes(); 3090480093f4SDimitry Andric 3091480093f4SDimitry Andric // Collect the new argument operands for the replacement call site. 3092480093f4SDimitry Andric SmallVector<Value *, 16> NewArgOperands; 3093480093f4SDimitry Andric SmallVector<AttributeSet, 16> NewArgOperandAttributes; 3094480093f4SDimitry Andric for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); ++OldArgNum) { 3095480093f4SDimitry Andric unsigned NewFirstArgNum = NewArgOperands.size(); 3096480093f4SDimitry Andric (void)NewFirstArgNum; // only used inside assert. 30975ffd83dbSDimitry Andric if (const std::unique_ptr<ArgumentReplacementInfo> &ARI = 30985ffd83dbSDimitry Andric ARIs[OldArgNum]) { 3099480093f4SDimitry Andric if (ARI->ACSRepairCB) 3100480093f4SDimitry Andric ARI->ACSRepairCB(*ARI, ACS, NewArgOperands); 3101480093f4SDimitry Andric assert(ARI->getNumReplacementArgs() + NewFirstArgNum == 3102480093f4SDimitry Andric NewArgOperands.size() && 3103480093f4SDimitry Andric "ACS repair callback did not provide as many operand as new " 3104480093f4SDimitry Andric "types were registered!"); 3105480093f4SDimitry Andric // TODO: Exose the attribute set to the ACS repair callback 3106480093f4SDimitry Andric NewArgOperandAttributes.append(ARI->ReplacementTypes.size(), 3107480093f4SDimitry Andric AttributeSet()); 3108480093f4SDimitry Andric } else { 3109480093f4SDimitry Andric NewArgOperands.push_back(ACS.getCallArgOperand(OldArgNum)); 3110480093f4SDimitry Andric NewArgOperandAttributes.push_back( 3111349cc55cSDimitry Andric OldCallAttributeList.getParamAttrs(OldArgNum)); 3112480093f4SDimitry Andric } 3113480093f4SDimitry Andric } 3114480093f4SDimitry Andric 3115480093f4SDimitry Andric assert(NewArgOperands.size() == NewArgOperandAttributes.size() && 3116480093f4SDimitry Andric "Mismatch # argument operands vs. # argument operand attributes!"); 3117480093f4SDimitry Andric assert(NewArgOperands.size() == NewFn->arg_size() && 3118480093f4SDimitry Andric "Mismatch # argument operands vs. # function arguments!"); 3119480093f4SDimitry Andric 3120480093f4SDimitry Andric SmallVector<OperandBundleDef, 4> OperandBundleDefs; 3121480093f4SDimitry Andric OldCB->getOperandBundlesAsDefs(OperandBundleDefs); 3122480093f4SDimitry Andric 3123480093f4SDimitry Andric // Create a new call or invoke instruction to replace the old one. 3124480093f4SDimitry Andric CallBase *NewCB; 3125480093f4SDimitry Andric if (InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) { 3126*0fca6ea1SDimitry Andric NewCB = InvokeInst::Create(NewFn, II->getNormalDest(), 3127*0fca6ea1SDimitry Andric II->getUnwindDest(), NewArgOperands, 3128*0fca6ea1SDimitry Andric OperandBundleDefs, "", OldCB->getIterator()); 3129480093f4SDimitry Andric } else { 3130480093f4SDimitry Andric auto *NewCI = CallInst::Create(NewFn, NewArgOperands, OperandBundleDefs, 3131*0fca6ea1SDimitry Andric "", OldCB->getIterator()); 3132480093f4SDimitry Andric NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind()); 3133480093f4SDimitry Andric NewCB = NewCI; 3134480093f4SDimitry Andric } 3135480093f4SDimitry Andric 3136480093f4SDimitry Andric // Copy over various properties and the new attributes. 31375ffd83dbSDimitry Andric NewCB->copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg}); 3138480093f4SDimitry Andric NewCB->setCallingConv(OldCB->getCallingConv()); 3139480093f4SDimitry Andric NewCB->takeName(OldCB); 3140480093f4SDimitry Andric NewCB->setAttributes(AttributeList::get( 3141349cc55cSDimitry Andric Ctx, OldCallAttributeList.getFnAttrs(), 3142349cc55cSDimitry Andric OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes)); 3143480093f4SDimitry Andric 314481ad6265SDimitry Andric AttributeFuncs::updateMinLegalVectorWidthAttr(*NewCB->getCaller(), 314581ad6265SDimitry Andric LargestVectorWidth); 314681ad6265SDimitry Andric 3147480093f4SDimitry Andric CallSitePairs.push_back({OldCB, NewCB}); 3148480093f4SDimitry Andric return true; 3149480093f4SDimitry Andric }; 3150480093f4SDimitry Andric 3151480093f4SDimitry Andric // Use the CallSiteReplacementCreator to create replacement call sites. 3152d781ede6SDimitry Andric bool UsedAssumedInformation = false; 31535ffd83dbSDimitry Andric bool Success = checkForAllCallSites(CallSiteReplacementCreator, *OldFn, 3154bdd1243dSDimitry Andric true, nullptr, UsedAssumedInformation, 3155bdd1243dSDimitry Andric /* CheckPotentiallyDead */ true); 3156480093f4SDimitry Andric (void)Success; 3157480093f4SDimitry Andric assert(Success && "Assumed call site replacement to succeed!"); 3158480093f4SDimitry Andric 3159480093f4SDimitry Andric // Rewire the arguments. 3160e8d8bef9SDimitry Andric Argument *OldFnArgIt = OldFn->arg_begin(); 3161e8d8bef9SDimitry Andric Argument *NewFnArgIt = NewFn->arg_begin(); 3162480093f4SDimitry Andric for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); 3163480093f4SDimitry Andric ++OldArgNum, ++OldFnArgIt) { 31645ffd83dbSDimitry Andric if (const std::unique_ptr<ArgumentReplacementInfo> &ARI = 31655ffd83dbSDimitry Andric ARIs[OldArgNum]) { 3166480093f4SDimitry Andric if (ARI->CalleeRepairCB) 3167480093f4SDimitry Andric ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt); 316881ad6265SDimitry Andric if (ARI->ReplacementTypes.empty()) 316981ad6265SDimitry Andric OldFnArgIt->replaceAllUsesWith( 317081ad6265SDimitry Andric PoisonValue::get(OldFnArgIt->getType())); 3171480093f4SDimitry Andric NewFnArgIt += ARI->ReplacementTypes.size(); 3172480093f4SDimitry Andric } else { 3173480093f4SDimitry Andric NewFnArgIt->takeName(&*OldFnArgIt); 3174480093f4SDimitry Andric OldFnArgIt->replaceAllUsesWith(&*NewFnArgIt); 3175480093f4SDimitry Andric ++NewFnArgIt; 3176480093f4SDimitry Andric } 3177480093f4SDimitry Andric } 3178480093f4SDimitry Andric 3179480093f4SDimitry Andric // Eliminate the instructions *after* we visited all of them. 3180480093f4SDimitry Andric for (auto &CallSitePair : CallSitePairs) { 3181480093f4SDimitry Andric CallBase &OldCB = *CallSitePair.first; 3182480093f4SDimitry Andric CallBase &NewCB = *CallSitePair.second; 31835ffd83dbSDimitry Andric assert(OldCB.getType() == NewCB.getType() && 31845ffd83dbSDimitry Andric "Cannot handle call sites with different types!"); 31855ffd83dbSDimitry Andric ModifiedFns.insert(OldCB.getFunction()); 3186480093f4SDimitry Andric OldCB.replaceAllUsesWith(&NewCB); 3187480093f4SDimitry Andric OldCB.eraseFromParent(); 3188480093f4SDimitry Andric } 3189480093f4SDimitry Andric 31905ffd83dbSDimitry Andric // Replace the function in the call graph (if any). 319181ad6265SDimitry Andric Configuration.CGUpdater.replaceFunctionWith(*OldFn, *NewFn); 31925ffd83dbSDimitry Andric 31935ffd83dbSDimitry Andric // If the old function was modified and needed to be reanalyzed, the new one 31945ffd83dbSDimitry Andric // does now. 319581ad6265SDimitry Andric if (ModifiedFns.remove(OldFn)) 31965ffd83dbSDimitry Andric ModifiedFns.insert(NewFn); 3197480093f4SDimitry Andric 3198480093f4SDimitry Andric Changed = ChangeStatus::CHANGED; 3199480093f4SDimitry Andric } 3200480093f4SDimitry Andric 3201480093f4SDimitry Andric return Changed; 3202480093f4SDimitry Andric } 3203480093f4SDimitry Andric 32045ffd83dbSDimitry Andric void InformationCache::initializeInformationCache(const Function &CF, 32055ffd83dbSDimitry Andric FunctionInfo &FI) { 32065ffd83dbSDimitry Andric // As we do not modify the function here we can remove the const 32075ffd83dbSDimitry Andric // withouth breaking implicit assumptions. At the end of the day, we could 32085ffd83dbSDimitry Andric // initialize the cache eagerly which would look the same to the users. 32095ffd83dbSDimitry Andric Function &F = const_cast<Function &>(CF); 32100b57cec5SDimitry Andric 32118bcb0991SDimitry Andric // Walk all instructions to find interesting instructions that might be 32128bcb0991SDimitry Andric // queried by abstract attributes during their initialization or update. 32138bcb0991SDimitry Andric // This has to happen before we create attributes. 32140b57cec5SDimitry Andric 3215bdd1243dSDimitry Andric DenseMap<const Value *, std::optional<short>> AssumeUsesMap; 321681ad6265SDimitry Andric 321781ad6265SDimitry Andric // Add \p V to the assume uses map which track the number of uses outside of 321881ad6265SDimitry Andric // "visited" assumes. If no outside uses are left the value is added to the 321981ad6265SDimitry Andric // assume only use vector. 322081ad6265SDimitry Andric auto AddToAssumeUsesMap = [&](const Value &V) -> void { 322181ad6265SDimitry Andric SmallVector<const Instruction *> Worklist; 322281ad6265SDimitry Andric if (auto *I = dyn_cast<Instruction>(&V)) 322381ad6265SDimitry Andric Worklist.push_back(I); 322481ad6265SDimitry Andric while (!Worklist.empty()) { 322581ad6265SDimitry Andric const Instruction *I = Worklist.pop_back_val(); 3226bdd1243dSDimitry Andric std::optional<short> &NumUses = AssumeUsesMap[I]; 322781ad6265SDimitry Andric if (!NumUses) 322881ad6265SDimitry Andric NumUses = I->getNumUses(); 3229bdd1243dSDimitry Andric NumUses = *NumUses - /* this assume */ 1; 3230bdd1243dSDimitry Andric if (*NumUses != 0) 323181ad6265SDimitry Andric continue; 323281ad6265SDimitry Andric AssumeOnlyValues.insert(I); 323381ad6265SDimitry Andric for (const Value *Op : I->operands()) 323481ad6265SDimitry Andric if (auto *OpI = dyn_cast<Instruction>(Op)) 323581ad6265SDimitry Andric Worklist.push_back(OpI); 323681ad6265SDimitry Andric } 323781ad6265SDimitry Andric }; 323881ad6265SDimitry Andric 32390b57cec5SDimitry Andric for (Instruction &I : instructions(&F)) { 32400b57cec5SDimitry Andric bool IsInterestingOpcode = false; 32410b57cec5SDimitry Andric 32420b57cec5SDimitry Andric // To allow easy access to all instructions in a function with a given 32430b57cec5SDimitry Andric // opcode we store them in the InfoCache. As not all opcodes are interesting 32440b57cec5SDimitry Andric // to concrete attributes we only cache the ones that are as identified in 32450b57cec5SDimitry Andric // the following switch. 32460b57cec5SDimitry Andric // Note: There are no concrete attributes now so this is initially empty. 32470b57cec5SDimitry Andric switch (I.getOpcode()) { 32480b57cec5SDimitry Andric default: 32495ffd83dbSDimitry Andric assert(!isa<CallBase>(&I) && 32505ffd83dbSDimitry Andric "New call base instruction type needs to be known in the " 32518bcb0991SDimitry Andric "Attributor."); 32520b57cec5SDimitry Andric break; 32530b57cec5SDimitry Andric case Instruction::Call: 32545ffd83dbSDimitry Andric // Calls are interesting on their own, additionally: 32555ffd83dbSDimitry Andric // For `llvm.assume` calls we also fill the KnowledgeMap as we find them. 32565ffd83dbSDimitry Andric // For `must-tail` calls we remember the caller and callee. 3257fe6060f1SDimitry Andric if (auto *Assume = dyn_cast<AssumeInst>(&I)) { 3258bdd1243dSDimitry Andric AssumeOnlyValues.insert(Assume); 32595ffd83dbSDimitry Andric fillMapFromAssume(*Assume, KnowledgeMap); 326081ad6265SDimitry Andric AddToAssumeUsesMap(*Assume->getArgOperand(0)); 32615ffd83dbSDimitry Andric } else if (cast<CallInst>(I).isMustTailCall()) { 32625ffd83dbSDimitry Andric FI.ContainsMustTailCall = true; 326306c3fb27SDimitry Andric if (auto *Callee = dyn_cast_if_present<Function>( 326406c3fb27SDimitry Andric cast<CallInst>(I).getCalledOperand())) 32655ffd83dbSDimitry Andric getFunctionInfo(*Callee).CalledViaMustTail = true; 32665ffd83dbSDimitry Andric } 3267bdd1243dSDimitry Andric [[fallthrough]]; 32680b57cec5SDimitry Andric case Instruction::CallBr: 32690b57cec5SDimitry Andric case Instruction::Invoke: 32700b57cec5SDimitry Andric case Instruction::CleanupRet: 32710b57cec5SDimitry Andric case Instruction::CatchSwitch: 3272480093f4SDimitry Andric case Instruction::AtomicRMW: 3273480093f4SDimitry Andric case Instruction::AtomicCmpXchg: 3274480093f4SDimitry Andric case Instruction::Br: 32750b57cec5SDimitry Andric case Instruction::Resume: 32760b57cec5SDimitry Andric case Instruction::Ret: 32775ffd83dbSDimitry Andric case Instruction::Load: 32785ffd83dbSDimitry Andric // The alignment of a pointer is interesting for loads. 32795ffd83dbSDimitry Andric case Instruction::Store: 32805ffd83dbSDimitry Andric // The alignment of a pointer is interesting for stores. 3281fe6060f1SDimitry Andric case Instruction::Alloca: 3282fe6060f1SDimitry Andric case Instruction::AddrSpaceCast: 32830b57cec5SDimitry Andric IsInterestingOpcode = true; 32840b57cec5SDimitry Andric } 32855ffd83dbSDimitry Andric if (IsInterestingOpcode) { 32865ffd83dbSDimitry Andric auto *&Insts = FI.OpcodeInstMap[I.getOpcode()]; 32875ffd83dbSDimitry Andric if (!Insts) 32885ffd83dbSDimitry Andric Insts = new (Allocator) InstructionVectorTy(); 32895ffd83dbSDimitry Andric Insts->push_back(&I); 32908bcb0991SDimitry Andric } 32915ffd83dbSDimitry Andric if (I.mayReadOrWriteMemory()) 32925ffd83dbSDimitry Andric FI.RWInsts.push_back(&I); 32935ffd83dbSDimitry Andric } 32945ffd83dbSDimitry Andric 32955ffd83dbSDimitry Andric if (F.hasFnAttribute(Attribute::AlwaysInline) && 32965ffd83dbSDimitry Andric isInlineViable(F).isSuccess()) 32975ffd83dbSDimitry Andric InlineableFunctions.insert(&F); 32985ffd83dbSDimitry Andric } 32995ffd83dbSDimitry Andric 33005ffd83dbSDimitry Andric InformationCache::FunctionInfo::~FunctionInfo() { 33015ffd83dbSDimitry Andric // The instruction vectors are allocated using a BumpPtrAllocator, we need to 33025ffd83dbSDimitry Andric // manually destroy them. 33035ffd83dbSDimitry Andric for (auto &It : OpcodeInstMap) 33045ffd83dbSDimitry Andric It.getSecond()->~InstructionVectorTy(); 33058bcb0991SDimitry Andric } 33060b57cec5SDimitry Andric 33075f757f3fSDimitry Andric const ArrayRef<Function *> 33085f757f3fSDimitry Andric InformationCache::getIndirectlyCallableFunctions(Attributor &A) const { 33095f757f3fSDimitry Andric assert(A.isClosedWorldModule() && "Cannot see all indirect callees!"); 33105f757f3fSDimitry Andric return IndirectlyCallableFunctions; 33115f757f3fSDimitry Andric } 33125f757f3fSDimitry Andric 3313480093f4SDimitry Andric void Attributor::recordDependence(const AbstractAttribute &FromAA, 3314480093f4SDimitry Andric const AbstractAttribute &ToAA, 3315480093f4SDimitry Andric DepClassTy DepClass) { 3316fe6060f1SDimitry Andric if (DepClass == DepClassTy::NONE) 3317fe6060f1SDimitry Andric return; 33185ffd83dbSDimitry Andric // If we are outside of an update, thus before the actual fixpoint iteration 33195ffd83dbSDimitry Andric // started (= when we create AAs), we do not track dependences because we will 33205ffd83dbSDimitry Andric // put all AAs into the initial worklist anyway. 33215ffd83dbSDimitry Andric if (DependenceStack.empty()) 33225ffd83dbSDimitry Andric return; 3323480093f4SDimitry Andric if (FromAA.getState().isAtFixpoint()) 3324480093f4SDimitry Andric return; 33255ffd83dbSDimitry Andric DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass}); 33265ffd83dbSDimitry Andric } 3327480093f4SDimitry Andric 33285ffd83dbSDimitry Andric void Attributor::rememberDependences() { 33295ffd83dbSDimitry Andric assert(!DependenceStack.empty() && "No dependences to remember!"); 33305ffd83dbSDimitry Andric 33315ffd83dbSDimitry Andric for (DepInfo &DI : *DependenceStack.back()) { 3332fe6060f1SDimitry Andric assert((DI.DepClass == DepClassTy::REQUIRED || 3333fe6060f1SDimitry Andric DI.DepClass == DepClassTy::OPTIONAL) && 3334fe6060f1SDimitry Andric "Expected required or optional dependence (1 bit)!"); 33355ffd83dbSDimitry Andric auto &DepAAs = const_cast<AbstractAttribute &>(*DI.FromAA).Deps; 333606c3fb27SDimitry Andric DepAAs.insert(AbstractAttribute::DepTy( 33375ffd83dbSDimitry Andric const_cast<AbstractAttribute *>(DI.ToAA), unsigned(DI.DepClass))); 33385ffd83dbSDimitry Andric } 3339480093f4SDimitry Andric } 3340480093f4SDimitry Andric 334106c3fb27SDimitry Andric template <Attribute::AttrKind AK, typename AAType> 334206c3fb27SDimitry Andric void Attributor::checkAndQueryIRAttr(const IRPosition &IRP, 334306c3fb27SDimitry Andric AttributeSet Attrs) { 334406c3fb27SDimitry Andric bool IsKnown; 334506c3fb27SDimitry Andric if (!Attrs.hasAttribute(AK)) 33465f757f3fSDimitry Andric if (!Configuration.Allowed || Configuration.Allowed->count(&AAType::ID)) 334706c3fb27SDimitry Andric if (!AA::hasAssumedIRAttr<AK>(*this, nullptr, IRP, DepClassTy::NONE, 334806c3fb27SDimitry Andric IsKnown)) 334906c3fb27SDimitry Andric getOrCreateAAFor<AAType>(IRP); 335006c3fb27SDimitry Andric } 335106c3fb27SDimitry Andric 33528bcb0991SDimitry Andric void Attributor::identifyDefaultAbstractAttributes(Function &F) { 33538bcb0991SDimitry Andric if (!VisitedFunctions.insert(&F).second) 33548bcb0991SDimitry Andric return; 3355480093f4SDimitry Andric if (F.isDeclaration()) 3356480093f4SDimitry Andric return; 33578bcb0991SDimitry Andric 33585ffd83dbSDimitry Andric // In non-module runs we need to look at the call sites of a function to 33595ffd83dbSDimitry Andric // determine if it is part of a must-tail call edge. This will influence what 33605ffd83dbSDimitry Andric // attributes we can derive. 33615ffd83dbSDimitry Andric InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(F); 33625ffd83dbSDimitry Andric if (!isModulePass() && !FI.CalledViaMustTail) { 33635ffd83dbSDimitry Andric for (const Use &U : F.uses()) 33645ffd83dbSDimitry Andric if (const auto *CB = dyn_cast<CallBase>(U.getUser())) 33655ffd83dbSDimitry Andric if (CB->isCallee(&U) && CB->isMustTailCall()) 33665ffd83dbSDimitry Andric FI.CalledViaMustTail = true; 33675ffd83dbSDimitry Andric } 33685ffd83dbSDimitry Andric 33698bcb0991SDimitry Andric IRPosition FPos = IRPosition::function(F); 337006c3fb27SDimitry Andric bool IsIPOAmendable = isFunctionIPOAmendable(F); 337106c3fb27SDimitry Andric auto Attrs = F.getAttributes(); 337206c3fb27SDimitry Andric auto FnAttrs = Attrs.getFnAttrs(); 33738bcb0991SDimitry Andric 33748bcb0991SDimitry Andric // Check for dead BasicBlocks in every function. 33758bcb0991SDimitry Andric // We need dead instruction detection because we do not want to deal with 33768bcb0991SDimitry Andric // broken IR in which SSA rules do not apply. 33778bcb0991SDimitry Andric getOrCreateAAFor<AAIsDead>(FPos); 33788bcb0991SDimitry Andric 337906c3fb27SDimitry Andric // Every function might contain instructions that cause "undefined 338006c3fb27SDimitry Andric // behavior". 3381480093f4SDimitry Andric getOrCreateAAFor<AAUndefinedBehavior>(FPos); 3382480093f4SDimitry Andric 338306c3fb27SDimitry Andric // Every function might be applicable for Heap-To-Stack conversion. 338406c3fb27SDimitry Andric if (EnableHeapToStack) 338506c3fb27SDimitry Andric getOrCreateAAFor<AAHeapToStack>(FPos); 33868bcb0991SDimitry Andric 338706c3fb27SDimitry Andric // Every function might be "must-progress". 338806c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs); 33898bcb0991SDimitry Andric 33908bcb0991SDimitry Andric // Every function might be "no-free". 339106c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs); 339206c3fb27SDimitry Andric 339306c3fb27SDimitry Andric // Every function might be "will-return". 339406c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs); 339506c3fb27SDimitry Andric 33965f757f3fSDimitry Andric // Every function might be marked "nosync" 33975f757f3fSDimitry Andric checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs); 33985f757f3fSDimitry Andric 339906c3fb27SDimitry Andric // Everything that is visible from the outside (=function, argument, return 340006c3fb27SDimitry Andric // positions), cannot be changed if the function is not IPO amendable. We can 340106c3fb27SDimitry Andric // however analyse the code inside. 340206c3fb27SDimitry Andric if (IsIPOAmendable) { 340306c3fb27SDimitry Andric 340406c3fb27SDimitry Andric // Every function can be nounwind. 340506c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs); 340606c3fb27SDimitry Andric 34078bcb0991SDimitry Andric // Every function might be "no-return". 340806c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs); 34098bcb0991SDimitry Andric 34108bcb0991SDimitry Andric // Every function might be "no-recurse". 341106c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs); 341206c3fb27SDimitry Andric 341306c3fb27SDimitry Andric // Every function can be "non-convergent". 341406c3fb27SDimitry Andric if (Attrs.hasFnAttr(Attribute::Convergent)) 341506c3fb27SDimitry Andric getOrCreateAAFor<AANonConvergent>(FPos); 34168bcb0991SDimitry Andric 34178bcb0991SDimitry Andric // Every function might be "readnone/readonly/writeonly/...". 34188bcb0991SDimitry Andric getOrCreateAAFor<AAMemoryBehavior>(FPos); 34198bcb0991SDimitry Andric 34205ffd83dbSDimitry Andric // Every function can be "readnone/argmemonly/inaccessiblememonly/...". 34215ffd83dbSDimitry Andric getOrCreateAAFor<AAMemoryLocation>(FPos); 34225ffd83dbSDimitry Andric 3423349cc55cSDimitry Andric // Every function can track active assumptions. 3424349cc55cSDimitry Andric getOrCreateAAFor<AAAssumptionInfo>(FPos); 3425349cc55cSDimitry Andric 34265f757f3fSDimitry Andric // If we're not using a dynamic mode for float, there's nothing worthwhile 34275f757f3fSDimitry Andric // to infer. This misses the edge case denormal-fp-math="dynamic" and 34285f757f3fSDimitry Andric // denormal-fp-math-f32=something, but that likely has no real world use. 34295f757f3fSDimitry Andric DenormalMode Mode = F.getDenormalMode(APFloat::IEEEsingle()); 34305f757f3fSDimitry Andric if (Mode.Input == DenormalMode::Dynamic || 34315f757f3fSDimitry Andric Mode.Output == DenormalMode::Dynamic) 34325f757f3fSDimitry Andric getOrCreateAAFor<AADenormalFPMath>(FPos); 34335f757f3fSDimitry Andric 34348bcb0991SDimitry Andric // Return attributes are only appropriate if the return type is non void. 34358bcb0991SDimitry Andric Type *ReturnType = F.getReturnType(); 34368bcb0991SDimitry Andric if (!ReturnType->isVoidTy()) { 34378bcb0991SDimitry Andric IRPosition RetPos = IRPosition::returned(F); 343806c3fb27SDimitry Andric AttributeSet RetAttrs = Attrs.getRetAttrs(); 34398bcb0991SDimitry Andric 3440480093f4SDimitry Andric // Every returned value might be dead. 3441480093f4SDimitry Andric getOrCreateAAFor<AAIsDead>(RetPos); 3442480093f4SDimitry Andric 34438bcb0991SDimitry Andric // Every function might be simplified. 344481ad6265SDimitry Andric bool UsedAssumedInformation = false; 3445fcaf7f86SDimitry Andric getAssumedSimplified(RetPos, nullptr, UsedAssumedInformation, 3446fcaf7f86SDimitry Andric AA::Intraprocedural); 34478bcb0991SDimitry Andric 3448e8d8bef9SDimitry Andric // Every returned value might be marked noundef. 344906c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs); 3450e8d8bef9SDimitry Andric 34518bcb0991SDimitry Andric if (ReturnType->isPointerTy()) { 34528bcb0991SDimitry Andric 34538bcb0991SDimitry Andric // Every function with pointer return type might be marked align. 34548bcb0991SDimitry Andric getOrCreateAAFor<AAAlign>(RetPos); 34558bcb0991SDimitry Andric 34568bcb0991SDimitry Andric // Every function with pointer return type might be marked nonnull. 345706c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs); 34588bcb0991SDimitry Andric 34598bcb0991SDimitry Andric // Every function with pointer return type might be marked noalias. 346006c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs); 34618bcb0991SDimitry Andric 34628bcb0991SDimitry Andric // Every function with pointer return type might be marked 34638bcb0991SDimitry Andric // dereferenceable. 34648bcb0991SDimitry Andric getOrCreateAAFor<AADereferenceable>(RetPos); 346506c3fb27SDimitry Andric } else if (AttributeFuncs::isNoFPClassCompatibleType(ReturnType)) { 346606c3fb27SDimitry Andric getOrCreateAAFor<AANoFPClass>(RetPos); 346706c3fb27SDimitry Andric } 34688bcb0991SDimitry Andric } 34698bcb0991SDimitry Andric } 34708bcb0991SDimitry Andric 34718bcb0991SDimitry Andric for (Argument &Arg : F.args()) { 34728bcb0991SDimitry Andric IRPosition ArgPos = IRPosition::argument(Arg); 347306c3fb27SDimitry Andric auto ArgNo = Arg.getArgNo(); 347406c3fb27SDimitry Andric AttributeSet ArgAttrs = Attrs.getParamAttrs(ArgNo); 34758bcb0991SDimitry Andric 347606c3fb27SDimitry Andric if (!IsIPOAmendable) { 347706c3fb27SDimitry Andric if (Arg.getType()->isPointerTy()) 347806c3fb27SDimitry Andric // Every argument with pointer type might be marked nofree. 347906c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs); 348006c3fb27SDimitry Andric continue; 348106c3fb27SDimitry Andric } 348206c3fb27SDimitry Andric 348306c3fb27SDimitry Andric // Every argument might be simplified. We have to go through the 348406c3fb27SDimitry Andric // Attributor interface though as outside AAs can register custom 348506c3fb27SDimitry Andric // simplification callbacks. 3486fe6060f1SDimitry Andric bool UsedAssumedInformation = false; 3487fcaf7f86SDimitry Andric getAssumedSimplified(ArgPos, /* AA */ nullptr, UsedAssumedInformation, 3488fcaf7f86SDimitry Andric AA::Intraprocedural); 34898bcb0991SDimitry Andric 34905ffd83dbSDimitry Andric // Every argument might be dead. 34915ffd83dbSDimitry Andric getOrCreateAAFor<AAIsDead>(ArgPos); 34925ffd83dbSDimitry Andric 3493e8d8bef9SDimitry Andric // Every argument might be marked noundef. 349406c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs); 3495e8d8bef9SDimitry Andric 34968bcb0991SDimitry Andric if (Arg.getType()->isPointerTy()) { 34978bcb0991SDimitry Andric // Every argument with pointer type might be marked nonnull. 349806c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs); 34998bcb0991SDimitry Andric 35008bcb0991SDimitry Andric // Every argument with pointer type might be marked noalias. 350106c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs); 35028bcb0991SDimitry Andric 35038bcb0991SDimitry Andric // Every argument with pointer type might be marked dereferenceable. 35048bcb0991SDimitry Andric getOrCreateAAFor<AADereferenceable>(ArgPos); 35058bcb0991SDimitry Andric 35068bcb0991SDimitry Andric // Every argument with pointer type might be marked align. 35078bcb0991SDimitry Andric getOrCreateAAFor<AAAlign>(ArgPos); 35088bcb0991SDimitry Andric 35098bcb0991SDimitry Andric // Every argument with pointer type might be marked nocapture. 351006c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(ArgPos, ArgAttrs); 35118bcb0991SDimitry Andric 35128bcb0991SDimitry Andric // Every argument with pointer type might be marked 35138bcb0991SDimitry Andric // "readnone/readonly/writeonly/..." 35148bcb0991SDimitry Andric getOrCreateAAFor<AAMemoryBehavior>(ArgPos); 3515480093f4SDimitry Andric 3516480093f4SDimitry Andric // Every argument with pointer type might be marked nofree. 351706c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs); 35185ffd83dbSDimitry Andric 351906c3fb27SDimitry Andric // Every argument with pointer type might be privatizable (or 352006c3fb27SDimitry Andric // promotable) 35215ffd83dbSDimitry Andric getOrCreateAAFor<AAPrivatizablePtr>(ArgPos); 352206c3fb27SDimitry Andric } else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) { 352306c3fb27SDimitry Andric getOrCreateAAFor<AANoFPClass>(ArgPos); 35248bcb0991SDimitry Andric } 35258bcb0991SDimitry Andric } 35268bcb0991SDimitry Andric 35278bcb0991SDimitry Andric auto CallSitePred = [&](Instruction &I) -> bool { 35285ffd83dbSDimitry Andric auto &CB = cast<CallBase>(I); 35291fd87a68SDimitry Andric IRPosition CBInstPos = IRPosition::inst(CB); 3530349cc55cSDimitry Andric IRPosition CBFnPos = IRPosition::callsite_function(CB); 35315ffd83dbSDimitry Andric 35325ffd83dbSDimitry Andric // Call sites might be dead if they do not have side effects and no live 35335ffd83dbSDimitry Andric // users. The return value might be dead if there are no live users. 35341fd87a68SDimitry Andric getOrCreateAAFor<AAIsDead>(CBInstPos); 35355ffd83dbSDimitry Andric 353606c3fb27SDimitry Andric Function *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand()); 35375ffd83dbSDimitry Andric // TODO: Even if the callee is not known now we might be able to simplify 35385ffd83dbSDimitry Andric // the call/callee. 35395f757f3fSDimitry Andric if (!Callee) { 35405f757f3fSDimitry Andric getOrCreateAAFor<AAIndirectCallInfo>(CBFnPos); 35415ffd83dbSDimitry Andric return true; 35425f757f3fSDimitry Andric } 35435ffd83dbSDimitry Andric 3544349cc55cSDimitry Andric // Every call site can track active assumptions. 3545349cc55cSDimitry Andric getOrCreateAAFor<AAAssumptionInfo>(CBFnPos); 3546349cc55cSDimitry Andric 35475ffd83dbSDimitry Andric // Skip declarations except if annotations on their call sites were 3548480093f4SDimitry Andric // explicitly requested. 3549480093f4SDimitry Andric if (!AnnotateDeclarationCallSites && Callee->isDeclaration() && 3550480093f4SDimitry Andric !Callee->hasMetadata(LLVMContext::MD_callback)) 3551480093f4SDimitry Andric return true; 3552480093f4SDimitry Andric 35535ffd83dbSDimitry Andric if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) { 35545ffd83dbSDimitry Andric IRPosition CBRetPos = IRPosition::callsite_returned(CB); 355581ad6265SDimitry Andric bool UsedAssumedInformation = false; 3556fcaf7f86SDimitry Andric getAssumedSimplified(CBRetPos, nullptr, UsedAssumedInformation, 3557fcaf7f86SDimitry Andric AA::Intraprocedural); 355806c3fb27SDimitry Andric 355906c3fb27SDimitry Andric if (AttributeFuncs::isNoFPClassCompatibleType(Callee->getReturnType())) 356006c3fb27SDimitry Andric getOrCreateAAFor<AANoFPClass>(CBInstPos); 3561480093f4SDimitry Andric } 3562480093f4SDimitry Andric 356306c3fb27SDimitry Andric const AttributeList &CBAttrs = CBFnPos.getAttrList(); 3564349cc55cSDimitry Andric for (int I = 0, E = CB.arg_size(); I < E; ++I) { 35658bcb0991SDimitry Andric 35665ffd83dbSDimitry Andric IRPosition CBArgPos = IRPosition::callsite_argument(CB, I); 356706c3fb27SDimitry Andric AttributeSet CBArgAttrs = CBAttrs.getParamAttrs(I); 35688bcb0991SDimitry Andric 3569480093f4SDimitry Andric // Every call site argument might be dead. 35705ffd83dbSDimitry Andric getOrCreateAAFor<AAIsDead>(CBArgPos); 3571480093f4SDimitry Andric 3572fe6060f1SDimitry Andric // Call site argument might be simplified. We have to go through the 3573fe6060f1SDimitry Andric // Attributor interface though as outside AAs can register custom 3574fe6060f1SDimitry Andric // simplification callbacks. 3575fe6060f1SDimitry Andric bool UsedAssumedInformation = false; 3576fcaf7f86SDimitry Andric getAssumedSimplified(CBArgPos, /* AA */ nullptr, UsedAssumedInformation, 3577fcaf7f86SDimitry Andric AA::Intraprocedural); 35788bcb0991SDimitry Andric 3579e8d8bef9SDimitry Andric // Every call site argument might be marked "noundef". 358006c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs); 3581e8d8bef9SDimitry Andric 358206c3fb27SDimitry Andric Type *ArgTy = CB.getArgOperand(I)->getType(); 358306c3fb27SDimitry Andric 358406c3fb27SDimitry Andric if (!ArgTy->isPointerTy()) { 358506c3fb27SDimitry Andric if (AttributeFuncs::isNoFPClassCompatibleType(ArgTy)) 358606c3fb27SDimitry Andric getOrCreateAAFor<AANoFPClass>(CBArgPos); 358706c3fb27SDimitry Andric 35880b57cec5SDimitry Andric continue; 358906c3fb27SDimitry Andric } 35900b57cec5SDimitry Andric 35910b57cec5SDimitry Andric // Call site argument attribute "non-null". 359206c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs); 35935ffd83dbSDimitry Andric 35945ffd83dbSDimitry Andric // Call site argument attribute "nocapture". 359506c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(CBArgPos, 359606c3fb27SDimitry Andric CBArgAttrs); 35978bcb0991SDimitry Andric 35988bcb0991SDimitry Andric // Call site argument attribute "no-alias". 359906c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs); 36008bcb0991SDimitry Andric 36018bcb0991SDimitry Andric // Call site argument attribute "dereferenceable". 36025ffd83dbSDimitry Andric getOrCreateAAFor<AADereferenceable>(CBArgPos); 36038bcb0991SDimitry Andric 36048bcb0991SDimitry Andric // Call site argument attribute "align". 36055ffd83dbSDimitry Andric getOrCreateAAFor<AAAlign>(CBArgPos); 3606480093f4SDimitry Andric 3607480093f4SDimitry Andric // Call site argument attribute 3608480093f4SDimitry Andric // "readnone/readonly/writeonly/..." 360906c3fb27SDimitry Andric if (!CBAttrs.hasParamAttr(I, Attribute::ReadNone)) 36105ffd83dbSDimitry Andric getOrCreateAAFor<AAMemoryBehavior>(CBArgPos); 3611480093f4SDimitry Andric 3612480093f4SDimitry Andric // Call site argument attribute "nofree". 361306c3fb27SDimitry Andric checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs); 36140b57cec5SDimitry Andric } 36158bcb0991SDimitry Andric return true; 36168bcb0991SDimitry Andric }; 36178bcb0991SDimitry Andric 36188bcb0991SDimitry Andric auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F); 36195f757f3fSDimitry Andric [[maybe_unused]] bool Success; 3620fe6060f1SDimitry Andric bool UsedAssumedInformation = false; 36218bcb0991SDimitry Andric Success = checkForAllInstructionsImpl( 36225ffd83dbSDimitry Andric nullptr, OpcodeInstMap, CallSitePred, nullptr, nullptr, 36238bcb0991SDimitry Andric {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr, 3624fe6060f1SDimitry Andric (unsigned)Instruction::Call}, 3625fe6060f1SDimitry Andric UsedAssumedInformation); 36265ffd83dbSDimitry Andric assert(Success && "Expected the check call to be successful!"); 36278bcb0991SDimitry Andric 36288bcb0991SDimitry Andric auto LoadStorePred = [&](Instruction &I) -> bool { 362906c3fb27SDimitry Andric if (auto *LI = dyn_cast<LoadInst>(&I)) { 363006c3fb27SDimitry Andric getOrCreateAAFor<AAAlign>(IRPosition::value(*LI->getPointerOperand())); 3631fe6060f1SDimitry Andric if (SimplifyAllLoads) 363281ad6265SDimitry Andric getAssumedSimplified(IRPosition::value(I), nullptr, 3633fcaf7f86SDimitry Andric UsedAssumedInformation, AA::Intraprocedural); 363406c3fb27SDimitry Andric getOrCreateAAFor<AAAddressSpace>( 363506c3fb27SDimitry Andric IRPosition::value(*LI->getPointerOperand())); 363681ad6265SDimitry Andric } else { 363781ad6265SDimitry Andric auto &SI = cast<StoreInst>(I); 363881ad6265SDimitry Andric getOrCreateAAFor<AAIsDead>(IRPosition::inst(I)); 363981ad6265SDimitry Andric getAssumedSimplified(IRPosition::value(*SI.getValueOperand()), nullptr, 3640fcaf7f86SDimitry Andric UsedAssumedInformation, AA::Intraprocedural); 364181ad6265SDimitry Andric getOrCreateAAFor<AAAlign>(IRPosition::value(*SI.getPointerOperand())); 364206c3fb27SDimitry Andric getOrCreateAAFor<AAAddressSpace>( 364306c3fb27SDimitry Andric IRPosition::value(*SI.getPointerOperand())); 364481ad6265SDimitry Andric } 36458bcb0991SDimitry Andric return true; 36468bcb0991SDimitry Andric }; 36478bcb0991SDimitry Andric Success = checkForAllInstructionsImpl( 36485ffd83dbSDimitry Andric nullptr, OpcodeInstMap, LoadStorePred, nullptr, nullptr, 3649fe6060f1SDimitry Andric {(unsigned)Instruction::Load, (unsigned)Instruction::Store}, 3650fe6060f1SDimitry Andric UsedAssumedInformation); 36515ffd83dbSDimitry Andric assert(Success && "Expected the check call to be successful!"); 36525f757f3fSDimitry Andric 36535f757f3fSDimitry Andric // AllocaInstPredicate 36545f757f3fSDimitry Andric auto AAAllocationInfoPred = [&](Instruction &I) -> bool { 36555f757f3fSDimitry Andric getOrCreateAAFor<AAAllocationInfo>(IRPosition::value(I)); 36565f757f3fSDimitry Andric return true; 36575f757f3fSDimitry Andric }; 36585f757f3fSDimitry Andric 36595f757f3fSDimitry Andric Success = checkForAllInstructionsImpl( 36605f757f3fSDimitry Andric nullptr, OpcodeInstMap, AAAllocationInfoPred, nullptr, nullptr, 36615f757f3fSDimitry Andric {(unsigned)Instruction::Alloca}, UsedAssumedInformation); 36625f757f3fSDimitry Andric assert(Success && "Expected the check call to be successful!"); 36635f757f3fSDimitry Andric } 36645f757f3fSDimitry Andric 36655f757f3fSDimitry Andric bool Attributor::isClosedWorldModule() const { 36665f757f3fSDimitry Andric if (CloseWorldAssumption.getNumOccurrences()) 36675f757f3fSDimitry Andric return CloseWorldAssumption; 36685f757f3fSDimitry Andric return isModulePass() && Configuration.IsClosedWorldModule; 36690b57cec5SDimitry Andric } 36700b57cec5SDimitry Andric 36710b57cec5SDimitry Andric /// Helpers to ease debugging through output streams and print calls. 36720b57cec5SDimitry Andric /// 36730b57cec5SDimitry Andric ///{ 36740b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) { 36750b57cec5SDimitry Andric return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged"); 36760b57cec5SDimitry Andric } 36770b57cec5SDimitry Andric 36788bcb0991SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) { 36790b57cec5SDimitry Andric switch (AP) { 36808bcb0991SDimitry Andric case IRPosition::IRP_INVALID: 36818bcb0991SDimitry Andric return OS << "inv"; 36828bcb0991SDimitry Andric case IRPosition::IRP_FLOAT: 36838bcb0991SDimitry Andric return OS << "flt"; 36848bcb0991SDimitry Andric case IRPosition::IRP_RETURNED: 36850b57cec5SDimitry Andric return OS << "fn_ret"; 36868bcb0991SDimitry Andric case IRPosition::IRP_CALL_SITE_RETURNED: 36878bcb0991SDimitry Andric return OS << "cs_ret"; 36888bcb0991SDimitry Andric case IRPosition::IRP_FUNCTION: 36898bcb0991SDimitry Andric return OS << "fn"; 36908bcb0991SDimitry Andric case IRPosition::IRP_CALL_SITE: 36918bcb0991SDimitry Andric return OS << "cs"; 36928bcb0991SDimitry Andric case IRPosition::IRP_ARGUMENT: 36938bcb0991SDimitry Andric return OS << "arg"; 36948bcb0991SDimitry Andric case IRPosition::IRP_CALL_SITE_ARGUMENT: 36958bcb0991SDimitry Andric return OS << "cs_arg"; 36960b57cec5SDimitry Andric } 36970b57cec5SDimitry Andric llvm_unreachable("Unknown attribute position!"); 36980b57cec5SDimitry Andric } 36990b57cec5SDimitry Andric 37008bcb0991SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) { 37018bcb0991SDimitry Andric const Value &AV = Pos.getAssociatedValue(); 3702fe6060f1SDimitry Andric OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " [" 3703fe6060f1SDimitry Andric << Pos.getAnchorValue().getName() << "@" << Pos.getCallSiteArgNo() << "]"; 3704fe6060f1SDimitry Andric 3705fe6060f1SDimitry Andric if (Pos.hasCallBaseContext()) 3706fe6060f1SDimitry Andric OS << "[cb_context:" << *Pos.getCallBaseContext() << "]"; 3707fe6060f1SDimitry Andric return OS << "}"; 37088bcb0991SDimitry Andric } 37098bcb0991SDimitry Andric 3710480093f4SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerRangeState &S) { 3711480093f4SDimitry Andric OS << "range-state(" << S.getBitWidth() << ")<"; 3712480093f4SDimitry Andric S.getKnown().print(OS); 3713480093f4SDimitry Andric OS << " / "; 3714480093f4SDimitry Andric S.getAssumed().print(OS); 3715480093f4SDimitry Andric OS << ">"; 3716480093f4SDimitry Andric 3717480093f4SDimitry Andric return OS << static_cast<const AbstractState &>(S); 3718480093f4SDimitry Andric } 3719480093f4SDimitry Andric 37200b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) { 37210b57cec5SDimitry Andric return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : "")); 37220b57cec5SDimitry Andric } 37230b57cec5SDimitry Andric 37240b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) { 37250b57cec5SDimitry Andric AA.print(OS); 37260b57cec5SDimitry Andric return OS; 37270b57cec5SDimitry Andric } 37280b57cec5SDimitry Andric 3729e8d8bef9SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, 3730e8d8bef9SDimitry Andric const PotentialConstantIntValuesState &S) { 3731e8d8bef9SDimitry Andric OS << "set-state(< {"; 3732e8d8bef9SDimitry Andric if (!S.isValidState()) 3733e8d8bef9SDimitry Andric OS << "full-set"; 3734e8d8bef9SDimitry Andric else { 3735bdd1243dSDimitry Andric for (const auto &It : S.getAssumedSet()) 373681ad6265SDimitry Andric OS << It << ", "; 3737e8d8bef9SDimitry Andric if (S.undefIsContained()) 3738e8d8bef9SDimitry Andric OS << "undef "; 3739e8d8bef9SDimitry Andric } 3740e8d8bef9SDimitry Andric OS << "} >)"; 3741e8d8bef9SDimitry Andric 3742e8d8bef9SDimitry Andric return OS; 3743e8d8bef9SDimitry Andric } 3744e8d8bef9SDimitry Andric 3745fcaf7f86SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, 3746fcaf7f86SDimitry Andric const PotentialLLVMValuesState &S) { 3747fcaf7f86SDimitry Andric OS << "set-state(< {"; 3748fcaf7f86SDimitry Andric if (!S.isValidState()) 3749fcaf7f86SDimitry Andric OS << "full-set"; 3750fcaf7f86SDimitry Andric else { 3751bdd1243dSDimitry Andric for (const auto &It : S.getAssumedSet()) { 3752fcaf7f86SDimitry Andric if (auto *F = dyn_cast<Function>(It.first.getValue())) 3753fcaf7f86SDimitry Andric OS << "@" << F->getName() << "[" << int(It.second) << "], "; 3754fcaf7f86SDimitry Andric else 3755fcaf7f86SDimitry Andric OS << *It.first.getValue() << "[" << int(It.second) << "], "; 3756fcaf7f86SDimitry Andric } 3757fcaf7f86SDimitry Andric if (S.undefIsContained()) 3758fcaf7f86SDimitry Andric OS << "undef "; 3759fcaf7f86SDimitry Andric } 3760fcaf7f86SDimitry Andric OS << "} >)"; 3761fcaf7f86SDimitry Andric 3762fcaf7f86SDimitry Andric return OS; 3763fcaf7f86SDimitry Andric } 3764fcaf7f86SDimitry Andric 376506c3fb27SDimitry Andric void AbstractAttribute::print(Attributor *A, raw_ostream &OS) const { 3766e8d8bef9SDimitry Andric OS << "["; 3767e8d8bef9SDimitry Andric OS << getName(); 3768e8d8bef9SDimitry Andric OS << "] for CtxI "; 3769e8d8bef9SDimitry Andric 3770e8d8bef9SDimitry Andric if (auto *I = getCtxI()) { 3771e8d8bef9SDimitry Andric OS << "'"; 3772e8d8bef9SDimitry Andric I->print(OS); 3773e8d8bef9SDimitry Andric OS << "'"; 3774e8d8bef9SDimitry Andric } else 3775e8d8bef9SDimitry Andric OS << "<<null inst>>"; 3776e8d8bef9SDimitry Andric 377706c3fb27SDimitry Andric OS << " at position " << getIRPosition() << " with state " << getAsStr(A) 3778e8d8bef9SDimitry Andric << '\n'; 3779e8d8bef9SDimitry Andric } 3780e8d8bef9SDimitry Andric 3781e8d8bef9SDimitry Andric void AbstractAttribute::printWithDeps(raw_ostream &OS) const { 3782e8d8bef9SDimitry Andric print(OS); 3783e8d8bef9SDimitry Andric 3784e8d8bef9SDimitry Andric for (const auto &DepAA : Deps) { 3785e8d8bef9SDimitry Andric auto *AA = DepAA.getPointer(); 3786e8d8bef9SDimitry Andric OS << " updates "; 3787e8d8bef9SDimitry Andric AA->print(OS); 3788e8d8bef9SDimitry Andric } 3789e8d8bef9SDimitry Andric 3790e8d8bef9SDimitry Andric OS << '\n'; 37910b57cec5SDimitry Andric } 3792fe6060f1SDimitry Andric 3793fe6060f1SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, 3794fe6060f1SDimitry Andric const AAPointerInfo::Access &Acc) { 3795fe6060f1SDimitry Andric OS << " [" << Acc.getKind() << "] " << *Acc.getRemoteInst(); 3796fe6060f1SDimitry Andric if (Acc.getLocalInst() != Acc.getRemoteInst()) 3797fe6060f1SDimitry Andric OS << " via " << *Acc.getLocalInst(); 379881ad6265SDimitry Andric if (Acc.getContent()) { 379981ad6265SDimitry Andric if (*Acc.getContent()) 380081ad6265SDimitry Andric OS << " [" << **Acc.getContent() << "]"; 380181ad6265SDimitry Andric else 380281ad6265SDimitry Andric OS << " [ <unknown> ]"; 380381ad6265SDimitry Andric } 3804fe6060f1SDimitry Andric return OS; 3805fe6060f1SDimitry Andric } 38060b57cec5SDimitry Andric ///} 38070b57cec5SDimitry Andric 38080b57cec5SDimitry Andric /// ---------------------------------------------------------------------------- 38090b57cec5SDimitry Andric /// Pass (Manager) Boilerplate 38100b57cec5SDimitry Andric /// ---------------------------------------------------------------------------- 38110b57cec5SDimitry Andric 38125ffd83dbSDimitry Andric static bool runAttributorOnFunctions(InformationCache &InfoCache, 38135ffd83dbSDimitry Andric SetVector<Function *> &Functions, 38145ffd83dbSDimitry Andric AnalysisGetter &AG, 3815fe6060f1SDimitry Andric CallGraphUpdater &CGUpdater, 381681ad6265SDimitry Andric bool DeleteFns, bool IsModulePass) { 38175ffd83dbSDimitry Andric if (Functions.empty()) 38180b57cec5SDimitry Andric return false; 38190b57cec5SDimitry Andric 3820fe6060f1SDimitry Andric LLVM_DEBUG({ 3821fe6060f1SDimitry Andric dbgs() << "[Attributor] Run on module with " << Functions.size() 3822fe6060f1SDimitry Andric << " functions:\n"; 3823fe6060f1SDimitry Andric for (Function *Fn : Functions) 3824fe6060f1SDimitry Andric dbgs() << " - " << Fn->getName() << "\n"; 3825fe6060f1SDimitry Andric }); 38260b57cec5SDimitry Andric 38270b57cec5SDimitry Andric // Create an Attributor and initially empty information cache that is filled 38280b57cec5SDimitry Andric // while we identify default attribute opportunities. 382981ad6265SDimitry Andric AttributorConfig AC(CGUpdater); 383081ad6265SDimitry Andric AC.IsModulePass = IsModulePass; 383181ad6265SDimitry Andric AC.DeleteFns = DeleteFns; 38325f757f3fSDimitry Andric 38335f757f3fSDimitry Andric /// Tracking callback for specialization of indirect calls. 38345f757f3fSDimitry Andric DenseMap<CallBase *, std::unique_ptr<SmallPtrSet<Function *, 8>>> 38355f757f3fSDimitry Andric IndirectCalleeTrackingMap; 38365f757f3fSDimitry Andric if (MaxSpecializationPerCB.getNumOccurrences()) { 38375f757f3fSDimitry Andric AC.IndirectCalleeSpecializationCallback = 38385f757f3fSDimitry Andric [&](Attributor &, const AbstractAttribute &AA, CallBase &CB, 38395f757f3fSDimitry Andric Function &Callee) { 38405f757f3fSDimitry Andric if (MaxSpecializationPerCB == 0) 38415f757f3fSDimitry Andric return false; 38425f757f3fSDimitry Andric auto &Set = IndirectCalleeTrackingMap[&CB]; 38435f757f3fSDimitry Andric if (!Set) 38445f757f3fSDimitry Andric Set = std::make_unique<SmallPtrSet<Function *, 8>>(); 38455f757f3fSDimitry Andric if (Set->size() >= MaxSpecializationPerCB) 38465f757f3fSDimitry Andric return Set->contains(&Callee); 38475f757f3fSDimitry Andric Set->insert(&Callee); 38485f757f3fSDimitry Andric return true; 38495f757f3fSDimitry Andric }; 38505f757f3fSDimitry Andric } 38515f757f3fSDimitry Andric 385281ad6265SDimitry Andric Attributor A(Functions, InfoCache, AC); 38538bcb0991SDimitry Andric 38545ffd83dbSDimitry Andric // Create shallow wrappers for all functions that are not IPO amendable 38555ffd83dbSDimitry Andric if (AllowShallowWrappers) 38565ffd83dbSDimitry Andric for (Function *F : Functions) 38575ffd83dbSDimitry Andric if (!A.isFunctionIPOAmendable(*F)) 3858e8d8bef9SDimitry Andric Attributor::createShallowWrapper(*F); 3859e8d8bef9SDimitry Andric 3860e8d8bef9SDimitry Andric // Internalize non-exact functions 3861e8d8bef9SDimitry Andric // TODO: for now we eagerly internalize functions without calculating the 3862e8d8bef9SDimitry Andric // cost, we need a cost interface to determine whether internalizing 3863bdd1243dSDimitry Andric // a function is "beneficial" 3864e8d8bef9SDimitry Andric if (AllowDeepWrapper) { 3865e8d8bef9SDimitry Andric unsigned FunSize = Functions.size(); 3866e8d8bef9SDimitry Andric for (unsigned u = 0; u < FunSize; u++) { 3867e8d8bef9SDimitry Andric Function *F = Functions[u]; 3868e8d8bef9SDimitry Andric if (!F->isDeclaration() && !F->isDefinitionExact() && F->getNumUses() && 3869e8d8bef9SDimitry Andric !GlobalValue::isInterposableLinkage(F->getLinkage())) { 3870fe6060f1SDimitry Andric Function *NewF = Attributor::internalizeFunction(*F); 3871fe6060f1SDimitry Andric assert(NewF && "Could not internalize function."); 3872e8d8bef9SDimitry Andric Functions.insert(NewF); 3873e8d8bef9SDimitry Andric 3874e8d8bef9SDimitry Andric // Update call graph 3875e8d8bef9SDimitry Andric CGUpdater.replaceFunctionWith(*F, *NewF); 3876e8d8bef9SDimitry Andric for (const Use &U : NewF->uses()) 3877e8d8bef9SDimitry Andric if (CallBase *CB = dyn_cast<CallBase>(U.getUser())) { 3878e8d8bef9SDimitry Andric auto *CallerF = CB->getCaller(); 3879e8d8bef9SDimitry Andric CGUpdater.reanalyzeFunction(*CallerF); 3880e8d8bef9SDimitry Andric } 3881e8d8bef9SDimitry Andric } 3882e8d8bef9SDimitry Andric } 3883e8d8bef9SDimitry Andric } 38840b57cec5SDimitry Andric 38855ffd83dbSDimitry Andric for (Function *F : Functions) { 38865ffd83dbSDimitry Andric if (F->hasExactDefinition()) 38878bcb0991SDimitry Andric NumFnWithExactDefinition++; 38888bcb0991SDimitry Andric else 38890b57cec5SDimitry Andric NumFnWithoutExactDefinition++; 38908bcb0991SDimitry Andric 38918bcb0991SDimitry Andric // We look at internal functions only on-demand but if any use is not a 3892e8d8bef9SDimitry Andric // direct call or outside the current set of analyzed functions, we have 3893e8d8bef9SDimitry Andric // to do it eagerly. 38945ffd83dbSDimitry Andric if (F->hasLocalLinkage()) { 38955ffd83dbSDimitry Andric if (llvm::all_of(F->uses(), [&Functions](const Use &U) { 38965ffd83dbSDimitry Andric const auto *CB = dyn_cast<CallBase>(U.getUser()); 38975ffd83dbSDimitry Andric return CB && CB->isCallee(&U) && 38985ffd83dbSDimitry Andric Functions.count(const_cast<Function *>(CB->getCaller())); 38998bcb0991SDimitry Andric })) 39000b57cec5SDimitry Andric continue; 39010b57cec5SDimitry Andric } 39020b57cec5SDimitry Andric 39030b57cec5SDimitry Andric // Populate the Attributor with abstract attribute opportunities in the 39040b57cec5SDimitry Andric // function and the information cache with IR information. 39055ffd83dbSDimitry Andric A.identifyDefaultAbstractAttributes(*F); 39060b57cec5SDimitry Andric } 39070b57cec5SDimitry Andric 39085ffd83dbSDimitry Andric ChangeStatus Changed = A.run(); 3909e8d8bef9SDimitry Andric 39105ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size() 39115ffd83dbSDimitry Andric << " functions, result: " << Changed << ".\n"); 39125ffd83dbSDimitry Andric return Changed == ChangeStatus::CHANGED; 39130b57cec5SDimitry Andric } 39140b57cec5SDimitry Andric 39155f757f3fSDimitry Andric static bool runAttributorLightOnFunctions(InformationCache &InfoCache, 39165f757f3fSDimitry Andric SetVector<Function *> &Functions, 39175f757f3fSDimitry Andric AnalysisGetter &AG, 39185f757f3fSDimitry Andric CallGraphUpdater &CGUpdater, 39195f757f3fSDimitry Andric FunctionAnalysisManager &FAM, 39205f757f3fSDimitry Andric bool IsModulePass) { 39215f757f3fSDimitry Andric if (Functions.empty()) 39225f757f3fSDimitry Andric return false; 39235f757f3fSDimitry Andric 39245f757f3fSDimitry Andric LLVM_DEBUG({ 39255f757f3fSDimitry Andric dbgs() << "[AttributorLight] Run on module with " << Functions.size() 39265f757f3fSDimitry Andric << " functions:\n"; 39275f757f3fSDimitry Andric for (Function *Fn : Functions) 39285f757f3fSDimitry Andric dbgs() << " - " << Fn->getName() << "\n"; 39295f757f3fSDimitry Andric }); 39305f757f3fSDimitry Andric 39315f757f3fSDimitry Andric // Create an Attributor and initially empty information cache that is filled 39325f757f3fSDimitry Andric // while we identify default attribute opportunities. 39335f757f3fSDimitry Andric AttributorConfig AC(CGUpdater); 39345f757f3fSDimitry Andric AC.IsModulePass = IsModulePass; 39355f757f3fSDimitry Andric AC.DeleteFns = false; 39365f757f3fSDimitry Andric DenseSet<const char *> Allowed( 39375f757f3fSDimitry Andric {&AAWillReturn::ID, &AANoUnwind::ID, &AANoRecurse::ID, &AANoSync::ID, 39385f757f3fSDimitry Andric &AANoFree::ID, &AANoReturn::ID, &AAMemoryLocation::ID, 39395f757f3fSDimitry Andric &AAMemoryBehavior::ID, &AAUnderlyingObjects::ID, &AANoCapture::ID, 39405f757f3fSDimitry Andric &AAInterFnReachability::ID, &AAIntraFnReachability::ID, &AACallEdges::ID, 39415f757f3fSDimitry Andric &AANoFPClass::ID, &AAMustProgress::ID, &AANonNull::ID}); 39425f757f3fSDimitry Andric AC.Allowed = &Allowed; 39435f757f3fSDimitry Andric AC.UseLiveness = false; 39445f757f3fSDimitry Andric 39455f757f3fSDimitry Andric Attributor A(Functions, InfoCache, AC); 39465f757f3fSDimitry Andric 39475f757f3fSDimitry Andric for (Function *F : Functions) { 39485f757f3fSDimitry Andric if (F->hasExactDefinition()) 39495f757f3fSDimitry Andric NumFnWithExactDefinition++; 39505f757f3fSDimitry Andric else 39515f757f3fSDimitry Andric NumFnWithoutExactDefinition++; 39525f757f3fSDimitry Andric 39535f757f3fSDimitry Andric // We look at internal functions only on-demand but if any use is not a 39545f757f3fSDimitry Andric // direct call or outside the current set of analyzed functions, we have 39555f757f3fSDimitry Andric // to do it eagerly. 3956*0fca6ea1SDimitry Andric if (AC.UseLiveness && F->hasLocalLinkage()) { 39575f757f3fSDimitry Andric if (llvm::all_of(F->uses(), [&Functions](const Use &U) { 39585f757f3fSDimitry Andric const auto *CB = dyn_cast<CallBase>(U.getUser()); 39595f757f3fSDimitry Andric return CB && CB->isCallee(&U) && 39605f757f3fSDimitry Andric Functions.count(const_cast<Function *>(CB->getCaller())); 39615f757f3fSDimitry Andric })) 39625f757f3fSDimitry Andric continue; 39635f757f3fSDimitry Andric } 39645f757f3fSDimitry Andric 39655f757f3fSDimitry Andric // Populate the Attributor with abstract attribute opportunities in the 39665f757f3fSDimitry Andric // function and the information cache with IR information. 39675f757f3fSDimitry Andric A.identifyDefaultAbstractAttributes(*F); 39685f757f3fSDimitry Andric } 39695f757f3fSDimitry Andric 39705f757f3fSDimitry Andric ChangeStatus Changed = A.run(); 39715f757f3fSDimitry Andric 39725f757f3fSDimitry Andric if (Changed == ChangeStatus::CHANGED) { 39735f757f3fSDimitry Andric // Invalidate analyses for modified functions so that we don't have to 39745f757f3fSDimitry Andric // invalidate all analyses for all functions in this SCC. 39755f757f3fSDimitry Andric PreservedAnalyses FuncPA; 39765f757f3fSDimitry Andric // We haven't changed the CFG for modified functions. 39775f757f3fSDimitry Andric FuncPA.preserveSet<CFGAnalyses>(); 39785f757f3fSDimitry Andric for (Function *Changed : A.getModifiedFunctions()) { 39795f757f3fSDimitry Andric FAM.invalidate(*Changed, FuncPA); 39805f757f3fSDimitry Andric // Also invalidate any direct callers of changed functions since analyses 39815f757f3fSDimitry Andric // may care about attributes of direct callees. For example, MemorySSA 39825f757f3fSDimitry Andric // cares about whether or not a call's callee modifies memory and queries 39835f757f3fSDimitry Andric // that through function attributes. 39845f757f3fSDimitry Andric for (auto *U : Changed->users()) { 39855f757f3fSDimitry Andric if (auto *Call = dyn_cast<CallBase>(U)) { 39865f757f3fSDimitry Andric if (Call->getCalledFunction() == Changed) 39875f757f3fSDimitry Andric FAM.invalidate(*Call->getFunction(), FuncPA); 39885f757f3fSDimitry Andric } 39895f757f3fSDimitry Andric } 39905f757f3fSDimitry Andric } 39915f757f3fSDimitry Andric } 39925f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size() 39935f757f3fSDimitry Andric << " functions, result: " << Changed << ".\n"); 39945f757f3fSDimitry Andric return Changed == ChangeStatus::CHANGED; 39955f757f3fSDimitry Andric } 39965f757f3fSDimitry Andric 3997e8d8bef9SDimitry Andric void AADepGraph::viewGraph() { llvm::ViewGraph(this, "Dependency Graph"); } 3998e8d8bef9SDimitry Andric 3999e8d8bef9SDimitry Andric void AADepGraph::dumpGraph() { 4000e8d8bef9SDimitry Andric static std::atomic<int> CallTimes; 4001e8d8bef9SDimitry Andric std::string Prefix; 4002e8d8bef9SDimitry Andric 4003e8d8bef9SDimitry Andric if (!DepGraphDotFileNamePrefix.empty()) 4004e8d8bef9SDimitry Andric Prefix = DepGraphDotFileNamePrefix; 4005e8d8bef9SDimitry Andric else 4006e8d8bef9SDimitry Andric Prefix = "dep_graph"; 4007e8d8bef9SDimitry Andric std::string Filename = 4008e8d8bef9SDimitry Andric Prefix + "_" + std::to_string(CallTimes.load()) + ".dot"; 4009e8d8bef9SDimitry Andric 4010e8d8bef9SDimitry Andric outs() << "Dependency graph dump to " << Filename << ".\n"; 4011e8d8bef9SDimitry Andric 4012e8d8bef9SDimitry Andric std::error_code EC; 4013e8d8bef9SDimitry Andric 4014fe6060f1SDimitry Andric raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF); 4015e8d8bef9SDimitry Andric if (!EC) 4016e8d8bef9SDimitry Andric llvm::WriteGraph(File, this); 4017e8d8bef9SDimitry Andric 4018e8d8bef9SDimitry Andric CallTimes++; 4019e8d8bef9SDimitry Andric } 4020e8d8bef9SDimitry Andric 4021e8d8bef9SDimitry Andric void AADepGraph::print() { 4022e8d8bef9SDimitry Andric for (auto DepAA : SyntheticRoot.Deps) 4023e8d8bef9SDimitry Andric cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(outs()); 4024e8d8bef9SDimitry Andric } 4025e8d8bef9SDimitry Andric 40260b57cec5SDimitry Andric PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) { 40275ffd83dbSDimitry Andric FunctionAnalysisManager &FAM = 40285ffd83dbSDimitry Andric AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 40295ffd83dbSDimitry Andric AnalysisGetter AG(FAM); 40305ffd83dbSDimitry Andric 40315ffd83dbSDimitry Andric SetVector<Function *> Functions; 40325ffd83dbSDimitry Andric for (Function &F : M) 40335ffd83dbSDimitry Andric Functions.insert(&F); 40345ffd83dbSDimitry Andric 40355ffd83dbSDimitry Andric CallGraphUpdater CGUpdater; 40365ffd83dbSDimitry Andric BumpPtrAllocator Allocator; 40375ffd83dbSDimitry Andric InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr); 4038fe6060f1SDimitry Andric if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater, 403981ad6265SDimitry Andric /* DeleteFns */ true, /* IsModulePass */ true)) { 40405ffd83dbSDimitry Andric // FIXME: Think about passes we will preserve and add them here. 40415ffd83dbSDimitry Andric return PreservedAnalyses::none(); 40425ffd83dbSDimitry Andric } 40435ffd83dbSDimitry Andric return PreservedAnalyses::all(); 40445ffd83dbSDimitry Andric } 40455ffd83dbSDimitry Andric 40465ffd83dbSDimitry Andric PreservedAnalyses AttributorCGSCCPass::run(LazyCallGraph::SCC &C, 40475ffd83dbSDimitry Andric CGSCCAnalysisManager &AM, 40485ffd83dbSDimitry Andric LazyCallGraph &CG, 40495ffd83dbSDimitry Andric CGSCCUpdateResult &UR) { 40505ffd83dbSDimitry Andric FunctionAnalysisManager &FAM = 40515ffd83dbSDimitry Andric AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); 40525ffd83dbSDimitry Andric AnalysisGetter AG(FAM); 40535ffd83dbSDimitry Andric 40545ffd83dbSDimitry Andric SetVector<Function *> Functions; 40555ffd83dbSDimitry Andric for (LazyCallGraph::Node &N : C) 40565ffd83dbSDimitry Andric Functions.insert(&N.getFunction()); 40575ffd83dbSDimitry Andric 40585ffd83dbSDimitry Andric if (Functions.empty()) 40595ffd83dbSDimitry Andric return PreservedAnalyses::all(); 40605ffd83dbSDimitry Andric 40615ffd83dbSDimitry Andric Module &M = *Functions.back()->getParent(); 40625ffd83dbSDimitry Andric CallGraphUpdater CGUpdater; 40635ffd83dbSDimitry Andric CGUpdater.initialize(CG, C, AM, UR); 40645ffd83dbSDimitry Andric BumpPtrAllocator Allocator; 40655ffd83dbSDimitry Andric InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ &Functions); 4066fe6060f1SDimitry Andric if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater, 406781ad6265SDimitry Andric /* DeleteFns */ false, 406881ad6265SDimitry Andric /* IsModulePass */ false)) { 40690b57cec5SDimitry Andric // FIXME: Think about passes we will preserve and add them here. 4070e8d8bef9SDimitry Andric PreservedAnalyses PA; 4071e8d8bef9SDimitry Andric PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 4072e8d8bef9SDimitry Andric return PA; 40730b57cec5SDimitry Andric } 40740b57cec5SDimitry Andric return PreservedAnalyses::all(); 40750b57cec5SDimitry Andric } 40760b57cec5SDimitry Andric 40775f757f3fSDimitry Andric PreservedAnalyses AttributorLightPass::run(Module &M, 40785f757f3fSDimitry Andric ModuleAnalysisManager &AM) { 40795f757f3fSDimitry Andric FunctionAnalysisManager &FAM = 40805f757f3fSDimitry Andric AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 40815f757f3fSDimitry Andric AnalysisGetter AG(FAM, /* CachedOnly */ true); 40825f757f3fSDimitry Andric 40835f757f3fSDimitry Andric SetVector<Function *> Functions; 40845f757f3fSDimitry Andric for (Function &F : M) 40855f757f3fSDimitry Andric Functions.insert(&F); 40865f757f3fSDimitry Andric 40875f757f3fSDimitry Andric CallGraphUpdater CGUpdater; 40885f757f3fSDimitry Andric BumpPtrAllocator Allocator; 40895f757f3fSDimitry Andric InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr); 40905f757f3fSDimitry Andric if (runAttributorLightOnFunctions(InfoCache, Functions, AG, CGUpdater, FAM, 40915f757f3fSDimitry Andric /* IsModulePass */ true)) { 40925f757f3fSDimitry Andric PreservedAnalyses PA; 40935f757f3fSDimitry Andric // We have not added or removed functions. 40945f757f3fSDimitry Andric PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 40955f757f3fSDimitry Andric // We already invalidated all relevant function analyses above. 40965f757f3fSDimitry Andric PA.preserveSet<AllAnalysesOn<Function>>(); 40975f757f3fSDimitry Andric return PA; 40985f757f3fSDimitry Andric } 40995f757f3fSDimitry Andric return PreservedAnalyses::all(); 41005f757f3fSDimitry Andric } 41015f757f3fSDimitry Andric 41025f757f3fSDimitry Andric PreservedAnalyses AttributorLightCGSCCPass::run(LazyCallGraph::SCC &C, 41035f757f3fSDimitry Andric CGSCCAnalysisManager &AM, 41045f757f3fSDimitry Andric LazyCallGraph &CG, 41055f757f3fSDimitry Andric CGSCCUpdateResult &UR) { 41065f757f3fSDimitry Andric FunctionAnalysisManager &FAM = 41075f757f3fSDimitry Andric AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); 41085f757f3fSDimitry Andric AnalysisGetter AG(FAM); 41095f757f3fSDimitry Andric 41105f757f3fSDimitry Andric SetVector<Function *> Functions; 41115f757f3fSDimitry Andric for (LazyCallGraph::Node &N : C) 41125f757f3fSDimitry Andric Functions.insert(&N.getFunction()); 41135f757f3fSDimitry Andric 41145f757f3fSDimitry Andric if (Functions.empty()) 41155f757f3fSDimitry Andric return PreservedAnalyses::all(); 41165f757f3fSDimitry Andric 41175f757f3fSDimitry Andric Module &M = *Functions.back()->getParent(); 41185f757f3fSDimitry Andric CallGraphUpdater CGUpdater; 41195f757f3fSDimitry Andric CGUpdater.initialize(CG, C, AM, UR); 41205f757f3fSDimitry Andric BumpPtrAllocator Allocator; 41215f757f3fSDimitry Andric InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ &Functions); 41225f757f3fSDimitry Andric if (runAttributorLightOnFunctions(InfoCache, Functions, AG, CGUpdater, FAM, 41235f757f3fSDimitry Andric /* IsModulePass */ false)) { 41245f757f3fSDimitry Andric PreservedAnalyses PA; 41255f757f3fSDimitry Andric // We have not added or removed functions. 41265f757f3fSDimitry Andric PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 41275f757f3fSDimitry Andric // We already invalidated all relevant function analyses above. 41285f757f3fSDimitry Andric PA.preserveSet<AllAnalysesOn<Function>>(); 41295f757f3fSDimitry Andric return PA; 41305f757f3fSDimitry Andric } 41315f757f3fSDimitry Andric return PreservedAnalyses::all(); 41325f757f3fSDimitry Andric } 4133e8d8bef9SDimitry Andric namespace llvm { 4134e8d8bef9SDimitry Andric 4135e8d8bef9SDimitry Andric template <> struct GraphTraits<AADepGraphNode *> { 4136e8d8bef9SDimitry Andric using NodeRef = AADepGraphNode *; 4137e8d8bef9SDimitry Andric using DepTy = PointerIntPair<AADepGraphNode *, 1>; 4138e8d8bef9SDimitry Andric using EdgeRef = PointerIntPair<AADepGraphNode *, 1>; 4139e8d8bef9SDimitry Andric 4140e8d8bef9SDimitry Andric static NodeRef getEntryNode(AADepGraphNode *DGN) { return DGN; } 414106c3fb27SDimitry Andric static NodeRef DepGetVal(const DepTy &DT) { return DT.getPointer(); } 4142e8d8bef9SDimitry Andric 4143e8d8bef9SDimitry Andric using ChildIteratorType = 414406c3fb27SDimitry Andric mapped_iterator<AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)>; 414506c3fb27SDimitry Andric using ChildEdgeIteratorType = AADepGraphNode::DepSetTy::iterator; 4146e8d8bef9SDimitry Andric 4147e8d8bef9SDimitry Andric static ChildIteratorType child_begin(NodeRef N) { return N->child_begin(); } 4148e8d8bef9SDimitry Andric 4149e8d8bef9SDimitry Andric static ChildIteratorType child_end(NodeRef N) { return N->child_end(); } 4150e8d8bef9SDimitry Andric }; 4151e8d8bef9SDimitry Andric 4152e8d8bef9SDimitry Andric template <> 4153e8d8bef9SDimitry Andric struct GraphTraits<AADepGraph *> : public GraphTraits<AADepGraphNode *> { 4154e8d8bef9SDimitry Andric static NodeRef getEntryNode(AADepGraph *DG) { return DG->GetEntryNode(); } 4155e8d8bef9SDimitry Andric 4156e8d8bef9SDimitry Andric using nodes_iterator = 415706c3fb27SDimitry Andric mapped_iterator<AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)>; 4158e8d8bef9SDimitry Andric 4159e8d8bef9SDimitry Andric static nodes_iterator nodes_begin(AADepGraph *DG) { return DG->begin(); } 4160e8d8bef9SDimitry Andric 4161e8d8bef9SDimitry Andric static nodes_iterator nodes_end(AADepGraph *DG) { return DG->end(); } 4162e8d8bef9SDimitry Andric }; 4163e8d8bef9SDimitry Andric 4164e8d8bef9SDimitry Andric template <> struct DOTGraphTraits<AADepGraph *> : public DefaultDOTGraphTraits { 4165e8d8bef9SDimitry Andric DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} 4166e8d8bef9SDimitry Andric 4167e8d8bef9SDimitry Andric static std::string getNodeLabel(const AADepGraphNode *Node, 4168e8d8bef9SDimitry Andric const AADepGraph *DG) { 4169e8d8bef9SDimitry Andric std::string AAString; 4170e8d8bef9SDimitry Andric raw_string_ostream O(AAString); 4171e8d8bef9SDimitry Andric Node->print(O); 4172e8d8bef9SDimitry Andric return AAString; 4173e8d8bef9SDimitry Andric } 4174e8d8bef9SDimitry Andric }; 4175e8d8bef9SDimitry Andric 4176e8d8bef9SDimitry Andric } // end namespace llvm 4177