xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/IPO/Attributor.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 ///{
operator |(ChangeStatus L,ChangeStatus R)185e8d8bef9SDimitry Andric ChangeStatus llvm::operator|(ChangeStatus L, ChangeStatus R) {
186e8d8bef9SDimitry Andric   return L == ChangeStatus::CHANGED ? L : R;
1870b57cec5SDimitry Andric }
operator |=(ChangeStatus & L,ChangeStatus R)188fe6060f1SDimitry Andric ChangeStatus &llvm::operator|=(ChangeStatus &L, ChangeStatus R) {
189fe6060f1SDimitry Andric   L = L | R;
190fe6060f1SDimitry Andric   return L;
191fe6060f1SDimitry Andric }
operator &(ChangeStatus L,ChangeStatus R)192e8d8bef9SDimitry Andric ChangeStatus llvm::operator&(ChangeStatus L, ChangeStatus R) {
193e8d8bef9SDimitry Andric   return L == ChangeStatus::UNCHANGED ? L : R;
1940b57cec5SDimitry Andric }
operator &=(ChangeStatus & L,ChangeStatus R)195fe6060f1SDimitry Andric ChangeStatus &llvm::operator&=(ChangeStatus &L, ChangeStatus R) {
196fe6060f1SDimitry Andric   L = L & R;
197fe6060f1SDimitry Andric   return L;
198fe6060f1SDimitry Andric }
1990b57cec5SDimitry Andric ///}
2000b57cec5SDimitry Andric 
isGPU(const Module & M)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 
isNoSyncInst(Attributor & A,const Instruction & I,const AbstractAttribute & QueryingAA)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 
isDynamicallyUnique(Attributor & A,const AbstractAttribute & QueryingAA,const Value & V,bool ForAnalysisOnly)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 *
getInitialValueForObj(Attributor & A,const AbstractAttribute & QueryingAA,Value & Obj,Type & Ty,const TargetLibraryInfo * TLI,const DataLayout & DL,AA::RangeTy * RangePtr)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 
isValidInScope(const Value & V,const Function * Scope)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 
isValidAtPosition(const AA::ValueAndContext & VAC,InformationCache & InfoCache)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 
getWithType(Value & V,Type & Ty)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 *>
combineOptionalValuesInAAValueLatice(const std::optional<Value * > & A,const std::optional<Value * > & B,Type * Ty)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>
getPotentialCopiesOfMemoryValue(Attributor & A,Ty & I,SmallSetVector<Value *,4> & PotentialCopies,SmallSetVector<Instruction *,4> * PotentialValueOrigins,const AbstractAttribute & QueryingAA,bool & UsedAssumedInformation,bool OnlyExact)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 
getPotentiallyLoadedValues(Attributor & A,LoadInst & LI,SmallSetVector<Value *,4> & PotentialValues,SmallSetVector<Instruction *,4> & PotentialValueOrigins,const AbstractAttribute & QueryingAA,bool & UsedAssumedInformation,bool OnlyExact)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 
getPotentialCopiesOfStoredValue(Attributor & A,StoreInst & SI,SmallSetVector<Value *,4> & PotentialCopies,const AbstractAttribute & QueryingAA,bool & UsedAssumedInformation,bool OnlyExact)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 
isAssumedReadOnlyOrReadNone(Attributor & A,const IRPosition & IRP,const AbstractAttribute & QueryingAA,bool RequireReadNone,bool & IsKnown)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 
isAssumedReadOnly(Attributor & A,const IRPosition & IRP,const AbstractAttribute & QueryingAA,bool & IsKnown)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 }
isAssumedReadNone(Attributor & A,const IRPosition & IRP,const AbstractAttribute & QueryingAA,bool & IsKnown)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
isPotentiallyReachable(Attributor & A,const Instruction & FromI,const Instruction * ToI,const Function & ToFn,const AbstractAttribute & QueryingAA,const AA::InstExclusionSetTy * ExclusionSet,std::function<bool (const Function & F)> GoBackwardsCB)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 
isPotentiallyReachable(Attributor & A,const Instruction & FromI,const Instruction & ToI,const AbstractAttribute & QueryingAA,const AA::InstExclusionSetTy * ExclusionSet,std::function<bool (const Function & F)> GoBackwardsCB)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 
isPotentiallyReachable(Attributor & A,const Instruction & FromI,const Function & ToFn,const AbstractAttribute & QueryingAA,const AA::InstExclusionSetTy * ExclusionSet,std::function<bool (const Function & F)> GoBackwardsCB)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 
isAssumedThreadLocalObject(Attributor & A,Value & Obj,const AbstractAttribute & QueryingAA)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 
isPotentiallyAffectedByBarrier(Attributor & A,const Instruction & I,const AbstractAttribute & QueryingAA)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 
isPotentiallyAffectedByBarrier(Attributor & A,ArrayRef<const Value * > Ptrs,const AbstractAttribute & QueryingAA,const Instruction * CtxI)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.
isEqualOrWorse(const Attribute & New,const Attribute & 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.
addIfNotExistent(LLVMContext & Ctx,const Attribute & Attr,AttributeSet AttrSet,bool ForceReplace,AttrBuilder & AB)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 
getAssociatedArgument() const9965ffd83dbSDimitry 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 
update(Attributor & A)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 
Attributor(SetVector<Function * > & Functions,InformationCache & InfoCache,AttributorConfig Configuration)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 
getAttrsFromAssumes(const IRPosition & IRP,Attribute::AttrKind AK,SmallVectorImpl<Attribute> & Attrs)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
updateAttrMap(const IRPosition & IRP,ArrayRef<DescTy> AttrDescs,function_ref<bool (const DescTy &,AttributeSet,AttributeMask &,AttrBuilder &)> CB)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 
hasAttr(const IRPosition & IRP,ArrayRef<Attribute::AttrKind> AttrKinds,bool IgnoreSubsumingPositions,Attribute::AttrKind ImpliedAttributeKind)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 
getAttrs(const IRPosition & IRP,ArrayRef<Attribute::AttrKind> AttrKinds,SmallVectorImpl<Attribute> & Attrs,bool IgnoreSubsumingPositions)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 
removeAttrs(const IRPosition & IRP,ArrayRef<Attribute::AttrKind> AttrKinds)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 
removeAttrs(const IRPosition & IRP,ArrayRef<StringRef> Attrs)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 
manifestAttrs(const IRPosition & IRP,ArrayRef<Attribute> Attrs,bool ForceReplace)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 
SubsumingPositionIterator(const IRPosition & IRP)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 
verify()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 *>
getAssumedConstant(const IRPosition & IRP,const AbstractAttribute & AA,bool & UsedAssumedInformation)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 
getAssumedSimplified(const IRPosition & IRP,const AbstractAttribute * AA,bool & UsedAssumedInformation,AA::ValueScope S)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 
getAssumedSimplifiedValues(const IRPosition & InitialIRP,const AbstractAttribute * AA,SmallVectorImpl<AA::ValueAndContext> & Values,AA::ValueScope S,bool & UsedAssumedInformation,bool RecurseForSelectAndPHI)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 
translateArgumentToCallSiteContent(std::optional<Value * > V,CallBase & CB,const AbstractAttribute & AA,bool & UsedAssumedInformation)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 
~Attributor()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 
isAssumedDead(const AbstractAttribute & AA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass)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 
isAssumedDead(const Use & U,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass)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 
isAssumedDead(const Instruction & I,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass,bool CheckForDeadStore)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 
isAssumedDead(const IRPosition & IRP,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass)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 
isAssumedDead(const BasicBlock & BB,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,DepClassTy DepClass)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 
checkForAllCallees(function_ref<bool (ArrayRef<const Function * >)> Pred,const AbstractAttribute & QueryingAA,const CallBase & CB)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 
canMarkAsVisited(const User * Usr)1752*0fca6ea1SDimitry Andric bool canMarkAsVisited(const User *Usr) {
1753*0fca6ea1SDimitry Andric   return isa<PHINode>(Usr) || !isa<Instruction>(Usr);
1754*0fca6ea1SDimitry Andric }
1755*0fca6ea1SDimitry Andric 
checkForAllUses(function_ref<bool (const Use &,bool &)> Pred,const AbstractAttribute & QueryingAA,const Value & V,bool CheckBBLivenessOnly,DepClassTy LivenessDepClass,bool IgnoreDroppableUses,function_ref<bool (const Use & OldU,const Use & NewU)> EquivalentUseCB)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 
checkForAllCallSites(function_ref<bool (AbstractCallSite)> Pred,const AbstractAttribute & QueryingAA,bool RequireAllCallSites,bool & UsedAssumedInformation)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 
checkForAllCallSites(function_ref<bool (AbstractCallSite)> Pred,const Function & Fn,bool RequireAllCallSites,const AbstractAttribute * QueryingAA,bool & UsedAssumedInformation,bool CheckPotentiallyDead)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 
shouldPropagateCallBaseContext(const IRPosition & IRP)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 
checkForAllReturnedValues(function_ref<bool (Value &)> Pred,const AbstractAttribute & QueryingAA,AA::ValueScope S,bool RecurseForSelectAndPHI)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 
checkForAllInstructionsImpl(Attributor * A,InformationCache::OpcodeInstMapTy & OpcodeInstMap,function_ref<bool (Instruction &)> Pred,const AbstractAttribute * QueryingAA,const AAIsDead * LivenessAA,ArrayRef<unsigned> Opcodes,bool & UsedAssumedInformation,bool CheckBBLivenessOnly=false,bool CheckPotentiallyDead=false)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 
checkForAllInstructions(function_ref<bool (Instruction &)> Pred,const Function * Fn,const AbstractAttribute * QueryingAA,ArrayRef<unsigned> Opcodes,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,bool CheckPotentiallyDead)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 
checkForAllInstructions(function_ref<bool (Instruction &)> Pred,const AbstractAttribute & QueryingAA,ArrayRef<unsigned> Opcodes,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,bool CheckPotentiallyDead)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 
checkForAllReadWriteInstructions(function_ref<bool (Instruction &)> Pred,AbstractAttribute & QueryingAA,bool & UsedAssumedInformation)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 
runTillFixpoint()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 
registerForUpdate(AbstractAttribute & AA)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 
manifestAttributes()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 
identifyDeadInternalFunctions()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 
cleanupIR()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 
run()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 
updateAA(AbstractAttribute & AA)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 
createShallowWrapper(Function & F)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 
isInternalizable(Function & F)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 
internalizeFunction(Function & F,bool Force)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 
internalizeFunctions(SmallPtrSetImpl<Function * > & FnSet,DenseMap<Function *,Function * > & FnMap)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 
isValidFunctionSignatureRewrite(Argument & Arg,ArrayRef<Type * > ReplacementTypes)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 
registerFunctionSignatureRewrite(Argument & Arg,ArrayRef<Type * > ReplacementTypes,ArgumentReplacementInfo::CalleeRepairCBTy && CalleeRepairCB,ArgumentReplacementInfo::ACSRepairCBTy && ACSRepairCB)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 
shouldSeedAttribute(AbstractAttribute & AA)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 
rewriteFunctionSignatures(SmallSetVector<Function *,8> & ModifiedFns)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 
initializeInformationCache(const Function & CF,FunctionInfo & FI)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 
~FunctionInfo()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 *>
getIndirectlyCallableFunctions(Attributor & A) const33085f757f3fSDimitry Andric InformationCache::getIndirectlyCallableFunctions(Attributor &A) const {
33095f757f3fSDimitry Andric   assert(A.isClosedWorldModule() && "Cannot see all indirect callees!");
33105f757f3fSDimitry Andric   return IndirectlyCallableFunctions;
33115f757f3fSDimitry Andric }
33125f757f3fSDimitry Andric 
recordDependence(const AbstractAttribute & FromAA,const AbstractAttribute & ToAA,DepClassTy DepClass)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 
rememberDependences()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>
checkAndQueryIRAttr(const IRPosition & IRP,AttributeSet Attrs)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 
identifyDefaultAbstractAttributes(Function & F)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 
isClosedWorldModule() const36655f757f3fSDimitry 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 ///{
operator <<(raw_ostream & OS,ChangeStatus S)36740b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
36750b57cec5SDimitry Andric   return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
36760b57cec5SDimitry Andric }
36770b57cec5SDimitry Andric 
operator <<(raw_ostream & OS,IRPosition::Kind AP)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 
operator <<(raw_ostream & OS,const IRPosition & Pos)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 
operator <<(raw_ostream & OS,const IntegerRangeState & S)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 
operator <<(raw_ostream & OS,const AbstractState & S)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 
operator <<(raw_ostream & OS,const AbstractAttribute & AA)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 
operator <<(raw_ostream & OS,const PotentialConstantIntValuesState & S)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 
operator <<(raw_ostream & OS,const PotentialLLVMValuesState & S)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 
print(Attributor * A,raw_ostream & OS) const376506c3fb27SDimitry 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 
printWithDeps(raw_ostream & OS) const3781e8d8bef9SDimitry 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 
operator <<(raw_ostream & OS,const AAPointerInfo::Access & Acc)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 
runAttributorOnFunctions(InformationCache & InfoCache,SetVector<Function * > & Functions,AnalysisGetter & AG,CallGraphUpdater & CGUpdater,bool DeleteFns,bool IsModulePass)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 
runAttributorLightOnFunctions(InformationCache & InfoCache,SetVector<Function * > & Functions,AnalysisGetter & AG,CallGraphUpdater & CGUpdater,FunctionAnalysisManager & FAM,bool IsModulePass)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 
viewGraph()3997e8d8bef9SDimitry Andric void AADepGraph::viewGraph() { llvm::ViewGraph(this, "Dependency Graph"); }
3998e8d8bef9SDimitry Andric 
dumpGraph()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 
print()4021e8d8bef9SDimitry Andric void AADepGraph::print() {
4022e8d8bef9SDimitry Andric   for (auto DepAA : SyntheticRoot.Deps)
4023e8d8bef9SDimitry Andric     cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(outs());
4024e8d8bef9SDimitry Andric }
4025e8d8bef9SDimitry Andric 
run(Module & M,ModuleAnalysisManager & AM)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 
run(LazyCallGraph::SCC & C,CGSCCAnalysisManager & AM,LazyCallGraph & CG,CGSCCUpdateResult & UR)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 
run(Module & M,ModuleAnalysisManager & AM)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 
run(LazyCallGraph::SCC & C,CGSCCAnalysisManager & AM,LazyCallGraph & CG,CGSCCUpdateResult & UR)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 
getEntryNodellvm::GraphTraits4140e8d8bef9SDimitry Andric   static NodeRef getEntryNode(AADepGraphNode *DGN) { return DGN; }
DepGetValllvm::GraphTraits414106c3fb27SDimitry 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 
child_beginllvm::GraphTraits4147e8d8bef9SDimitry Andric   static ChildIteratorType child_begin(NodeRef N) { return N->child_begin(); }
4148e8d8bef9SDimitry Andric 
child_endllvm::GraphTraits4149e8d8bef9SDimitry 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 *> {
getEntryNodellvm::GraphTraits4154e8d8bef9SDimitry 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 
nodes_beginllvm::GraphTraits4159e8d8bef9SDimitry Andric   static nodes_iterator nodes_begin(AADepGraph *DG) { return DG->begin(); }
4160e8d8bef9SDimitry Andric 
nodes_endllvm::GraphTraits4161e8d8bef9SDimitry Andric   static nodes_iterator nodes_end(AADepGraph *DG) { return DG->end(); }
4162e8d8bef9SDimitry Andric };
4163e8d8bef9SDimitry Andric 
4164e8d8bef9SDimitry Andric template <> struct DOTGraphTraits<AADepGraph *> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits4165e8d8bef9SDimitry Andric   DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
4166e8d8bef9SDimitry Andric 
getNodeLabelllvm::DOTGraphTraits4167e8d8bef9SDimitry 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