1aade782aSJohannes Doerfert //===- Attributor.cpp - Module-wide attribute deduction -------------------===//
2aade782aSJohannes Doerfert //
3aade782aSJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4aade782aSJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information.
5aade782aSJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aade782aSJohannes Doerfert //
7aade782aSJohannes Doerfert //===----------------------------------------------------------------------===//
8aade782aSJohannes Doerfert //
906066c40SUday Bondhugula // This file implements an interprocedural pass that deduces and/or propagates
10aade782aSJohannes Doerfert // attributes. This is done in an abstract interpretation style fixpoint
11aade782aSJohannes Doerfert // iteration. See the Attributor.h file comment and the class descriptions in
12aade782aSJohannes Doerfert // that file for more information.
13aade782aSJohannes Doerfert //
14aade782aSJohannes Doerfert //===----------------------------------------------------------------------===//
15aade782aSJohannes Doerfert
16aade782aSJohannes Doerfert #include "llvm/Transforms/IPO/Attributor.h"
17aade782aSJohannes Doerfert
185ee07dc5SLuofan Chen #include "llvm/ADT/PointerIntPair.h"
191ba2929bSJohannes Doerfert #include "llvm/ADT/STLExtras.h"
20aade782aSJohannes Doerfert #include "llvm/ADT/Statistic.h"
215ee07dc5SLuofan Chen #include "llvm/ADT/TinyPtrVector.h"
22f1985a3fSserge-sans-paille #include "llvm/Analysis/AliasAnalysis.h"
23a494ae43Sserge-sans-paille #include "llvm/Analysis/CallGraph.h"
24f1985a3fSserge-sans-paille #include "llvm/Analysis/CallGraphSCCPass.h"
256316b002SSimon Pilgrim #include "llvm/Analysis/InlineCost.h"
265602c866SJohannes Doerfert #include "llvm/Analysis/MemoryBuiltins.h"
27b285b333Somarahmed1111 #include "llvm/Analysis/MustExecute.h"
2881429abdSJohannes Doerfert #include "llvm/IR/Attributes.h"
295ef18e24SJohannes Doerfert #include "llvm/IR/Constant.h"
30d9194b6eSJohannes Doerfert #include "llvm/IR/Constants.h"
3187a85f3dSLuofan Chen #include "llvm/IR/GlobalValue.h"
32adddd3dbSJohannes Doerfert #include "llvm/IR/GlobalVariable.h"
331ba2929bSJohannes Doerfert #include "llvm/IR/Instruction.h"
3496da6dd6SJohannes Doerfert #include "llvm/IR/Instructions.h"
350c0eb767SJohannes Doerfert #include "llvm/IR/IntrinsicInst.h"
361ba2929bSJohannes Doerfert #include "llvm/IR/ValueHandle.h"
3705da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
38233af895SLuofan Chen #include "llvm/Support/Casting.h"
3936bc10e7SSimon Pilgrim #include "llvm/Support/CommandLine.h"
405ee07dc5SLuofan Chen #include "llvm/Support/Debug.h"
4150d34958SJohannes Doerfert #include "llvm/Support/DebugCounter.h"
425ee07dc5SLuofan Chen #include "llvm/Support/FileSystem.h"
435ee07dc5SLuofan Chen #include "llvm/Support/GraphWriter.h"
445ee07dc5SLuofan Chen #include "llvm/Support/raw_ostream.h"
456058b863SStefan Stipanovic #include "llvm/Transforms/Utils/BasicBlockUtils.h"
4687a85f3dSLuofan Chen #include "llvm/Transforms/Utils/Cloning.h"
476058b863SStefan Stipanovic #include "llvm/Transforms/Utils/Local.h"
486058b863SStefan Stipanovic
49a53b689fSserge-sans-paille #ifdef EXPENSIVE_CHECKS
50a53b689fSserge-sans-paille #include "llvm/IR/Verifier.h"
51a53b689fSserge-sans-paille #endif
52a53b689fSserge-sans-paille
53aade782aSJohannes Doerfert #include <cassert>
545ee07dc5SLuofan Chen #include <string>
55aade782aSJohannes Doerfert
56aade782aSJohannes Doerfert using namespace llvm;
57aade782aSJohannes Doerfert
58aade782aSJohannes Doerfert #define DEBUG_TYPE "attributor"
59aade782aSJohannes Doerfert
6050d34958SJohannes Doerfert DEBUG_COUNTER(ManifestDBGCounter, "attributor-manifest",
6150d34958SJohannes Doerfert "Determine what attributes are manifested in the IR");
6250d34958SJohannes Doerfert
63898bbc25SJohannes Doerfert STATISTIC(NumFnDeleted, "Number of function deleted");
64aade782aSJohannes Doerfert STATISTIC(NumFnWithExactDefinition,
6506066c40SUday Bondhugula "Number of functions with exact definitions");
66aade782aSJohannes Doerfert STATISTIC(NumFnWithoutExactDefinition,
6706066c40SUday Bondhugula "Number of functions without exact definitions");
68ce16be25Ssstefan1 STATISTIC(NumFnShallowWrappersCreated, "Number of shallow wrappers created");
69aade782aSJohannes Doerfert STATISTIC(NumAttributesTimedOut,
70aade782aSJohannes Doerfert "Number of abstract attributes timed out before fixpoint");
71aade782aSJohannes Doerfert STATISTIC(NumAttributesValidFixpoint,
72aade782aSJohannes Doerfert "Number of abstract attributes in a valid fixpoint state");
73aade782aSJohannes Doerfert STATISTIC(NumAttributesManifested,
74aade782aSJohannes Doerfert "Number of abstract attributes manifested in IR");
75aade782aSJohannes Doerfert
76aade782aSJohannes Doerfert // TODO: Determine a good default value.
77aade782aSJohannes Doerfert //
78aade782aSJohannes Doerfert // In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
79aade782aSJohannes Doerfert // (when run with the first 5 abstract attributes). The results also indicate
80aade782aSJohannes Doerfert // that we never reach 32 iterations but always find a fixpoint sooner.
81aade782aSJohannes Doerfert //
82aade782aSJohannes Doerfert // This will become more evolved once we perform two interleaved fixpoint
83aade782aSJohannes Doerfert // iterations: bottom-up and top-down.
84aade782aSJohannes Doerfert static cl::opt<unsigned>
85b54ccab5SJoseph Huber SetFixpointIterations("attributor-max-iterations", cl::Hidden,
86aade782aSJohannes Doerfert cl::desc("Maximal number of fixpoint iterations."),
87aade782aSJohannes Doerfert cl::init(32));
88d5d75f61SJohannes Doerfert
89d5d75f61SJohannes Doerfert static cl::opt<unsigned, true> MaxInitializationChainLengthX(
90d5d75f61SJohannes Doerfert "attributor-max-initialization-chain-length", cl::Hidden,
91d5d75f61SJohannes Doerfert cl::desc(
92d5d75f61SJohannes Doerfert "Maximal number of chained initializations (to avoid stack overflows)"),
93d5d75f61SJohannes Doerfert cl::location(MaxInitializationChainLength), cl::init(1024));
94d5d75f61SJohannes Doerfert unsigned llvm::MaxInitializationChainLength;
95d5d75f61SJohannes Doerfert
96b504eb8bSJohannes Doerfert static cl::opt<bool> VerifyMaxFixpointIterations(
97b504eb8bSJohannes Doerfert "attributor-max-iterations-verify", cl::Hidden,
98b504eb8bSJohannes Doerfert cl::desc("Verify that max-iterations is a tight bound for a fixpoint"),
99b504eb8bSJohannes Doerfert cl::init(false));
100aade782aSJohannes Doerfert
101c36e2ebfSJohannes Doerfert static cl::opt<bool> AnnotateDeclarationCallSites(
102c36e2ebfSJohannes Doerfert "attributor-annotate-decl-cs", cl::Hidden,
103d68904f9SJames Henderson cl::desc("Annotate call sites of function declarations."), cl::init(false));
104c36e2ebfSJohannes Doerfert
105431141c5SStefan Stipanovic static cl::opt<bool> EnableHeapToStack("enable-heap-to-stack-conversion",
106431141c5SStefan Stipanovic cl::init(true), cl::Hidden);
107431141c5SStefan Stipanovic
108eec6d876SLuofan Chen static cl::opt<bool>
109eec6d876SLuofan Chen AllowShallowWrappers("attributor-allow-shallow-wrappers", cl::Hidden,
110eec6d876SLuofan Chen cl::desc("Allow the Attributor to create shallow "
111eec6d876SLuofan Chen "wrappers for non-exact definitions."),
112eec6d876SLuofan Chen cl::init(false));
113eec6d876SLuofan Chen
11487a85f3dSLuofan Chen static cl::opt<bool>
11587a85f3dSLuofan Chen AllowDeepWrapper("attributor-allow-deep-wrappers", cl::Hidden,
11687a85f3dSLuofan Chen cl::desc("Allow the Attributor to use IP information "
11787a85f3dSLuofan Chen "derived from non-exact functions via cloning"),
11887a85f3dSLuofan Chen cl::init(false));
11987a85f3dSLuofan Chen
12065fcc0eeSkuterd // These options can only used for debug builds.
12165fcc0eeSkuterd #ifndef NDEBUG
1224dbe82eeSkuter static cl::list<std::string>
1234dbe82eeSkuter SeedAllowList("attributor-seed-allow-list", cl::Hidden,
12465fcc0eeSkuterd cl::desc("Comma seperated list of attribute names that are "
1254dbe82eeSkuter "allowed to be seeded."),
126d86a206fSFangrui Song cl::CommaSeparated);
1274dbe82eeSkuter
12865fcc0eeSkuterd static cl::list<std::string> FunctionSeedAllowList(
12965fcc0eeSkuterd "attributor-function-seed-allow-list", cl::Hidden,
13065fcc0eeSkuterd cl::desc("Comma seperated list of function names that are "
13165fcc0eeSkuterd "allowed to be seeded."),
13295a13425SFangrui Song cl::CommaSeparated);
13365fcc0eeSkuterd #endif
13465fcc0eeSkuterd
1355ee07dc5SLuofan Chen static cl::opt<bool>
1365ee07dc5SLuofan Chen DumpDepGraph("attributor-dump-dep-graph", cl::Hidden,
1375ee07dc5SLuofan Chen cl::desc("Dump the dependency graph to dot files."),
1385ee07dc5SLuofan Chen cl::init(false));
1395ee07dc5SLuofan Chen
1405ee07dc5SLuofan Chen static cl::opt<std::string> DepGraphDotFileNamePrefix(
1415ee07dc5SLuofan Chen "attributor-depgraph-dot-filename-prefix", cl::Hidden,
1425ee07dc5SLuofan Chen cl::desc("The prefix used for the CallGraph dot file names."));
1435ee07dc5SLuofan Chen
1445ee07dc5SLuofan Chen static cl::opt<bool> ViewDepGraph("attributor-view-dep-graph", cl::Hidden,
1455ee07dc5SLuofan Chen cl::desc("View the dependency graph."),
1465ee07dc5SLuofan Chen cl::init(false));
1475ee07dc5SLuofan Chen
1485ee07dc5SLuofan Chen static cl::opt<bool> PrintDependencies("attributor-print-dep", cl::Hidden,
1495ee07dc5SLuofan Chen cl::desc("Print attribute dependencies"),
1505ee07dc5SLuofan Chen cl::init(false));
1515ee07dc5SLuofan Chen
152d75c9e61Skuterd static cl::opt<bool> EnableCallSiteSpecific(
153d75c9e61Skuterd "attributor-enable-call-site-specific-deduction", cl::Hidden,
154d75c9e61Skuterd cl::desc("Allow the Attributor to do call site specific analysis"),
155d75c9e61Skuterd cl::init(false));
156d75c9e61Skuterd
157eaf1b681SKuter Dinel static cl::opt<bool>
158eaf1b681SKuter Dinel PrintCallGraph("attributor-print-call-graph", cl::Hidden,
159eaf1b681SKuter Dinel cl::desc("Print Attributor's internal call graph"),
160eaf1b681SKuter Dinel cl::init(false));
161eaf1b681SKuter Dinel
162c2281f15SJohannes Doerfert static cl::opt<bool> SimplifyAllLoads("attributor-simplify-all-loads",
163c2281f15SJohannes Doerfert cl::Hidden,
164c2281f15SJohannes Doerfert cl::desc("Try to simplify all loads."),
165c2281f15SJohannes Doerfert cl::init(true));
166c2281f15SJohannes Doerfert
167aade782aSJohannes Doerfert /// Logic operators for the change status enum class.
168aade782aSJohannes Doerfert ///
169aade782aSJohannes Doerfert ///{
operator |(ChangeStatus L,ChangeStatus R)170e6208849SJohannes Doerfert ChangeStatus llvm::operator|(ChangeStatus L, ChangeStatus R) {
171e6208849SJohannes Doerfert return L == ChangeStatus::CHANGED ? L : R;
172aade782aSJohannes Doerfert }
operator |=(ChangeStatus & L,ChangeStatus R)173c23da666SShilei Tian ChangeStatus &llvm::operator|=(ChangeStatus &L, ChangeStatus R) {
174c23da666SShilei Tian L = L | R;
175c23da666SShilei Tian return L;
176c23da666SShilei Tian }
operator &(ChangeStatus L,ChangeStatus R)177e6208849SJohannes Doerfert ChangeStatus llvm::operator&(ChangeStatus L, ChangeStatus R) {
178e6208849SJohannes Doerfert return L == ChangeStatus::UNCHANGED ? L : R;
179aade782aSJohannes Doerfert }
operator &=(ChangeStatus & L,ChangeStatus R)180c23da666SShilei Tian ChangeStatus &llvm::operator&=(ChangeStatus &L, ChangeStatus R) {
181c23da666SShilei Tian L = L & R;
182c23da666SShilei Tian return L;
183c23da666SShilei Tian }
184aade782aSJohannes Doerfert ///}
185aade782aSJohannes Doerfert
isNoSyncInst(Attributor & A,const Instruction & I,const AbstractAttribute & QueryingAA)1863f0e6704SJohannes Doerfert bool AA::isNoSyncInst(Attributor &A, const Instruction &I,
1873f0e6704SJohannes Doerfert const AbstractAttribute &QueryingAA) {
1883f0e6704SJohannes Doerfert // We are looking for volatile instructions or non-relaxed atomics.
1893f0e6704SJohannes Doerfert if (const auto *CB = dyn_cast<CallBase>(&I)) {
1903f0e6704SJohannes Doerfert if (CB->hasFnAttr(Attribute::NoSync))
1913f0e6704SJohannes Doerfert return true;
1923f0e6704SJohannes Doerfert
1933f0e6704SJohannes Doerfert // Non-convergent and readnone imply nosync.
1943f0e6704SJohannes Doerfert if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
1953f0e6704SJohannes Doerfert return true;
1963f0e6704SJohannes Doerfert
1973f0e6704SJohannes Doerfert if (AANoSync::isNoSyncIntrinsic(&I))
1983f0e6704SJohannes Doerfert return true;
1993f0e6704SJohannes Doerfert
2003f0e6704SJohannes Doerfert const auto &NoSyncAA = A.getAAFor<AANoSync>(
2013f0e6704SJohannes Doerfert QueryingAA, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
2023f0e6704SJohannes Doerfert return NoSyncAA.isAssumedNoSync();
2033f0e6704SJohannes Doerfert }
2043f0e6704SJohannes Doerfert
2053f0e6704SJohannes Doerfert if (!I.mayReadOrWriteMemory())
2063f0e6704SJohannes Doerfert return true;
2073f0e6704SJohannes Doerfert
2083f0e6704SJohannes Doerfert return !I.isVolatile() && !AANoSync::isNonRelaxedAtomic(&I);
2093f0e6704SJohannes Doerfert }
2103f0e6704SJohannes Doerfert
isDynamicallyUnique(Attributor & A,const AbstractAttribute & QueryingAA,const Value & V,bool ForAnalysisOnly)21194d3b59cSJohannes Doerfert bool AA::isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA,
212af30de77SJohannes Doerfert const Value &V, bool ForAnalysisOnly) {
213af30de77SJohannes Doerfert // TODO: See the AAInstanceInfo class comment.
214af30de77SJohannes Doerfert if (!ForAnalysisOnly)
21594d3b59cSJohannes Doerfert return false;
216af30de77SJohannes Doerfert auto &InstanceInfoAA = A.getAAFor<AAInstanceInfo>(
217af30de77SJohannes Doerfert QueryingAA, IRPosition::value(V), DepClassTy::OPTIONAL);
218af30de77SJohannes Doerfert return InstanceInfoAA.isAssumedUniqueForAnalysis();
21994d3b59cSJohannes Doerfert }
22094d3b59cSJohannes Doerfert
getInitialValueForObj(Value & Obj,Type & Ty,const TargetLibraryInfo * TLI)2215602c866SJohannes Doerfert Constant *AA::getInitialValueForObj(Value &Obj, Type &Ty,
2225602c866SJohannes Doerfert const TargetLibraryInfo *TLI) {
22328c78a9eSJohannes Doerfert if (isa<AllocaInst>(Obj))
22428c78a9eSJohannes Doerfert return UndefValue::get(&Ty);
225871197d0SNikita Popov if (Constant *Init = getInitialValueOfAllocation(&Obj, TLI, &Ty))
226871197d0SNikita Popov return Init;
22728c78a9eSJohannes Doerfert auto *GV = dyn_cast<GlobalVariable>(&Obj);
228cb8adf76SJohannes Doerfert if (!GV)
229cb8adf76SJohannes Doerfert return nullptr;
230cb8adf76SJohannes Doerfert if (!GV->hasLocalLinkage() && !(GV->isConstant() && GV->hasInitializer()))
23128c78a9eSJohannes Doerfert return nullptr;
23228c78a9eSJohannes Doerfert if (!GV->hasInitializer())
23328c78a9eSJohannes Doerfert return UndefValue::get(&Ty);
23428c78a9eSJohannes Doerfert return dyn_cast_or_null<Constant>(getWithType(*GV->getInitializer(), Ty));
23528c78a9eSJohannes Doerfert }
23628c78a9eSJohannes Doerfert
isValidInScope(const Value & V,const Function * Scope)237fc82409bSJohannes Doerfert bool AA::isValidInScope(const Value &V, const Function *Scope) {
238fc82409bSJohannes Doerfert if (isa<Constant>(V))
239fc82409bSJohannes Doerfert return true;
240fc82409bSJohannes Doerfert if (auto *I = dyn_cast<Instruction>(&V))
241fc82409bSJohannes Doerfert return I->getFunction() == Scope;
242fc82409bSJohannes Doerfert if (auto *A = dyn_cast<Argument>(&V))
243fc82409bSJohannes Doerfert return A->getParent() == Scope;
244fc82409bSJohannes Doerfert return false;
245fc82409bSJohannes Doerfert }
246fc82409bSJohannes Doerfert
isValidAtPosition(const AA::ValueAndContext & VAC,InformationCache & InfoCache)247481b8f31SJohannes Doerfert bool AA::isValidAtPosition(const AA::ValueAndContext &VAC,
248dbb3a65fSJohannes Doerfert InformationCache &InfoCache) {
249481b8f31SJohannes Doerfert if (isa<Constant>(VAC.getValue()) || VAC.getValue() == VAC.getCtxI())
250dbb3a65fSJohannes Doerfert return true;
251481b8f31SJohannes Doerfert const Function *Scope = nullptr;
252481b8f31SJohannes Doerfert const Instruction *CtxI = VAC.getCtxI();
253481b8f31SJohannes Doerfert if (CtxI)
254481b8f31SJohannes Doerfert Scope = CtxI->getFunction();
255481b8f31SJohannes Doerfert if (auto *A = dyn_cast<Argument>(VAC.getValue()))
256dbb3a65fSJohannes Doerfert return A->getParent() == Scope;
257481b8f31SJohannes Doerfert if (auto *I = dyn_cast<Instruction>(VAC.getValue())) {
258dbb3a65fSJohannes Doerfert if (I->getFunction() == Scope) {
259acb37734SJohannes Doerfert if (const DominatorTree *DT =
260acb37734SJohannes Doerfert InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
261acb37734SJohannes Doerfert *Scope))
262481b8f31SJohannes Doerfert return DT->dominates(I, CtxI);
263acb37734SJohannes Doerfert // Local dominance check mostly for the old PM passes.
264481b8f31SJohannes Doerfert if (CtxI && I->getParent() == CtxI->getParent())
265acb37734SJohannes Doerfert return llvm::any_of(
266acb37734SJohannes Doerfert make_range(I->getIterator(), I->getParent()->end()),
267481b8f31SJohannes Doerfert [&](const Instruction &AfterI) { return &AfterI == CtxI; });
268acb37734SJohannes Doerfert }
269dbb3a65fSJohannes Doerfert }
270dbb3a65fSJohannes Doerfert return false;
271dbb3a65fSJohannes Doerfert }
272dbb3a65fSJohannes Doerfert
getWithType(Value & V,Type & Ty)2736caea8a7SJohannes Doerfert Value *AA::getWithType(Value &V, Type &Ty) {
2746caea8a7SJohannes Doerfert if (V.getType() == &Ty)
2756caea8a7SJohannes Doerfert return &V;
276d9194b6eSJohannes Doerfert if (isa<PoisonValue>(V))
277d9194b6eSJohannes Doerfert return PoisonValue::get(&Ty);
2786caea8a7SJohannes Doerfert if (isa<UndefValue>(V))
2796caea8a7SJohannes Doerfert return UndefValue::get(&Ty);
2806caea8a7SJohannes Doerfert if (auto *C = dyn_cast<Constant>(&V)) {
2816caea8a7SJohannes Doerfert if (C->isNullValue())
2826caea8a7SJohannes Doerfert return Constant::getNullValue(&Ty);
2836caea8a7SJohannes Doerfert if (C->getType()->isPointerTy() && Ty.isPointerTy())
2846caea8a7SJohannes Doerfert return ConstantExpr::getPointerCast(C, &Ty);
2855f543919SJohannes Doerfert if (C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) {
2866caea8a7SJohannes Doerfert if (C->getType()->isIntegerTy() && Ty.isIntegerTy())
2876caea8a7SJohannes Doerfert return ConstantExpr::getTrunc(C, &Ty, /* OnlyIfReduced */ true);
2886caea8a7SJohannes Doerfert if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy())
2896caea8a7SJohannes Doerfert return ConstantExpr::getFPTrunc(C, &Ty, /* OnlyIfReduced */ true);
2906caea8a7SJohannes Doerfert }
2915f543919SJohannes Doerfert }
2926caea8a7SJohannes Doerfert return nullptr;
2936caea8a7SJohannes Doerfert }
2946caea8a7SJohannes Doerfert
295aa376827SJohannes Doerfert Optional<Value *>
combineOptionalValuesInAAValueLatice(const Optional<Value * > & A,const Optional<Value * > & B,Type * Ty)296aa376827SJohannes Doerfert AA::combineOptionalValuesInAAValueLatice(const Optional<Value *> &A,
297aa376827SJohannes Doerfert const Optional<Value *> &B, Type *Ty) {
298aa376827SJohannes Doerfert if (A == B)
299aa376827SJohannes Doerfert return A;
300a7938c74SKazu Hirata if (!B)
301aa376827SJohannes Doerfert return A;
302aa376827SJohannes Doerfert if (*B == nullptr)
303aa376827SJohannes Doerfert return nullptr;
304a7938c74SKazu Hirata if (!A)
305aa376827SJohannes Doerfert return Ty ? getWithType(**B, *Ty) : nullptr;
306aa376827SJohannes Doerfert if (*A == nullptr)
307aa376827SJohannes Doerfert return nullptr;
308aa376827SJohannes Doerfert if (!Ty)
309aa376827SJohannes Doerfert Ty = (*A)->getType();
310aa376827SJohannes Doerfert if (isa_and_nonnull<UndefValue>(*A))
311aa376827SJohannes Doerfert return getWithType(**B, *Ty);
312aa376827SJohannes Doerfert if (isa<UndefValue>(*B))
313aa376827SJohannes Doerfert return A;
314aa376827SJohannes Doerfert if (*A && *B && *A == getWithType(**B, *Ty))
315aa376827SJohannes Doerfert return A;
316aa376827SJohannes Doerfert return nullptr;
317aa376827SJohannes Doerfert }
318aa376827SJohannes Doerfert
3195af11ec3SJohannes Doerfert 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)320c42aa1beSJohannes Doerfert static bool getPotentialCopiesOfMemoryValue(
321c42aa1beSJohannes Doerfert Attributor &A, Ty &I, SmallSetVector<Value *, 4> &PotentialCopies,
322c42aa1beSJohannes Doerfert SmallSetVector<Instruction *, 4> &PotentialValueOrigins,
323c42aa1beSJohannes Doerfert const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
324c42aa1beSJohannes Doerfert bool OnlyExact) {
3255af11ec3SJohannes Doerfert LLVM_DEBUG(dbgs() << "Trying to determine the potential copies of " << I
3265af11ec3SJohannes Doerfert << " (only exact: " << OnlyExact << ")\n";);
327adddd3dbSJohannes Doerfert
3285af11ec3SJohannes Doerfert Value &Ptr = *I.getPointerOperand();
329bf789b19SJohannes Doerfert SmallSetVector<Value *, 8> Objects;
3305af11ec3SJohannes Doerfert if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, QueryingAA, &I,
3316ed1ef06SJohannes Doerfert UsedAssumedInformation)) {
332adddd3dbSJohannes Doerfert LLVM_DEBUG(
333adddd3dbSJohannes Doerfert dbgs() << "Underlying objects stored into could not be determined\n";);
334adddd3dbSJohannes Doerfert return false;
335adddd3dbSJohannes Doerfert }
336adddd3dbSJohannes Doerfert
3375af11ec3SJohannes Doerfert // Containers to remember the pointer infos and new copies while we are not
3385af11ec3SJohannes Doerfert // sure that we can find all of them. If we abort we want to avoid spurious
3395af11ec3SJohannes Doerfert // dependences and potential copies in the provided container.
340adddd3dbSJohannes Doerfert SmallVector<const AAPointerInfo *> PIs;
341adddd3dbSJohannes Doerfert SmallVector<Value *> NewCopies;
342c42aa1beSJohannes Doerfert SmallVector<Instruction *> NewCopyOrigins;
343adddd3dbSJohannes Doerfert
3445af11ec3SJohannes Doerfert const auto *TLI =
3455af11ec3SJohannes Doerfert A.getInfoCache().getTargetLibraryInfoForFunction(*I.getFunction());
3464f2ccdd0SJohannes Doerfert LLVM_DEBUG(dbgs() << "Visit " << Objects.size() << " objects:\n");
347adddd3dbSJohannes Doerfert for (Value *Obj : Objects) {
348adddd3dbSJohannes Doerfert LLVM_DEBUG(dbgs() << "Visit underlying object " << *Obj << "\n");
349adddd3dbSJohannes Doerfert if (isa<UndefValue>(Obj))
350adddd3dbSJohannes Doerfert continue;
351adddd3dbSJohannes Doerfert if (isa<ConstantPointerNull>(Obj)) {
352adddd3dbSJohannes Doerfert // A null pointer access can be undefined but any offset from null may
353adddd3dbSJohannes Doerfert // be OK. We do not try to optimize the latter.
3545af11ec3SJohannes Doerfert if (!NullPointerIsDefined(I.getFunction(),
355adddd3dbSJohannes Doerfert Ptr.getType()->getPointerAddressSpace()) &&
356bf789b19SJohannes Doerfert A.getAssumedSimplified(Ptr, QueryingAA, UsedAssumedInformation,
357bf789b19SJohannes Doerfert AA::Interprocedural) == Obj)
358adddd3dbSJohannes Doerfert continue;
359adddd3dbSJohannes Doerfert LLVM_DEBUG(
360adddd3dbSJohannes Doerfert dbgs() << "Underlying object is a valid nullptr, giving up.\n";);
361adddd3dbSJohannes Doerfert return false;
362adddd3dbSJohannes Doerfert }
3635af11ec3SJohannes Doerfert // TODO: Use assumed noalias return.
3645602c866SJohannes Doerfert if (!isa<AllocaInst>(Obj) && !isa<GlobalVariable>(Obj) &&
3655af11ec3SJohannes Doerfert !(IsLoad ? isAllocationFn(Obj, TLI) : isNoAliasCall(Obj))) {
366adddd3dbSJohannes Doerfert LLVM_DEBUG(dbgs() << "Underlying object is not supported yet: " << *Obj
367adddd3dbSJohannes Doerfert << "\n";);
368adddd3dbSJohannes Doerfert return false;
369adddd3dbSJohannes Doerfert }
370adddd3dbSJohannes Doerfert if (auto *GV = dyn_cast<GlobalVariable>(Obj))
371cb8adf76SJohannes Doerfert if (!GV->hasLocalLinkage() &&
372cb8adf76SJohannes Doerfert !(GV->isConstant() && GV->hasInitializer())) {
373adddd3dbSJohannes Doerfert LLVM_DEBUG(dbgs() << "Underlying object is global with external "
374adddd3dbSJohannes Doerfert "linkage, not supported yet: "
375adddd3dbSJohannes Doerfert << *Obj << "\n";);
376adddd3dbSJohannes Doerfert return false;
377adddd3dbSJohannes Doerfert }
378adddd3dbSJohannes Doerfert
379bf789b19SJohannes Doerfert bool NullOnly = true;
380bf789b19SJohannes Doerfert bool NullRequired = false;
381142897ddSJohannes Doerfert auto CheckForNullOnlyAndUndef = [&](Optional<Value *> V, bool IsExact) {
382bf789b19SJohannes Doerfert if (!V || *V == nullptr)
383bf789b19SJohannes Doerfert NullOnly = false;
384bf789b19SJohannes Doerfert else if (isa<UndefValue>(*V))
385bf789b19SJohannes Doerfert /* No op */;
386bf789b19SJohannes Doerfert else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue())
387142897ddSJohannes Doerfert NullRequired = !IsExact;
388bf789b19SJohannes Doerfert else
389bf789b19SJohannes Doerfert NullOnly = false;
390bf789b19SJohannes Doerfert };
391bf789b19SJohannes Doerfert
392adddd3dbSJohannes Doerfert auto CheckAccess = [&](const AAPointerInfo::Access &Acc, bool IsExact) {
3935af11ec3SJohannes Doerfert if ((IsLoad && !Acc.isWrite()) || (!IsLoad && !Acc.isRead()))
394adddd3dbSJohannes Doerfert return true;
395857bf306SJohannes Doerfert if (IsLoad && Acc.isWrittenValueYetUndetermined())
396857bf306SJohannes Doerfert return true;
397142897ddSJohannes Doerfert CheckForNullOnlyAndUndef(Acc.getContent(), IsExact);
398bf789b19SJohannes Doerfert if (OnlyExact && !IsExact && !NullOnly &&
399857bf306SJohannes Doerfert !isa_and_nonnull<UndefValue>(Acc.getWrittenValue())) {
4005af11ec3SJohannes Doerfert LLVM_DEBUG(dbgs() << "Non exact access " << *Acc.getRemoteInst()
4015af11ec3SJohannes Doerfert << ", abort!\n");
4025af11ec3SJohannes Doerfert return false;
4035af11ec3SJohannes Doerfert }
404bf789b19SJohannes Doerfert if (NullRequired && !NullOnly) {
405bf789b19SJohannes Doerfert LLVM_DEBUG(dbgs() << "Required all `null` accesses due to non exact "
406bf789b19SJohannes Doerfert "one, however found non-null one: "
407bf789b19SJohannes Doerfert << *Acc.getRemoteInst() << ", abort!\n");
408bf789b19SJohannes Doerfert return false;
409bf789b19SJohannes Doerfert }
4105af11ec3SJohannes Doerfert if (IsLoad) {
4115af11ec3SJohannes Doerfert assert(isa<LoadInst>(I) && "Expected load or store instruction only!");
4125af11ec3SJohannes Doerfert if (!Acc.isWrittenValueUnknown()) {
4135af11ec3SJohannes Doerfert NewCopies.push_back(Acc.getWrittenValue());
414c42aa1beSJohannes Doerfert NewCopyOrigins.push_back(Acc.getRemoteInst());
4155af11ec3SJohannes Doerfert return true;
4165af11ec3SJohannes Doerfert }
4175af11ec3SJohannes Doerfert auto *SI = dyn_cast<StoreInst>(Acc.getRemoteInst());
4185af11ec3SJohannes Doerfert if (!SI) {
4195af11ec3SJohannes Doerfert LLVM_DEBUG(dbgs() << "Underlying object written through a non-store "
4205af11ec3SJohannes Doerfert "instruction not supported yet: "
4215af11ec3SJohannes Doerfert << *Acc.getRemoteInst() << "\n";);
4225af11ec3SJohannes Doerfert return false;
4235af11ec3SJohannes Doerfert }
4245af11ec3SJohannes Doerfert NewCopies.push_back(SI->getValueOperand());
425c42aa1beSJohannes Doerfert NewCopyOrigins.push_back(SI);
4265af11ec3SJohannes Doerfert } else {
4275af11ec3SJohannes Doerfert assert(isa<StoreInst>(I) && "Expected load or store instruction only!");
428adddd3dbSJohannes Doerfert auto *LI = dyn_cast<LoadInst>(Acc.getRemoteInst());
4295af11ec3SJohannes Doerfert if (!LI && OnlyExact) {
430adddd3dbSJohannes Doerfert LLVM_DEBUG(dbgs() << "Underlying object read through a non-load "
431adddd3dbSJohannes Doerfert "instruction not supported yet: "
432adddd3dbSJohannes Doerfert << *Acc.getRemoteInst() << "\n";);
433adddd3dbSJohannes Doerfert return false;
434adddd3dbSJohannes Doerfert }
4355af11ec3SJohannes Doerfert NewCopies.push_back(Acc.getRemoteInst());
4365af11ec3SJohannes Doerfert }
437adddd3dbSJohannes Doerfert return true;
438adddd3dbSJohannes Doerfert };
439adddd3dbSJohannes Doerfert
44062f7888dSJohannes Doerfert // If the value has been written to we don't need the initial value of the
44162f7888dSJohannes Doerfert // object.
44262f7888dSJohannes Doerfert bool HasBeenWrittenTo = false;
44362f7888dSJohannes Doerfert
444adddd3dbSJohannes Doerfert auto &PI = A.getAAFor<AAPointerInfo>(QueryingAA, IRPosition::value(*Obj),
445adddd3dbSJohannes Doerfert DepClassTy::NONE);
44662f7888dSJohannes Doerfert if (!PI.forallInterferingAccesses(A, QueryingAA, I, CheckAccess,
44762f7888dSJohannes Doerfert HasBeenWrittenTo)) {
448adddd3dbSJohannes Doerfert LLVM_DEBUG(
449adddd3dbSJohannes Doerfert dbgs()
450adddd3dbSJohannes Doerfert << "Failed to verify all interfering accesses for underlying object: "
451adddd3dbSJohannes Doerfert << *Obj << "\n");
452adddd3dbSJohannes Doerfert return false;
453adddd3dbSJohannes Doerfert }
45462f7888dSJohannes Doerfert
45562f7888dSJohannes Doerfert if (IsLoad && !HasBeenWrittenTo) {
45662f7888dSJohannes Doerfert Value *InitialValue = AA::getInitialValueForObj(*Obj, *I.getType(), TLI);
45762f7888dSJohannes Doerfert if (!InitialValue)
45862f7888dSJohannes Doerfert return false;
45962f7888dSJohannes Doerfert CheckForNullOnlyAndUndef(InitialValue, /* IsExact */ true);
46062f7888dSJohannes Doerfert if (NullRequired && !NullOnly) {
46162f7888dSJohannes Doerfert LLVM_DEBUG(dbgs() << "Non exact access but initial value that is not "
46262f7888dSJohannes Doerfert "null or undef, abort!\n");
46362f7888dSJohannes Doerfert return false;
46462f7888dSJohannes Doerfert }
46562f7888dSJohannes Doerfert
46662f7888dSJohannes Doerfert NewCopies.push_back(InitialValue);
46762f7888dSJohannes Doerfert NewCopyOrigins.push_back(nullptr);
46862f7888dSJohannes Doerfert }
46962f7888dSJohannes Doerfert
470adddd3dbSJohannes Doerfert PIs.push_back(&PI);
471adddd3dbSJohannes Doerfert }
472adddd3dbSJohannes Doerfert
4735af11ec3SJohannes Doerfert // Only if we were successful collection all potential copies we record
4745af11ec3SJohannes Doerfert // dependences (on non-fix AAPointerInfo AAs). We also only then modify the
4755af11ec3SJohannes Doerfert // given PotentialCopies container.
476adddd3dbSJohannes Doerfert for (auto *PI : PIs) {
477adddd3dbSJohannes Doerfert if (!PI->getState().isAtFixpoint())
478adddd3dbSJohannes Doerfert UsedAssumedInformation = true;
479adddd3dbSJohannes Doerfert A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL);
480adddd3dbSJohannes Doerfert }
481adddd3dbSJohannes Doerfert PotentialCopies.insert(NewCopies.begin(), NewCopies.end());
482c42aa1beSJohannes Doerfert PotentialValueOrigins.insert(NewCopyOrigins.begin(), NewCopyOrigins.end());
483adddd3dbSJohannes Doerfert
484adddd3dbSJohannes Doerfert return true;
485adddd3dbSJohannes Doerfert }
486adddd3dbSJohannes Doerfert
getPotentiallyLoadedValues(Attributor & A,LoadInst & LI,SmallSetVector<Value *,4> & PotentialValues,SmallSetVector<Instruction *,4> & PotentialValueOrigins,const AbstractAttribute & QueryingAA,bool & UsedAssumedInformation,bool OnlyExact)487c42aa1beSJohannes Doerfert bool AA::getPotentiallyLoadedValues(
488c42aa1beSJohannes Doerfert Attributor &A, LoadInst &LI, SmallSetVector<Value *, 4> &PotentialValues,
489c42aa1beSJohannes Doerfert SmallSetVector<Instruction *, 4> &PotentialValueOrigins,
490c42aa1beSJohannes Doerfert const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
4915af11ec3SJohannes Doerfert bool OnlyExact) {
4925af11ec3SJohannes Doerfert return getPotentialCopiesOfMemoryValue</* IsLoad */ true>(
493c42aa1beSJohannes Doerfert A, LI, PotentialValues, PotentialValueOrigins, QueryingAA,
494c42aa1beSJohannes Doerfert UsedAssumedInformation, OnlyExact);
4955af11ec3SJohannes Doerfert }
4965af11ec3SJohannes Doerfert
getPotentialCopiesOfStoredValue(Attributor & A,StoreInst & SI,SmallSetVector<Value *,4> & PotentialCopies,const AbstractAttribute & QueryingAA,bool & UsedAssumedInformation,bool OnlyExact)4975af11ec3SJohannes Doerfert bool AA::getPotentialCopiesOfStoredValue(
4985af11ec3SJohannes Doerfert Attributor &A, StoreInst &SI, SmallSetVector<Value *, 4> &PotentialCopies,
4995af11ec3SJohannes Doerfert const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
5005af11ec3SJohannes Doerfert bool OnlyExact) {
501c42aa1beSJohannes Doerfert SmallSetVector<Instruction *, 4> PotentialValueOrigins;
5025af11ec3SJohannes Doerfert return getPotentialCopiesOfMemoryValue</* IsLoad */ false>(
503c42aa1beSJohannes Doerfert A, SI, PotentialCopies, PotentialValueOrigins, QueryingAA,
504c42aa1beSJohannes Doerfert UsedAssumedInformation, OnlyExact);
5055af11ec3SJohannes Doerfert }
5065af11ec3SJohannes Doerfert
isAssumedReadOnlyOrReadNone(Attributor & A,const IRPosition & IRP,const AbstractAttribute & QueryingAA,bool RequireReadNone,bool & IsKnown)507adf0d57fSJohannes Doerfert static bool isAssumedReadOnlyOrReadNone(Attributor &A, const IRPosition &IRP,
508adf0d57fSJohannes Doerfert const AbstractAttribute &QueryingAA,
509adf0d57fSJohannes Doerfert bool RequireReadNone, bool &IsKnown) {
510adf0d57fSJohannes Doerfert
511adf0d57fSJohannes Doerfert IRPosition::Kind Kind = IRP.getPositionKind();
512adf0d57fSJohannes Doerfert if (Kind == IRPosition::IRP_FUNCTION || Kind == IRPosition::IRP_CALL_SITE) {
513adf0d57fSJohannes Doerfert const auto &MemLocAA =
514adf0d57fSJohannes Doerfert A.getAAFor<AAMemoryLocation>(QueryingAA, IRP, DepClassTy::NONE);
515adf0d57fSJohannes Doerfert if (MemLocAA.isAssumedReadNone()) {
516adf0d57fSJohannes Doerfert IsKnown = MemLocAA.isKnownReadNone();
517adf0d57fSJohannes Doerfert if (!IsKnown)
518adf0d57fSJohannes Doerfert A.recordDependence(MemLocAA, QueryingAA, DepClassTy::OPTIONAL);
519adf0d57fSJohannes Doerfert return true;
520adf0d57fSJohannes Doerfert }
521adf0d57fSJohannes Doerfert }
522adf0d57fSJohannes Doerfert
523adf0d57fSJohannes Doerfert const auto &MemBehaviorAA =
524adf0d57fSJohannes Doerfert A.getAAFor<AAMemoryBehavior>(QueryingAA, IRP, DepClassTy::NONE);
525adf0d57fSJohannes Doerfert if (MemBehaviorAA.isAssumedReadNone() ||
526adf0d57fSJohannes Doerfert (!RequireReadNone && MemBehaviorAA.isAssumedReadOnly())) {
527adf0d57fSJohannes Doerfert IsKnown = RequireReadNone ? MemBehaviorAA.isKnownReadNone()
528adf0d57fSJohannes Doerfert : MemBehaviorAA.isKnownReadOnly();
529adf0d57fSJohannes Doerfert if (!IsKnown)
530adf0d57fSJohannes Doerfert A.recordDependence(MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL);
531adf0d57fSJohannes Doerfert return true;
532adf0d57fSJohannes Doerfert }
533adf0d57fSJohannes Doerfert
534adf0d57fSJohannes Doerfert return false;
535adf0d57fSJohannes Doerfert }
536adf0d57fSJohannes Doerfert
isAssumedReadOnly(Attributor & A,const IRPosition & IRP,const AbstractAttribute & QueryingAA,bool & IsKnown)537adf0d57fSJohannes Doerfert bool AA::isAssumedReadOnly(Attributor &A, const IRPosition &IRP,
538adf0d57fSJohannes Doerfert const AbstractAttribute &QueryingAA, bool &IsKnown) {
539adf0d57fSJohannes Doerfert return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA,
540adf0d57fSJohannes Doerfert /* RequireReadNone */ false, IsKnown);
541adf0d57fSJohannes Doerfert }
isAssumedReadNone(Attributor & A,const IRPosition & IRP,const AbstractAttribute & QueryingAA,bool & IsKnown)542adf0d57fSJohannes Doerfert bool AA::isAssumedReadNone(Attributor &A, const IRPosition &IRP,
543adf0d57fSJohannes Doerfert const AbstractAttribute &QueryingAA, bool &IsKnown) {
544adf0d57fSJohannes Doerfert return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA,
545adf0d57fSJohannes Doerfert /* RequireReadNone */ true, IsKnown);
546adf0d57fSJohannes Doerfert }
547adf0d57fSJohannes Doerfert
548a265cf22SJohannes Doerfert static bool
isPotentiallyReachable(Attributor & A,const Instruction & FromI,const Instruction * ToI,const Function & ToFn,const AbstractAttribute & QueryingAA,std::function<bool (const Function & F)> GoBackwardsCB)549a265cf22SJohannes Doerfert isPotentiallyReachable(Attributor &A, const Instruction &FromI,
550a265cf22SJohannes Doerfert const Instruction *ToI, const Function &ToFn,
551a265cf22SJohannes Doerfert const AbstractAttribute &QueryingAA,
552a265cf22SJohannes Doerfert std::function<bool(const Function &F)> GoBackwardsCB) {
553a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] isPotentiallyReachable @" << ToFn.getName()
554a265cf22SJohannes Doerfert << " from " << FromI << " [GBCB: " << bool(GoBackwardsCB)
555a265cf22SJohannes Doerfert << "]\n");
556a265cf22SJohannes Doerfert
557*a50b9f9fSJohannes Doerfert // TODO: If we can go arbitrarily backwards we will eventually reach an
558*a50b9f9fSJohannes Doerfert // entry point that can reach ToI. Only once this takes a set of blocks
559*a50b9f9fSJohannes Doerfert // through which we cannot go, or once we track internal functions not
560*a50b9f9fSJohannes Doerfert // accessible from the outside, it makes sense to perform backwards analysis
561*a50b9f9fSJohannes Doerfert // in the absence of a GoBackwardsCB.
562*a50b9f9fSJohannes Doerfert if (!GoBackwardsCB) {
563*a50b9f9fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] check @" << ToFn.getName() << " from " << FromI
564*a50b9f9fSJohannes Doerfert << " is not checked backwards, abort\n");
565*a50b9f9fSJohannes Doerfert return true;
566*a50b9f9fSJohannes Doerfert }
567*a50b9f9fSJohannes Doerfert
568a265cf22SJohannes Doerfert SmallPtrSet<const Instruction *, 8> Visited;
569a265cf22SJohannes Doerfert SmallVector<const Instruction *> Worklist;
570a265cf22SJohannes Doerfert Worklist.push_back(&FromI);
571a265cf22SJohannes Doerfert
572a265cf22SJohannes Doerfert while (!Worklist.empty()) {
573a265cf22SJohannes Doerfert const Instruction *CurFromI = Worklist.pop_back_val();
574a265cf22SJohannes Doerfert if (!Visited.insert(CurFromI).second)
575a265cf22SJohannes Doerfert continue;
576a265cf22SJohannes Doerfert
577a265cf22SJohannes Doerfert const Function *FromFn = CurFromI->getFunction();
578a265cf22SJohannes Doerfert if (FromFn == &ToFn) {
579a265cf22SJohannes Doerfert if (!ToI)
580a265cf22SJohannes Doerfert return true;
581a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] check " << *ToI << " from " << *CurFromI
582a265cf22SJohannes Doerfert << " intraprocedurally\n");
583a265cf22SJohannes Doerfert const auto &ReachabilityAA = A.getAAFor<AAReachability>(
584a265cf22SJohannes Doerfert QueryingAA, IRPosition::function(ToFn), DepClassTy::OPTIONAL);
585a265cf22SJohannes Doerfert bool Result = ReachabilityAA.isAssumedReachable(A, *CurFromI, *ToI);
586a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " "
587a265cf22SJohannes Doerfert << (Result ? "can potentially " : "cannot ") << "reach "
588a265cf22SJohannes Doerfert << *ToI << " [Intra]\n");
589a265cf22SJohannes Doerfert if (Result)
590a265cf22SJohannes Doerfert return true;
591a265cf22SJohannes Doerfert }
592a265cf22SJohannes Doerfert
593a265cf22SJohannes Doerfert // Check if the current instruction is already known to reach the ToFn.
594a265cf22SJohannes Doerfert const auto &FnReachabilityAA = A.getAAFor<AAFunctionReachability>(
595a265cf22SJohannes Doerfert QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL);
596a265cf22SJohannes Doerfert bool Result = FnReachabilityAA.instructionCanReach(
597*a50b9f9fSJohannes Doerfert A, *CurFromI, ToFn);
598a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " in @" << FromFn->getName()
599a265cf22SJohannes Doerfert << " " << (Result ? "can potentially " : "cannot ")
600a265cf22SJohannes Doerfert << "reach @" << ToFn.getName() << " [FromFn]\n");
601a265cf22SJohannes Doerfert if (Result)
602a265cf22SJohannes Doerfert return true;
603a265cf22SJohannes Doerfert
604a265cf22SJohannes Doerfert // If we do not go backwards from the FromFn we are done here and so far we
605a265cf22SJohannes Doerfert // could not find a way to reach ToFn/ToI.
606a265cf22SJohannes Doerfert if (!GoBackwardsCB(*FromFn))
607a265cf22SJohannes Doerfert continue;
608a265cf22SJohannes Doerfert
609a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "Stepping backwards to the call sites of @"
610a265cf22SJohannes Doerfert << FromFn->getName() << "\n");
611a265cf22SJohannes Doerfert
612a265cf22SJohannes Doerfert auto CheckCallSite = [&](AbstractCallSite ACS) {
613a265cf22SJohannes Doerfert CallBase *CB = ACS.getInstruction();
614a265cf22SJohannes Doerfert if (!CB)
615a265cf22SJohannes Doerfert return false;
616a265cf22SJohannes Doerfert
617a265cf22SJohannes Doerfert if (isa<InvokeInst>(CB))
618a265cf22SJohannes Doerfert return false;
619a265cf22SJohannes Doerfert
620a265cf22SJohannes Doerfert Instruction *Inst = CB->getNextNonDebugInstruction();
621a265cf22SJohannes Doerfert Worklist.push_back(Inst);
622a265cf22SJohannes Doerfert return true;
623a265cf22SJohannes Doerfert };
624a265cf22SJohannes Doerfert
6256ed1ef06SJohannes Doerfert bool UsedAssumedInformation = false;
626a265cf22SJohannes Doerfert Result = !A.checkForAllCallSites(CheckCallSite, *FromFn,
627a265cf22SJohannes Doerfert /* RequireAllCallSites */ true,
6286ed1ef06SJohannes Doerfert &QueryingAA, UsedAssumedInformation);
629a265cf22SJohannes Doerfert if (Result) {
630a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromI
631a265cf22SJohannes Doerfert << " in @" << FromFn->getName()
632a265cf22SJohannes Doerfert << " failed, give up\n");
633a265cf22SJohannes Doerfert return true;
634a265cf22SJohannes Doerfert }
635a265cf22SJohannes Doerfert
636a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] stepped back to call sites from " << *CurFromI
637a265cf22SJohannes Doerfert << " in @" << FromFn->getName()
638a265cf22SJohannes Doerfert << " worklist size is: " << Worklist.size() << "\n");
639a265cf22SJohannes Doerfert }
640a265cf22SJohannes Doerfert return false;
641a265cf22SJohannes Doerfert }
642a265cf22SJohannes Doerfert
isPotentiallyReachable(Attributor & A,const Instruction & FromI,const Instruction & ToI,const AbstractAttribute & QueryingAA,std::function<bool (const Function & F)> GoBackwardsCB)643a265cf22SJohannes Doerfert bool AA::isPotentiallyReachable(
644a265cf22SJohannes Doerfert Attributor &A, const Instruction &FromI, const Instruction &ToI,
645a265cf22SJohannes Doerfert const AbstractAttribute &QueryingAA,
646a265cf22SJohannes Doerfert std::function<bool(const Function &F)> GoBackwardsCB) {
647a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << "[AA] isPotentiallyReachable " << ToI << " from "
648a265cf22SJohannes Doerfert << FromI << " [GBCB: " << bool(GoBackwardsCB) << "]\n");
649a265cf22SJohannes Doerfert const Function *ToFn = ToI.getFunction();
650a265cf22SJohannes Doerfert return ::isPotentiallyReachable(A, FromI, &ToI, *ToFn, QueryingAA,
651a265cf22SJohannes Doerfert GoBackwardsCB);
652a265cf22SJohannes Doerfert }
653a265cf22SJohannes Doerfert
isPotentiallyReachable(Attributor & A,const Instruction & FromI,const Function & ToFn,const AbstractAttribute & QueryingAA,std::function<bool (const Function & F)> GoBackwardsCB)654a265cf22SJohannes Doerfert bool AA::isPotentiallyReachable(
655a265cf22SJohannes Doerfert Attributor &A, const Instruction &FromI, const Function &ToFn,
656a265cf22SJohannes Doerfert const AbstractAttribute &QueryingAA,
657a265cf22SJohannes Doerfert std::function<bool(const Function &F)> GoBackwardsCB) {
658a265cf22SJohannes Doerfert return ::isPotentiallyReachable(A, FromI, /* ToI */ nullptr, ToFn, QueryingAA,
659a265cf22SJohannes Doerfert GoBackwardsCB);
660a265cf22SJohannes Doerfert }
661a265cf22SJohannes Doerfert
6620985554bSJohannes Doerfert /// Return true if \p New is equal or worse than \p Old.
isEqualOrWorse(const Attribute & New,const Attribute & Old)6630985554bSJohannes Doerfert static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
6640985554bSJohannes Doerfert if (!Old.isIntAttribute())
6650985554bSJohannes Doerfert return true;
6660985554bSJohannes Doerfert
6670985554bSJohannes Doerfert return Old.getValueAsInt() >= New.getValueAsInt();
6680985554bSJohannes Doerfert }
6690985554bSJohannes Doerfert
6700985554bSJohannes Doerfert /// Return true if the information provided by \p Attr was added to the
6710985554bSJohannes Doerfert /// attribute list \p Attrs. This is only the case if it was not already present
6720985554bSJohannes Doerfert /// in \p Attrs at the position describe by \p PK and \p AttrIdx.
addIfNotExistent(LLVMContext & Ctx,const Attribute & Attr,AttributeList & Attrs,int AttrIdx,bool ForceReplace=false)6730985554bSJohannes Doerfert static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
67496709823SKuter Dinel AttributeList &Attrs, int AttrIdx,
67596709823SKuter Dinel bool ForceReplace = false) {
6760985554bSJohannes Doerfert
6770985554bSJohannes Doerfert if (Attr.isEnumAttribute()) {
6780985554bSJohannes Doerfert Attribute::AttrKind Kind = Attr.getKindAsEnum();
67952e6d70cSArthur Eubanks if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
68096709823SKuter Dinel if (!ForceReplace &&
68152e6d70cSArthur Eubanks isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind)))
6820985554bSJohannes Doerfert return false;
68352e6d70cSArthur Eubanks Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
6840985554bSJohannes Doerfert return true;
6850985554bSJohannes Doerfert }
6860985554bSJohannes Doerfert if (Attr.isStringAttribute()) {
6870985554bSJohannes Doerfert StringRef Kind = Attr.getKindAsString();
68852e6d70cSArthur Eubanks if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
68996709823SKuter Dinel if (!ForceReplace &&
69052e6d70cSArthur Eubanks isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind)))
6910985554bSJohannes Doerfert return false;
69252e6d70cSArthur Eubanks Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
6930985554bSJohannes Doerfert return true;
6940985554bSJohannes Doerfert }
6950985554bSJohannes Doerfert if (Attr.isIntAttribute()) {
6960985554bSJohannes Doerfert Attribute::AttrKind Kind = Attr.getKindAsEnum();
69752e6d70cSArthur Eubanks if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
69896709823SKuter Dinel if (!ForceReplace &&
69952e6d70cSArthur Eubanks isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind)))
7000985554bSJohannes Doerfert return false;
70152e6d70cSArthur Eubanks Attrs = Attrs.removeAttributeAtIndex(Ctx, AttrIdx, Kind);
70252e6d70cSArthur Eubanks Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
7030985554bSJohannes Doerfert return true;
7040985554bSJohannes Doerfert }
7050985554bSJohannes Doerfert
7060985554bSJohannes Doerfert llvm_unreachable("Expected enum or string attribute!");
7070985554bSJohannes Doerfert }
7080985554bSJohannes Doerfert
getAssociatedArgument() const709b1b441d2SJohannes Doerfert Argument *IRPosition::getAssociatedArgument() const {
710b1b441d2SJohannes Doerfert if (getPositionKind() == IRP_ARGUMENT)
711b1b441d2SJohannes Doerfert return cast<Argument>(&getAnchorValue());
712b1b441d2SJohannes Doerfert
713b1b441d2SJohannes Doerfert // Not an Argument and no argument number means this is not a call site
714b1b441d2SJohannes Doerfert // argument, thus we cannot find a callback argument to return.
715cefd2a2cSJohannes Doerfert int ArgNo = getCallSiteArgNo();
716b1b441d2SJohannes Doerfert if (ArgNo < 0)
717b1b441d2SJohannes Doerfert return nullptr;
718b1b441d2SJohannes Doerfert
719b1b441d2SJohannes Doerfert // Use abstract call sites to make the connection between the call site
720b1b441d2SJohannes Doerfert // values and the ones in callbacks. If a callback was found that makes use
721b1b441d2SJohannes Doerfert // of the underlying call site operand, we want the corresponding callback
722b1b441d2SJohannes Doerfert // callee argument and not the direct callee argument.
723b1b441d2SJohannes Doerfert Optional<Argument *> CBCandidateArg;
724798b262cSCraig Topper SmallVector<const Use *, 4> CallbackUses;
725798b262cSCraig Topper const auto &CB = cast<CallBase>(getAnchorValue());
726798b262cSCraig Topper AbstractCallSite::getCallbackUses(CB, CallbackUses);
727798b262cSCraig Topper for (const Use *U : CallbackUses) {
728b1b441d2SJohannes Doerfert AbstractCallSite ACS(U);
729b1b441d2SJohannes Doerfert assert(ACS && ACS.isCallbackCall());
730b1b441d2SJohannes Doerfert if (!ACS.getCalledFunction())
731b1b441d2SJohannes Doerfert continue;
732b1b441d2SJohannes Doerfert
733b1b441d2SJohannes Doerfert for (unsigned u = 0, e = ACS.getNumArgOperands(); u < e; u++) {
734b1b441d2SJohannes Doerfert
735b1b441d2SJohannes Doerfert // Test if the underlying call site operand is argument number u of the
736b1b441d2SJohannes Doerfert // callback callee.
737b1b441d2SJohannes Doerfert if (ACS.getCallArgOperandNo(u) != ArgNo)
738b1b441d2SJohannes Doerfert continue;
739b1b441d2SJohannes Doerfert
740b1b441d2SJohannes Doerfert assert(ACS.getCalledFunction()->arg_size() > u &&
741b1b441d2SJohannes Doerfert "ACS mapped into var-args arguments!");
742e0e687a6SKazu Hirata if (CBCandidateArg) {
743b1b441d2SJohannes Doerfert CBCandidateArg = nullptr;
744b1b441d2SJohannes Doerfert break;
745b1b441d2SJohannes Doerfert }
746b1b441d2SJohannes Doerfert CBCandidateArg = ACS.getCalledFunction()->getArg(u);
747b1b441d2SJohannes Doerfert }
748b1b441d2SJohannes Doerfert }
749b1b441d2SJohannes Doerfert
750b1b441d2SJohannes Doerfert // If we found a unique callback candidate argument, return it.
751611ffcf4SKazu Hirata if (CBCandidateArg && CBCandidateArg.value())
752611ffcf4SKazu Hirata return CBCandidateArg.value();
753b1b441d2SJohannes Doerfert
754b1b441d2SJohannes Doerfert // If no callbacks were found, or none used the underlying call site operand
755b1b441d2SJohannes Doerfert // exclusively, use the direct callee argument if available.
756798b262cSCraig Topper const Function *Callee = CB.getCalledFunction();
757b1b441d2SJohannes Doerfert if (Callee && Callee->arg_size() > unsigned(ArgNo))
758b1b441d2SJohannes Doerfert return Callee->getArg(ArgNo);
759b1b441d2SJohannes Doerfert
760b1b441d2SJohannes Doerfert return nullptr;
761b1b441d2SJohannes Doerfert }
762b1b441d2SJohannes Doerfert
update(Attributor & A)763ece81904SJohannes Doerfert ChangeStatus AbstractAttribute::update(Attributor &A) {
764aade782aSJohannes Doerfert ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
765aade782aSJohannes Doerfert if (getState().isAtFixpoint())
766aade782aSJohannes Doerfert return HasChanged;
767aade782aSJohannes Doerfert
768aade782aSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
769aade782aSJohannes Doerfert
770ece81904SJohannes Doerfert HasChanged = updateImpl(A);
771aade782aSJohannes Doerfert
772aade782aSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
773aade782aSJohannes Doerfert << "\n");
774aade782aSJohannes Doerfert
775aade782aSJohannes Doerfert return HasChanged;
776aade782aSJohannes Doerfert }
777aade782aSJohannes Doerfert
778d1b79e07SJohannes Doerfert ChangeStatus
manifestAttrs(Attributor & A,const IRPosition & IRP,const ArrayRef<Attribute> & DeducedAttrs,bool ForceReplace)779b2083c53SJohannes Doerfert IRAttributeManifest::manifestAttrs(Attributor &A, const IRPosition &IRP,
78096709823SKuter Dinel const ArrayRef<Attribute> &DeducedAttrs,
78196709823SKuter Dinel bool ForceReplace) {
782a650d555SStefanos Baziotis Function *ScopeFn = IRP.getAnchorScope();
78326e60f06SKristina Brooks IRPosition::Kind PK = IRP.getPositionKind();
784aade782aSJohannes Doerfert
785aade782aSJohannes Doerfert // In the following some generic code that will manifest attributes in
786aade782aSJohannes Doerfert // DeducedAttrs if they improve the current IR. Due to the different
787aade782aSJohannes Doerfert // annotation positions we use the underlying AttributeList interface.
788aade782aSJohannes Doerfert
789fb69f768SJohannes Doerfert AttributeList Attrs;
790fb69f768SJohannes Doerfert switch (PK) {
791710ebb03SJohannes Doerfert case IRPosition::IRP_INVALID:
792710ebb03SJohannes Doerfert case IRPosition::IRP_FLOAT:
79312cbbab9SJohannes Doerfert return ChangeStatus::UNCHANGED;
794fb69f768SJohannes Doerfert case IRPosition::IRP_ARGUMENT:
795fb69f768SJohannes Doerfert case IRPosition::IRP_FUNCTION:
796fb69f768SJohannes Doerfert case IRPosition::IRP_RETURNED:
797710ebb03SJohannes Doerfert Attrs = ScopeFn->getAttributes();
798aade782aSJohannes Doerfert break;
799710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE:
800710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE_RETURNED:
801fb69f768SJohannes Doerfert case IRPosition::IRP_CALL_SITE_ARGUMENT:
8025f6d93c7SCraig Topper Attrs = cast<CallBase>(IRP.getAnchorValue()).getAttributes();
803aade782aSJohannes Doerfert break;
804aade782aSJohannes Doerfert }
805aade782aSJohannes Doerfert
80612cbbab9SJohannes Doerfert ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
807710ebb03SJohannes Doerfert LLVMContext &Ctx = IRP.getAnchorValue().getContext();
808aade782aSJohannes Doerfert for (const Attribute &Attr : DeducedAttrs) {
80996709823SKuter Dinel if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx(), ForceReplace))
810aade782aSJohannes Doerfert continue;
811aade782aSJohannes Doerfert
812aade782aSJohannes Doerfert HasChanged = ChangeStatus::CHANGED;
813aade782aSJohannes Doerfert }
814aade782aSJohannes Doerfert
815aade782aSJohannes Doerfert if (HasChanged == ChangeStatus::UNCHANGED)
816aade782aSJohannes Doerfert return HasChanged;
817aade782aSJohannes Doerfert
818fb69f768SJohannes Doerfert switch (PK) {
819fb69f768SJohannes Doerfert case IRPosition::IRP_ARGUMENT:
820fb69f768SJohannes Doerfert case IRPosition::IRP_FUNCTION:
821fb69f768SJohannes Doerfert case IRPosition::IRP_RETURNED:
822710ebb03SJohannes Doerfert ScopeFn->setAttributes(Attrs);
823aade782aSJohannes Doerfert break;
824710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE:
825710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE_RETURNED:
826fb69f768SJohannes Doerfert case IRPosition::IRP_CALL_SITE_ARGUMENT:
8275f6d93c7SCraig Topper cast<CallBase>(IRP.getAnchorValue()).setAttributes(Attrs);
8284395b31dSJohannes Doerfert break;
829710ebb03SJohannes Doerfert case IRPosition::IRP_INVALID:
8304395b31dSJohannes Doerfert case IRPosition::IRP_FLOAT:
831710ebb03SJohannes Doerfert break;
832aade782aSJohannes Doerfert }
833aade782aSJohannes Doerfert
834aade782aSJohannes Doerfert return HasChanged;
835aade782aSJohannes Doerfert }
836aade782aSJohannes Doerfert
8378228153fSJohannes Doerfert const IRPosition IRPosition::EmptyKey(DenseMapInfo<void *>::getEmptyKey());
8388228153fSJohannes Doerfert const IRPosition
8398228153fSJohannes Doerfert IRPosition::TombstoneKey(DenseMapInfo<void *>::getTombstoneKey());
840710ebb03SJohannes Doerfert
SubsumingPositionIterator(const IRPosition & IRP)841710ebb03SJohannes Doerfert SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) {
842710ebb03SJohannes Doerfert IRPositions.emplace_back(IRP);
843710ebb03SJohannes Doerfert
844c0ab901bSJohannes Doerfert // Helper to determine if operand bundles on a call site are benin or
845c0ab901bSJohannes Doerfert // potentially problematic. We handle only llvm.assume for now.
846c0ab901bSJohannes Doerfert auto CanIgnoreOperandBundles = [](const CallBase &CB) {
847c0ab901bSJohannes Doerfert return (isa<IntrinsicInst>(CB) &&
848c0ab901bSJohannes Doerfert cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume);
849c0ab901bSJohannes Doerfert };
850c0ab901bSJohannes Doerfert
8515f6d93c7SCraig Topper const auto *CB = dyn_cast<CallBase>(&IRP.getAnchorValue());
852710ebb03SJohannes Doerfert switch (IRP.getPositionKind()) {
853710ebb03SJohannes Doerfert case IRPosition::IRP_INVALID:
854710ebb03SJohannes Doerfert case IRPosition::IRP_FLOAT:
855710ebb03SJohannes Doerfert case IRPosition::IRP_FUNCTION:
856710ebb03SJohannes Doerfert return;
857710ebb03SJohannes Doerfert case IRPosition::IRP_ARGUMENT:
858710ebb03SJohannes Doerfert case IRPosition::IRP_RETURNED:
859a650d555SStefanos Baziotis IRPositions.emplace_back(IRPosition::function(*IRP.getAnchorScope()));
860710ebb03SJohannes Doerfert return;
861710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE:
8625f6d93c7SCraig Topper assert(CB && "Expected call site!");
863710ebb03SJohannes Doerfert // TODO: We need to look at the operand bundles similar to the redirection
864710ebb03SJohannes Doerfert // in CallBase.
865c0ab901bSJohannes Doerfert if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
8665f6d93c7SCraig Topper if (const Function *Callee = CB->getCalledFunction())
867710ebb03SJohannes Doerfert IRPositions.emplace_back(IRPosition::function(*Callee));
868710ebb03SJohannes Doerfert return;
869710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE_RETURNED:
8705f6d93c7SCraig Topper assert(CB && "Expected call site!");
871710ebb03SJohannes Doerfert // TODO: We need to look at the operand bundles similar to the redirection
872710ebb03SJohannes Doerfert // in CallBase.
873c0ab901bSJohannes Doerfert if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
8745f6d93c7SCraig Topper if (const Function *Callee = CB->getCalledFunction()) {
875710ebb03SJohannes Doerfert IRPositions.emplace_back(IRPosition::returned(*Callee));
876710ebb03SJohannes Doerfert IRPositions.emplace_back(IRPosition::function(*Callee));
877f8ad7357SJohannes Doerfert for (const Argument &Arg : Callee->args())
878f8ad7357SJohannes Doerfert if (Arg.hasReturnedAttr()) {
879f8ad7357SJohannes Doerfert IRPositions.emplace_back(
8805f6d93c7SCraig Topper IRPosition::callsite_argument(*CB, Arg.getArgNo()));
881f8ad7357SJohannes Doerfert IRPositions.emplace_back(
8825f6d93c7SCraig Topper IRPosition::value(*CB->getArgOperand(Arg.getArgNo())));
883f8ad7357SJohannes Doerfert IRPositions.emplace_back(IRPosition::argument(Arg));
884f8ad7357SJohannes Doerfert }
885710ebb03SJohannes Doerfert }
886710ebb03SJohannes Doerfert }
8875f6d93c7SCraig Topper IRPositions.emplace_back(IRPosition::callsite_function(*CB));
888710ebb03SJohannes Doerfert return;
889710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE_ARGUMENT: {
890cefd2a2cSJohannes Doerfert assert(CB && "Expected call site!");
891710ebb03SJohannes Doerfert // TODO: We need to look at the operand bundles similar to the redirection
892710ebb03SJohannes Doerfert // in CallBase.
893c0ab901bSJohannes Doerfert if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
8945f6d93c7SCraig Topper const Function *Callee = CB->getCalledFunction();
895cefd2a2cSJohannes Doerfert if (Callee) {
896cefd2a2cSJohannes Doerfert if (Argument *Arg = IRP.getAssociatedArgument())
897cefd2a2cSJohannes Doerfert IRPositions.emplace_back(IRPosition::argument(*Arg));
898710ebb03SJohannes Doerfert IRPositions.emplace_back(IRPosition::function(*Callee));
899710ebb03SJohannes Doerfert }
900cefd2a2cSJohannes Doerfert }
901710ebb03SJohannes Doerfert IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue()));
902710ebb03SJohannes Doerfert return;
903710ebb03SJohannes Doerfert }
904710ebb03SJohannes Doerfert }
905710ebb03SJohannes Doerfert }
906710ebb03SJohannes Doerfert
hasAttr(ArrayRef<Attribute::AttrKind> AKs,bool IgnoreSubsumingPositions,Attributor * A) const9071097fab1SJohannes Doerfert bool IRPosition::hasAttr(ArrayRef<Attribute::AttrKind> AKs,
9085699d08bSJohannes Doerfert bool IgnoreSubsumingPositions, Attributor *A) const {
9096185fb13SJohannes Doerfert SmallVector<Attribute, 4> Attrs;
9101097fab1SJohannes Doerfert for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this)) {
911710ebb03SJohannes Doerfert for (Attribute::AttrKind AK : AKs)
9126185fb13SJohannes Doerfert if (EquivIRP.getAttrsFromIRAttr(AK, Attrs))
913710ebb03SJohannes Doerfert return true;
9141097fab1SJohannes Doerfert // The first position returned by the SubsumingPositionIterator is
9151097fab1SJohannes Doerfert // always the position itself. If we ignore subsuming positions we
9161097fab1SJohannes Doerfert // are done after the first iteration.
9171097fab1SJohannes Doerfert if (IgnoreSubsumingPositions)
9181097fab1SJohannes Doerfert break;
9191097fab1SJohannes Doerfert }
9205699d08bSJohannes Doerfert if (A)
9215699d08bSJohannes Doerfert for (Attribute::AttrKind AK : AKs)
9225699d08bSJohannes Doerfert if (getAttrsFromAssumes(AK, Attrs, *A))
9235699d08bSJohannes Doerfert return true;
924710ebb03SJohannes Doerfert return false;
925710ebb03SJohannes Doerfert }
926710ebb03SJohannes Doerfert
getAttrs(ArrayRef<Attribute::AttrKind> AKs,SmallVectorImpl<Attribute> & Attrs,bool IgnoreSubsumingPositions,Attributor * A) const927710ebb03SJohannes Doerfert void IRPosition::getAttrs(ArrayRef<Attribute::AttrKind> AKs,
9286abd01e4SJohannes Doerfert SmallVectorImpl<Attribute> &Attrs,
9295699d08bSJohannes Doerfert bool IgnoreSubsumingPositions, Attributor *A) const {
9306abd01e4SJohannes Doerfert for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this)) {
9316185fb13SJohannes Doerfert for (Attribute::AttrKind AK : AKs)
9326185fb13SJohannes Doerfert EquivIRP.getAttrsFromIRAttr(AK, Attrs);
9336abd01e4SJohannes Doerfert // The first position returned by the SubsumingPositionIterator is
9346abd01e4SJohannes Doerfert // always the position itself. If we ignore subsuming positions we
9356abd01e4SJohannes Doerfert // are done after the first iteration.
9366abd01e4SJohannes Doerfert if (IgnoreSubsumingPositions)
9376abd01e4SJohannes Doerfert break;
9386abd01e4SJohannes Doerfert }
9395699d08bSJohannes Doerfert if (A)
9405699d08bSJohannes Doerfert for (Attribute::AttrKind AK : AKs)
9415699d08bSJohannes Doerfert getAttrsFromAssumes(AK, Attrs, *A);
942710ebb03SJohannes Doerfert }
943710ebb03SJohannes Doerfert
getAttrsFromIRAttr(Attribute::AttrKind AK,SmallVectorImpl<Attribute> & Attrs) const9446185fb13SJohannes Doerfert bool IRPosition::getAttrsFromIRAttr(Attribute::AttrKind AK,
9456185fb13SJohannes Doerfert SmallVectorImpl<Attribute> &Attrs) const {
9466185fb13SJohannes Doerfert if (getPositionKind() == IRP_INVALID || getPositionKind() == IRP_FLOAT)
9476185fb13SJohannes Doerfert return false;
9486185fb13SJohannes Doerfert
9496185fb13SJohannes Doerfert AttributeList AttrList;
9505f6d93c7SCraig Topper if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue()))
9515f6d93c7SCraig Topper AttrList = CB->getAttributes();
9526185fb13SJohannes Doerfert else
9536185fb13SJohannes Doerfert AttrList = getAssociatedFunction()->getAttributes();
9546185fb13SJohannes Doerfert
95552e6d70cSArthur Eubanks bool HasAttr = AttrList.hasAttributeAtIndex(getAttrIdx(), AK);
9566185fb13SJohannes Doerfert if (HasAttr)
95752e6d70cSArthur Eubanks Attrs.push_back(AttrList.getAttributeAtIndex(getAttrIdx(), AK));
9586185fb13SJohannes Doerfert return HasAttr;
9596185fb13SJohannes Doerfert }
9606185fb13SJohannes Doerfert
getAttrsFromAssumes(Attribute::AttrKind AK,SmallVectorImpl<Attribute> & Attrs,Attributor & A) const9615699d08bSJohannes Doerfert bool IRPosition::getAttrsFromAssumes(Attribute::AttrKind AK,
9625699d08bSJohannes Doerfert SmallVectorImpl<Attribute> &Attrs,
9635699d08bSJohannes Doerfert Attributor &A) const {
9645699d08bSJohannes Doerfert assert(getPositionKind() != IRP_INVALID && "Did expect a valid position!");
9655699d08bSJohannes Doerfert Value &AssociatedValue = getAssociatedValue();
9665699d08bSJohannes Doerfert
9675699d08bSJohannes Doerfert const Assume2KnowledgeMap &A2K =
9685699d08bSJohannes Doerfert A.getInfoCache().getKnowledgeMap().lookup({&AssociatedValue, AK});
9695699d08bSJohannes Doerfert
9705699d08bSJohannes Doerfert // Check if we found any potential assume use, if not we don't need to create
9715699d08bSJohannes Doerfert // explorer iterators.
9725699d08bSJohannes Doerfert if (A2K.empty())
9735699d08bSJohannes Doerfert return false;
9745699d08bSJohannes Doerfert
9755699d08bSJohannes Doerfert LLVMContext &Ctx = AssociatedValue.getContext();
9765699d08bSJohannes Doerfert unsigned AttrsSize = Attrs.size();
9775699d08bSJohannes Doerfert MustBeExecutedContextExplorer &Explorer =
9785699d08bSJohannes Doerfert A.getInfoCache().getMustBeExecutedContextExplorer();
9795699d08bSJohannes Doerfert auto EIt = Explorer.begin(getCtxI()), EEnd = Explorer.end(getCtxI());
9805699d08bSJohannes Doerfert for (auto &It : A2K)
9815699d08bSJohannes Doerfert if (Explorer.findInContextOf(It.first, EIt, EEnd))
9825699d08bSJohannes Doerfert Attrs.push_back(Attribute::get(Ctx, AK, It.second.Max));
9835699d08bSJohannes Doerfert return AttrsSize != Attrs.size();
9845699d08bSJohannes Doerfert }
9855699d08bSJohannes Doerfert
verify()986710ebb03SJohannes Doerfert void IRPosition::verify() {
987f20ff4b1SJohannes Doerfert #ifdef EXPENSIVE_CHECKS
9888228153fSJohannes Doerfert switch (getPositionKind()) {
989710ebb03SJohannes Doerfert case IRP_INVALID:
990d75c9e61Skuterd assert((CBContext == nullptr) &&
991d75c9e61Skuterd "Invalid position must not have CallBaseContext!");
9928228153fSJohannes Doerfert assert(!Enc.getOpaqueValue() &&
9938228153fSJohannes Doerfert "Expected a nullptr for an invalid position!");
9948228153fSJohannes Doerfert return;
995710ebb03SJohannes Doerfert case IRP_FLOAT:
9963b8ffe66SJohannes Doerfert assert((!isa<Argument>(&getAssociatedValue())) &&
9973b8ffe66SJohannes Doerfert "Expected specialized kind for argument values!");
9988228153fSJohannes Doerfert return;
999710ebb03SJohannes Doerfert case IRP_RETURNED:
10008228153fSJohannes Doerfert assert(isa<Function>(getAsValuePtr()) &&
1001710ebb03SJohannes Doerfert "Expected function for a 'returned' position!");
10028228153fSJohannes Doerfert assert(getAsValuePtr() == &getAssociatedValue() &&
10038228153fSJohannes Doerfert "Associated value mismatch!");
10048228153fSJohannes Doerfert return;
1005710ebb03SJohannes Doerfert case IRP_CALL_SITE_RETURNED:
1006d75c9e61Skuterd assert((CBContext == nullptr) &&
1007d75c9e61Skuterd "'call site returned' position must not have CallBaseContext!");
10088228153fSJohannes Doerfert assert((isa<CallBase>(getAsValuePtr())) &&
1009710ebb03SJohannes Doerfert "Expected call base for 'call site returned' position!");
10108228153fSJohannes Doerfert assert(getAsValuePtr() == &getAssociatedValue() &&
10118228153fSJohannes Doerfert "Associated value mismatch!");
10128228153fSJohannes Doerfert return;
1013710ebb03SJohannes Doerfert case IRP_CALL_SITE:
1014d75c9e61Skuterd assert((CBContext == nullptr) &&
1015d75c9e61Skuterd "'call site function' position must not have CallBaseContext!");
10168228153fSJohannes Doerfert assert((isa<CallBase>(getAsValuePtr())) &&
1017710ebb03SJohannes Doerfert "Expected call base for 'call site function' position!");
10188228153fSJohannes Doerfert assert(getAsValuePtr() == &getAssociatedValue() &&
10198228153fSJohannes Doerfert "Associated value mismatch!");
10208228153fSJohannes Doerfert return;
1021710ebb03SJohannes Doerfert case IRP_FUNCTION:
10228228153fSJohannes Doerfert assert(isa<Function>(getAsValuePtr()) &&
1023710ebb03SJohannes Doerfert "Expected function for a 'function' position!");
10248228153fSJohannes Doerfert assert(getAsValuePtr() == &getAssociatedValue() &&
10258228153fSJohannes Doerfert "Associated value mismatch!");
10268228153fSJohannes Doerfert return;
10278228153fSJohannes Doerfert case IRP_ARGUMENT:
10288228153fSJohannes Doerfert assert(isa<Argument>(getAsValuePtr()) &&
10298228153fSJohannes Doerfert "Expected argument for a 'argument' position!");
10308228153fSJohannes Doerfert assert(getAsValuePtr() == &getAssociatedValue() &&
10318228153fSJohannes Doerfert "Associated value mismatch!");
10328228153fSJohannes Doerfert return;
10338228153fSJohannes Doerfert case IRP_CALL_SITE_ARGUMENT: {
1034d75c9e61Skuterd assert((CBContext == nullptr) &&
1035d75c9e61Skuterd "'call site argument' position must not have CallBaseContext!");
10368228153fSJohannes Doerfert Use *U = getAsUsePtr();
1037e550dfa4SSjoerd Meijer (void)U; // Silence unused variable warning.
10388228153fSJohannes Doerfert assert(U && "Expected use for a 'call site argument' position!");
10398228153fSJohannes Doerfert assert(isa<CallBase>(U->getUser()) &&
10408228153fSJohannes Doerfert "Expected call base user for a 'call site argument' position!");
10418228153fSJohannes Doerfert assert(cast<CallBase>(U->getUser())->isArgOperand(U) &&
10428228153fSJohannes Doerfert "Expected call base argument operand for a 'call site argument' "
10438228153fSJohannes Doerfert "position");
10448228153fSJohannes Doerfert assert(cast<CallBase>(U->getUser())->getArgOperandNo(U) ==
1045cefd2a2cSJohannes Doerfert unsigned(getCallSiteArgNo()) &&
10468228153fSJohannes Doerfert "Argument number mismatch!");
10478228153fSJohannes Doerfert assert(U->get() == &getAssociatedValue() && "Associated value mismatch!");
10488228153fSJohannes Doerfert return;
10498228153fSJohannes Doerfert }
1050710ebb03SJohannes Doerfert }
1051f20ff4b1SJohannes Doerfert #endif
1052710ebb03SJohannes Doerfert }
1053710ebb03SJohannes Doerfert
10540985554bSJohannes Doerfert Optional<Constant *>
getAssumedConstant(const IRPosition & IRP,const AbstractAttribute & AA,bool & UsedAssumedInformation)1055c819266eSJohannes Doerfert Attributor::getAssumedConstant(const IRPosition &IRP,
1056c819266eSJohannes Doerfert const AbstractAttribute &AA,
10570985554bSJohannes Doerfert bool &UsedAssumedInformation) {
1058d9659bf6SJohannes Doerfert // First check all callbacks provided by outside AAs. If any of them returns
1059d9659bf6SJohannes Doerfert // a non-null value that is different from the associated value, or None, we
1060982053e8SJohannes Doerfert // assume it's simplified.
10613dca8396SJohannes Doerfert for (auto &CB : SimplificationCallbacks.lookup(IRP)) {
1062d9659bf6SJohannes Doerfert Optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);
1063e0e687a6SKazu Hirata if (!SimplifiedV)
1064d9659bf6SJohannes Doerfert return llvm::None;
1065c819266eSJohannes Doerfert if (isa_and_nonnull<Constant>(*SimplifiedV))
1066d9659bf6SJohannes Doerfert return cast<Constant>(*SimplifiedV);
1067c819266eSJohannes Doerfert return nullptr;
1068d9659bf6SJohannes Doerfert }
1069ae10b8a5SJohannes Doerfert if (auto *C = dyn_cast<Constant>(&IRP.getAssociatedValue()))
1070ae10b8a5SJohannes Doerfert return C;
1071bf789b19SJohannes Doerfert SmallVector<AA::ValueAndContext> Values;
1072bf789b19SJohannes Doerfert if (getAssumedSimplifiedValues(IRP, &AA, Values,
1073bf789b19SJohannes Doerfert AA::ValueScope::Interprocedural,
1074bf789b19SJohannes Doerfert UsedAssumedInformation)) {
1075bf789b19SJohannes Doerfert if (Values.empty())
1076ef4febd8SHideto Ueno return llvm::None;
1077bf789b19SJohannes Doerfert if (auto *C = dyn_cast_or_null<Constant>(
1078bf789b19SJohannes Doerfert AAPotentialValues::getSingleValue(*this, AA, IRP, Values)))
1079bf789b19SJohannes Doerfert return C;
1080ef4febd8SHideto Ueno }
1081bf789b19SJohannes Doerfert return nullptr;
1082188f9a34SHideto Ueno }
1083aade782aSJohannes Doerfert
getAssumedSimplified(const IRPosition & IRP,const AbstractAttribute * AA,bool & UsedAssumedInformation,AA::ValueScope S)1084bf789b19SJohannes Doerfert Optional<Value *> Attributor::getAssumedSimplified(const IRPosition &IRP,
1085666dc6f1SJohannes Doerfert const AbstractAttribute *AA,
1086bf789b19SJohannes Doerfert bool &UsedAssumedInformation,
1087bf789b19SJohannes Doerfert AA::ValueScope S) {
1088666dc6f1SJohannes Doerfert // First check all callbacks provided by outside AAs. If any of them returns
1089666dc6f1SJohannes Doerfert // a non-null value that is different from the associated value, or None, we
1090982053e8SJohannes Doerfert // assume it's simplified.
10913dca8396SJohannes Doerfert for (auto &CB : SimplificationCallbacks.lookup(IRP))
10926ca96935SJohannes Doerfert return CB(IRP, AA, UsedAssumedInformation);
1093666dc6f1SJohannes Doerfert
1094bf789b19SJohannes Doerfert SmallVector<AA::ValueAndContext> Values;
1095bf789b19SJohannes Doerfert if (!getAssumedSimplifiedValues(IRP, AA, Values, S, UsedAssumedInformation))
1096bf789b19SJohannes Doerfert return &IRP.getAssociatedValue();
1097bf789b19SJohannes Doerfert if (Values.empty())
1098f6e0c05eSJohannes Doerfert return llvm::None;
1099f6e0c05eSJohannes Doerfert if (AA)
1100bf789b19SJohannes Doerfert if (Value *V = AAPotentialValues::getSingleValue(*this, *AA, IRP, Values))
1101bf789b19SJohannes Doerfert return V;
1102bf789b19SJohannes Doerfert if (IRP.getPositionKind() == IRPosition::IRP_RETURNED ||
1103bf789b19SJohannes Doerfert IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED)
1104bf789b19SJohannes Doerfert return nullptr;
1105bf789b19SJohannes Doerfert return &IRP.getAssociatedValue();
1106f17639eaSJohannes Doerfert }
1107bf789b19SJohannes Doerfert
getAssumedSimplifiedValues(const IRPosition & IRP,const AbstractAttribute * AA,SmallVectorImpl<AA::ValueAndContext> & Values,AA::ValueScope S,bool & UsedAssumedInformation)1108bf789b19SJohannes Doerfert bool Attributor::getAssumedSimplifiedValues(
1109bf789b19SJohannes Doerfert const IRPosition &IRP, const AbstractAttribute *AA,
1110bf789b19SJohannes Doerfert SmallVectorImpl<AA::ValueAndContext> &Values, AA::ValueScope S,
1111bf789b19SJohannes Doerfert bool &UsedAssumedInformation) {
1112bf789b19SJohannes Doerfert // First check all callbacks provided by outside AAs. If any of them returns
1113bf789b19SJohannes Doerfert // a non-null value that is different from the associated value, or None, we
1114bf789b19SJohannes Doerfert // assume it's simplified.
1115bf789b19SJohannes Doerfert const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1116bf789b19SJohannes Doerfert for (auto &CB : SimplificationCBs) {
1117bf789b19SJohannes Doerfert Optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);
111841ae78eaSKazu Hirata if (!CBResult.has_value())
1119bf789b19SJohannes Doerfert continue;
11200387da6fSKazu Hirata Value *V = CBResult.value();
1121bf789b19SJohannes Doerfert if (!V)
1122bf789b19SJohannes Doerfert return false;
1123bf789b19SJohannes Doerfert if ((S & AA::ValueScope::Interprocedural) ||
1124bf789b19SJohannes Doerfert AA::isValidInScope(*V, IRP.getAnchorScope()))
1125bf789b19SJohannes Doerfert Values.push_back(AA::ValueAndContext{*V, nullptr});
1126bf789b19SJohannes Doerfert else
1127bf789b19SJohannes Doerfert return false;
1128bf789b19SJohannes Doerfert }
1129bf789b19SJohannes Doerfert if (!SimplificationCBs.empty())
1130bf789b19SJohannes Doerfert return true;
1131bf789b19SJohannes Doerfert
1132bf789b19SJohannes Doerfert // If no high-level/outside simplification occurred, use AAPotentialValues.
1133bf789b19SJohannes Doerfert const auto &PotentialValuesAA =
1134bf789b19SJohannes Doerfert getOrCreateAAFor<AAPotentialValues>(IRP, AA, DepClassTy::OPTIONAL);
1135bf789b19SJohannes Doerfert if (!PotentialValuesAA.getAssumedSimplifiedValues(*this, Values, S))
1136bf789b19SJohannes Doerfert return false;
1137bf789b19SJohannes Doerfert UsedAssumedInformation |= !PotentialValuesAA.isAtFixpoint();
1138bf789b19SJohannes Doerfert return true;
1139666dc6f1SJohannes Doerfert }
1140666dc6f1SJohannes Doerfert
translateArgumentToCallSiteContent(Optional<Value * > V,CallBase & CB,const AbstractAttribute & AA,bool & UsedAssumedInformation)11415ef18e24SJohannes Doerfert Optional<Value *> Attributor::translateArgumentToCallSiteContent(
11425ef18e24SJohannes Doerfert Optional<Value *> V, CallBase &CB, const AbstractAttribute &AA,
11435ef18e24SJohannes Doerfert bool &UsedAssumedInformation) {
1144e0e687a6SKazu Hirata if (!V)
11455ef18e24SJohannes Doerfert return V;
11465ef18e24SJohannes Doerfert if (*V == nullptr || isa<Constant>(*V))
11475ef18e24SJohannes Doerfert return V;
11485ef18e24SJohannes Doerfert if (auto *Arg = dyn_cast<Argument>(*V))
114928c78a9eSJohannes Doerfert if (CB.getCalledFunction() == Arg->getParent())
11505ef18e24SJohannes Doerfert if (!Arg->hasPointeeInMemoryValueAttr())
11515ef18e24SJohannes Doerfert return getAssumedSimplified(
11525ef18e24SJohannes Doerfert IRPosition::callsite_argument(CB, Arg->getArgNo()), AA,
1153bf789b19SJohannes Doerfert UsedAssumedInformation, AA::Intraprocedural);
11545ef18e24SJohannes Doerfert return nullptr;
11555ef18e24SJohannes Doerfert }
11565ef18e24SJohannes Doerfert
~Attributor()115741f2a57dSJohannes Doerfert Attributor::~Attributor() {
115841f2a57dSJohannes Doerfert // The abstract attributes are allocated via the BumpPtrAllocator Allocator,
115941f2a57dSJohannes Doerfert // thus we cannot delete them. We can, and want to, destruct them though.
11605ee07dc5SLuofan Chen for (auto &DepAA : DG.SyntheticRoot.Deps) {
11615ee07dc5SLuofan Chen AbstractAttribute *AA = cast<AbstractAttribute>(DepAA.getPointer());
116241f2a57dSJohannes Doerfert AA->~AbstractAttribute();
116341f2a57dSJohannes Doerfert }
11645ee07dc5SLuofan Chen }
116541f2a57dSJohannes Doerfert
isAssumedDead(const AbstractAttribute & AA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass)11669a1a1f96SJohannes Doerfert bool Attributor::isAssumedDead(const AbstractAttribute &AA,
116723f41f16SJohannes Doerfert const AAIsDead *FnLivenessAA,
1168792aac98SJohannes Doerfert bool &UsedAssumedInformation,
116923f41f16SJohannes Doerfert bool CheckBBLivenessOnly, DepClassTy DepClass) {
117023f41f16SJohannes Doerfert const IRPosition &IRP = AA.getIRPosition();
117123f41f16SJohannes Doerfert if (!Functions.count(IRP.getAnchorScope()))
11729a1a1f96SJohannes Doerfert return false;
1173792aac98SJohannes Doerfert return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
1174792aac98SJohannes Doerfert CheckBBLivenessOnly, DepClass);
117523f41f16SJohannes Doerfert }
11769a1a1f96SJohannes Doerfert
isAssumedDead(const Use & U,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass)117723f41f16SJohannes Doerfert bool Attributor::isAssumedDead(const Use &U,
117823f41f16SJohannes Doerfert const AbstractAttribute *QueryingAA,
117923f41f16SJohannes Doerfert const AAIsDead *FnLivenessAA,
1180792aac98SJohannes Doerfert bool &UsedAssumedInformation,
118123f41f16SJohannes Doerfert bool CheckBBLivenessOnly, DepClassTy DepClass) {
118223f41f16SJohannes Doerfert Instruction *UserI = dyn_cast<Instruction>(U.getUser());
118323f41f16SJohannes Doerfert if (!UserI)
118423f41f16SJohannes Doerfert return isAssumedDead(IRPosition::value(*U.get()), QueryingAA, FnLivenessAA,
1185792aac98SJohannes Doerfert UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
118623f41f16SJohannes Doerfert
11875f6d93c7SCraig Topper if (auto *CB = dyn_cast<CallBase>(UserI)) {
118823f41f16SJohannes Doerfert // For call site argument uses we can check if the argument is
118923f41f16SJohannes Doerfert // unused/dead.
11905f6d93c7SCraig Topper if (CB->isArgOperand(&U)) {
119123f41f16SJohannes Doerfert const IRPosition &CSArgPos =
11925f6d93c7SCraig Topper IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
119323f41f16SJohannes Doerfert return isAssumedDead(CSArgPos, QueryingAA, FnLivenessAA,
1194792aac98SJohannes Doerfert UsedAssumedInformation, CheckBBLivenessOnly,
1195792aac98SJohannes Doerfert DepClass);
119623f41f16SJohannes Doerfert }
119723f41f16SJohannes Doerfert } else if (ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
119823f41f16SJohannes Doerfert const IRPosition &RetPos = IRPosition::returned(*RI->getFunction());
1199792aac98SJohannes Doerfert return isAssumedDead(RetPos, QueryingAA, FnLivenessAA,
1200792aac98SJohannes Doerfert UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
120123f41f16SJohannes Doerfert } else if (PHINode *PHI = dyn_cast<PHINode>(UserI)) {
120223f41f16SJohannes Doerfert BasicBlock *IncomingBB = PHI->getIncomingBlock(U);
120323f41f16SJohannes Doerfert return isAssumedDead(*IncomingBB->getTerminator(), QueryingAA, FnLivenessAA,
1204792aac98SJohannes Doerfert UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1205c42aa1beSJohannes Doerfert } else if (StoreInst *SI = dyn_cast<StoreInst>(UserI)) {
1206c42aa1beSJohannes Doerfert if (!CheckBBLivenessOnly && SI->getPointerOperand() != U.get()) {
1207c42aa1beSJohannes Doerfert const IRPosition IRP = IRPosition::inst(*SI);
1208c42aa1beSJohannes Doerfert const AAIsDead &IsDeadAA =
1209c42aa1beSJohannes Doerfert getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);
1210c42aa1beSJohannes Doerfert if (IsDeadAA.isRemovableStore()) {
1211c42aa1beSJohannes Doerfert if (QueryingAA)
1212c42aa1beSJohannes Doerfert recordDependence(IsDeadAA, *QueryingAA, DepClass);
1213c42aa1beSJohannes Doerfert if (!IsDeadAA.isKnown(AAIsDead::IS_REMOVABLE))
1214c42aa1beSJohannes Doerfert UsedAssumedInformation = true;
1215c42aa1beSJohannes Doerfert return true;
1216c42aa1beSJohannes Doerfert }
1217c42aa1beSJohannes Doerfert }
121823f41f16SJohannes Doerfert }
121923f41f16SJohannes Doerfert
1220a1db0e52SJohannes Doerfert return isAssumedDead(IRPosition::inst(*UserI), QueryingAA, FnLivenessAA,
1221792aac98SJohannes Doerfert UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
122223f41f16SJohannes Doerfert }
122323f41f16SJohannes Doerfert
isAssumedDead(const Instruction & I,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass)122423f41f16SJohannes Doerfert bool Attributor::isAssumedDead(const Instruction &I,
122523f41f16SJohannes Doerfert const AbstractAttribute *QueryingAA,
122623f41f16SJohannes Doerfert const AAIsDead *FnLivenessAA,
1227792aac98SJohannes Doerfert bool &UsedAssumedInformation,
122823f41f16SJohannes Doerfert bool CheckBBLivenessOnly, DepClassTy DepClass) {
122964ef29bcSKuter Dinel const IRPosition::CallBaseContext *CBCtx =
123064ef29bcSKuter Dinel QueryingAA ? QueryingAA->getCallBaseContext() : nullptr;
123164ef29bcSKuter Dinel
12323f71b425SGiorgis Georgakoudis if (ManifestAddedBlocks.contains(I.getParent()))
12333f71b425SGiorgis Georgakoudis return false;
12343f71b425SGiorgis Georgakoudis
12355011b4caSEvgenii Stepanov if (!FnLivenessAA)
12365011b4caSEvgenii Stepanov FnLivenessAA =
12375011b4caSEvgenii Stepanov lookupAAFor<AAIsDead>(IRPosition::function(*I.getFunction(), CBCtx),
12385011b4caSEvgenii Stepanov QueryingAA, DepClassTy::NONE);
123926121ae4SStefan Stipanovic
124023f41f16SJohannes Doerfert // If we have a context instruction and a liveness AA we use it.
12415011b4caSEvgenii Stepanov if (FnLivenessAA &&
12425011b4caSEvgenii Stepanov FnLivenessAA->getIRPosition().getAnchorScope() == I.getFunction() &&
12435011b4caSEvgenii Stepanov (CheckBBLivenessOnly ? FnLivenessAA->isAssumedDead(I.getParent())
12445011b4caSEvgenii Stepanov : FnLivenessAA->isAssumedDead(&I))) {
124523f41f16SJohannes Doerfert if (QueryingAA)
124623f41f16SJohannes Doerfert recordDependence(*FnLivenessAA, *QueryingAA, DepClass);
1247792aac98SJohannes Doerfert if (!FnLivenessAA->isKnownDead(&I))
1248792aac98SJohannes Doerfert UsedAssumedInformation = true;
12499a1a1f96SJohannes Doerfert return true;
12509a1a1f96SJohannes Doerfert }
12519a1a1f96SJohannes Doerfert
125223f41f16SJohannes Doerfert if (CheckBBLivenessOnly)
125323f41f16SJohannes Doerfert return false;
125423f41f16SJohannes Doerfert
1255a1db0e52SJohannes Doerfert const IRPosition IRP = IRPosition::inst(I, CBCtx);
1256a1db0e52SJohannes Doerfert const AAIsDead &IsDeadAA =
1257a1db0e52SJohannes Doerfert getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);
125823f41f16SJohannes Doerfert // Don't check liveness for AAIsDead.
125923f41f16SJohannes Doerfert if (QueryingAA == &IsDeadAA)
126023f41f16SJohannes Doerfert return false;
126123f41f16SJohannes Doerfert
126223f41f16SJohannes Doerfert if (IsDeadAA.isAssumedDead()) {
126323f41f16SJohannes Doerfert if (QueryingAA)
126423f41f16SJohannes Doerfert recordDependence(IsDeadAA, *QueryingAA, DepClass);
1265792aac98SJohannes Doerfert if (!IsDeadAA.isKnownDead())
1266792aac98SJohannes Doerfert UsedAssumedInformation = true;
126723f41f16SJohannes Doerfert return true;
126823f41f16SJohannes Doerfert }
126923f41f16SJohannes Doerfert
127023f41f16SJohannes Doerfert return false;
127123f41f16SJohannes Doerfert }
127223f41f16SJohannes Doerfert
isAssumedDead(const IRPosition & IRP,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,DepClassTy DepClass)127323f41f16SJohannes Doerfert bool Attributor::isAssumedDead(const IRPosition &IRP,
127423f41f16SJohannes Doerfert const AbstractAttribute *QueryingAA,
127523f41f16SJohannes Doerfert const AAIsDead *FnLivenessAA,
1276792aac98SJohannes Doerfert bool &UsedAssumedInformation,
127723f41f16SJohannes Doerfert bool CheckBBLivenessOnly, DepClassTy DepClass) {
127823f41f16SJohannes Doerfert Instruction *CtxI = IRP.getCtxI();
127923f41f16SJohannes Doerfert if (CtxI &&
1280792aac98SJohannes Doerfert isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
128123f41f16SJohannes Doerfert /* CheckBBLivenessOnly */ true,
128223f41f16SJohannes Doerfert CheckBBLivenessOnly ? DepClass : DepClassTy::OPTIONAL))
128323f41f16SJohannes Doerfert return true;
128423f41f16SJohannes Doerfert
128523f41f16SJohannes Doerfert if (CheckBBLivenessOnly)
128623f41f16SJohannes Doerfert return false;
128723f41f16SJohannes Doerfert
128823f41f16SJohannes Doerfert // If we haven't succeeded we query the specific liveness info for the IRP.
128923f41f16SJohannes Doerfert const AAIsDead *IsDeadAA;
129023f41f16SJohannes Doerfert if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE)
129123f41f16SJohannes Doerfert IsDeadAA = &getOrCreateAAFor<AAIsDead>(
129223f41f16SJohannes Doerfert IRPosition::callsite_returned(cast<CallBase>(IRP.getAssociatedValue())),
1293e592dad8SJohannes Doerfert QueryingAA, DepClassTy::NONE);
129423f41f16SJohannes Doerfert else
1295e592dad8SJohannes Doerfert IsDeadAA = &getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);
129623f41f16SJohannes Doerfert // Don't check liveness for AAIsDead.
129723f41f16SJohannes Doerfert if (QueryingAA == IsDeadAA)
129823f41f16SJohannes Doerfert return false;
129923f41f16SJohannes Doerfert
130023f41f16SJohannes Doerfert if (IsDeadAA->isAssumedDead()) {
130123f41f16SJohannes Doerfert if (QueryingAA)
130223f41f16SJohannes Doerfert recordDependence(*IsDeadAA, *QueryingAA, DepClass);
1303792aac98SJohannes Doerfert if (!IsDeadAA->isKnownDead())
1304792aac98SJohannes Doerfert UsedAssumedInformation = true;
130523f41f16SJohannes Doerfert return true;
130623f41f16SJohannes Doerfert }
130723f41f16SJohannes Doerfert
130823f41f16SJohannes Doerfert return false;
130923f41f16SJohannes Doerfert }
131023f41f16SJohannes Doerfert
isAssumedDead(const BasicBlock & BB,const AbstractAttribute * QueryingAA,const AAIsDead * FnLivenessAA,DepClassTy DepClass)131196709823SKuter Dinel bool Attributor::isAssumedDead(const BasicBlock &BB,
131296709823SKuter Dinel const AbstractAttribute *QueryingAA,
131396709823SKuter Dinel const AAIsDead *FnLivenessAA,
131496709823SKuter Dinel DepClassTy DepClass) {
13155011b4caSEvgenii Stepanov if (!FnLivenessAA)
13165011b4caSEvgenii Stepanov FnLivenessAA = lookupAAFor<AAIsDead>(IRPosition::function(*BB.getParent()),
13175011b4caSEvgenii Stepanov QueryingAA, DepClassTy::NONE);
131896709823SKuter Dinel if (FnLivenessAA->isAssumedDead(&BB)) {
131996709823SKuter Dinel if (QueryingAA)
132096709823SKuter Dinel recordDependence(*FnLivenessAA, *QueryingAA, DepClass);
132196709823SKuter Dinel return true;
132296709823SKuter Dinel }
132396709823SKuter Dinel
132496709823SKuter Dinel return false;
132596709823SKuter Dinel }
132696709823SKuter Dinel
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)13276e2fcf85SJohannes Doerfert bool Attributor::checkForAllUses(
13286e2fcf85SJohannes Doerfert function_ref<bool(const Use &, bool &)> Pred,
13296e2fcf85SJohannes Doerfert const AbstractAttribute &QueryingAA, const Value &V,
13306e2fcf85SJohannes Doerfert bool CheckBBLivenessOnly, DepClassTy LivenessDepClass,
13313e8c4366SJohannes Doerfert bool IgnoreDroppableUses,
13326e2fcf85SJohannes Doerfert function_ref<bool(const Use &OldU, const Use &NewU)> EquivalentUseCB) {
1333b2c76002SJohannes Doerfert
1334b2c76002SJohannes Doerfert // Check the trivial case first as it catches void values.
1335b2c76002SJohannes Doerfert if (V.use_empty())
1336b2c76002SJohannes Doerfert return true;
1337b2c76002SJohannes Doerfert
1338cd4aab4aSJohannes Doerfert const IRPosition &IRP = QueryingAA.getIRPosition();
1339cd4aab4aSJohannes Doerfert SmallVector<const Use *, 16> Worklist;
1340cd4aab4aSJohannes Doerfert SmallPtrSet<const Use *, 16> Visited;
1341cd4aab4aSJohannes Doerfert
1342f84712f0SJohannes Doerfert auto AddUsers = [&](const Value &V, const Use *OldUse) {
1343f84712f0SJohannes Doerfert for (const Use &UU : V.uses()) {
1344f84712f0SJohannes Doerfert if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1345f84712f0SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Potential copy was "
1346f84712f0SJohannes Doerfert "rejected by the equivalence call back: "
1347f84712f0SJohannes Doerfert << *UU << "!\n");
1348f84712f0SJohannes Doerfert return false;
1349f84712f0SJohannes Doerfert }
1350f84712f0SJohannes Doerfert
1351f84712f0SJohannes Doerfert Worklist.push_back(&UU);
1352f84712f0SJohannes Doerfert }
1353f84712f0SJohannes Doerfert return true;
1354f84712f0SJohannes Doerfert };
1355f84712f0SJohannes Doerfert
1356f84712f0SJohannes Doerfert AddUsers(V, /* OldUse */ nullptr);
1357cd4aab4aSJohannes Doerfert
1358cd4aab4aSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Got " << Worklist.size()
1359cd4aab4aSJohannes Doerfert << " initial uses to check\n");
1360cd4aab4aSJohannes Doerfert
1361cd4aab4aSJohannes Doerfert const Function *ScopeFn = IRP.getAnchorScope();
1362cd4aab4aSJohannes Doerfert const auto *LivenessAA =
1363cd4aab4aSJohannes Doerfert ScopeFn ? &getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*ScopeFn),
1364e592dad8SJohannes Doerfert DepClassTy::NONE)
1365cd4aab4aSJohannes Doerfert : nullptr;
1366cd4aab4aSJohannes Doerfert
1367cd4aab4aSJohannes Doerfert while (!Worklist.empty()) {
1368cd4aab4aSJohannes Doerfert const Use *U = Worklist.pop_back_val();
136996da6dd6SJohannes Doerfert if (isa<PHINode>(U->getUser()) && !Visited.insert(U).second)
1370cd4aab4aSJohannes Doerfert continue;
1371191fa419SJohannes Doerfert LLVM_DEBUG({
1372191fa419SJohannes Doerfert if (auto *Fn = dyn_cast<Function>(U->getUser()))
1373191fa419SJohannes Doerfert dbgs() << "[Attributor] Check use: " << **U << " in " << Fn->getName()
1374191fa419SJohannes Doerfert << "\n";
1375191fa419SJohannes Doerfert else
1376191fa419SJohannes Doerfert dbgs() << "[Attributor] Check use: " << **U << " in " << *U->getUser()
1377191fa419SJohannes Doerfert << "\n";
1378191fa419SJohannes Doerfert });
1379792aac98SJohannes Doerfert bool UsedAssumedInformation = false;
1380792aac98SJohannes Doerfert if (isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1381c2281f15SJohannes Doerfert CheckBBLivenessOnly, LivenessDepClass)) {
138223f41f16SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Dead use, skip!\n");
1383cd4aab4aSJohannes Doerfert continue;
1384cd4aab4aSJohannes Doerfert }
13853e8c4366SJohannes Doerfert if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
13865699d08bSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Droppable user, skip!\n");
13875699d08bSJohannes Doerfert continue;
13885699d08bSJohannes Doerfert }
1389cd4aab4aSJohannes Doerfert
1390adddd3dbSJohannes Doerfert if (auto *SI = dyn_cast<StoreInst>(U->getUser())) {
1391adddd3dbSJohannes Doerfert if (&SI->getOperandUse(0) == U) {
1392e05940deSJohannes Doerfert if (!Visited.insert(U).second)
1393e05940deSJohannes Doerfert continue;
1394adddd3dbSJohannes Doerfert SmallSetVector<Value *, 4> PotentialCopies;
139555a970fbSJohannes Doerfert if (AA::getPotentialCopiesOfStoredValue(
139655a970fbSJohannes Doerfert *this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
139755a970fbSJohannes Doerfert /* OnlyExact */ true)) {
1398adddd3dbSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Value is stored, continue with "
1399adddd3dbSJohannes Doerfert << PotentialCopies.size()
1400adddd3dbSJohannes Doerfert << " potential copies instead!\n");
1401adddd3dbSJohannes Doerfert for (Value *PotentialCopy : PotentialCopies)
1402f84712f0SJohannes Doerfert if (!AddUsers(*PotentialCopy, U))
14036e2fcf85SJohannes Doerfert return false;
1404adddd3dbSJohannes Doerfert continue;
1405adddd3dbSJohannes Doerfert }
1406adddd3dbSJohannes Doerfert }
1407adddd3dbSJohannes Doerfert }
1408adddd3dbSJohannes Doerfert
1409cd4aab4aSJohannes Doerfert bool Follow = false;
1410cd4aab4aSJohannes Doerfert if (!Pred(*U, Follow))
1411cd4aab4aSJohannes Doerfert return false;
1412cd4aab4aSJohannes Doerfert if (!Follow)
1413cd4aab4aSJohannes Doerfert continue;
1414f84712f0SJohannes Doerfert
1415f84712f0SJohannes Doerfert User &Usr = *U->getUser();
1416f84712f0SJohannes Doerfert AddUsers(Usr, /* OldUse */ nullptr);
1417f84712f0SJohannes Doerfert
1418f84712f0SJohannes Doerfert auto *RI = dyn_cast<ReturnInst>(&Usr);
1419f84712f0SJohannes Doerfert if (!RI)
1420f84712f0SJohannes Doerfert continue;
1421f84712f0SJohannes Doerfert
1422f84712f0SJohannes Doerfert Function &F = *RI->getFunction();
1423f84712f0SJohannes Doerfert auto CallSitePred = [&](AbstractCallSite ACS) {
1424f84712f0SJohannes Doerfert return AddUsers(*ACS.getInstruction(), U);
1425f84712f0SJohannes Doerfert };
1426f84712f0SJohannes Doerfert if (!checkForAllCallSites(CallSitePred, F, /* RequireAllCallSites */ true,
1427f84712f0SJohannes Doerfert &QueryingAA, UsedAssumedInformation)) {
1428f84712f0SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Could not follow return instruction "
1429f84712f0SJohannes Doerfert "to all call sites: "
1430f84712f0SJohannes Doerfert << *RI << "\n");
1431f84712f0SJohannes Doerfert return false;
1432f84712f0SJohannes Doerfert }
1433cd4aab4aSJohannes Doerfert }
1434cd4aab4aSJohannes Doerfert
1435cd4aab4aSJohannes Doerfert return true;
1436cd4aab4aSJohannes Doerfert }
1437cd4aab4aSJohannes Doerfert
checkForAllCallSites(function_ref<bool (AbstractCallSite)> Pred,const AbstractAttribute & QueryingAA,bool RequireAllCallSites,bool & UsedAssumedInformation)1438c57689beSJohannes Doerfert bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred,
1439c57689beSJohannes Doerfert const AbstractAttribute &QueryingAA,
1440c57689beSJohannes Doerfert bool RequireAllCallSites,
14416ed1ef06SJohannes Doerfert bool &UsedAssumedInformation) {
144254869ec9SHideto Ueno // We can try to determine information from
144354869ec9SHideto Ueno // the call sites. However, this is only possible all call sites are known,
144454869ec9SHideto Ueno // hence the function has internal linkage.
1445710ebb03SJohannes Doerfert const IRPosition &IRP = QueryingAA.getIRPosition();
1446710ebb03SJohannes Doerfert const Function *AssociatedFunction = IRP.getAssociatedFunction();
1447748538e1SJohannes Doerfert if (!AssociatedFunction) {
1448748538e1SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRP
1449748538e1SJohannes Doerfert << "\n");
1450710ebb03SJohannes Doerfert return false;
1451748538e1SJohannes Doerfert }
1452710ebb03SJohannes Doerfert
14533753aa75SJohannes Doerfert return checkForAllCallSites(Pred, *AssociatedFunction, RequireAllCallSites,
14546ed1ef06SJohannes Doerfert &QueryingAA, UsedAssumedInformation);
14553753aa75SJohannes Doerfert }
14563753aa75SJohannes Doerfert
checkForAllCallSites(function_ref<bool (AbstractCallSite)> Pred,const Function & Fn,bool RequireAllCallSites,const AbstractAttribute * QueryingAA,bool & UsedAssumedInformation)1457c57689beSJohannes Doerfert bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred,
1458c57689beSJohannes Doerfert const Function &Fn,
1459c57689beSJohannes Doerfert bool RequireAllCallSites,
1460c57689beSJohannes Doerfert const AbstractAttribute *QueryingAA,
14616ed1ef06SJohannes Doerfert bool &UsedAssumedInformation) {
14623753aa75SJohannes Doerfert if (RequireAllCallSites && !Fn.hasLocalLinkage()) {
146354869ec9SHideto Ueno LLVM_DEBUG(
146454869ec9SHideto Ueno dbgs()
14653753aa75SJohannes Doerfert << "[Attributor] Function " << Fn.getName()
146654869ec9SHideto Ueno << " has no internal linkage, hence not all call sites are known\n");
146754869ec9SHideto Ueno return false;
146854869ec9SHideto Ueno }
146954869ec9SHideto Ueno
1470c6ac717aSJohannes Doerfert SmallVector<const Use *, 8> Uses(make_pointer_range(Fn.uses()));
1471c6ac717aSJohannes Doerfert for (unsigned u = 0; u < Uses.size(); ++u) {
1472c6ac717aSJohannes Doerfert const Use &U = *Uses[u];
1473191fa419SJohannes Doerfert LLVM_DEBUG({
1474191fa419SJohannes Doerfert if (auto *Fn = dyn_cast<Function>(U))
1475191fa419SJohannes Doerfert dbgs() << "[Attributor] Check use: " << Fn->getName() << " in "
1476191fa419SJohannes Doerfert << *U.getUser() << "\n";
1477191fa419SJohannes Doerfert else
1478191fa419SJohannes Doerfert dbgs() << "[Attributor] Check use: " << *U << " in " << *U.getUser()
1479191fa419SJohannes Doerfert << "\n";
1480191fa419SJohannes Doerfert });
1481792aac98SJohannes Doerfert if (isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation,
1482792aac98SJohannes Doerfert /* CheckBBLivenessOnly */ true)) {
148323f41f16SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Dead use, skip!\n");
148423f41f16SJohannes Doerfert continue;
148523f41f16SJohannes Doerfert }
1486c6ac717aSJohannes Doerfert if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
14876b5b3678SNikita Popov if (CE->isCast() && CE->getType()->isPointerTy()) {
1488734f9144SJohannes Doerfert LLVM_DEBUG(
1489734f9144SJohannes Doerfert dbgs() << "[Attributor] Use, is constant cast expression, add "
1490734f9144SJohannes Doerfert << CE->getNumUses()
1491734f9144SJohannes Doerfert << " uses of that expression instead!\n");
1492c6ac717aSJohannes Doerfert for (const Use &CEU : CE->uses())
1493c6ac717aSJohannes Doerfert Uses.push_back(&CEU);
1494c6ac717aSJohannes Doerfert continue;
1495c6ac717aSJohannes Doerfert }
1496c6ac717aSJohannes Doerfert }
149723f41f16SJohannes Doerfert
1498661db04bSJohannes Doerfert AbstractCallSite ACS(&U);
1499661db04bSJohannes Doerfert if (!ACS) {
1500f35740d6SStefan Stipanovic LLVM_DEBUG(dbgs() << "[Attributor] Function " << Fn.getName()
1501661db04bSJohannes Doerfert << " has non call site use " << *U.get() << " in "
1502661db04bSJohannes Doerfert << *U.getUser() << "\n");
15032d77b0caSJohannes Doerfert // BlockAddress users are allowed.
15042d77b0caSJohannes Doerfert if (isa<BlockAddress>(U.getUser()))
15052d77b0caSJohannes Doerfert continue;
1506d98f9750SJohannes Doerfert return false;
1507661db04bSJohannes Doerfert }
1508d98f9750SJohannes Doerfert
1509661db04bSJohannes Doerfert const Use *EffectiveUse =
1510661db04bSJohannes Doerfert ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U;
1511661db04bSJohannes Doerfert if (!ACS.isCallee(EffectiveUse)) {
1512734f9144SJohannes Doerfert if (!RequireAllCallSites) {
1513734f9144SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()
1514734f9144SJohannes Doerfert << " is not a call of " << Fn.getName()
1515734f9144SJohannes Doerfert << ", skip use\n");
151654869ec9SHideto Ueno continue;
1517734f9144SJohannes Doerfert }
1518734f9144SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()
1519f35740d6SStefan Stipanovic << " is an invalid use of " << Fn.getName() << "\n");
152054869ec9SHideto Ueno return false;
152154869ec9SHideto Ueno }
152254869ec9SHideto Ueno
15231e99fc9dSJohannes Doerfert // Make sure the arguments that can be matched between the call site and the
15241e99fc9dSJohannes Doerfert // callee argee on their type. It is unlikely they do not and it doesn't
15251e99fc9dSJohannes Doerfert // make sense for all attributes to know/care about this.
15261e99fc9dSJohannes Doerfert assert(&Fn == ACS.getCalledFunction() && "Expected known callee");
15271e99fc9dSJohannes Doerfert unsigned MinArgsParams =
15281e99fc9dSJohannes Doerfert std::min(size_t(ACS.getNumArgOperands()), Fn.arg_size());
15291e99fc9dSJohannes Doerfert for (unsigned u = 0; u < MinArgsParams; ++u) {
15301e99fc9dSJohannes Doerfert Value *CSArgOp = ACS.getCallArgOperand(u);
15311e99fc9dSJohannes Doerfert if (CSArgOp && Fn.getArg(u)->getType() != CSArgOp->getType()) {
15321e99fc9dSJohannes Doerfert LLVM_DEBUG(
15331e99fc9dSJohannes Doerfert dbgs() << "[Attributor] Call site / callee argument type mismatch ["
15341e99fc9dSJohannes Doerfert << u << "@" << Fn.getName() << ": "
15351e99fc9dSJohannes Doerfert << *Fn.getArg(u)->getType() << " vs. "
15361e99fc9dSJohannes Doerfert << *ACS.getCallArgOperand(u)->getType() << "\n");
15371e99fc9dSJohannes Doerfert return false;
15381e99fc9dSJohannes Doerfert }
15391e99fc9dSJohannes Doerfert }
15401e99fc9dSJohannes Doerfert
1541661db04bSJohannes Doerfert if (Pred(ACS))
154254869ec9SHideto Ueno continue;
154354869ec9SHideto Ueno
15445304b72aSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
1545661db04bSJohannes Doerfert << *ACS.getInstruction() << "\n");
154654869ec9SHideto Ueno return false;
154754869ec9SHideto Ueno }
154854869ec9SHideto Ueno
154954869ec9SHideto Ueno return true;
155054869ec9SHideto Ueno }
155154869ec9SHideto Ueno
shouldPropagateCallBaseContext(const IRPosition & IRP)1552d75c9e61Skuterd bool Attributor::shouldPropagateCallBaseContext(const IRPosition &IRP) {
1553d75c9e61Skuterd // TODO: Maintain a cache of Values that are
1554d75c9e61Skuterd // on the pathway from a Argument to a Instruction that would effect the
1555d75c9e61Skuterd // liveness/return state etc.
1556d75c9e61Skuterd return EnableCallSiteSpecific;
1557d75c9e61Skuterd }
1558d75c9e61Skuterd
checkForAllReturnedValuesAndReturnInsts(function_ref<bool (Value &,const SmallSetVector<ReturnInst *,4> &)> Pred,const AbstractAttribute & QueryingAA)155914a0493aSJohannes Doerfert bool Attributor::checkForAllReturnedValuesAndReturnInsts(
1560c57689beSJohannes Doerfert function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred,
156114a0493aSJohannes Doerfert const AbstractAttribute &QueryingAA) {
156214a0493aSJohannes Doerfert
1563710ebb03SJohannes Doerfert const IRPosition &IRP = QueryingAA.getIRPosition();
1564710ebb03SJohannes Doerfert // Since we need to provide return instructions we have to have an exact
1565710ebb03SJohannes Doerfert // definition.
1566710ebb03SJohannes Doerfert const Function *AssociatedFunction = IRP.getAssociatedFunction();
1567b0412e43SJohannes Doerfert if (!AssociatedFunction)
156814a0493aSJohannes Doerfert return false;
156914a0493aSJohannes Doerfert
1570710ebb03SJohannes Doerfert // If this is a call site query we use the call site specific return values
1571710ebb03SJohannes Doerfert // and liveness information.
157207a5c129SJohannes Doerfert // TODO: use the function scope once we have call site AAReturnedValues.
157307a5c129SJohannes Doerfert const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
15745b70c12fSJohannes Doerfert const auto &AARetVal =
15755b70c12fSJohannes Doerfert getAAFor<AAReturnedValues>(QueryingAA, QueryIRP, DepClassTy::REQUIRED);
157612cbbab9SJohannes Doerfert if (!AARetVal.getState().isValidState())
1577710ebb03SJohannes Doerfert return false;
1578710ebb03SJohannes Doerfert
157912cbbab9SJohannes Doerfert return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred);
158014a0493aSJohannes Doerfert }
158114a0493aSJohannes Doerfert
checkForAllReturnedValues(function_ref<bool (Value &)> Pred,const AbstractAttribute & QueryingAA)158214a0493aSJohannes Doerfert bool Attributor::checkForAllReturnedValues(
1583c57689beSJohannes Doerfert function_ref<bool(Value &)> Pred, const AbstractAttribute &QueryingAA) {
158414a0493aSJohannes Doerfert
1585710ebb03SJohannes Doerfert const IRPosition &IRP = QueryingAA.getIRPosition();
1586710ebb03SJohannes Doerfert const Function *AssociatedFunction = IRP.getAssociatedFunction();
1587b0412e43SJohannes Doerfert if (!AssociatedFunction)
158814a0493aSJohannes Doerfert return false;
158914a0493aSJohannes Doerfert
159007a5c129SJohannes Doerfert // TODO: use the function scope once we have call site AAReturnedValues.
159164ef29bcSKuter Dinel const IRPosition &QueryIRP = IRPosition::function(
159264ef29bcSKuter Dinel *AssociatedFunction, QueryingAA.getCallBaseContext());
15935b70c12fSJohannes Doerfert const auto &AARetVal =
15945b70c12fSJohannes Doerfert getAAFor<AAReturnedValues>(QueryingAA, QueryIRP, DepClassTy::REQUIRED);
159512cbbab9SJohannes Doerfert if (!AARetVal.getState().isValidState())
1596710ebb03SJohannes Doerfert return false;
1597710ebb03SJohannes Doerfert
159812cbbab9SJohannes Doerfert return AARetVal.checkForAllReturnedValuesAndReturnInsts(
1599695089ecSJohannes Doerfert [&](Value &RV, const SmallSetVector<ReturnInst *, 4> &) {
160014a0493aSJohannes Doerfert return Pred(RV);
160114a0493aSJohannes Doerfert });
160214a0493aSJohannes Doerfert }
160314a0493aSJohannes Doerfert
checkForAllInstructionsImpl(Attributor * A,InformationCache::OpcodeInstMapTy & OpcodeInstMap,function_ref<bool (Instruction &)> Pred,const AbstractAttribute * QueryingAA,const AAIsDead * LivenessAA,const ArrayRef<unsigned> & Opcodes,bool & UsedAssumedInformation,bool CheckBBLivenessOnly=false,bool CheckPotentiallyDead=false)160423f41f16SJohannes Doerfert static bool checkForAllInstructionsImpl(
160523f41f16SJohannes Doerfert Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap,
1606c57689beSJohannes Doerfert function_ref<bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA,
1607c57689beSJohannes Doerfert const AAIsDead *LivenessAA, const ArrayRef<unsigned> &Opcodes,
1608792aac98SJohannes Doerfert bool &UsedAssumedInformation, bool CheckBBLivenessOnly = false,
1609792aac98SJohannes Doerfert bool CheckPotentiallyDead = false) {
16103ab9e8b8SJohannes Doerfert for (unsigned Opcode : Opcodes) {
1611177c065eSJohannes Doerfert // Check if we have instructions with this opcode at all first.
1612177c065eSJohannes Doerfert auto *Insts = OpcodeInstMap.lookup(Opcode);
1613177c065eSJohannes Doerfert if (!Insts)
1614177c065eSJohannes Doerfert continue;
1615177c065eSJohannes Doerfert
1616177c065eSJohannes Doerfert for (Instruction *I : *Insts) {
16173ab9e8b8SJohannes Doerfert // Skip dead instructions.
1618c1c1fe93SJohannes Doerfert if (A && !CheckPotentiallyDead &&
1619a1db0e52SJohannes Doerfert A->isAssumedDead(IRPosition::inst(*I), QueryingAA, LivenessAA,
1620a1db0e52SJohannes Doerfert UsedAssumedInformation, CheckBBLivenessOnly)) {
1621a1db0e52SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Instruction " << *I
1622a1db0e52SJohannes Doerfert << " is potentially dead, skip!\n";);
16233ab9e8b8SJohannes Doerfert continue;
1624a1db0e52SJohannes Doerfert }
16253ab9e8b8SJohannes Doerfert
16263ab9e8b8SJohannes Doerfert if (!Pred(*I))
16273ab9e8b8SJohannes Doerfert return false;
16283ab9e8b8SJohannes Doerfert }
16293ab9e8b8SJohannes Doerfert }
16303ab9e8b8SJohannes Doerfert return true;
16313ab9e8b8SJohannes Doerfert }
16323ab9e8b8SJohannes Doerfert
checkForAllInstructions(function_ref<bool (Instruction &)> Pred,const Function * Fn,const AbstractAttribute & QueryingAA,const ArrayRef<unsigned> & Opcodes,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,bool CheckPotentiallyDead)1633c57689beSJohannes Doerfert bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
1634efedf70aSJohannes Doerfert const Function *Fn,
1635c57689beSJohannes Doerfert const AbstractAttribute &QueryingAA,
1636c57689beSJohannes Doerfert const ArrayRef<unsigned> &Opcodes,
1637792aac98SJohannes Doerfert bool &UsedAssumedInformation,
1638c1c1fe93SJohannes Doerfert bool CheckBBLivenessOnly,
1639c1c1fe93SJohannes Doerfert bool CheckPotentiallyDead) {
1640710ebb03SJohannes Doerfert // Since we need to provide instructions we have to have an exact definition.
1641efedf70aSJohannes Doerfert if (!Fn || Fn->isDeclaration())
16420cd964ffSKuter Dinel return false;
16430cd964ffSKuter Dinel
164407a5c129SJohannes Doerfert // TODO: use the function scope once we have call site AAReturnedValues.
1645efedf70aSJohannes Doerfert const IRPosition &QueryIRP = IRPosition::function(*Fn);
16465dfd7cc4Ssstefan1 const auto *LivenessAA =
1647c1c1fe93SJohannes Doerfert (CheckBBLivenessOnly || CheckPotentiallyDead)
1648e592dad8SJohannes Doerfert ? nullptr
1649e592dad8SJohannes Doerfert : &(getAAFor<AAIsDead>(QueryingAA, QueryIRP, DepClassTy::NONE));
1650710ebb03SJohannes Doerfert
1651efedf70aSJohannes Doerfert auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
165223f41f16SJohannes Doerfert if (!checkForAllInstructionsImpl(this, OpcodeInstMap, Pred, &QueryingAA,
1653792aac98SJohannes Doerfert LivenessAA, Opcodes, UsedAssumedInformation,
1654792aac98SJohannes Doerfert CheckBBLivenessOnly, CheckPotentiallyDead))
1655d0f64009SJohannes Doerfert return false;
1656d0f64009SJohannes Doerfert
1657d0f64009SJohannes Doerfert return true;
1658d0f64009SJohannes Doerfert }
1659d0f64009SJohannes Doerfert
checkForAllInstructions(function_ref<bool (Instruction &)> Pred,const AbstractAttribute & QueryingAA,const ArrayRef<unsigned> & Opcodes,bool & UsedAssumedInformation,bool CheckBBLivenessOnly,bool CheckPotentiallyDead)1660efedf70aSJohannes Doerfert bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
1661efedf70aSJohannes Doerfert const AbstractAttribute &QueryingAA,
1662efedf70aSJohannes Doerfert const ArrayRef<unsigned> &Opcodes,
1663efedf70aSJohannes Doerfert bool &UsedAssumedInformation,
1664efedf70aSJohannes Doerfert bool CheckBBLivenessOnly,
1665efedf70aSJohannes Doerfert bool CheckPotentiallyDead) {
1666efedf70aSJohannes Doerfert const IRPosition &IRP = QueryingAA.getIRPosition();
1667efedf70aSJohannes Doerfert const Function *AssociatedFunction = IRP.getAssociatedFunction();
1668efedf70aSJohannes Doerfert return checkForAllInstructions(Pred, AssociatedFunction, QueryingAA, Opcodes,
1669efedf70aSJohannes Doerfert UsedAssumedInformation, CheckBBLivenessOnly,
1670efedf70aSJohannes Doerfert CheckPotentiallyDead);
1671efedf70aSJohannes Doerfert }
1672efedf70aSJohannes Doerfert
checkForAllReadWriteInstructions(function_ref<bool (Instruction &)> Pred,AbstractAttribute & QueryingAA,bool & UsedAssumedInformation)1673aaa5270cSStefan Stipanovic bool Attributor::checkForAllReadWriteInstructions(
1674792aac98SJohannes Doerfert function_ref<bool(Instruction &)> Pred, AbstractAttribute &QueryingAA,
1675792aac98SJohannes Doerfert bool &UsedAssumedInformation) {
1676aaa5270cSStefan Stipanovic
1677710ebb03SJohannes Doerfert const Function *AssociatedFunction =
1678710ebb03SJohannes Doerfert QueryingAA.getIRPosition().getAssociatedFunction();
1679710ebb03SJohannes Doerfert if (!AssociatedFunction)
1680710ebb03SJohannes Doerfert return false;
1681aaa5270cSStefan Stipanovic
168207a5c129SJohannes Doerfert // TODO: use the function scope once we have call site AAReturnedValues.
168307a5c129SJohannes Doerfert const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
168407a5c129SJohannes Doerfert const auto &LivenessAA =
1685e592dad8SJohannes Doerfert getAAFor<AAIsDead>(QueryingAA, QueryIRP, DepClassTy::NONE);
1686710ebb03SJohannes Doerfert
1687710ebb03SJohannes Doerfert for (Instruction *I :
1688710ebb03SJohannes Doerfert InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
1689aaa5270cSStefan Stipanovic // Skip dead instructions.
1690a1db0e52SJohannes Doerfert if (isAssumedDead(IRPosition::inst(*I), &QueryingAA, &LivenessAA,
1691792aac98SJohannes Doerfert UsedAssumedInformation))
1692aaa5270cSStefan Stipanovic continue;
1693aaa5270cSStefan Stipanovic
1694aaa5270cSStefan Stipanovic if (!Pred(*I))
1695aaa5270cSStefan Stipanovic return false;
1696aaa5270cSStefan Stipanovic }
1697aaa5270cSStefan Stipanovic
1698aaa5270cSStefan Stipanovic return true;
1699aaa5270cSStefan Stipanovic }
1700aaa5270cSStefan Stipanovic
runTillFixpoint()170170330edcSKuter Dinel void Attributor::runTillFixpoint() {
170249def10eSkuterd TimeTraceScope TimeScope("Attributor::runTillFixpoint");
1703aade782aSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
17045ee07dc5SLuofan Chen << DG.SyntheticRoot.Deps.size()
1705aade782aSJohannes Doerfert << " abstract attributes.\n");
1706aade782aSJohannes Doerfert
17075360589bSStefan Stipanovic // Now that all abstract attributes are collected and initialized we start
17085360589bSStefan Stipanovic // the abstract analysis.
1709aade782aSJohannes Doerfert
1710aade782aSJohannes Doerfert unsigned IterationCounter = 1;
17113be3b401SJohannes Doerfert unsigned MaxIterations =
1712129b531cSKazu Hirata Configuration.MaxFixpointIterations.value_or(SetFixpointIterations);
1713b54ccab5SJoseph Huber
1714a650d555SStefanos Baziotis SmallVector<AbstractAttribute *, 32> ChangedAAs;
1715680f6380SJohannes Doerfert SetVector<AbstractAttribute *> Worklist, InvalidAAs;
17165ee07dc5SLuofan Chen Worklist.insert(DG.SyntheticRoot.begin(), DG.SyntheticRoot.end());
1717aade782aSJohannes Doerfert
1718aade782aSJohannes Doerfert do {
171912cbbab9SJohannes Doerfert // Remember the size to determine new attributes.
17205ee07dc5SLuofan Chen size_t NumAAs = DG.SyntheticRoot.Deps.size();
1721aade782aSJohannes Doerfert LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
1722aade782aSJohannes Doerfert << ", Worklist size: " << Worklist.size() << "\n");
1723aade782aSJohannes Doerfert
1724680f6380SJohannes Doerfert // For invalid AAs we can fix dependent AAs that have a required dependence,
1725680f6380SJohannes Doerfert // thereby folding long dependence chains in a single step without the need
1726680f6380SJohannes Doerfert // to run updates.
1727680f6380SJohannes Doerfert for (unsigned u = 0; u < InvalidAAs.size(); ++u) {
1728680f6380SJohannes Doerfert AbstractAttribute *InvalidAA = InvalidAAs[u];
172999662c22SJohannes Doerfert
173099662c22SJohannes Doerfert // Check the dependences to fast track invalidation.
1731680f6380SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] InvalidAA: " << *InvalidAA << " has "
17323a8740bdSJohannes Doerfert << InvalidAA->Deps.size()
17333a8740bdSJohannes Doerfert << " required & optional dependences\n");
17343a8740bdSJohannes Doerfert while (!InvalidAA->Deps.empty()) {
17353a8740bdSJohannes Doerfert const auto &Dep = InvalidAA->Deps.back();
17363a8740bdSJohannes Doerfert InvalidAA->Deps.pop_back();
17375ee07dc5SLuofan Chen AbstractAttribute *DepAA = cast<AbstractAttribute>(Dep.getPointer());
17383a8740bdSJohannes Doerfert if (Dep.getInt() == unsigned(DepClassTy::OPTIONAL)) {
1739a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << " - recompute: " << *DepAA);
17403a8740bdSJohannes Doerfert Worklist.insert(DepAA);
17413a8740bdSJohannes Doerfert continue;
1742680f6380SJohannes Doerfert }
1743a265cf22SJohannes Doerfert LLVM_DEBUG(dbgs() << " - invalidate: " << *DepAA);
17443a8740bdSJohannes Doerfert DepAA->getState().indicatePessimisticFixpoint();
17453a8740bdSJohannes Doerfert assert(DepAA->getState().isAtFixpoint() && "Expected fixpoint state!");
17463a8740bdSJohannes Doerfert if (!DepAA->getState().isValidState())
17473a8740bdSJohannes Doerfert InvalidAAs.insert(DepAA);
17483a8740bdSJohannes Doerfert else
17493a8740bdSJohannes Doerfert ChangedAAs.push_back(DepAA);
17503a8740bdSJohannes Doerfert }
1751f7ca0fe1SJohannes Doerfert }
1752f7ca0fe1SJohannes Doerfert
1753aade782aSJohannes Doerfert // Add all abstract attributes that are potentially dependent on one that
1754aade782aSJohannes Doerfert // changed to the work list.
17553a8740bdSJohannes Doerfert for (AbstractAttribute *ChangedAA : ChangedAAs)
17563a8740bdSJohannes Doerfert while (!ChangedAA->Deps.empty()) {
17575ee07dc5SLuofan Chen Worklist.insert(
17585ee07dc5SLuofan Chen cast<AbstractAttribute>(ChangedAA->Deps.back().getPointer()));
17593a8740bdSJohannes Doerfert ChangedAA->Deps.pop_back();
1760aade782aSJohannes Doerfert }
1761aade782aSJohannes Doerfert
1762b504eb8bSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] #Iteration: " << IterationCounter
1763b504eb8bSJohannes Doerfert << ", Worklist+Dependent size: " << Worklist.size()
1764b504eb8bSJohannes Doerfert << "\n");
1765b504eb8bSJohannes Doerfert
1766680f6380SJohannes Doerfert // Reset the changed and invalid set.
1767aade782aSJohannes Doerfert ChangedAAs.clear();
1768680f6380SJohannes Doerfert InvalidAAs.clear();
1769aade782aSJohannes Doerfert
1770aade782aSJohannes Doerfert // Update all abstract attribute in the work list and record the ones that
1771aade782aSJohannes Doerfert // changed.
177295e0d28bSJohannes Doerfert for (AbstractAttribute *AA : Worklist) {
177395e0d28bSJohannes Doerfert const auto &AAState = AA->getState();
1774edf03914SJohannes Doerfert if (!AAState.isAtFixpoint())
1775edf03914SJohannes Doerfert if (updateAA(*AA) == ChangeStatus::CHANGED)
1776aade782aSJohannes Doerfert ChangedAAs.push_back(AA);
1777edf03914SJohannes Doerfert
177895e0d28bSJohannes Doerfert // Use the InvalidAAs vector to propagate invalid states fast transitively
177995e0d28bSJohannes Doerfert // without requiring updates.
178095e0d28bSJohannes Doerfert if (!AAState.isValidState())
1781680f6380SJohannes Doerfert InvalidAAs.insert(AA);
17822dad729fSJohannes Doerfert }
1783f7ca0fe1SJohannes Doerfert
17849543f149SJohannes Doerfert // Add attributes to the changed set if they have been created in the last
17859543f149SJohannes Doerfert // iteration.
17865ee07dc5SLuofan Chen ChangedAAs.append(DG.SyntheticRoot.begin() + NumAAs,
17875ee07dc5SLuofan Chen DG.SyntheticRoot.end());
17889543f149SJohannes Doerfert
1789aade782aSJohannes Doerfert // Reset the work list and repopulate with the changed abstract attributes.
1790aade782aSJohannes Doerfert // Note that dependent ones are added above.
1791aade782aSJohannes Doerfert Worklist.clear();
1792aade782aSJohannes Doerfert Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
1793b51b83f6SJohannes Doerfert Worklist.insert(QueryAAsAwaitingUpdate.begin(),
1794b51b83f6SJohannes Doerfert QueryAAsAwaitingUpdate.end());
1795b51b83f6SJohannes Doerfert QueryAAsAwaitingUpdate.clear();
1796aade782aSJohannes Doerfert
17973be3b401SJohannes Doerfert } while (!Worklist.empty() &&
17983be3b401SJohannes Doerfert (IterationCounter++ < MaxIterations || VerifyMaxFixpointIterations));
1799f7ca0fe1SJohannes Doerfert
18003be3b401SJohannes Doerfert if (IterationCounter > MaxIterations && !Functions.empty()) {
1801f074a6a0SJoseph Huber auto Remark = [&](OptimizationRemarkMissed ORM) {
1802f074a6a0SJoseph Huber return ORM << "Attributor did not reach a fixpoint after "
18033be3b401SJohannes Doerfert << ore::NV("Iterations", MaxIterations) << " iterations.";
1804f074a6a0SJoseph Huber };
1805caf7f05cSJoseph Huber Function *F = Functions.front();
1806f074a6a0SJoseph Huber emitRemark<OptimizationRemarkMissed>(F, "FixedPoint", Remark);
1807f074a6a0SJoseph Huber }
1808f074a6a0SJoseph Huber
1809aade782aSJohannes Doerfert LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
18103be3b401SJohannes Doerfert << IterationCounter << "/" << MaxIterations
1811aade782aSJohannes Doerfert << " iterations\n");
1812aade782aSJohannes Doerfert
1813aade782aSJohannes Doerfert // Reset abstract arguments not settled in a sound fixpoint by now. This
1814aade782aSJohannes Doerfert // happens when we stopped the fixpoint iteration early. Note that only the
1815aade782aSJohannes Doerfert // ones marked as "changed" *and* the ones transitively depending on them
1816aade782aSJohannes Doerfert // need to be reverted to a pessimistic state. Others might not be in a
1817aade782aSJohannes Doerfert // fixpoint state but we can use the optimistic results for them anyway.
1818aade782aSJohannes Doerfert SmallPtrSet<AbstractAttribute *, 32> Visited;
1819aade782aSJohannes Doerfert for (unsigned u = 0; u < ChangedAAs.size(); u++) {
1820aade782aSJohannes Doerfert AbstractAttribute *ChangedAA = ChangedAAs[u];
1821aade782aSJohannes Doerfert if (!Visited.insert(ChangedAA).second)
1822aade782aSJohannes Doerfert continue;
1823aade782aSJohannes Doerfert
1824aade782aSJohannes Doerfert AbstractState &State = ChangedAA->getState();
1825aade782aSJohannes Doerfert if (!State.isAtFixpoint()) {
1826aade782aSJohannes Doerfert State.indicatePessimisticFixpoint();
1827aade782aSJohannes Doerfert
1828aade782aSJohannes Doerfert NumAttributesTimedOut++;
1829aade782aSJohannes Doerfert }
1830aade782aSJohannes Doerfert
18313a8740bdSJohannes Doerfert while (!ChangedAA->Deps.empty()) {
18325ee07dc5SLuofan Chen ChangedAAs.push_back(
18335ee07dc5SLuofan Chen cast<AbstractAttribute>(ChangedAA->Deps.back().getPointer()));
18343a8740bdSJohannes Doerfert ChangedAA->Deps.pop_back();
183599662c22SJohannes Doerfert }
1836aade782aSJohannes Doerfert }
1837aade782aSJohannes Doerfert
1838aade782aSJohannes Doerfert LLVM_DEBUG({
1839aade782aSJohannes Doerfert if (!Visited.empty())
1840aade782aSJohannes Doerfert dbgs() << "\n[Attributor] Finalized " << Visited.size()
1841aade782aSJohannes Doerfert << " abstract attributes.\n";
1842aade782aSJohannes Doerfert });
1843aade782aSJohannes Doerfert
18443be3b401SJohannes Doerfert if (VerifyMaxFixpointIterations && IterationCounter != MaxIterations) {
184570330edcSKuter Dinel errs() << "\n[Attributor] Fixpoint iteration done after: "
18463be3b401SJohannes Doerfert << IterationCounter << "/" << MaxIterations << " iterations\n";
184770330edcSKuter Dinel llvm_unreachable("The fixpoint was not reached with exactly the number of "
184870330edcSKuter Dinel "specified iterations!");
184970330edcSKuter Dinel }
185070330edcSKuter Dinel }
185170330edcSKuter Dinel
registerForUpdate(AbstractAttribute & AA)1852b51b83f6SJohannes Doerfert void Attributor::registerForUpdate(AbstractAttribute &AA) {
1853b51b83f6SJohannes Doerfert assert(AA.isQueryAA() &&
1854b51b83f6SJohannes Doerfert "Non-query AAs should not be required to register for updates!");
1855b51b83f6SJohannes Doerfert QueryAAsAwaitingUpdate.insert(&AA);
1856b51b83f6SJohannes Doerfert }
1857b51b83f6SJohannes Doerfert
manifestAttributes()185870330edcSKuter Dinel ChangeStatus Attributor::manifestAttributes() {
185949def10eSkuterd TimeTraceScope TimeScope("Attributor::manifestAttributes");
18605ee07dc5SLuofan Chen size_t NumFinalAAs = DG.SyntheticRoot.Deps.size();
186170330edcSKuter Dinel
1862aade782aSJohannes Doerfert unsigned NumManifested = 0;
1863aade782aSJohannes Doerfert unsigned NumAtFixpoint = 0;
1864aade782aSJohannes Doerfert ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
18655ee07dc5SLuofan Chen for (auto &DepAA : DG.SyntheticRoot.Deps) {
18665ee07dc5SLuofan Chen AbstractAttribute *AA = cast<AbstractAttribute>(DepAA.getPointer());
1867aade782aSJohannes Doerfert AbstractState &State = AA->getState();
1868aade782aSJohannes Doerfert
1869aade782aSJohannes Doerfert // If there is not already a fixpoint reached, we can now take the
1870aade782aSJohannes Doerfert // optimistic state. This is correct because we enforced a pessimistic one
1871aade782aSJohannes Doerfert // on abstract attributes that were transitively dependent on a changed one
1872aade782aSJohannes Doerfert // already above.
1873aade782aSJohannes Doerfert if (!State.isAtFixpoint())
1874aade782aSJohannes Doerfert State.indicateOptimisticFixpoint();
1875aade782aSJohannes Doerfert
1876d75c9e61Skuterd // We must not manifest Attributes that use Callbase info.
1877d75c9e61Skuterd if (AA->hasCallBaseContext())
1878d75c9e61Skuterd continue;
1879aade782aSJohannes Doerfert // If the state is invalid, we do not try to manifest it.
1880aade782aSJohannes Doerfert if (!State.isValidState())
1881aade782aSJohannes Doerfert continue;
1882aade782aSJohannes Doerfert
1883f3ad8cf0SJohannes Doerfert if (AA->getCtxI() && !isRunOn(*AA->getAnchorScope()))
1884f3ad8cf0SJohannes Doerfert continue;
1885f3ad8cf0SJohannes Doerfert
18869a1a1f96SJohannes Doerfert // Skip dead code.
1887792aac98SJohannes Doerfert bool UsedAssumedInformation = false;
1888792aac98SJohannes Doerfert if (isAssumedDead(*AA, nullptr, UsedAssumedInformation,
1889792aac98SJohannes Doerfert /* CheckBBLivenessOnly */ true))
18909a1a1f96SJohannes Doerfert continue;
189150d34958SJohannes Doerfert // Check if the manifest debug counter that allows skipping manifestation of
189250d34958SJohannes Doerfert // AAs
189350d34958SJohannes Doerfert if (!DebugCounter::shouldExecute(ManifestDBGCounter))
189450d34958SJohannes Doerfert continue;
1895aade782aSJohannes Doerfert // Manifest the state and record if we changed the IR.
1896aade782aSJohannes Doerfert ChangeStatus LocalChange = AA->manifest(*this);
1897d1b79e07SJohannes Doerfert if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
1898d1b79e07SJohannes Doerfert AA->trackStatistics();
18998e76fec0SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Manifest " << LocalChange << " : " << *AA
19008e76fec0SJohannes Doerfert << "\n");
1901d1b79e07SJohannes Doerfert
1902aade782aSJohannes Doerfert ManifestChange = ManifestChange | LocalChange;
1903aade782aSJohannes Doerfert
1904aade782aSJohannes Doerfert NumAtFixpoint++;
1905aade782aSJohannes Doerfert NumManifested += (LocalChange == ChangeStatus::CHANGED);
1906aade782aSJohannes Doerfert }
1907aade782aSJohannes Doerfert
1908aade782aSJohannes Doerfert (void)NumManifested;
1909aade782aSJohannes Doerfert (void)NumAtFixpoint;
1910aade782aSJohannes Doerfert LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
1911aade782aSJohannes Doerfert << " arguments while " << NumAtFixpoint
1912aade782aSJohannes Doerfert << " were in a valid fixpoint state\n");
1913aade782aSJohannes Doerfert
1914aade782aSJohannes Doerfert NumAttributesManifested += NumManifested;
1915aade782aSJohannes Doerfert NumAttributesValidFixpoint += NumAtFixpoint;
1916aade782aSJohannes Doerfert
1917f1826173SFangrui Song (void)NumFinalAAs;
19185ee07dc5SLuofan Chen if (NumFinalAAs != DG.SyntheticRoot.Deps.size()) {
19195ee07dc5SLuofan Chen for (unsigned u = NumFinalAAs; u < DG.SyntheticRoot.Deps.size(); ++u)
19205ee07dc5SLuofan Chen errs() << "Unexpected abstract attribute: "
19215ee07dc5SLuofan Chen << cast<AbstractAttribute>(DG.SyntheticRoot.Deps[u].getPointer())
1922b70297a3SJohannes Doerfert << " :: "
19235ee07dc5SLuofan Chen << cast<AbstractAttribute>(DG.SyntheticRoot.Deps[u].getPointer())
19245ee07dc5SLuofan Chen ->getIRPosition()
19255ee07dc5SLuofan Chen .getAssociatedValue()
1926b70297a3SJohannes Doerfert << "\n";
1927b70297a3SJohannes Doerfert llvm_unreachable("Expected the final number of abstract attributes to "
1928b70297a3SJohannes Doerfert "remain unchanged!");
1929b70297a3SJohannes Doerfert }
193070330edcSKuter Dinel return ManifestChange;
193170330edcSKuter Dinel }
193239681e73SJohannes Doerfert
identifyDeadInternalFunctions()19331c2531c9SJohannes Doerfert void Attributor::identifyDeadInternalFunctions() {
1934b077d82bSWilliam S. Moses // Early exit if we don't intend to delete functions.
19353be3b401SJohannes Doerfert if (!Configuration.DeleteFns)
1936b077d82bSWilliam S. Moses return;
1937b077d82bSWilliam S. Moses
19381c2531c9SJohannes Doerfert // Identify dead internal functions and delete them. This happens outside
19391c2531c9SJohannes Doerfert // the other fixpoint analysis as we might treat potentially dead functions
19401c2531c9SJohannes Doerfert // as live to lower the number of iterations. If they happen to be dead, the
19411c2531c9SJohannes Doerfert // below fixpoint loop will identify and eliminate them.
19421c2531c9SJohannes Doerfert SmallVector<Function *, 8> InternalFns;
19431c2531c9SJohannes Doerfert for (Function *F : Functions)
19441c2531c9SJohannes Doerfert if (F->hasLocalLinkage())
19451c2531c9SJohannes Doerfert InternalFns.push_back(F);
19461c2531c9SJohannes Doerfert
19471c2531c9SJohannes Doerfert SmallPtrSet<Function *, 8> LiveInternalFns;
19481c2531c9SJohannes Doerfert bool FoundLiveInternal = true;
19491c2531c9SJohannes Doerfert while (FoundLiveInternal) {
19501c2531c9SJohannes Doerfert FoundLiveInternal = false;
19511c2531c9SJohannes Doerfert for (unsigned u = 0, e = InternalFns.size(); u < e; ++u) {
19521c2531c9SJohannes Doerfert Function *F = InternalFns[u];
19531c2531c9SJohannes Doerfert if (!F)
19541c2531c9SJohannes Doerfert continue;
19551c2531c9SJohannes Doerfert
19566ed1ef06SJohannes Doerfert bool UsedAssumedInformation = false;
19571c2531c9SJohannes Doerfert if (checkForAllCallSites(
19581c2531c9SJohannes Doerfert [&](AbstractCallSite ACS) {
19591c2531c9SJohannes Doerfert Function *Callee = ACS.getInstruction()->getFunction();
19601c2531c9SJohannes Doerfert return ToBeDeletedFunctions.count(Callee) ||
19611c2531c9SJohannes Doerfert (Functions.count(Callee) && Callee->hasLocalLinkage() &&
19621c2531c9SJohannes Doerfert !LiveInternalFns.count(Callee));
19631c2531c9SJohannes Doerfert },
19646ed1ef06SJohannes Doerfert *F, true, nullptr, UsedAssumedInformation)) {
19651c2531c9SJohannes Doerfert continue;
19661c2531c9SJohannes Doerfert }
19671c2531c9SJohannes Doerfert
19681c2531c9SJohannes Doerfert LiveInternalFns.insert(F);
19691c2531c9SJohannes Doerfert InternalFns[u] = nullptr;
19701c2531c9SJohannes Doerfert FoundLiveInternal = true;
19711c2531c9SJohannes Doerfert }
19721c2531c9SJohannes Doerfert }
19731c2531c9SJohannes Doerfert
19741c2531c9SJohannes Doerfert for (unsigned u = 0, e = InternalFns.size(); u < e; ++u)
19751c2531c9SJohannes Doerfert if (Function *F = InternalFns[u])
19761c2531c9SJohannes Doerfert ToBeDeletedFunctions.insert(F);
19771c2531c9SJohannes Doerfert }
19781c2531c9SJohannes Doerfert
cleanupIR()197970330edcSKuter Dinel ChangeStatus Attributor::cleanupIR() {
198049def10eSkuterd TimeTraceScope TimeScope("Attributor::cleanupIR");
198139681e73SJohannes Doerfert // Delete stuff at the end to avoid invalid references and a nice order.
1982168a9234SJohannes Doerfert LLVM_DEBUG(dbgs() << "\n[Attributor] Delete/replace at least "
19832f622063SJohannes Doerfert << ToBeDeletedFunctions.size() << " functions and "
19842f622063SJohannes Doerfert << ToBeDeletedBlocks.size() << " blocks and "
1985cd4aab4aSJohannes Doerfert << ToBeDeletedInsts.size() << " instructions and "
1986168a9234SJohannes Doerfert << ToBeChangedValues.size() << " values and "
1987982053e8SJohannes Doerfert << ToBeChangedUses.size() << " uses. To insert "
1988bf789b19SJohannes Doerfert << ToBeChangedToUnreachableInsts.size()
1989bf789b19SJohannes Doerfert << " unreachables.\n"
19903f71b425SGiorgis Georgakoudis << "Preserve manifest added " << ManifestAddedBlocks.size()
19913f71b425SGiorgis Georgakoudis << " blocks\n");
1992cd4aab4aSJohannes Doerfert
19939e66c4ecSAlina Sbirlea SmallVector<WeakTrackingVH, 32> DeadInsts;
1994cd4aab4aSJohannes Doerfert SmallVector<Instruction *, 32> TerminatorsToFold;
1995cd4aab4aSJohannes Doerfert
1996168a9234SJohannes Doerfert auto ReplaceUse = [&](Use *U, Value *NewV) {
1997cd4aab4aSJohannes Doerfert Value *OldV = U->get();
199854ec9b54SJohannes Doerfert
1999168a9234SJohannes Doerfert // If we plan to replace NewV we need to update it at this point.
2000168a9234SJohannes Doerfert do {
2001168a9234SJohannes Doerfert const auto &Entry = ToBeChangedValues.lookup(NewV);
2002168a9234SJohannes Doerfert if (!Entry.first)
2003168a9234SJohannes Doerfert break;
2004168a9234SJohannes Doerfert NewV = Entry.first;
2005168a9234SJohannes Doerfert } while (true);
2006168a9234SJohannes Doerfert
2007f3ad8cf0SJohannes Doerfert Instruction *I = dyn_cast<Instruction>(U->getUser());
2008f3ad8cf0SJohannes Doerfert assert((!I || isRunOn(*I->getFunction())) &&
2009982053e8SJohannes Doerfert "Cannot replace an instruction outside the current SCC!");
2010f3ad8cf0SJohannes Doerfert
201154ec9b54SJohannes Doerfert // Do not replace uses in returns if the value is a must-tail call we will
201254ec9b54SJohannes Doerfert // not delete.
2013f3ad8cf0SJohannes Doerfert if (auto *RI = dyn_cast_or_null<ReturnInst>(I)) {
201454ec9b54SJohannes Doerfert if (auto *CI = dyn_cast<CallInst>(OldV->stripPointerCasts()))
2015f3ad8cf0SJohannes Doerfert if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2016168a9234SJohannes Doerfert return;
20175ef18e24SJohannes Doerfert // If we rewrite a return and the new value is not an argument, strip the
20185ef18e24SJohannes Doerfert // `returned` attribute as it is wrong now.
20195ef18e24SJohannes Doerfert if (!isa<Argument>(NewV))
20205ef18e24SJohannes Doerfert for (auto &Arg : RI->getFunction()->args())
20215ef18e24SJohannes Doerfert Arg.removeAttr(Attribute::Returned);
20225ef18e24SJohannes Doerfert }
20231ba2929bSJohannes Doerfert
20241ba2929bSJohannes Doerfert // Do not perform call graph altering changes outside the SCC.
2025f3ad8cf0SJohannes Doerfert if (auto *CB = dyn_cast_or_null<CallBase>(I))
2026f3ad8cf0SJohannes Doerfert if (CB->isCallee(U))
2027168a9234SJohannes Doerfert return;
202854ec9b54SJohannes Doerfert
2029cd4aab4aSJohannes Doerfert LLVM_DEBUG(dbgs() << "Use " << *NewV << " in " << *U->getUser()
2030cd4aab4aSJohannes Doerfert << " instead of " << *OldV << "\n");
2031cd4aab4aSJohannes Doerfert U->set(NewV);
20321ba2929bSJohannes Doerfert
2033b0c77c36SJohannes Doerfert if (Instruction *I = dyn_cast<Instruction>(OldV)) {
2034b0c77c36SJohannes Doerfert CGModifiedFunctions.insert(I->getFunction());
2035f35740d6SStefan Stipanovic if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) &&
2036b0c77c36SJohannes Doerfert isInstructionTriviallyDead(I))
2037cd4aab4aSJohannes Doerfert DeadInsts.push_back(I);
2038cd4aab4aSJohannes Doerfert }
203981429abdSJohannes Doerfert if (isa<UndefValue>(NewV) && isa<CallBase>(U->getUser())) {
204081429abdSJohannes Doerfert auto *CB = cast<CallBase>(U->getUser());
204181429abdSJohannes Doerfert if (CB->isArgOperand(U)) {
204281429abdSJohannes Doerfert unsigned Idx = CB->getArgOperandNo(U);
204381429abdSJohannes Doerfert CB->removeParamAttr(Idx, Attribute::NoUndef);
204481429abdSJohannes Doerfert Function *Fn = CB->getCalledFunction();
204530c9d68aSJohannes Doerfert if (Fn && Fn->arg_size() > Idx)
204681429abdSJohannes Doerfert Fn->removeParamAttr(Idx, Attribute::NoUndef);
204781429abdSJohannes Doerfert }
204881429abdSJohannes Doerfert }
2049cd4aab4aSJohannes Doerfert if (isa<Constant>(NewV) && isa<BranchInst>(U->getUser())) {
2050cd4aab4aSJohannes Doerfert Instruction *UserI = cast<Instruction>(U->getUser());
2051cd4aab4aSJohannes Doerfert if (isa<UndefValue>(NewV)) {
2052cb5eb13eSHideto Ueno ToBeChangedToUnreachableInsts.insert(UserI);
2053cd4aab4aSJohannes Doerfert } else {
2054cd4aab4aSJohannes Doerfert TerminatorsToFold.push_back(UserI);
2055cd4aab4aSJohannes Doerfert }
2056cd4aab4aSJohannes Doerfert }
2057168a9234SJohannes Doerfert };
2058168a9234SJohannes Doerfert
2059168a9234SJohannes Doerfert for (auto &It : ToBeChangedUses) {
2060168a9234SJohannes Doerfert Use *U = It.first;
2061168a9234SJohannes Doerfert Value *NewV = It.second;
2062168a9234SJohannes Doerfert ReplaceUse(U, NewV);
2063cd4aab4aSJohannes Doerfert }
2064168a9234SJohannes Doerfert
2065168a9234SJohannes Doerfert SmallVector<Use *, 4> Uses;
2066168a9234SJohannes Doerfert for (auto &It : ToBeChangedValues) {
2067168a9234SJohannes Doerfert Value *OldV = It.first;
2068168a9234SJohannes Doerfert auto &Entry = It.second;
2069168a9234SJohannes Doerfert Value *NewV = Entry.first;
2070168a9234SJohannes Doerfert Uses.clear();
2071168a9234SJohannes Doerfert for (auto &U : OldV->uses())
2072168a9234SJohannes Doerfert if (Entry.second || !U.getUser()->isDroppable())
2073168a9234SJohannes Doerfert Uses.push_back(&U);
20740ece283fSJohannes Doerfert for (Use *U : Uses) {
20750ece283fSJohannes Doerfert if (auto *I = dyn_cast<Instruction>(U->getUser()))
20760ece283fSJohannes Doerfert if (!isRunOn(*I->getFunction()))
20770ece283fSJohannes Doerfert continue;
2078168a9234SJohannes Doerfert ReplaceUse(U, NewV);
2079168a9234SJohannes Doerfert }
20800ece283fSJohannes Doerfert }
2081168a9234SJohannes Doerfert
2082a4088c75SJohannes Doerfert for (auto &V : InvokeWithDeadSuccessor)
2083a4088c75SJohannes Doerfert if (InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) {
20841ba2929bSJohannes Doerfert assert(isRunOn(*II->getFunction()) &&
20851ba2929bSJohannes Doerfert "Cannot replace an invoke outside the current SCC!");
2086a4088c75SJohannes Doerfert bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind);
2087a4088c75SJohannes Doerfert bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn);
2088a4088c75SJohannes Doerfert bool Invoke2CallAllowed =
20890985554bSJohannes Doerfert !AAIsDead::mayCatchAsynchronousExceptions(*II->getFunction());
2090a4088c75SJohannes Doerfert assert((UnwindBBIsDead || NormalBBIsDead) &&
2091a4088c75SJohannes Doerfert "Invoke does not have dead successors!");
2092a4088c75SJohannes Doerfert BasicBlock *BB = II->getParent();
2093a4088c75SJohannes Doerfert BasicBlock *NormalDestBB = II->getNormalDest();
2094a4088c75SJohannes Doerfert if (UnwindBBIsDead) {
2095a4088c75SJohannes Doerfert Instruction *NormalNextIP = &NormalDestBB->front();
2096a4088c75SJohannes Doerfert if (Invoke2CallAllowed) {
2097a4088c75SJohannes Doerfert changeToCall(II);
2098a4088c75SJohannes Doerfert NormalNextIP = BB->getTerminator();
2099a4088c75SJohannes Doerfert }
2100a4088c75SJohannes Doerfert if (NormalBBIsDead)
2101a4088c75SJohannes Doerfert ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2102a4088c75SJohannes Doerfert } else {
2103a4088c75SJohannes Doerfert assert(NormalBBIsDead && "Broken invariant!");
2104a4088c75SJohannes Doerfert if (!NormalDestBB->getUniquePredecessor())
2105a4088c75SJohannes Doerfert NormalDestBB = SplitBlockPredecessors(NormalDestBB, {BB}, ".dead");
2106a4088c75SJohannes Doerfert ToBeChangedToUnreachableInsts.insert(&NormalDestBB->front());
2107a4088c75SJohannes Doerfert }
2108a4088c75SJohannes Doerfert }
210901c48d7dSStefanos Baziotis for (Instruction *I : TerminatorsToFold) {
2110f3ad8cf0SJohannes Doerfert assert(isRunOn(*I->getFunction()) &&
2111f3ad8cf0SJohannes Doerfert "Cannot replace a terminator outside the current SCC!");
211201c48d7dSStefanos Baziotis CGModifiedFunctions.insert(I->getFunction());
211301c48d7dSStefanos Baziotis ConstantFoldTerminator(I->getParent());
211401c48d7dSStefanos Baziotis }
21151e46eb74SJohannes Doerfert for (auto &V : ToBeChangedToUnreachableInsts)
2116b0c77c36SJohannes Doerfert if (Instruction *I = dyn_cast_or_null<Instruction>(V)) {
2117bf789b19SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Change to unreachable: " << *I
2118bf789b19SJohannes Doerfert << "\n");
2119f3ad8cf0SJohannes Doerfert assert(isRunOn(*I->getFunction()) &&
2120f3ad8cf0SJohannes Doerfert "Cannot replace an instruction outside the current SCC!");
2121b0c77c36SJohannes Doerfert CGModifiedFunctions.insert(I->getFunction());
212225a3130dSJohannes Doerfert changeToUnreachable(I);
2123b0c77c36SJohannes Doerfert }
2124cd4aab4aSJohannes Doerfert
21255429c82dSJohannes Doerfert for (auto &V : ToBeDeletedInsts) {
21265429c82dSJohannes Doerfert if (Instruction *I = dyn_cast_or_null<Instruction>(V)) {
21270c0eb767SJohannes Doerfert if (auto *CB = dyn_cast<CallBase>(I)) {
2128f3ad8cf0SJohannes Doerfert assert(isRunOn(*I->getFunction()) &&
2129f3ad8cf0SJohannes Doerfert "Cannot delete an instruction outside the current SCC!");
21300c0eb767SJohannes Doerfert if (!isa<IntrinsicInst>(CB))
21313be3b401SJohannes Doerfert Configuration.CGUpdater.removeCallSite(*CB);
21320c0eb767SJohannes Doerfert }
21330741dec2SJohannes Doerfert I->dropDroppableUses();
2134b0c77c36SJohannes Doerfert CGModifiedFunctions.insert(I->getFunction());
2135b4352e43SJohannes Doerfert if (!I->getType()->isVoidTy())
213639681e73SJohannes Doerfert I->replaceAllUsesWith(UndefValue::get(I->getType()));
2137cd4aab4aSJohannes Doerfert if (!isa<PHINode>(I) && isInstructionTriviallyDead(I))
2138cd4aab4aSJohannes Doerfert DeadInsts.push_back(I);
2139cd4aab4aSJohannes Doerfert else
214039681e73SJohannes Doerfert I->eraseFromParent();
214139681e73SJohannes Doerfert }
21425429c82dSJohannes Doerfert }
2143b19cd27bSJohannes Doerfert
2144f3ad8cf0SJohannes Doerfert llvm::erase_if(DeadInsts, [&](WeakTrackingVH I) { return !I; });
2145850b150cSsstefan1
21462bc51d39SJohannes Doerfert LLVM_DEBUG({
21472bc51d39SJohannes Doerfert dbgs() << "[Attributor] DeadInsts size: " << DeadInsts.size() << "\n";
21482bc51d39SJohannes Doerfert for (auto &I : DeadInsts)
21492bc51d39SJohannes Doerfert if (I)
21502bc51d39SJohannes Doerfert dbgs() << " - " << *I << "\n";
21512bc51d39SJohannes Doerfert });
21522bc51d39SJohannes Doerfert
2153cd4aab4aSJohannes Doerfert RecursivelyDeleteTriviallyDeadInstructions(DeadInsts);
2154cd4aab4aSJohannes Doerfert
2155b19cd27bSJohannes Doerfert if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2156b19cd27bSJohannes Doerfert SmallVector<BasicBlock *, 8> ToBeDeletedBBs;
2157b19cd27bSJohannes Doerfert ToBeDeletedBBs.reserve(NumDeadBlocks);
2158b0c77c36SJohannes Doerfert for (BasicBlock *BB : ToBeDeletedBlocks) {
21591ba2929bSJohannes Doerfert assert(isRunOn(*BB->getParent()) &&
21601ba2929bSJohannes Doerfert "Cannot delete a block outside the current SCC!");
2161b0c77c36SJohannes Doerfert CGModifiedFunctions.insert(BB->getParent());
21623f71b425SGiorgis Georgakoudis // Do not delete BBs added during manifests of AAs.
21633f71b425SGiorgis Georgakoudis if (ManifestAddedBlocks.contains(BB))
21643f71b425SGiorgis Georgakoudis continue;
2165b0c77c36SJohannes Doerfert ToBeDeletedBBs.push_back(BB);
2166b0c77c36SJohannes Doerfert }
21675e442a51SJohannes Doerfert // Actually we do not delete the blocks but squash them into a single
21685e442a51SJohannes Doerfert // unreachable but untangling branches that jump here is something we need
21695e442a51SJohannes Doerfert // to do in a more generic way.
2170cf0357a5SNikita Popov detachDeadBlocks(ToBeDeletedBBs, nullptr);
217139681e73SJohannes Doerfert }
2172b19cd27bSJohannes Doerfert
21731c2531c9SJohannes Doerfert identifyDeadInternalFunctions();
217439681e73SJohannes Doerfert
2175b0c77c36SJohannes Doerfert // Rewrite the functions as requested during manifest.
217610b05397Sclfbbn ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2177b0c77c36SJohannes Doerfert
2178b0c77c36SJohannes Doerfert for (Function *Fn : CGModifiedFunctions)
21791ba2929bSJohannes Doerfert if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
21803be3b401SJohannes Doerfert Configuration.CGUpdater.reanalyzeFunction(*Fn);
2181b0c77c36SJohannes Doerfert
21828d8ce85bSsstefan1 for (Function *Fn : ToBeDeletedFunctions) {
21838d8ce85bSsstefan1 if (!Functions.count(Fn))
21848d8ce85bSsstefan1 continue;
21853be3b401SJohannes Doerfert Configuration.CGUpdater.removeFunction(*Fn);
21868d8ce85bSsstefan1 }
21876b9ee2d6SJohannes Doerfert
218879651265SJohannes Doerfert if (!ToBeChangedUses.empty())
218979651265SJohannes Doerfert ManifestChange = ChangeStatus::CHANGED;
219079651265SJohannes Doerfert
219179651265SJohannes Doerfert if (!ToBeChangedToUnreachableInsts.empty())
219279651265SJohannes Doerfert ManifestChange = ChangeStatus::CHANGED;
219379651265SJohannes Doerfert
21945621571fSserge-sans-paille if (!ToBeDeletedFunctions.empty())
21955621571fSserge-sans-paille ManifestChange = ChangeStatus::CHANGED;
21965621571fSserge-sans-paille
219779651265SJohannes Doerfert if (!ToBeDeletedBlocks.empty())
219879651265SJohannes Doerfert ManifestChange = ChangeStatus::CHANGED;
219979651265SJohannes Doerfert
220079651265SJohannes Doerfert if (!ToBeDeletedInsts.empty())
220179651265SJohannes Doerfert ManifestChange = ChangeStatus::CHANGED;
220279651265SJohannes Doerfert
220379651265SJohannes Doerfert if (!InvokeWithDeadSuccessor.empty())
220479651265SJohannes Doerfert ManifestChange = ChangeStatus::CHANGED;
220579651265SJohannes Doerfert
220679651265SJohannes Doerfert if (!DeadInsts.empty())
220779651265SJohannes Doerfert ManifestChange = ChangeStatus::CHANGED;
220879651265SJohannes Doerfert
22090985554bSJohannes Doerfert NumFnDeleted += ToBeDeletedFunctions.size();
22100985554bSJohannes Doerfert
22111d57b7f5SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Deleted " << ToBeDeletedFunctions.size()
2212850b150cSsstefan1 << " functions after manifest.\n");
2213850b150cSsstefan1
2214ad9c284cSJohannes Doerfert #ifdef EXPENSIVE_CHECKS
2215ad9c284cSJohannes Doerfert for (Function *F : Functions) {
2216ad9c284cSJohannes Doerfert if (ToBeDeletedFunctions.count(F))
2217ad9c284cSJohannes Doerfert continue;
2218ad9c284cSJohannes Doerfert assert(!verifyFunction(*F, &errs()) && "Module verification failed!");
2219ad9c284cSJohannes Doerfert }
2220ad9c284cSJohannes Doerfert #endif
2221ad9c284cSJohannes Doerfert
2222aade782aSJohannes Doerfert return ManifestChange;
2223aade782aSJohannes Doerfert }
2224aade782aSJohannes Doerfert
run()222570330edcSKuter Dinel ChangeStatus Attributor::run() {
222649def10eSkuterd TimeTraceScope TimeScope("Attributor::run");
2227eaf1b681SKuter Dinel AttributorCallGraph ACallGraph(*this);
2228eaf1b681SKuter Dinel
2229eaf1b681SKuter Dinel if (PrintCallGraph)
2230eaf1b681SKuter Dinel ACallGraph.populateAll();
223149def10eSkuterd
22327a68f0f1SShinji Okumura Phase = AttributorPhase::UPDATE;
223370330edcSKuter Dinel runTillFixpoint();
22345ee07dc5SLuofan Chen
22355ee07dc5SLuofan Chen // dump graphs on demand
22365ee07dc5SLuofan Chen if (DumpDepGraph)
22375ee07dc5SLuofan Chen DG.dumpGraph();
22385ee07dc5SLuofan Chen
22395ee07dc5SLuofan Chen if (ViewDepGraph)
22405ee07dc5SLuofan Chen DG.viewGraph();
22415ee07dc5SLuofan Chen
22425ee07dc5SLuofan Chen if (PrintDependencies)
22435ee07dc5SLuofan Chen DG.print();
22445ee07dc5SLuofan Chen
22457a68f0f1SShinji Okumura Phase = AttributorPhase::MANIFEST;
224670330edcSKuter Dinel ChangeStatus ManifestChange = manifestAttributes();
22477a68f0f1SShinji Okumura
22487a68f0f1SShinji Okumura Phase = AttributorPhase::CLEANUP;
224970330edcSKuter Dinel ChangeStatus CleanupChange = cleanupIR();
22507a68f0f1SShinji Okumura
2251eaf1b681SKuter Dinel if (PrintCallGraph)
2252eaf1b681SKuter Dinel ACallGraph.print();
2253eaf1b681SKuter Dinel
225470330edcSKuter Dinel return ManifestChange | CleanupChange;
225570330edcSKuter Dinel }
225670330edcSKuter Dinel
updateAA(AbstractAttribute & AA)225795e0d28bSJohannes Doerfert ChangeStatus Attributor::updateAA(AbstractAttribute &AA) {
2258cb813ab6SJohannes Doerfert TimeTraceScope TimeScope(
2259cb813ab6SJohannes Doerfert AA.getName() + std::to_string(AA.getIRPosition().getPositionKind()) +
2260cb813ab6SJohannes Doerfert "::updateAA");
2261c5e6872eSShinji Okumura assert(Phase == AttributorPhase::UPDATE &&
2262c5e6872eSShinji Okumura "We can update AA only in the update stage!");
226349def10eSkuterd
226495e0d28bSJohannes Doerfert // Use a new dependence vector for this update.
226595e0d28bSJohannes Doerfert DependenceVector DV;
226695e0d28bSJohannes Doerfert DependenceStack.push_back(&DV);
226795e0d28bSJohannes Doerfert
226895e0d28bSJohannes Doerfert auto &AAState = AA.getState();
2269edf03914SJohannes Doerfert ChangeStatus CS = ChangeStatus::UNCHANGED;
2270792aac98SJohannes Doerfert bool UsedAssumedInformation = false;
2271792aac98SJohannes Doerfert if (!isAssumedDead(AA, nullptr, UsedAssumedInformation,
2272792aac98SJohannes Doerfert /* CheckBBLivenessOnly */ true))
2273edf03914SJohannes Doerfert CS = AA.update(*this);
2274edf03914SJohannes Doerfert
2275b51b83f6SJohannes Doerfert if (!AA.isQueryAA() && DV.empty()) {
227695e0d28bSJohannes Doerfert // If the attribute did not query any non-fix information, the state
227795e0d28bSJohannes Doerfert // will not change and we can indicate that right away.
227895e0d28bSJohannes Doerfert AAState.indicateOptimisticFixpoint();
227995e0d28bSJohannes Doerfert }
228095e0d28bSJohannes Doerfert
228195e0d28bSJohannes Doerfert if (!AAState.isAtFixpoint())
228295e0d28bSJohannes Doerfert rememberDependences();
228395e0d28bSJohannes Doerfert
228495e0d28bSJohannes Doerfert // Verify the stack was used properly, that is we pop the dependence vector we
228595e0d28bSJohannes Doerfert // put there earlier.
228695e0d28bSJohannes Doerfert DependenceVector *PoppedDV = DependenceStack.pop_back_val();
228795e0d28bSJohannes Doerfert (void)PoppedDV;
228895e0d28bSJohannes Doerfert assert(PoppedDV == &DV && "Inconsistent usage of the dependence stack!");
228995e0d28bSJohannes Doerfert
229095e0d28bSJohannes Doerfert return CS;
229195e0d28bSJohannes Doerfert }
229295e0d28bSJohannes Doerfert
createShallowWrapper(Function & F)2293ce16be25Ssstefan1 void Attributor::createShallowWrapper(Function &F) {
2294eec6d876SLuofan Chen assert(!F.isDeclaration() && "Cannot create a wrapper around a declaration!");
2295eec6d876SLuofan Chen
2296eec6d876SLuofan Chen Module &M = *F.getParent();
2297eec6d876SLuofan Chen LLVMContext &Ctx = M.getContext();
2298eec6d876SLuofan Chen FunctionType *FnTy = F.getFunctionType();
2299eec6d876SLuofan Chen
2300eec6d876SLuofan Chen Function *Wrapper =
2301eec6d876SLuofan Chen Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(), F.getName());
2302eec6d876SLuofan Chen F.setName(""); // set the inside function anonymous
2303eec6d876SLuofan Chen M.getFunctionList().insert(F.getIterator(), Wrapper);
2304eec6d876SLuofan Chen
2305eec6d876SLuofan Chen F.setLinkage(GlobalValue::InternalLinkage);
2306eec6d876SLuofan Chen
2307eec6d876SLuofan Chen F.replaceAllUsesWith(Wrapper);
2308b7e23582SNikita Popov assert(F.use_empty() && "Uses remained after wrapper was created!");
2309eec6d876SLuofan Chen
2310eec6d876SLuofan Chen // Move the COMDAT section to the wrapper.
2311eec6d876SLuofan Chen // TODO: Check if we need to keep it for F as well.
2312eec6d876SLuofan Chen Wrapper->setComdat(F.getComdat());
2313eec6d876SLuofan Chen F.setComdat(nullptr);
2314eec6d876SLuofan Chen
2315eec6d876SLuofan Chen // Copy all metadata and attributes but keep them on F as well.
2316eec6d876SLuofan Chen SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
2317eec6d876SLuofan Chen F.getAllMetadata(MDs);
2318eec6d876SLuofan Chen for (auto MDIt : MDs)
2319eec6d876SLuofan Chen Wrapper->addMetadata(MDIt.first, *MDIt.second);
2320eec6d876SLuofan Chen Wrapper->setAttributes(F.getAttributes());
2321eec6d876SLuofan Chen
2322eec6d876SLuofan Chen // Create the call in the wrapper.
2323eec6d876SLuofan Chen BasicBlock *EntryBB = BasicBlock::Create(Ctx, "entry", Wrapper);
2324eec6d876SLuofan Chen
2325eec6d876SLuofan Chen SmallVector<Value *, 8> Args;
2326ff70c25dSJohannes Doerfert Argument *FArgIt = F.arg_begin();
2327eec6d876SLuofan Chen for (Argument &Arg : Wrapper->args()) {
2328eec6d876SLuofan Chen Args.push_back(&Arg);
2329eec6d876SLuofan Chen Arg.setName((FArgIt++)->getName());
2330eec6d876SLuofan Chen }
2331eec6d876SLuofan Chen
2332eec6d876SLuofan Chen CallInst *CI = CallInst::Create(&F, Args, "", EntryBB);
2333eec6d876SLuofan Chen CI->setTailCall(true);
23343f4d00bcSArthur Eubanks CI->addFnAttr(Attribute::NoInline);
2335eec6d876SLuofan Chen ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI, EntryBB);
2336eec6d876SLuofan Chen
2337ce16be25Ssstefan1 NumFnShallowWrappersCreated++;
2338eec6d876SLuofan Chen }
2339eec6d876SLuofan Chen
isInternalizable(Function & F)2340adbaa39dSJoseph Huber bool Attributor::isInternalizable(Function &F) {
2341adbaa39dSJoseph Huber if (F.isDeclaration() || F.hasLocalLinkage() ||
2342adbaa39dSJoseph Huber GlobalValue::isInterposableLinkage(F.getLinkage()))
2343adbaa39dSJoseph Huber return false;
2344adbaa39dSJoseph Huber return true;
2345adbaa39dSJoseph Huber }
2346adbaa39dSJoseph Huber
internalizeFunction(Function & F,bool Force)234703d7e61cSJoseph Huber Function *Attributor::internalizeFunction(Function &F, bool Force) {
234803d7e61cSJoseph Huber if (!AllowDeepWrapper && !Force)
234903d7e61cSJoseph Huber return nullptr;
2350adbaa39dSJoseph Huber if (!isInternalizable(F))
235103d7e61cSJoseph Huber return nullptr;
235287a85f3dSLuofan Chen
2353adbaa39dSJoseph Huber SmallPtrSet<Function *, 2> FnSet = {&F};
2354adbaa39dSJoseph Huber DenseMap<Function *, Function *> InternalizedFns;
2355adbaa39dSJoseph Huber internalizeFunctions(FnSet, InternalizedFns);
235687a85f3dSLuofan Chen
2357adbaa39dSJoseph Huber return InternalizedFns[&F];
2358adbaa39dSJoseph Huber }
2359adbaa39dSJoseph Huber
internalizeFunctions(SmallPtrSetImpl<Function * > & FnSet,DenseMap<Function *,Function * > & FnMap)2360adbaa39dSJoseph Huber bool Attributor::internalizeFunctions(SmallPtrSetImpl<Function *> &FnSet,
2361adbaa39dSJoseph Huber DenseMap<Function *, Function *> &FnMap) {
2362adbaa39dSJoseph Huber for (Function *F : FnSet)
2363adbaa39dSJoseph Huber if (!Attributor::isInternalizable(*F))
2364adbaa39dSJoseph Huber return false;
2365adbaa39dSJoseph Huber
2366adbaa39dSJoseph Huber FnMap.clear();
2367adbaa39dSJoseph Huber // Generate the internalized version of each function.
2368adbaa39dSJoseph Huber for (Function *F : FnSet) {
2369adbaa39dSJoseph Huber Module &M = *F->getParent();
2370adbaa39dSJoseph Huber FunctionType *FnTy = F->getFunctionType();
2371adbaa39dSJoseph Huber
2372adbaa39dSJoseph Huber // Create a copy of the current function
2373adbaa39dSJoseph Huber Function *Copied =
2374adbaa39dSJoseph Huber Function::Create(FnTy, F->getLinkage(), F->getAddressSpace(),
2375adbaa39dSJoseph Huber F->getName() + ".internalized");
237687a85f3dSLuofan Chen ValueToValueMapTy VMap;
237787a85f3dSLuofan Chen auto *NewFArgIt = Copied->arg_begin();
2378adbaa39dSJoseph Huber for (auto &Arg : F->args()) {
237987a85f3dSLuofan Chen auto ArgName = Arg.getName();
238087a85f3dSLuofan Chen NewFArgIt->setName(ArgName);
238187a85f3dSLuofan Chen VMap[&Arg] = &(*NewFArgIt++);
238287a85f3dSLuofan Chen }
238387a85f3dSLuofan Chen SmallVector<ReturnInst *, 8> Returns;
238487a85f3dSLuofan Chen
238587a85f3dSLuofan Chen // Copy the body of the original function to the new one
2386adbaa39dSJoseph Huber CloneFunctionInto(Copied, F, VMap,
2387adbaa39dSJoseph Huber CloneFunctionChangeType::LocalChangesOnly, Returns);
238887a85f3dSLuofan Chen
2389adbaa39dSJoseph Huber // Set the linakage and visibility late as CloneFunctionInto has some
2390adbaa39dSJoseph Huber // implicit requirements.
2391711bf7dcSJohannes Doerfert Copied->setVisibility(GlobalValue::DefaultVisibility);
2392711bf7dcSJohannes Doerfert Copied->setLinkage(GlobalValue::PrivateLinkage);
2393711bf7dcSJohannes Doerfert
239487a85f3dSLuofan Chen // Copy metadata
239587a85f3dSLuofan Chen SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
2396adbaa39dSJoseph Huber F->getAllMetadata(MDs);
239787a85f3dSLuofan Chen for (auto MDIt : MDs)
239803d7e61cSJoseph Huber if (!Copied->hasMetadata())
239987a85f3dSLuofan Chen Copied->addMetadata(MDIt.first, *MDIt.second);
240087a85f3dSLuofan Chen
2401adbaa39dSJoseph Huber M.getFunctionList().insert(F->getIterator(), Copied);
240287a85f3dSLuofan Chen Copied->setDSOLocal(true);
2403adbaa39dSJoseph Huber FnMap[F] = Copied;
2404adbaa39dSJoseph Huber }
240587a85f3dSLuofan Chen
2406adbaa39dSJoseph Huber // Replace all uses of the old function with the new internalized function
2407adbaa39dSJoseph Huber // unless the caller is a function that was just internalized.
2408adbaa39dSJoseph Huber for (Function *F : FnSet) {
2409adbaa39dSJoseph Huber auto &InternalizedFn = FnMap[F];
2410adbaa39dSJoseph Huber auto IsNotInternalized = [&](Use &U) -> bool {
2411adbaa39dSJoseph Huber if (auto *CB = dyn_cast<CallBase>(U.getUser()))
2412adbaa39dSJoseph Huber return !FnMap.lookup(CB->getCaller());
2413adbaa39dSJoseph Huber return false;
2414adbaa39dSJoseph Huber };
2415adbaa39dSJoseph Huber F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2416adbaa39dSJoseph Huber }
2417adbaa39dSJoseph Huber
2418adbaa39dSJoseph Huber return true;
241987a85f3dSLuofan Chen }
242087a85f3dSLuofan Chen
isValidFunctionSignatureRewrite(Argument & Arg,ArrayRef<Type * > ReplacementTypes)242189c2e733SJohannes Doerfert bool Attributor::isValidFunctionSignatureRewrite(
242289c2e733SJohannes Doerfert Argument &Arg, ArrayRef<Type *> ReplacementTypes) {
242375133634SJohannes Doerfert
24243be3b401SJohannes Doerfert if (!Configuration.RewriteSignatures)
242503d7e61cSJoseph Huber return false;
242603d7e61cSJoseph Huber
24274e7d7caeSJohannes Doerfert Function *Fn = Arg.getParent();
24284e7d7caeSJohannes Doerfert auto CallSiteCanBeChanged = [Fn](AbstractCallSite ACS) {
24298d94d3c3SJohannes Doerfert // Forbid the call site to cast the function return type. If we need to
24308d94d3c3SJohannes Doerfert // rewrite these functions we need to re-create a cast for the new call site
24318d94d3c3SJohannes Doerfert // (if the old had uses).
24328d94d3c3SJohannes Doerfert if (!ACS.getCalledFunction() ||
24338d94d3c3SJohannes Doerfert ACS.getInstruction()->getType() !=
24348d94d3c3SJohannes Doerfert ACS.getCalledFunction()->getReturnType())
24358d94d3c3SJohannes Doerfert return false;
24364e7d7caeSJohannes Doerfert if (ACS.getCalledOperand()->getType() != Fn->getType())
24374e7d7caeSJohannes Doerfert return false;
243875133634SJohannes Doerfert // Forbid must-tail calls for now.
2439798b262cSCraig Topper return !ACS.isCallbackCall() && !ACS.getInstruction()->isMustTailCall();
244075133634SJohannes Doerfert };
244175133634SJohannes Doerfert
244275133634SJohannes Doerfert // Avoid var-arg functions for now.
244375133634SJohannes Doerfert if (Fn->isVarArg()) {
244475133634SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite var-args functions\n");
244575133634SJohannes Doerfert return false;
244675133634SJohannes Doerfert }
244775133634SJohannes Doerfert
244875133634SJohannes Doerfert // Avoid functions with complicated argument passing semantics.
244975133634SJohannes Doerfert AttributeList FnAttributeList = Fn->getAttributes();
245075133634SJohannes Doerfert if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) ||
245175133634SJohannes Doerfert FnAttributeList.hasAttrSomewhere(Attribute::StructRet) ||
24528a887556SArthur Eubanks FnAttributeList.hasAttrSomewhere(Attribute::InAlloca) ||
24538a887556SArthur Eubanks FnAttributeList.hasAttrSomewhere(Attribute::Preallocated)) {
245475133634SJohannes Doerfert LLVM_DEBUG(
245575133634SJohannes Doerfert dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n");
245675133634SJohannes Doerfert return false;
245775133634SJohannes Doerfert }
245875133634SJohannes Doerfert
245975133634SJohannes Doerfert // Avoid callbacks for now.
24606ed1ef06SJohannes Doerfert bool UsedAssumedInformation = false;
2461368f7ee7SJohannes Doerfert if (!checkForAllCallSites(CallSiteCanBeChanged, *Fn, true, nullptr,
24626ed1ef06SJohannes Doerfert UsedAssumedInformation)) {
246375133634SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n");
246475133634SJohannes Doerfert return false;
246575133634SJohannes Doerfert }
246675133634SJohannes Doerfert
246775133634SJohannes Doerfert auto InstPred = [](Instruction &I) {
246875133634SJohannes Doerfert if (auto *CI = dyn_cast<CallInst>(&I))
246975133634SJohannes Doerfert return !CI->isMustTailCall();
247075133634SJohannes Doerfert return true;
247175133634SJohannes Doerfert };
247275133634SJohannes Doerfert
247375133634SJohannes Doerfert // Forbid must-tail calls for now.
247475133634SJohannes Doerfert // TODO:
247575133634SJohannes Doerfert auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
247623f41f16SJohannes Doerfert if (!checkForAllInstructionsImpl(nullptr, OpcodeInstMap, InstPred, nullptr,
2477792aac98SJohannes Doerfert nullptr, {Instruction::Call},
2478792aac98SJohannes Doerfert UsedAssumedInformation)) {
247975133634SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite due to instructions\n");
248075133634SJohannes Doerfert return false;
248175133634SJohannes Doerfert }
248275133634SJohannes Doerfert
248389c2e733SJohannes Doerfert return true;
248489c2e733SJohannes Doerfert }
248589c2e733SJohannes Doerfert
registerFunctionSignatureRewrite(Argument & Arg,ArrayRef<Type * > ReplacementTypes,ArgumentReplacementInfo::CalleeRepairCBTy && CalleeRepairCB,ArgumentReplacementInfo::ACSRepairCBTy && ACSRepairCB)248689c2e733SJohannes Doerfert bool Attributor::registerFunctionSignatureRewrite(
248789c2e733SJohannes Doerfert Argument &Arg, ArrayRef<Type *> ReplacementTypes,
248889c2e733SJohannes Doerfert ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB,
248989c2e733SJohannes Doerfert ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB) {
249089c2e733SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "
249189c2e733SJohannes Doerfert << Arg.getParent()->getName() << " with "
249289c2e733SJohannes Doerfert << ReplacementTypes.size() << " replacements\n");
249389c2e733SJohannes Doerfert assert(isValidFunctionSignatureRewrite(Arg, ReplacementTypes) &&
249489c2e733SJohannes Doerfert "Cannot register an invalid rewrite");
249589c2e733SJohannes Doerfert
249689c2e733SJohannes Doerfert Function *Fn = Arg.getParent();
24973c89256dSDavid Blaikie SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs =
24983c89256dSDavid Blaikie ArgumentReplacementMap[Fn];
249989c2e733SJohannes Doerfert if (ARIs.empty())
250075133634SJohannes Doerfert ARIs.resize(Fn->arg_size());
250175133634SJohannes Doerfert
250275133634SJohannes Doerfert // If we have a replacement already with less than or equal new arguments,
250375133634SJohannes Doerfert // ignore this request.
25043c89256dSDavid Blaikie std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.getArgNo()];
250575133634SJohannes Doerfert if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.size()) {
250675133634SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Existing rewrite is preferred\n");
250775133634SJohannes Doerfert return false;
250875133634SJohannes Doerfert }
250975133634SJohannes Doerfert
251075133634SJohannes Doerfert // If we have a replacement already but we like the new one better, delete
251175133634SJohannes Doerfert // the old.
25123c89256dSDavid Blaikie ARI.reset();
251375133634SJohannes Doerfert
251489c2e733SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "
251589c2e733SJohannes Doerfert << Arg.getParent()->getName() << " with "
251689c2e733SJohannes Doerfert << ReplacementTypes.size() << " replacements\n");
251789c2e733SJohannes Doerfert
251875133634SJohannes Doerfert // Remember the replacement.
25193c89256dSDavid Blaikie ARI.reset(new ArgumentReplacementInfo(*this, Arg, ReplacementTypes,
252075133634SJohannes Doerfert std::move(CalleeRepairCB),
25213c89256dSDavid Blaikie std::move(ACSRepairCB)));
252275133634SJohannes Doerfert
252375133634SJohannes Doerfert return true;
252475133634SJohannes Doerfert }
252575133634SJohannes Doerfert
shouldSeedAttribute(AbstractAttribute & AA)25264dbe82eeSkuter bool Attributor::shouldSeedAttribute(AbstractAttribute &AA) {
252765fcc0eeSkuterd bool Result = true;
252865fcc0eeSkuterd #ifndef NDEBUG
252965fcc0eeSkuterd if (SeedAllowList.size() != 0)
253036b8a4f9SKazu Hirata Result = llvm::is_contained(SeedAllowList, AA.getName());
253165fcc0eeSkuterd Function *Fn = AA.getAnchorScope();
253265fcc0eeSkuterd if (FunctionSeedAllowList.size() != 0 && Fn)
253336b8a4f9SKazu Hirata Result &= llvm::is_contained(FunctionSeedAllowList, Fn->getName());
253465fcc0eeSkuterd #endif
253565fcc0eeSkuterd return Result;
25364dbe82eeSkuter }
25374dbe82eeSkuter
rewriteFunctionSignatures(SmallSetVector<Function *,8> & ModifiedFns)2538b0c77c36SJohannes Doerfert ChangeStatus Attributor::rewriteFunctionSignatures(
25397211dbd0SJohannes Doerfert SmallSetVector<Function *, 8> &ModifiedFns) {
254075133634SJohannes Doerfert ChangeStatus Changed = ChangeStatus::UNCHANGED;
254175133634SJohannes Doerfert
254275133634SJohannes Doerfert for (auto &It : ArgumentReplacementMap) {
254375133634SJohannes Doerfert Function *OldFn = It.getFirst();
254475133634SJohannes Doerfert
254575133634SJohannes Doerfert // Deleted functions do not require rewrites.
25468d8ce85bSsstefan1 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
254775133634SJohannes Doerfert continue;
254875133634SJohannes Doerfert
2549a9ee8b49SJohannes Doerfert const SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs =
2550a9ee8b49SJohannes Doerfert It.getSecond();
255175133634SJohannes Doerfert assert(ARIs.size() == OldFn->arg_size() && "Inconsistent state!");
255275133634SJohannes Doerfert
255375133634SJohannes Doerfert SmallVector<Type *, 16> NewArgumentTypes;
255475133634SJohannes Doerfert SmallVector<AttributeSet, 16> NewArgumentAttributes;
255575133634SJohannes Doerfert
255675133634SJohannes Doerfert // Collect replacement argument types and copy over existing attributes.
255775133634SJohannes Doerfert AttributeList OldFnAttributeList = OldFn->getAttributes();
255875133634SJohannes Doerfert for (Argument &Arg : OldFn->args()) {
2559a9ee8b49SJohannes Doerfert if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2560a9ee8b49SJohannes Doerfert ARIs[Arg.getArgNo()]) {
256175133634SJohannes Doerfert NewArgumentTypes.append(ARI->ReplacementTypes.begin(),
256275133634SJohannes Doerfert ARI->ReplacementTypes.end());
256375133634SJohannes Doerfert NewArgumentAttributes.append(ARI->getNumReplacementArgs(),
256475133634SJohannes Doerfert AttributeSet());
256575133634SJohannes Doerfert } else {
256675133634SJohannes Doerfert NewArgumentTypes.push_back(Arg.getType());
256775133634SJohannes Doerfert NewArgumentAttributes.push_back(
256880ea2bb5SArthur Eubanks OldFnAttributeList.getParamAttrs(Arg.getArgNo()));
256975133634SJohannes Doerfert }
257075133634SJohannes Doerfert }
257175133634SJohannes Doerfert
25727c044542SPhoebe Wang uint64_t LargestVectorWidth = 0;
25737c044542SPhoebe Wang for (auto *I : NewArgumentTypes)
25747c044542SPhoebe Wang if (auto *VT = dyn_cast<llvm::VectorType>(I))
25757c044542SPhoebe Wang LargestVectorWidth = std::max(
25767c044542SPhoebe Wang LargestVectorWidth, VT->getPrimitiveSizeInBits().getKnownMinSize());
25777c044542SPhoebe Wang
257875133634SJohannes Doerfert FunctionType *OldFnTy = OldFn->getFunctionType();
257975133634SJohannes Doerfert Type *RetTy = OldFnTy->getReturnType();
258075133634SJohannes Doerfert
258175133634SJohannes Doerfert // Construct the new function type using the new arguments types.
258275133634SJohannes Doerfert FunctionType *NewFnTy =
258375133634SJohannes Doerfert FunctionType::get(RetTy, NewArgumentTypes, OldFnTy->isVarArg());
258475133634SJohannes Doerfert
258575133634SJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Function rewrite '" << OldFn->getName()
258675133634SJohannes Doerfert << "' from " << *OldFn->getFunctionType() << " to "
258775133634SJohannes Doerfert << *NewFnTy << "\n");
258875133634SJohannes Doerfert
258975133634SJohannes Doerfert // Create the new function body and insert it into the module.
259075133634SJohannes Doerfert Function *NewFn = Function::Create(NewFnTy, OldFn->getLinkage(),
259175133634SJohannes Doerfert OldFn->getAddressSpace(), "");
25921ba2929bSJohannes Doerfert Functions.insert(NewFn);
259375133634SJohannes Doerfert OldFn->getParent()->getFunctionList().insert(OldFn->getIterator(), NewFn);
259475133634SJohannes Doerfert NewFn->takeName(OldFn);
259575133634SJohannes Doerfert NewFn->copyAttributesFrom(OldFn);
259675133634SJohannes Doerfert
259775133634SJohannes Doerfert // Patch the pointer to LLVM function in debug info descriptor.
259875133634SJohannes Doerfert NewFn->setSubprogram(OldFn->getSubprogram());
259975133634SJohannes Doerfert OldFn->setSubprogram(nullptr);
260075133634SJohannes Doerfert
260175133634SJohannes Doerfert // Recompute the parameter attributes list based on the new arguments for
260275133634SJohannes Doerfert // the function.
260375133634SJohannes Doerfert LLVMContext &Ctx = OldFn->getContext();
260475133634SJohannes Doerfert NewFn->setAttributes(AttributeList::get(
260580ea2bb5SArthur Eubanks Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(),
260680ea2bb5SArthur Eubanks NewArgumentAttributes));
26077c044542SPhoebe Wang AttributeFuncs::updateMinLegalVectorWidthAttr(*NewFn, LargestVectorWidth);
260875133634SJohannes Doerfert
260975133634SJohannes Doerfert // Since we have now created the new function, splice the body of the old
261075133634SJohannes Doerfert // function right into the new function, leaving the old rotting hulk of the
261175133634SJohannes Doerfert // function empty.
261275133634SJohannes Doerfert NewFn->getBasicBlockList().splice(NewFn->begin(),
261375133634SJohannes Doerfert OldFn->getBasicBlockList());
261475133634SJohannes Doerfert
261532f5ee83SSergey Dmitriev // Fixup block addresses to reference new function.
261632f5ee83SSergey Dmitriev SmallVector<BlockAddress *, 8u> BlockAddresses;
261732f5ee83SSergey Dmitriev for (User *U : OldFn->users())
261832f5ee83SSergey Dmitriev if (auto *BA = dyn_cast<BlockAddress>(U))
261932f5ee83SSergey Dmitriev BlockAddresses.push_back(BA);
262032f5ee83SSergey Dmitriev for (auto *BA : BlockAddresses)
262132f5ee83SSergey Dmitriev BA->replaceAllUsesWith(BlockAddress::get(NewFn, BA->getBasicBlock()));
262232f5ee83SSergey Dmitriev
2623d2d2fb19SJohannes Doerfert // Set of all "call-like" instructions that invoke the old function mapped
2624d2d2fb19SJohannes Doerfert // to their new replacements.
2625d2d2fb19SJohannes Doerfert SmallVector<std::pair<CallBase *, CallBase *>, 8> CallSitePairs;
262675133634SJohannes Doerfert
262775133634SJohannes Doerfert // Callback to create a new "call-like" instruction for a given one.
262875133634SJohannes Doerfert auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) {
262975133634SJohannes Doerfert CallBase *OldCB = cast<CallBase>(ACS.getInstruction());
263075133634SJohannes Doerfert const AttributeList &OldCallAttributeList = OldCB->getAttributes();
263175133634SJohannes Doerfert
263275133634SJohannes Doerfert // Collect the new argument operands for the replacement call site.
263375133634SJohannes Doerfert SmallVector<Value *, 16> NewArgOperands;
263475133634SJohannes Doerfert SmallVector<AttributeSet, 16> NewArgOperandAttributes;
263575133634SJohannes Doerfert for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); ++OldArgNum) {
263675133634SJohannes Doerfert unsigned NewFirstArgNum = NewArgOperands.size();
26374f82af81SIlya Biryukov (void)NewFirstArgNum; // only used inside assert.
2638a9ee8b49SJohannes Doerfert if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2639a9ee8b49SJohannes Doerfert ARIs[OldArgNum]) {
264075133634SJohannes Doerfert if (ARI->ACSRepairCB)
264175133634SJohannes Doerfert ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
264275133634SJohannes Doerfert assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
264375133634SJohannes Doerfert NewArgOperands.size() &&
264475133634SJohannes Doerfert "ACS repair callback did not provide as many operand as new "
264575133634SJohannes Doerfert "types were registered!");
264675133634SJohannes Doerfert // TODO: Exose the attribute set to the ACS repair callback
264775133634SJohannes Doerfert NewArgOperandAttributes.append(ARI->ReplacementTypes.size(),
264875133634SJohannes Doerfert AttributeSet());
264975133634SJohannes Doerfert } else {
265075133634SJohannes Doerfert NewArgOperands.push_back(ACS.getCallArgOperand(OldArgNum));
265175133634SJohannes Doerfert NewArgOperandAttributes.push_back(
265280ea2bb5SArthur Eubanks OldCallAttributeList.getParamAttrs(OldArgNum));
265375133634SJohannes Doerfert }
265475133634SJohannes Doerfert }
265575133634SJohannes Doerfert
265675133634SJohannes Doerfert assert(NewArgOperands.size() == NewArgOperandAttributes.size() &&
265775133634SJohannes Doerfert "Mismatch # argument operands vs. # argument operand attributes!");
265875133634SJohannes Doerfert assert(NewArgOperands.size() == NewFn->arg_size() &&
265975133634SJohannes Doerfert "Mismatch # argument operands vs. # function arguments!");
266075133634SJohannes Doerfert
266175133634SJohannes Doerfert SmallVector<OperandBundleDef, 4> OperandBundleDefs;
266275133634SJohannes Doerfert OldCB->getOperandBundlesAsDefs(OperandBundleDefs);
266375133634SJohannes Doerfert
266475133634SJohannes Doerfert // Create a new call or invoke instruction to replace the old one.
266575133634SJohannes Doerfert CallBase *NewCB;
266675133634SJohannes Doerfert if (InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) {
266775133634SJohannes Doerfert NewCB =
266875133634SJohannes Doerfert InvokeInst::Create(NewFn, II->getNormalDest(), II->getUnwindDest(),
266975133634SJohannes Doerfert NewArgOperands, OperandBundleDefs, "", OldCB);
267075133634SJohannes Doerfert } else {
267175133634SJohannes Doerfert auto *NewCI = CallInst::Create(NewFn, NewArgOperands, OperandBundleDefs,
267275133634SJohannes Doerfert "", OldCB);
267375133634SJohannes Doerfert NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
267475133634SJohannes Doerfert NewCB = NewCI;
267575133634SJohannes Doerfert }
267675133634SJohannes Doerfert
267775133634SJohannes Doerfert // Copy over various properties and the new attributes.
2678417bcb88SYevgeny Rouban NewCB->copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
267975133634SJohannes Doerfert NewCB->setCallingConv(OldCB->getCallingConv());
268075133634SJohannes Doerfert NewCB->takeName(OldCB);
268175133634SJohannes Doerfert NewCB->setAttributes(AttributeList::get(
268280ea2bb5SArthur Eubanks Ctx, OldCallAttributeList.getFnAttrs(),
268380ea2bb5SArthur Eubanks OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes));
268475133634SJohannes Doerfert
26857c044542SPhoebe Wang AttributeFuncs::updateMinLegalVectorWidthAttr(*NewCB->getCaller(),
26867c044542SPhoebe Wang LargestVectorWidth);
26877c044542SPhoebe Wang
2688d2d2fb19SJohannes Doerfert CallSitePairs.push_back({OldCB, NewCB});
268975133634SJohannes Doerfert return true;
269075133634SJohannes Doerfert };
269175133634SJohannes Doerfert
269275133634SJohannes Doerfert // Use the CallSiteReplacementCreator to create replacement call sites.
26936ed1ef06SJohannes Doerfert bool UsedAssumedInformation = false;
2694368f7ee7SJohannes Doerfert bool Success = checkForAllCallSites(CallSiteReplacementCreator, *OldFn,
26956ed1ef06SJohannes Doerfert true, nullptr, UsedAssumedInformation);
26964f82af81SIlya Biryukov (void)Success;
269775133634SJohannes Doerfert assert(Success && "Assumed call site replacement to succeed!");
269875133634SJohannes Doerfert
269975133634SJohannes Doerfert // Rewire the arguments.
2700ff70c25dSJohannes Doerfert Argument *OldFnArgIt = OldFn->arg_begin();
2701ff70c25dSJohannes Doerfert Argument *NewFnArgIt = NewFn->arg_begin();
270275133634SJohannes Doerfert for (unsigned OldArgNum = 0; OldArgNum < ARIs.size();
270375133634SJohannes Doerfert ++OldArgNum, ++OldFnArgIt) {
27043c89256dSDavid Blaikie if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
27053c89256dSDavid Blaikie ARIs[OldArgNum]) {
270675133634SJohannes Doerfert if (ARI->CalleeRepairCB)
270775133634SJohannes Doerfert ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
2708f3ad8cf0SJohannes Doerfert if (ARI->ReplacementTypes.empty())
2709f3ad8cf0SJohannes Doerfert OldFnArgIt->replaceAllUsesWith(
2710f3ad8cf0SJohannes Doerfert PoisonValue::get(OldFnArgIt->getType()));
271175133634SJohannes Doerfert NewFnArgIt += ARI->ReplacementTypes.size();
271275133634SJohannes Doerfert } else {
271375133634SJohannes Doerfert NewFnArgIt->takeName(&*OldFnArgIt);
271475133634SJohannes Doerfert OldFnArgIt->replaceAllUsesWith(&*NewFnArgIt);
271575133634SJohannes Doerfert ++NewFnArgIt;
271675133634SJohannes Doerfert }
271775133634SJohannes Doerfert }
271875133634SJohannes Doerfert
271975133634SJohannes Doerfert // Eliminate the instructions *after* we visited all of them.
2720d2d2fb19SJohannes Doerfert for (auto &CallSitePair : CallSitePairs) {
2721d2d2fb19SJohannes Doerfert CallBase &OldCB = *CallSitePair.first;
2722d2d2fb19SJohannes Doerfert CallBase &NewCB = *CallSitePair.second;
27238d94d3c3SJohannes Doerfert assert(OldCB.getType() == NewCB.getType() &&
27248d94d3c3SJohannes Doerfert "Cannot handle call sites with different types!");
2725b0c77c36SJohannes Doerfert ModifiedFns.insert(OldCB.getFunction());
27263be3b401SJohannes Doerfert Configuration.CGUpdater.replaceCallSite(OldCB, NewCB);
2727d2d2fb19SJohannes Doerfert OldCB.replaceAllUsesWith(&NewCB);
2728d2d2fb19SJohannes Doerfert OldCB.eraseFromParent();
2729d2d2fb19SJohannes Doerfert }
273075133634SJohannes Doerfert
2731b0c77c36SJohannes Doerfert // Replace the function in the call graph (if any).
27323be3b401SJohannes Doerfert Configuration.CGUpdater.replaceFunctionWith(*OldFn, *NewFn);
2733b0c77c36SJohannes Doerfert
2734b0c77c36SJohannes Doerfert // If the old function was modified and needed to be reanalyzed, the new one
2735b0c77c36SJohannes Doerfert // does now.
27367211dbd0SJohannes Doerfert if (ModifiedFns.remove(OldFn))
2737b0c77c36SJohannes Doerfert ModifiedFns.insert(NewFn);
2738d2d2fb19SJohannes Doerfert
273975133634SJohannes Doerfert Changed = ChangeStatus::CHANGED;
274075133634SJohannes Doerfert }
274175133634SJohannes Doerfert
274275133634SJohannes Doerfert return Changed;
274375133634SJohannes Doerfert }
274475133634SJohannes Doerfert
initializeInformationCache(const Function & CF,FunctionInfo & FI)2745898bbc25SJohannes Doerfert void InformationCache::initializeInformationCache(const Function &CF,
2746898bbc25SJohannes Doerfert FunctionInfo &FI) {
2747898bbc25SJohannes Doerfert // As we do not modify the function here we can remove the const
2748898bbc25SJohannes Doerfert // withouth breaking implicit assumptions. At the end of the day, we could
2749898bbc25SJohannes Doerfert // initialize the cache eagerly which would look the same to the users.
2750898bbc25SJohannes Doerfert Function &F = const_cast<Function &>(CF);
27513ab9e8b8SJohannes Doerfert
27523ab9e8b8SJohannes Doerfert // Walk all instructions to find interesting instructions that might be
27533ab9e8b8SJohannes Doerfert // queried by abstract attributes during their initialization or update.
27543ab9e8b8SJohannes Doerfert // This has to happen before we create attributes.
27553ab9e8b8SJohannes Doerfert
2756c42aa1beSJohannes Doerfert DenseMap<const Value *, Optional<short>> AssumeUsesMap;
2757c42aa1beSJohannes Doerfert
2758c42aa1beSJohannes Doerfert // Add \p V to the assume uses map which track the number of uses outside of
2759c42aa1beSJohannes Doerfert // "visited" assumes. If no outside uses are left the value is added to the
2760c42aa1beSJohannes Doerfert // assume only use vector.
2761c42aa1beSJohannes Doerfert auto AddToAssumeUsesMap = [&](const Value &V) -> void {
2762c42aa1beSJohannes Doerfert SmallVector<const Instruction *> Worklist;
2763c42aa1beSJohannes Doerfert if (auto *I = dyn_cast<Instruction>(&V))
2764c42aa1beSJohannes Doerfert Worklist.push_back(I);
2765c42aa1beSJohannes Doerfert while (!Worklist.empty()) {
2766c42aa1beSJohannes Doerfert const Instruction *I = Worklist.pop_back_val();
2767c42aa1beSJohannes Doerfert Optional<short> &NumUses = AssumeUsesMap[I];
2768a7938c74SKazu Hirata if (!NumUses)
2769c42aa1beSJohannes Doerfert NumUses = I->getNumUses();
2770611ffcf4SKazu Hirata NumUses = NumUses.value() - /* this assume */ 1;
2771611ffcf4SKazu Hirata if (NumUses.value() != 0)
2772c42aa1beSJohannes Doerfert continue;
2773c42aa1beSJohannes Doerfert AssumeOnlyValues.insert(I);
2774c42aa1beSJohannes Doerfert for (const Value *Op : I->operands())
2775c42aa1beSJohannes Doerfert if (auto *OpI = dyn_cast<Instruction>(Op))
2776c42aa1beSJohannes Doerfert Worklist.push_back(OpI);
2777c42aa1beSJohannes Doerfert }
2778c42aa1beSJohannes Doerfert };
2779c42aa1beSJohannes Doerfert
27803ab9e8b8SJohannes Doerfert for (Instruction &I : instructions(&F)) {
27813ab9e8b8SJohannes Doerfert bool IsInterestingOpcode = false;
27823ab9e8b8SJohannes Doerfert
27833ab9e8b8SJohannes Doerfert // To allow easy access to all instructions in a function with a given
27843ab9e8b8SJohannes Doerfert // opcode we store them in the InfoCache. As not all opcodes are interesting
27853ab9e8b8SJohannes Doerfert // to concrete attributes we only cache the ones that are as identified in
27863ab9e8b8SJohannes Doerfert // the following switch.
27873ab9e8b8SJohannes Doerfert // Note: There are no concrete attributes now so this is initially empty.
27883ab9e8b8SJohannes Doerfert switch (I.getOpcode()) {
27893ab9e8b8SJohannes Doerfert default:
27905f6d93c7SCraig Topper assert(!isa<CallBase>(&I) &&
27915f6d93c7SCraig Topper "New call base instruction type needs to be known in the "
27923ab9e8b8SJohannes Doerfert "Attributor.");
27933ab9e8b8SJohannes Doerfert break;
27945699d08bSJohannes Doerfert case Instruction::Call:
2795b1c788d0SJohannes Doerfert // Calls are interesting on their own, additionally:
2796b1c788d0SJohannes Doerfert // For `llvm.assume` calls we also fill the KnowledgeMap as we find them.
2797b1c788d0SJohannes Doerfert // For `must-tail` calls we remember the caller and callee.
27989ef6aa02SPhilip Reames if (auto *Assume = dyn_cast<AssumeInst>(&I)) {
2799898bbc25SJohannes Doerfert fillMapFromAssume(*Assume, KnowledgeMap);
2800c42aa1beSJohannes Doerfert AddToAssumeUsesMap(*Assume->getArgOperand(0));
2801b1c788d0SJohannes Doerfert } else if (cast<CallInst>(I).isMustTailCall()) {
2802898bbc25SJohannes Doerfert FI.ContainsMustTailCall = true;
2803898bbc25SJohannes Doerfert if (const Function *Callee = cast<CallInst>(I).getCalledFunction())
2804898bbc25SJohannes Doerfert getFunctionInfo(*Callee).CalledViaMustTail = true;
28055699d08bSJohannes Doerfert }
28065699d08bSJohannes Doerfert LLVM_FALLTHROUGH;
28073ab9e8b8SJohannes Doerfert case Instruction::CallBr:
28083ab9e8b8SJohannes Doerfert case Instruction::Invoke:
28093ab9e8b8SJohannes Doerfert case Instruction::CleanupRet:
28103ab9e8b8SJohannes Doerfert case Instruction::CatchSwitch:
28115732f56bSJohannes Doerfert case Instruction::AtomicRMW:
28125732f56bSJohannes Doerfert case Instruction::AtomicCmpXchg:
2813ef4febd8SHideto Ueno case Instruction::Br:
28143ab9e8b8SJohannes Doerfert case Instruction::Resume:
28153ab9e8b8SJohannes Doerfert case Instruction::Ret:
2816b1c788d0SJohannes Doerfert case Instruction::Load:
2817b1c788d0SJohannes Doerfert // The alignment of a pointer is interesting for loads.
2818b1c788d0SJohannes Doerfert case Instruction::Store:
2819b1c788d0SJohannes Doerfert // The alignment of a pointer is interesting for stores.
282096709823SKuter Dinel case Instruction::Alloca:
282196709823SKuter Dinel case Instruction::AddrSpaceCast:
28223ab9e8b8SJohannes Doerfert IsInterestingOpcode = true;
28233ab9e8b8SJohannes Doerfert }
2824177c065eSJohannes Doerfert if (IsInterestingOpcode) {
2825177c065eSJohannes Doerfert auto *&Insts = FI.OpcodeInstMap[I.getOpcode()];
2826177c065eSJohannes Doerfert if (!Insts)
2827177c065eSJohannes Doerfert Insts = new (Allocator) InstructionVectorTy();
2828177c065eSJohannes Doerfert Insts->push_back(&I);
2829177c065eSJohannes Doerfert }
28303ab9e8b8SJohannes Doerfert if (I.mayReadOrWriteMemory())
2831898bbc25SJohannes Doerfert FI.RWInsts.push_back(&I);
28323ab9e8b8SJohannes Doerfert }
2833a198adb4SJohannes Doerfert
2834a198adb4SJohannes Doerfert if (F.hasFnAttribute(Attribute::AlwaysInline) &&
2835a198adb4SJohannes Doerfert isInlineViable(F).isSuccess())
2836898bbc25SJohannes Doerfert InlineableFunctions.insert(&F);
28373ab9e8b8SJohannes Doerfert }
28383ab9e8b8SJohannes Doerfert
getAAResultsForFunction(const Function & F)28392ce38b3fSdfukalov AAResults *InformationCache::getAAResultsForFunction(const Function &F) {
28402ce38b3fSdfukalov return AG.getAnalysis<AAManager>(F);
28412ce38b3fSdfukalov }
28422ce38b3fSdfukalov
~FunctionInfo()2843177c065eSJohannes Doerfert InformationCache::FunctionInfo::~FunctionInfo() {
2844177c065eSJohannes Doerfert // The instruction vectors are allocated using a BumpPtrAllocator, we need to
2845177c065eSJohannes Doerfert // manually destroy them.
2846177c065eSJohannes Doerfert for (auto &It : OpcodeInstMap)
2847177c065eSJohannes Doerfert It.getSecond()->~InstructionVectorTy();
2848177c065eSJohannes Doerfert }
2849177c065eSJohannes Doerfert
recordDependence(const AbstractAttribute & FromAA,const AbstractAttribute & ToAA,DepClassTy DepClass)285012173e60SJohannes Doerfert void Attributor::recordDependence(const AbstractAttribute &FromAA,
2851680f6380SJohannes Doerfert const AbstractAttribute &ToAA,
2852680f6380SJohannes Doerfert DepClassTy DepClass) {
2853e592dad8SJohannes Doerfert if (DepClass == DepClassTy::NONE)
2854e592dad8SJohannes Doerfert return;
285595e0d28bSJohannes Doerfert // If we are outside of an update, thus before the actual fixpoint iteration
285695e0d28bSJohannes Doerfert // started (= when we create AAs), we do not track dependences because we will
285795e0d28bSJohannes Doerfert // put all AAs into the initial worklist anyway.
285895e0d28bSJohannes Doerfert if (DependenceStack.empty())
285995e0d28bSJohannes Doerfert return;
28602dad729fSJohannes Doerfert if (FromAA.getState().isAtFixpoint())
28612dad729fSJohannes Doerfert return;
286295e0d28bSJohannes Doerfert DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
286395e0d28bSJohannes Doerfert }
28642dad729fSJohannes Doerfert
rememberDependences()286595e0d28bSJohannes Doerfert void Attributor::rememberDependences() {
286695e0d28bSJohannes Doerfert assert(!DependenceStack.empty() && "No dependences to remember!");
286795e0d28bSJohannes Doerfert
286895e0d28bSJohannes Doerfert for (DepInfo &DI : *DependenceStack.back()) {
2869e592dad8SJohannes Doerfert assert((DI.DepClass == DepClassTy::REQUIRED ||
2870e592dad8SJohannes Doerfert DI.DepClass == DepClassTy::OPTIONAL) &&
2871e592dad8SJohannes Doerfert "Expected required or optional dependence (1 bit)!");
28723a8740bdSJohannes Doerfert auto &DepAAs = const_cast<AbstractAttribute &>(*DI.FromAA).Deps;
28733a8740bdSJohannes Doerfert DepAAs.push_back(AbstractAttribute::DepTy(
28743a8740bdSJohannes Doerfert const_cast<AbstractAttribute *>(DI.ToAA), unsigned(DI.DepClass)));
287595e0d28bSJohannes Doerfert }
287612173e60SJohannes Doerfert }
287712173e60SJohannes Doerfert
identifyDefaultAbstractAttributes(Function & F)28783bb5cbc2SHideto Ueno void Attributor::identifyDefaultAbstractAttributes(Function &F) {
28792f622063SJohannes Doerfert if (!VisitedFunctions.insert(&F).second)
28802f622063SJohannes Doerfert return;
2881c36e2ebfSJohannes Doerfert if (F.isDeclaration())
2882c36e2ebfSJohannes Doerfert return;
2883aade782aSJohannes Doerfert
2884b1c788d0SJohannes Doerfert // In non-module runs we need to look at the call sites of a function to
2885b1c788d0SJohannes Doerfert // determine if it is part of a must-tail call edge. This will influence what
2886b1c788d0SJohannes Doerfert // attributes we can derive.
2887898bbc25SJohannes Doerfert InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(F);
2888898bbc25SJohannes Doerfert if (!isModulePass() && !FI.CalledViaMustTail) {
2889b1c788d0SJohannes Doerfert for (const Use &U : F.uses())
28905f6d93c7SCraig Topper if (const auto *CB = dyn_cast<CallBase>(U.getUser()))
28915f6d93c7SCraig Topper if (CB->isCallee(&U) && CB->isMustTailCall())
2892898bbc25SJohannes Doerfert FI.CalledViaMustTail = true;
2893898bbc25SJohannes Doerfert }
2894b1c788d0SJohannes Doerfert
2895710ebb03SJohannes Doerfert IRPosition FPos = IRPosition::function(F);
2896710ebb03SJohannes Doerfert
2897305b961fSJohannes Doerfert // Check for dead BasicBlocks in every function.
289821fe0a31SJohannes Doerfert // We need dead instruction detection because we do not want to deal with
289921fe0a31SJohannes Doerfert // broken IR in which SSA rules do not apply.
290097fd582bSJohannes Doerfert getOrCreateAAFor<AAIsDead>(FPos);
2901305b961fSJohannes Doerfert
2902305b961fSJohannes Doerfert // Every function might be "will-return".
290397fd582bSJohannes Doerfert getOrCreateAAFor<AAWillReturn>(FPos);
2904305b961fSJohannes Doerfert
290558f324a4SJohannes Doerfert // Every function might contain instructions that cause "undefined behavior".
290658f324a4SJohannes Doerfert getOrCreateAAFor<AAUndefinedBehavior>(FPos);
290758f324a4SJohannes Doerfert
29085360589bSStefan Stipanovic // Every function can be nounwind.
290997fd582bSJohannes Doerfert getOrCreateAAFor<AANoUnwind>(FPos);
29105360589bSStefan Stipanovic
291106263672SStefan Stipanovic // Every function might be marked "nosync"
291297fd582bSJohannes Doerfert getOrCreateAAFor<AANoSync>(FPos);
291306263672SStefan Stipanovic
291465bbaf9eSHideto Ueno // Every function might be "no-free".
291597fd582bSJohannes Doerfert getOrCreateAAFor<AANoFree>(FPos);
291665bbaf9eSHideto Ueno
2917e83f3039SJohannes Doerfert // Every function might be "no-return".
291897fd582bSJohannes Doerfert getOrCreateAAFor<AANoReturn>(FPos);
2919e83f3039SJohannes Doerfert
292063f6066bSHideto Ueno // Every function might be "no-recurse".
292163f6066bSHideto Ueno getOrCreateAAFor<AANoRecurse>(FPos);
292263f6066bSHideto Ueno
29231097fab1SJohannes Doerfert // Every function might be "readnone/readonly/writeonly/...".
29241097fab1SJohannes Doerfert getOrCreateAAFor<AAMemoryBehavior>(FPos);
29251097fab1SJohannes Doerfert
2926282f5d7aSJohannes Doerfert // Every function can be "readnone/argmemonly/inaccessiblememonly/...".
2927282f5d7aSJohannes Doerfert getOrCreateAAFor<AAMemoryLocation>(FPos);
2928282f5d7aSJohannes Doerfert
2929b8a825b4SJoseph Huber // Every function can track active assumptions.
2930b8a825b4SJoseph Huber getOrCreateAAFor<AAAssumptionInfo>(FPos);
2931b8a825b4SJoseph Huber
2932431141c5SStefan Stipanovic // Every function might be applicable for Heap-To-Stack conversion.
2933431141c5SStefan Stipanovic if (EnableHeapToStack)
2934431141c5SStefan Stipanovic getOrCreateAAFor<AAHeapToStack>(FPos);
2935431141c5SStefan Stipanovic
2936accd3e87SJohannes Doerfert // Return attributes are only appropriate if the return type is non void.
2937accd3e87SJohannes Doerfert Type *ReturnType = F.getReturnType();
2938accd3e87SJohannes Doerfert if (!ReturnType->isVoidTy()) {
2939accd3e87SJohannes Doerfert // Argument attribute "returned" --- Create only one per function even
2940accd3e87SJohannes Doerfert // though it is an argument attribute.
294197fd582bSJohannes Doerfert getOrCreateAAFor<AAReturnedValues>(FPos);
294254869ec9SHideto Ueno
2943710ebb03SJohannes Doerfert IRPosition RetPos = IRPosition::returned(F);
2944710ebb03SJohannes Doerfert
2945cd4aab4aSJohannes Doerfert // Every returned value might be dead.
2946cd4aab4aSJohannes Doerfert getOrCreateAAFor<AAIsDead>(RetPos);
2947cd4aab4aSJohannes Doerfert
2948f2b9dc47SHideto Ueno // Every function might be simplified.
294994841c71SJohannes Doerfert bool UsedAssumedInformation = false;
2950bf789b19SJohannes Doerfert getAssumedSimplified(RetPos, nullptr, UsedAssumedInformation,
2951bf789b19SJohannes Doerfert AA::Intraprocedural);
2952f2b9dc47SHideto Ueno
29537a15dfd0SShinji Okumura // Every returned value might be marked noundef.
29547a15dfd0SShinji Okumura getOrCreateAAFor<AANoUndef>(RetPos);
29557a15dfd0SShinji Okumura
2956f2b9dc47SHideto Ueno if (ReturnType->isPointerTy()) {
2957f2b9dc47SHideto Ueno
2958e7bea9b7SHideto Ueno // Every function with pointer return type might be marked align.
295997fd582bSJohannes Doerfert getOrCreateAAFor<AAAlign>(RetPos);
2960e7bea9b7SHideto Ueno
296154869ec9SHideto Ueno // Every function with pointer return type might be marked nonnull.
296297fd582bSJohannes Doerfert getOrCreateAAFor<AANonNull>(RetPos);
296369ebb020SStefan Stipanovic
296469ebb020SStefan Stipanovic // Every function with pointer return type might be marked noalias.
296597fd582bSJohannes Doerfert getOrCreateAAFor<AANoAlias>(RetPos);
296619c07afeSHideto Ueno
296719c07afeSHideto Ueno // Every function with pointer return type might be marked
296819c07afeSHideto Ueno // dereferenceable.
296997fd582bSJohannes Doerfert getOrCreateAAFor<AADereferenceable>(RetPos);
297069ebb020SStefan Stipanovic }
297154869ec9SHideto Ueno }
297254869ec9SHideto Ueno
297354869ec9SHideto Ueno for (Argument &Arg : F.args()) {
2974710ebb03SJohannes Doerfert IRPosition ArgPos = IRPosition::argument(Arg);
2975f2b9dc47SHideto Ueno
2976666dc6f1SJohannes Doerfert // Every argument might be simplified. We have to go through the Attributor
2977666dc6f1SJohannes Doerfert // interface though as outside AAs can register custom simplification
2978666dc6f1SJohannes Doerfert // callbacks.
29793f5d53a5SHaojian Wu bool UsedAssumedInformation = false;
2980bf789b19SJohannes Doerfert getAssumedSimplified(ArgPos, /* AA */ nullptr, UsedAssumedInformation,
2981bf789b19SJohannes Doerfert AA::Intraprocedural);
2982f2b9dc47SHideto Ueno
29831e99fc9dSJohannes Doerfert // Every argument might be dead.
29841e99fc9dSJohannes Doerfert getOrCreateAAFor<AAIsDead>(ArgPos);
29851e99fc9dSJohannes Doerfert
29867a15dfd0SShinji Okumura // Every argument might be marked noundef.
29877a15dfd0SShinji Okumura getOrCreateAAFor<AANoUndef>(ArgPos);
29887a15dfd0SShinji Okumura
2989f2b9dc47SHideto Ueno if (Arg.getType()->isPointerTy()) {
299019c07afeSHideto Ueno // Every argument with pointer type might be marked nonnull.
299197fd582bSJohannes Doerfert getOrCreateAAFor<AANonNull>(ArgPos);
299219c07afeSHideto Ueno
2993cbab334eSHideto Ueno // Every argument with pointer type might be marked noalias.
299497fd582bSJohannes Doerfert getOrCreateAAFor<AANoAlias>(ArgPos);
2995cbab334eSHideto Ueno
299619c07afeSHideto Ueno // Every argument with pointer type might be marked dereferenceable.
299797fd582bSJohannes Doerfert getOrCreateAAFor<AADereferenceable>(ArgPos);
2998e7bea9b7SHideto Ueno
2999e7bea9b7SHideto Ueno // Every argument with pointer type might be marked align.
300097fd582bSJohannes Doerfert getOrCreateAAFor<AAAlign>(ArgPos);
30017516a5e0SJohannes Doerfert
30027516a5e0SJohannes Doerfert // Every argument with pointer type might be marked nocapture.
300397fd582bSJohannes Doerfert getOrCreateAAFor<AANoCapture>(ArgPos);
30041097fab1SJohannes Doerfert
30051097fab1SJohannes Doerfert // Every argument with pointer type might be marked
30061097fab1SJohannes Doerfert // "readnone/readonly/writeonly/..."
30071097fab1SJohannes Doerfert getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3008f35740d6SStefan Stipanovic
3009f35740d6SStefan Stipanovic // Every argument with pointer type might be marked nofree.
3010f35740d6SStefan Stipanovic getOrCreateAAFor<AANoFree>(ArgPos);
301189c2e733SJohannes Doerfert
301289c2e733SJohannes Doerfert // Every argument with pointer type might be privatizable (or promotable)
301389c2e733SJohannes Doerfert getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
301419c07afeSHideto Ueno }
3015accd3e87SJohannes Doerfert }
3016accd3e87SJohannes Doerfert
30173ab9e8b8SJohannes Doerfert auto CallSitePred = [&](Instruction &I) -> bool {
301887f1e939SJohannes Doerfert auto &CB = cast<CallBase>(I);
3019a1db0e52SJohannes Doerfert IRPosition CBInstPos = IRPosition::inst(CB);
3020b8a825b4SJoseph Huber IRPosition CBFnPos = IRPosition::callsite_function(CB);
302186509e8cSJohannes Doerfert
302286509e8cSJohannes Doerfert // Call sites might be dead if they do not have side effects and no live
302386509e8cSJohannes Doerfert // users. The return value might be dead if there are no live users.
3024a1db0e52SJohannes Doerfert getOrCreateAAFor<AAIsDead>(CBInstPos);
302586509e8cSJohannes Doerfert
302687f1e939SJohannes Doerfert Function *Callee = CB.getCalledFunction();
3027c4d3188aSJohannes Doerfert // TODO: Even if the callee is not known now we might be able to simplify
3028c4d3188aSJohannes Doerfert // the call/callee.
3029c4d3188aSJohannes Doerfert if (!Callee)
3030c4d3188aSJohannes Doerfert return true;
3031c4d3188aSJohannes Doerfert
3032b8a825b4SJoseph Huber // Every call site can track active assumptions.
3033b8a825b4SJoseph Huber getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);
3034b8a825b4SJoseph Huber
3035c4d3188aSJohannes Doerfert // Skip declarations except if annotations on their call sites were
3036c36e2ebfSJohannes Doerfert // explicitly requested.
3037139c9ef4SJohannes Doerfert if (!AnnotateDeclarationCallSites && Callee->isDeclaration() &&
3038139c9ef4SJohannes Doerfert !Callee->hasMetadata(LLVMContext::MD_callback))
3039c36e2ebfSJohannes Doerfert return true;
3040c36e2ebfSJohannes Doerfert
304187f1e939SJohannes Doerfert if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3042188f9a34SHideto Ueno
304387f1e939SJohannes Doerfert IRPosition CBRetPos = IRPosition::callsite_returned(CB);
304494841c71SJohannes Doerfert bool UsedAssumedInformation = false;
3045bf789b19SJohannes Doerfert getAssumedSimplified(CBRetPos, nullptr, UsedAssumedInformation,
3046bf789b19SJohannes Doerfert AA::Intraprocedural);
3047188f9a34SHideto Ueno }
3048cd4aab4aSJohannes Doerfert
30494f0225f6SKazu Hirata for (int I = 0, E = CB.arg_size(); I < E; ++I) {
3050f2b9dc47SHideto Ueno
305187f1e939SJohannes Doerfert IRPosition CBArgPos = IRPosition::callsite_argument(CB, I);
3052f2b9dc47SHideto Ueno
3053cd4aab4aSJohannes Doerfert // Every call site argument might be dead.
30545f6d93c7SCraig Topper getOrCreateAAFor<AAIsDead>(CBArgPos);
3055cd4aab4aSJohannes Doerfert
3056666dc6f1SJohannes Doerfert // Call site argument might be simplified. We have to go through the
3057666dc6f1SJohannes Doerfert // Attributor interface though as outside AAs can register custom
3058666dc6f1SJohannes Doerfert // simplification callbacks.
30593f5d53a5SHaojian Wu bool UsedAssumedInformation = false;
3060bf789b19SJohannes Doerfert getAssumedSimplified(CBArgPos, /* AA */ nullptr, UsedAssumedInformation,
3061bf789b19SJohannes Doerfert AA::Intraprocedural);
3062f2b9dc47SHideto Ueno
30637a15dfd0SShinji Okumura // Every call site argument might be marked "noundef".
30647a15dfd0SShinji Okumura getOrCreateAAFor<AANoUndef>(CBArgPos);
30657a15dfd0SShinji Okumura
306687f1e939SJohannes Doerfert if (!CB.getArgOperand(I)->getType()->isPointerTy())
306754869ec9SHideto Ueno continue;
306854869ec9SHideto Ueno
306954869ec9SHideto Ueno // Call site argument attribute "non-null".
30705f6d93c7SCraig Topper getOrCreateAAFor<AANonNull>(CBArgPos);
307119c07afeSHideto Ueno
30722f97b8b8SJohannes Doerfert // Call site argument attribute "nocapture".
30732f97b8b8SJohannes Doerfert getOrCreateAAFor<AANoCapture>(CBArgPos);
30742f97b8b8SJohannes Doerfert
3075cbab334eSHideto Ueno // Call site argument attribute "no-alias".
30765f6d93c7SCraig Topper getOrCreateAAFor<AANoAlias>(CBArgPos);
3077cbab334eSHideto Ueno
307819c07afeSHideto Ueno // Call site argument attribute "dereferenceable".
30795f6d93c7SCraig Topper getOrCreateAAFor<AADereferenceable>(CBArgPos);
3080e7bea9b7SHideto Ueno
3081e7bea9b7SHideto Ueno // Call site argument attribute "align".
30825f6d93c7SCraig Topper getOrCreateAAFor<AAAlign>(CBArgPos);
3083f35740d6SStefan Stipanovic
308428880198SJohannes Doerfert // Call site argument attribute
308528880198SJohannes Doerfert // "readnone/readonly/writeonly/..."
30865f6d93c7SCraig Topper getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);
308728880198SJohannes Doerfert
3088f35740d6SStefan Stipanovic // Call site argument attribute "nofree".
30895f6d93c7SCraig Topper getOrCreateAAFor<AANoFree>(CBArgPos);
309054869ec9SHideto Ueno }
30913ab9e8b8SJohannes Doerfert return true;
30923ab9e8b8SJohannes Doerfert };
30933ab9e8b8SJohannes Doerfert
30943ab9e8b8SJohannes Doerfert auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
309523f41f16SJohannes Doerfert bool Success;
3096792aac98SJohannes Doerfert bool UsedAssumedInformation = false;
30973ab9e8b8SJohannes Doerfert Success = checkForAllInstructionsImpl(
309823f41f16SJohannes Doerfert nullptr, OpcodeInstMap, CallSitePred, nullptr, nullptr,
30993ab9e8b8SJohannes Doerfert {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
3100792aac98SJohannes Doerfert (unsigned)Instruction::Call},
3101792aac98SJohannes Doerfert UsedAssumedInformation);
31023ab9e8b8SJohannes Doerfert (void)Success;
310323f41f16SJohannes Doerfert assert(Success && "Expected the check call to be successful!");
31043ab9e8b8SJohannes Doerfert
31053ab9e8b8SJohannes Doerfert auto LoadStorePred = [&](Instruction &I) -> bool {
3106c2281f15SJohannes Doerfert if (isa<LoadInst>(I)) {
31073ab9e8b8SJohannes Doerfert getOrCreateAAFor<AAAlign>(
31083ab9e8b8SJohannes Doerfert IRPosition::value(*cast<LoadInst>(I).getPointerOperand()));
3109c2281f15SJohannes Doerfert if (SimplifyAllLoads)
311094841c71SJohannes Doerfert getAssumedSimplified(IRPosition::value(I), nullptr,
3111bf789b19SJohannes Doerfert UsedAssumedInformation, AA::Intraprocedural);
311294841c71SJohannes Doerfert } else {
311394841c71SJohannes Doerfert auto &SI = cast<StoreInst>(I);
311494841c71SJohannes Doerfert getOrCreateAAFor<AAIsDead>(IRPosition::inst(I));
311594841c71SJohannes Doerfert getAssumedSimplified(IRPosition::value(*SI.getValueOperand()), nullptr,
3116bf789b19SJohannes Doerfert UsedAssumedInformation, AA::Intraprocedural);
311794841c71SJohannes Doerfert getOrCreateAAFor<AAAlign>(IRPosition::value(*SI.getPointerOperand()));
311894841c71SJohannes Doerfert }
31193ab9e8b8SJohannes Doerfert return true;
31203ab9e8b8SJohannes Doerfert };
31213ab9e8b8SJohannes Doerfert Success = checkForAllInstructionsImpl(
312223f41f16SJohannes Doerfert nullptr, OpcodeInstMap, LoadStorePred, nullptr, nullptr,
3123792aac98SJohannes Doerfert {(unsigned)Instruction::Load, (unsigned)Instruction::Store},
3124792aac98SJohannes Doerfert UsedAssumedInformation);
31253ab9e8b8SJohannes Doerfert (void)Success;
312623f41f16SJohannes Doerfert assert(Success && "Expected the check call to be successful!");
3127aade782aSJohannes Doerfert }
3128aade782aSJohannes Doerfert
3129aade782aSJohannes Doerfert /// Helpers to ease debugging through output streams and print calls.
3130aade782aSJohannes Doerfert ///
3131aade782aSJohannes Doerfert ///{
operator <<(raw_ostream & OS,ChangeStatus S)3132aade782aSJohannes Doerfert raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
3133aade782aSJohannes Doerfert return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
3134aade782aSJohannes Doerfert }
3135aade782aSJohannes Doerfert
operator <<(raw_ostream & OS,IRPosition::Kind AP)3136fb69f768SJohannes Doerfert raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
3137aade782aSJohannes Doerfert switch (AP) {
3138710ebb03SJohannes Doerfert case IRPosition::IRP_INVALID:
3139710ebb03SJohannes Doerfert return OS << "inv";
3140710ebb03SJohannes Doerfert case IRPosition::IRP_FLOAT:
3141710ebb03SJohannes Doerfert return OS << "flt";
3142710ebb03SJohannes Doerfert case IRPosition::IRP_RETURNED:
3143710ebb03SJohannes Doerfert return OS << "fn_ret";
3144710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE_RETURNED:
3145710ebb03SJohannes Doerfert return OS << "cs_ret";
3146710ebb03SJohannes Doerfert case IRPosition::IRP_FUNCTION:
3147710ebb03SJohannes Doerfert return OS << "fn";
3148710ebb03SJohannes Doerfert case IRPosition::IRP_CALL_SITE:
3149710ebb03SJohannes Doerfert return OS << "cs";
3150fb69f768SJohannes Doerfert case IRPosition::IRP_ARGUMENT:
3151aade782aSJohannes Doerfert return OS << "arg";
3152fb69f768SJohannes Doerfert case IRPosition::IRP_CALL_SITE_ARGUMENT:
3153aade782aSJohannes Doerfert return OS << "cs_arg";
3154aade782aSJohannes Doerfert }
3155aade782aSJohannes Doerfert llvm_unreachable("Unknown attribute position!");
3156aade782aSJohannes Doerfert }
3157aade782aSJohannes Doerfert
operator <<(raw_ostream & OS,const IRPosition & Pos)3158fb69f768SJohannes Doerfert raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
3159710ebb03SJohannes Doerfert const Value &AV = Pos.getAssociatedValue();
3160d75c9e61Skuterd OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
3161d75c9e61Skuterd << Pos.getAnchorValue().getName() << "@" << Pos.getCallSiteArgNo() << "]";
3162d75c9e61Skuterd
3163d75c9e61Skuterd if (Pos.hasCallBaseContext())
3164d75c9e61Skuterd OS << "[cb_context:" << *Pos.getCallBaseContext() << "]";
3165d75c9e61Skuterd return OS << "}";
3166fb69f768SJohannes Doerfert }
3167fb69f768SJohannes Doerfert
operator <<(raw_ostream & OS,const IntegerRangeState & S)3168188f9a34SHideto Ueno raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerRangeState &S) {
3169188f9a34SHideto Ueno OS << "range-state(" << S.getBitWidth() << ")<";
3170188f9a34SHideto Ueno S.getKnown().print(OS);
3171188f9a34SHideto Ueno OS << " / ";
3172188f9a34SHideto Ueno S.getAssumed().print(OS);
3173188f9a34SHideto Ueno OS << ">";
3174188f9a34SHideto Ueno
3175188f9a34SHideto Ueno return OS << static_cast<const AbstractState &>(S);
3176188f9a34SHideto Ueno }
3177188f9a34SHideto Ueno
operator <<(raw_ostream & OS,const AbstractState & S)3178aade782aSJohannes Doerfert raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
3179aade782aSJohannes Doerfert return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
3180aade782aSJohannes Doerfert }
3181aade782aSJohannes Doerfert
operator <<(raw_ostream & OS,const AbstractAttribute & AA)3182aade782aSJohannes Doerfert raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
3183aade782aSJohannes Doerfert AA.print(OS);
3184aade782aSJohannes Doerfert return OS;
3185aade782aSJohannes Doerfert }
3186aade782aSJohannes Doerfert
operator <<(raw_ostream & OS,const PotentialConstantIntValuesState & S)3187c575ba28SShinji Okumura raw_ostream &llvm::operator<<(raw_ostream &OS,
3188c575ba28SShinji Okumura const PotentialConstantIntValuesState &S) {
3189c575ba28SShinji Okumura OS << "set-state(< {";
3190c575ba28SShinji Okumura if (!S.isValidState())
3191c575ba28SShinji Okumura OS << "full-set";
31926c25eca6SShinji Okumura else {
3193982053e8SJohannes Doerfert for (auto &It : S.getAssumedSet())
3194982053e8SJohannes Doerfert OS << It << ", ";
31956c25eca6SShinji Okumura if (S.undefIsContained())
31966c25eca6SShinji Okumura OS << "undef ";
31976c25eca6SShinji Okumura }
3198c575ba28SShinji Okumura OS << "} >)";
3199c575ba28SShinji Okumura
3200c575ba28SShinji Okumura return OS;
3201c575ba28SShinji Okumura }
3202c575ba28SShinji Okumura
operator <<(raw_ostream & OS,const PotentialLLVMValuesState & S)3203bf789b19SJohannes Doerfert raw_ostream &llvm::operator<<(raw_ostream &OS,
3204bf789b19SJohannes Doerfert const PotentialLLVMValuesState &S) {
3205bf789b19SJohannes Doerfert OS << "set-state(< {";
3206bf789b19SJohannes Doerfert if (!S.isValidState())
3207bf789b19SJohannes Doerfert OS << "full-set";
3208bf789b19SJohannes Doerfert else {
3209bf789b19SJohannes Doerfert for (auto &It : S.getAssumedSet()) {
3210bf789b19SJohannes Doerfert if (auto *F = dyn_cast<Function>(It.first.getValue()))
3211bf789b19SJohannes Doerfert OS << "@" << F->getName() << "[" << int(It.second) << "], ";
3212bf789b19SJohannes Doerfert else
3213bf789b19SJohannes Doerfert OS << *It.first.getValue() << "[" << int(It.second) << "], ";
3214bf789b19SJohannes Doerfert }
3215bf789b19SJohannes Doerfert if (S.undefIsContained())
3216bf789b19SJohannes Doerfert OS << "undef ";
3217bf789b19SJohannes Doerfert }
3218bf789b19SJohannes Doerfert OS << "} >)";
3219bf789b19SJohannes Doerfert
3220bf789b19SJohannes Doerfert return OS;
3221bf789b19SJohannes Doerfert }
3222bf789b19SJohannes Doerfert
print(raw_ostream & OS) const3223aade782aSJohannes Doerfert void AbstractAttribute::print(raw_ostream &OS) const {
32245ee07dc5SLuofan Chen OS << "[";
32255ee07dc5SLuofan Chen OS << getName();
32265ee07dc5SLuofan Chen OS << "] for CtxI ";
32275ee07dc5SLuofan Chen
32285ee07dc5SLuofan Chen if (auto *I = getCtxI()) {
32295ee07dc5SLuofan Chen OS << "'";
32305ee07dc5SLuofan Chen I->print(OS);
32315ee07dc5SLuofan Chen OS << "'";
32325ee07dc5SLuofan Chen } else
32335ee07dc5SLuofan Chen OS << "<<null inst>>";
32345ee07dc5SLuofan Chen
32355ee07dc5SLuofan Chen OS << " at position " << getIRPosition() << " with state " << getAsStr()
32365ee07dc5SLuofan Chen << '\n';
32375ee07dc5SLuofan Chen }
32385ee07dc5SLuofan Chen
printWithDeps(raw_ostream & OS) const32395ee07dc5SLuofan Chen void AbstractAttribute::printWithDeps(raw_ostream &OS) const {
32405ee07dc5SLuofan Chen print(OS);
32415ee07dc5SLuofan Chen
32425ee07dc5SLuofan Chen for (const auto &DepAA : Deps) {
32435ee07dc5SLuofan Chen auto *AA = DepAA.getPointer();
32445ee07dc5SLuofan Chen OS << " updates ";
32455ee07dc5SLuofan Chen AA->print(OS);
32465ee07dc5SLuofan Chen }
32475ee07dc5SLuofan Chen
32485ee07dc5SLuofan Chen OS << '\n';
3249aade782aSJohannes Doerfert }
3250c2281f15SJohannes Doerfert
operator <<(raw_ostream & OS,const AAPointerInfo::Access & Acc)3251c7781a09SJohannes Doerfert raw_ostream &llvm::operator<<(raw_ostream &OS,
3252c7781a09SJohannes Doerfert const AAPointerInfo::Access &Acc) {
3253c2281f15SJohannes Doerfert OS << " [" << Acc.getKind() << "] " << *Acc.getRemoteInst();
3254c2281f15SJohannes Doerfert if (Acc.getLocalInst() != Acc.getRemoteInst())
3255c55e1882SJohannes Doerfert OS << " via " << *Acc.getLocalInst();
3256e0e687a6SKazu Hirata if (Acc.getContent()) {
32574308fdf8SJohannes Doerfert if (*Acc.getContent())
32584308fdf8SJohannes Doerfert OS << " [" << **Acc.getContent() << "]";
32594308fdf8SJohannes Doerfert else
32604308fdf8SJohannes Doerfert OS << " [ <unknown> ]";
32614308fdf8SJohannes Doerfert }
3262c2281f15SJohannes Doerfert return OS;
3263c2281f15SJohannes Doerfert }
3264aade782aSJohannes Doerfert ///}
3265aade782aSJohannes Doerfert
3266aade782aSJohannes Doerfert /// ----------------------------------------------------------------------------
3267aade782aSJohannes Doerfert /// Pass (Manager) Boilerplate
3268aade782aSJohannes Doerfert /// ----------------------------------------------------------------------------
3269aade782aSJohannes Doerfert
runAttributorOnFunctions(InformationCache & InfoCache,SetVector<Function * > & Functions,AnalysisGetter & AG,CallGraphUpdater & CGUpdater,bool DeleteFns,bool IsModulePass)3270b0c77c36SJohannes Doerfert static bool runAttributorOnFunctions(InformationCache &InfoCache,
3271b0c77c36SJohannes Doerfert SetVector<Function *> &Functions,
3272b0c77c36SJohannes Doerfert AnalysisGetter &AG,
3273b077d82bSWilliam S. Moses CallGraphUpdater &CGUpdater,
32743be3b401SJohannes Doerfert bool DeleteFns, bool IsModulePass) {
3275b43b59fcSTarindu Jayatilaka if (Functions.empty())
3276aade782aSJohannes Doerfert return false;
3277aade782aSJohannes Doerfert
32782bc51d39SJohannes Doerfert LLVM_DEBUG({
32792bc51d39SJohannes Doerfert dbgs() << "[Attributor] Run on module with " << Functions.size()
32802bc51d39SJohannes Doerfert << " functions:\n";
32812bc51d39SJohannes Doerfert for (Function *Fn : Functions)
32822bc51d39SJohannes Doerfert dbgs() << " - " << Fn->getName() << "\n";
32832bc51d39SJohannes Doerfert });
3284aade782aSJohannes Doerfert
3285aade782aSJohannes Doerfert // Create an Attributor and initially empty information cache that is filled
3286aade782aSJohannes Doerfert // while we identify default attribute opportunities.
32873be3b401SJohannes Doerfert AttributorConfig AC(CGUpdater);
32883be3b401SJohannes Doerfert AC.IsModulePass = IsModulePass;
32893be3b401SJohannes Doerfert AC.DeleteFns = DeleteFns;
32903be3b401SJohannes Doerfert Attributor A(Functions, InfoCache, AC);
3291aade782aSJohannes Doerfert
3292eec6d876SLuofan Chen // Create shallow wrappers for all functions that are not IPO amendable
3293eec6d876SLuofan Chen if (AllowShallowWrappers)
3294eec6d876SLuofan Chen for (Function *F : Functions)
3295eec6d876SLuofan Chen if (!A.isFunctionIPOAmendable(*F))
3296ce16be25Ssstefan1 Attributor::createShallowWrapper(*F);
3297eec6d876SLuofan Chen
329887a85f3dSLuofan Chen // Internalize non-exact functions
329987a85f3dSLuofan Chen // TODO: for now we eagerly internalize functions without calculating the
330087a85f3dSLuofan Chen // cost, we need a cost interface to determine whether internalizing
330187a85f3dSLuofan Chen // a function is "benefitial"
3302266949b2SLuofan Chen if (AllowDeepWrapper) {
3303266949b2SLuofan Chen unsigned FunSize = Functions.size();
3304266949b2SLuofan Chen for (unsigned u = 0; u < FunSize; u++) {
3305b7448a34SLuofan Chen Function *F = Functions[u];
330687a85f3dSLuofan Chen if (!F->isDeclaration() && !F->isDefinitionExact() && F->getNumUses() &&
330787a85f3dSLuofan Chen !GlobalValue::isInterposableLinkage(F->getLinkage())) {
330803d7e61cSJoseph Huber Function *NewF = Attributor::internalizeFunction(*F);
330903d7e61cSJoseph Huber assert(NewF && "Could not internalize function.");
331087a85f3dSLuofan Chen Functions.insert(NewF);
331187a85f3dSLuofan Chen
331287a85f3dSLuofan Chen // Update call graph
3313012819f3SJohannes Doerfert CGUpdater.replaceFunctionWith(*F, *NewF);
331487a85f3dSLuofan Chen for (const Use &U : NewF->uses())
331587a85f3dSLuofan Chen if (CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
331687a85f3dSLuofan Chen auto *CallerF = CB->getCaller();
331787a85f3dSLuofan Chen CGUpdater.reanalyzeFunction(*CallerF);
331887a85f3dSLuofan Chen }
331987a85f3dSLuofan Chen }
332087a85f3dSLuofan Chen }
3321266949b2SLuofan Chen }
332287a85f3dSLuofan Chen
3323b0c77c36SJohannes Doerfert for (Function *F : Functions) {
3324b0c77c36SJohannes Doerfert if (F->hasExactDefinition())
3325b0412e43SJohannes Doerfert NumFnWithExactDefinition++;
3326b0412e43SJohannes Doerfert else
3327aade782aSJohannes Doerfert NumFnWithoutExactDefinition++;
3328aade782aSJohannes Doerfert
33292f622063SJohannes Doerfert // We look at internal functions only on-demand but if any use is not a
33305ee07dc5SLuofan Chen // direct call or outside the current set of analyzed functions, we have
33315ee07dc5SLuofan Chen // to do it eagerly.
3332b0c77c36SJohannes Doerfert if (F->hasLocalLinkage()) {
3333b0c77c36SJohannes Doerfert if (llvm::all_of(F->uses(), [&Functions](const Use &U) {
33345f6d93c7SCraig Topper const auto *CB = dyn_cast<CallBase>(U.getUser());
33355f6d93c7SCraig Topper return CB && CB->isCallee(&U) &&
33365f6d93c7SCraig Topper Functions.count(const_cast<Function *>(CB->getCaller()));
33372f622063SJohannes Doerfert }))
33382f622063SJohannes Doerfert continue;
33392f622063SJohannes Doerfert }
33402f622063SJohannes Doerfert
3341aade782aSJohannes Doerfert // Populate the Attributor with abstract attribute opportunities in the
3342aade782aSJohannes Doerfert // function and the information cache with IR information.
3343b0c77c36SJohannes Doerfert A.identifyDefaultAbstractAttributes(*F);
3344aade782aSJohannes Doerfert }
3345aade782aSJohannes Doerfert
334677a9e61cSJohannes Doerfert ChangeStatus Changed = A.run();
33475ee07dc5SLuofan Chen
334877a9e61cSJohannes Doerfert LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size()
334977a9e61cSJohannes Doerfert << " functions, result: " << Changed << ".\n");
335077a9e61cSJohannes Doerfert return Changed == ChangeStatus::CHANGED;
3351aade782aSJohannes Doerfert }
3352aade782aSJohannes Doerfert
viewGraph()33535ee07dc5SLuofan Chen void AADepGraph::viewGraph() { llvm::ViewGraph(this, "Dependency Graph"); }
33545ee07dc5SLuofan Chen
dumpGraph()33555ee07dc5SLuofan Chen void AADepGraph::dumpGraph() {
33565ee07dc5SLuofan Chen static std::atomic<int> CallTimes;
33575ee07dc5SLuofan Chen std::string Prefix;
33585ee07dc5SLuofan Chen
33595ee07dc5SLuofan Chen if (!DepGraphDotFileNamePrefix.empty())
33605ee07dc5SLuofan Chen Prefix = DepGraphDotFileNamePrefix;
33615ee07dc5SLuofan Chen else
33625ee07dc5SLuofan Chen Prefix = "dep_graph";
33635ee07dc5SLuofan Chen std::string Filename =
33645ee07dc5SLuofan Chen Prefix + "_" + std::to_string(CallTimes.load()) + ".dot";
33655ee07dc5SLuofan Chen
33665ee07dc5SLuofan Chen outs() << "Dependency graph dump to " << Filename << ".\n";
33675ee07dc5SLuofan Chen
33685ee07dc5SLuofan Chen std::error_code EC;
33695ee07dc5SLuofan Chen
337082b3e28eSAbhina Sreeskantharajan raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
33715ee07dc5SLuofan Chen if (!EC)
33725ee07dc5SLuofan Chen llvm::WriteGraph(File, this);
33735ee07dc5SLuofan Chen
33745ee07dc5SLuofan Chen CallTimes++;
33755ee07dc5SLuofan Chen }
33765ee07dc5SLuofan Chen
print()33775ee07dc5SLuofan Chen void AADepGraph::print() {
33785ee07dc5SLuofan Chen for (auto DepAA : SyntheticRoot.Deps)
33795ee07dc5SLuofan Chen cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(outs());
33805ee07dc5SLuofan Chen }
33815ee07dc5SLuofan Chen
run(Module & M,ModuleAnalysisManager & AM)3382aade782aSJohannes Doerfert PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
3383b0c77c36SJohannes Doerfert FunctionAnalysisManager &FAM =
3384b0c77c36SJohannes Doerfert AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
3385b0c77c36SJohannes Doerfert AnalysisGetter AG(FAM);
3386b0c77c36SJohannes Doerfert
3387b0c77c36SJohannes Doerfert SetVector<Function *> Functions;
3388b0c77c36SJohannes Doerfert for (Function &F : M)
3389b0c77c36SJohannes Doerfert Functions.insert(&F);
3390b0c77c36SJohannes Doerfert
3391b0c77c36SJohannes Doerfert CallGraphUpdater CGUpdater;
339287aa3629SJohannes Doerfert BumpPtrAllocator Allocator;
339387aa3629SJohannes Doerfert InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr);
3394b077d82bSWilliam S. Moses if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
33953be3b401SJohannes Doerfert /* DeleteFns */ true, /* IsModulePass */ true)) {
3396b0c77c36SJohannes Doerfert // FIXME: Think about passes we will preserve and add them here.
3397b0c77c36SJohannes Doerfert return PreservedAnalyses::none();
3398b0c77c36SJohannes Doerfert }
3399b0c77c36SJohannes Doerfert return PreservedAnalyses::all();
3400b0c77c36SJohannes Doerfert }
3401b0c77c36SJohannes Doerfert
run(LazyCallGraph::SCC & C,CGSCCAnalysisManager & AM,LazyCallGraph & CG,CGSCCUpdateResult & UR)3402b0c77c36SJohannes Doerfert PreservedAnalyses AttributorCGSCCPass::run(LazyCallGraph::SCC &C,
3403b0c77c36SJohannes Doerfert CGSCCAnalysisManager &AM,
3404b0c77c36SJohannes Doerfert LazyCallGraph &CG,
3405b0c77c36SJohannes Doerfert CGSCCUpdateResult &UR) {
3406b0c77c36SJohannes Doerfert FunctionAnalysisManager &FAM =
3407b0c77c36SJohannes Doerfert AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
3408b0c77c36SJohannes Doerfert AnalysisGetter AG(FAM);
3409b0c77c36SJohannes Doerfert
3410b0c77c36SJohannes Doerfert SetVector<Function *> Functions;
3411b0c77c36SJohannes Doerfert for (LazyCallGraph::Node &N : C)
3412b0c77c36SJohannes Doerfert Functions.insert(&N.getFunction());
3413b0c77c36SJohannes Doerfert
3414b0c77c36SJohannes Doerfert if (Functions.empty())
3415b0c77c36SJohannes Doerfert return PreservedAnalyses::all();
3416b0c77c36SJohannes Doerfert
3417b0c77c36SJohannes Doerfert Module &M = *Functions.back()->getParent();
3418b0c77c36SJohannes Doerfert CallGraphUpdater CGUpdater;
3419b0c77c36SJohannes Doerfert CGUpdater.initialize(CG, C, AM, UR);
342087aa3629SJohannes Doerfert BumpPtrAllocator Allocator;
342187aa3629SJohannes Doerfert InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ &Functions);
3422b077d82bSWilliam S. Moses if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
34233be3b401SJohannes Doerfert /* DeleteFns */ false,
34243be3b401SJohannes Doerfert /* IsModulePass */ false)) {
3425aade782aSJohannes Doerfert // FIXME: Think about passes we will preserve and add them here.
34261d99c3d7SJohannes Doerfert PreservedAnalyses PA;
34271d99c3d7SJohannes Doerfert PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
34281d99c3d7SJohannes Doerfert return PA;
3429aade782aSJohannes Doerfert }
3430aade782aSJohannes Doerfert return PreservedAnalyses::all();
3431aade782aSJohannes Doerfert }
3432aade782aSJohannes Doerfert
34335ee07dc5SLuofan Chen namespace llvm {
34345ee07dc5SLuofan Chen
34355ee07dc5SLuofan Chen template <> struct GraphTraits<AADepGraphNode *> {
34365ee07dc5SLuofan Chen using NodeRef = AADepGraphNode *;
34375ee07dc5SLuofan Chen using DepTy = PointerIntPair<AADepGraphNode *, 1>;
34385ee07dc5SLuofan Chen using EdgeRef = PointerIntPair<AADepGraphNode *, 1>;
34395ee07dc5SLuofan Chen
getEntryNodellvm::GraphTraits34405ee07dc5SLuofan Chen static NodeRef getEntryNode(AADepGraphNode *DGN) { return DGN; }
DepGetValllvm::GraphTraits34415ee07dc5SLuofan Chen static NodeRef DepGetVal(DepTy &DT) { return DT.getPointer(); }
34425ee07dc5SLuofan Chen
34435ee07dc5SLuofan Chen using ChildIteratorType =
34445ee07dc5SLuofan Chen mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>;
34455ee07dc5SLuofan Chen using ChildEdgeIteratorType = TinyPtrVector<DepTy>::iterator;
34465ee07dc5SLuofan Chen
child_beginllvm::GraphTraits34475ee07dc5SLuofan Chen static ChildIteratorType child_begin(NodeRef N) { return N->child_begin(); }
34485ee07dc5SLuofan Chen
child_endllvm::GraphTraits34495ee07dc5SLuofan Chen static ChildIteratorType child_end(NodeRef N) { return N->child_end(); }
34505ee07dc5SLuofan Chen };
34515ee07dc5SLuofan Chen
34525ee07dc5SLuofan Chen template <>
34535ee07dc5SLuofan Chen struct GraphTraits<AADepGraph *> : public GraphTraits<AADepGraphNode *> {
getEntryNodellvm::GraphTraits34545ee07dc5SLuofan Chen static NodeRef getEntryNode(AADepGraph *DG) { return DG->GetEntryNode(); }
34555ee07dc5SLuofan Chen
34565ee07dc5SLuofan Chen using nodes_iterator =
34575ee07dc5SLuofan Chen mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>;
34585ee07dc5SLuofan Chen
nodes_beginllvm::GraphTraits34595ee07dc5SLuofan Chen static nodes_iterator nodes_begin(AADepGraph *DG) { return DG->begin(); }
34605ee07dc5SLuofan Chen
nodes_endllvm::GraphTraits34615ee07dc5SLuofan Chen static nodes_iterator nodes_end(AADepGraph *DG) { return DG->end(); }
34625ee07dc5SLuofan Chen };
34635ee07dc5SLuofan Chen
34645ee07dc5SLuofan Chen template <> struct DOTGraphTraits<AADepGraph *> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits34655ee07dc5SLuofan Chen DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
34665ee07dc5SLuofan Chen
getNodeLabelllvm::DOTGraphTraits34675ee07dc5SLuofan Chen static std::string getNodeLabel(const AADepGraphNode *Node,
34685ee07dc5SLuofan Chen const AADepGraph *DG) {
346912fc9ca3SKazu Hirata std::string AAString;
34705ee07dc5SLuofan Chen raw_string_ostream O(AAString);
34715ee07dc5SLuofan Chen Node->print(O);
34725ee07dc5SLuofan Chen return AAString;
34735ee07dc5SLuofan Chen }
34745ee07dc5SLuofan Chen };
34755ee07dc5SLuofan Chen
34765ee07dc5SLuofan Chen } // end namespace llvm
34775ee07dc5SLuofan Chen
3478aade782aSJohannes Doerfert namespace {
3479aade782aSJohannes Doerfert
3480aade782aSJohannes Doerfert struct AttributorLegacyPass : public ModulePass {
3481aade782aSJohannes Doerfert static char ID;
3482aade782aSJohannes Doerfert
AttributorLegacyPass__anon708136851511::AttributorLegacyPass3483aade782aSJohannes Doerfert AttributorLegacyPass() : ModulePass(ID) {
3484aade782aSJohannes Doerfert initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
3485aade782aSJohannes Doerfert }
3486aade782aSJohannes Doerfert
runOnModule__anon708136851511::AttributorLegacyPass3487aade782aSJohannes Doerfert bool runOnModule(Module &M) override {
3488aade782aSJohannes Doerfert if (skipModule(M))
3489aade782aSJohannes Doerfert return false;
3490431141c5SStefan Stipanovic
34913bb5cbc2SHideto Ueno AnalysisGetter AG;
3492b0c77c36SJohannes Doerfert SetVector<Function *> Functions;
3493b0c77c36SJohannes Doerfert for (Function &F : M)
3494b0c77c36SJohannes Doerfert Functions.insert(&F);
3495b0c77c36SJohannes Doerfert
3496b0c77c36SJohannes Doerfert CallGraphUpdater CGUpdater;
349787aa3629SJohannes Doerfert BumpPtrAllocator Allocator;
349887aa3629SJohannes Doerfert InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr);
3499b077d82bSWilliam S. Moses return runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
35003be3b401SJohannes Doerfert /* DeleteFns*/ true,
35013be3b401SJohannes Doerfert /* IsModulePass */ true);
3502aade782aSJohannes Doerfert }
3503aade782aSJohannes Doerfert
getAnalysisUsage__anon708136851511::AttributorLegacyPass3504aade782aSJohannes Doerfert void getAnalysisUsage(AnalysisUsage &AU) const override {
3505aade782aSJohannes Doerfert // FIXME: Think about passes we will preserve and add them here.
3506431141c5SStefan Stipanovic AU.addRequired<TargetLibraryInfoWrapperPass>();
3507aade782aSJohannes Doerfert }
3508aade782aSJohannes Doerfert };
3509aade782aSJohannes Doerfert
3510b0c77c36SJohannes Doerfert struct AttributorCGSCCLegacyPass : public CallGraphSCCPass {
3511b0c77c36SJohannes Doerfert static char ID;
3512b0c77c36SJohannes Doerfert
AttributorCGSCCLegacyPass__anon708136851511::AttributorCGSCCLegacyPass3513b0c77c36SJohannes Doerfert AttributorCGSCCLegacyPass() : CallGraphSCCPass(ID) {
3514b0c77c36SJohannes Doerfert initializeAttributorCGSCCLegacyPassPass(*PassRegistry::getPassRegistry());
3515b0c77c36SJohannes Doerfert }
3516b0c77c36SJohannes Doerfert
runOnSCC__anon708136851511::AttributorCGSCCLegacyPass3517b0c77c36SJohannes Doerfert bool runOnSCC(CallGraphSCC &SCC) override {
3518b0c77c36SJohannes Doerfert if (skipSCC(SCC))
3519b0c77c36SJohannes Doerfert return false;
3520b0c77c36SJohannes Doerfert
3521b0c77c36SJohannes Doerfert SetVector<Function *> Functions;
3522b0c77c36SJohannes Doerfert for (CallGraphNode *CGN : SCC)
3523b0c77c36SJohannes Doerfert if (Function *Fn = CGN->getFunction())
3524b0c77c36SJohannes Doerfert if (!Fn->isDeclaration())
3525b0c77c36SJohannes Doerfert Functions.insert(Fn);
3526b0c77c36SJohannes Doerfert
3527b0c77c36SJohannes Doerfert if (Functions.empty())
3528b0c77c36SJohannes Doerfert return false;
3529b0c77c36SJohannes Doerfert
3530b0c77c36SJohannes Doerfert AnalysisGetter AG;
3531b0c77c36SJohannes Doerfert CallGraph &CG = const_cast<CallGraph &>(SCC.getCallGraph());
3532d13daa40SJohannes Doerfert CallGraphUpdater CGUpdater;
3533b0c77c36SJohannes Doerfert CGUpdater.initialize(CG, SCC);
3534b0c77c36SJohannes Doerfert Module &M = *Functions.back()->getParent();
353587aa3629SJohannes Doerfert BumpPtrAllocator Allocator;
353687aa3629SJohannes Doerfert InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ &Functions);
3537b077d82bSWilliam S. Moses return runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
35383be3b401SJohannes Doerfert /* DeleteFns */ false,
35393be3b401SJohannes Doerfert /* IsModulePass */ false);
3540b0c77c36SJohannes Doerfert }
3541b0c77c36SJohannes Doerfert
getAnalysisUsage__anon708136851511::AttributorCGSCCLegacyPass3542b0c77c36SJohannes Doerfert void getAnalysisUsage(AnalysisUsage &AU) const override {
3543b0c77c36SJohannes Doerfert // FIXME: Think about passes we will preserve and add them here.
3544b0c77c36SJohannes Doerfert AU.addRequired<TargetLibraryInfoWrapperPass>();
3545b0c77c36SJohannes Doerfert CallGraphSCCPass::getAnalysisUsage(AU);
3546b0c77c36SJohannes Doerfert }
3547b0c77c36SJohannes Doerfert };
3548b0c77c36SJohannes Doerfert
3549aade782aSJohannes Doerfert } // end anonymous namespace
3550aade782aSJohannes Doerfert
createAttributorLegacyPass()3551aade782aSJohannes Doerfert Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
createAttributorCGSCCLegacyPass()3552b0c77c36SJohannes Doerfert Pass *llvm::createAttributorCGSCCLegacyPass() {
3553b0c77c36SJohannes Doerfert return new AttributorCGSCCLegacyPass();
3554b0c77c36SJohannes Doerfert }
3555aade782aSJohannes Doerfert
3556aade782aSJohannes Doerfert char AttributorLegacyPass::ID = 0;
3557b0c77c36SJohannes Doerfert char AttributorCGSCCLegacyPass::ID = 0;
355824020625SJohannes Doerfert
3559aade782aSJohannes Doerfert INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
3560aade782aSJohannes Doerfert "Deduce and propagate attributes", false, false)
3561431141c5SStefan Stipanovic INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
3562aade782aSJohannes Doerfert INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
3563aade782aSJohannes Doerfert "Deduce and propagate attributes", false, false)
3564b0c77c36SJohannes Doerfert INITIALIZE_PASS_BEGIN(AttributorCGSCCLegacyPass, "attributor-cgscc",
3565b0c77c36SJohannes Doerfert "Deduce and propagate attributes (CGSCC pass)", false,
3566b0c77c36SJohannes Doerfert false)
3567b0c77c36SJohannes Doerfert INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
3568b0c77c36SJohannes Doerfert INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
3569b0c77c36SJohannes Doerfert INITIALIZE_PASS_END(AttributorCGSCCLegacyPass, "attributor-cgscc",
3570b0c77c36SJohannes Doerfert "Deduce and propagate attributes (CGSCC pass)", false,
3571b0c77c36SJohannes Doerfert false)
3572