Bug Summary

File:build/source/llvm/lib/Transforms/IPO/Attributor.cpp
Warning:line 285, column 15
Forming reference to null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Attributor.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Transforms/IPO -I /build/source/llvm/lib/Transforms/IPO -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/llvm/lib/Transforms/IPO/Attributor.cpp
1//===- Attributor.cpp - Module-wide attribute deduction -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements an interprocedural pass that deduces and/or propagates
10// attributes. This is done in an abstract interpretation style fixpoint
11// iteration. See the Attributor.h file comment and the class descriptions in
12// that file for more information.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/Transforms/IPO/Attributor.h"
17
18#include "llvm/ADT/PointerIntPair.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/Statistic.h"
21#include "llvm/Analysis/AliasAnalysis.h"
22#include "llvm/Analysis/CallGraph.h"
23#include "llvm/Analysis/CallGraphSCCPass.h"
24#include "llvm/Analysis/InlineCost.h"
25#include "llvm/Analysis/MemoryBuiltins.h"
26#include "llvm/Analysis/MustExecute.h"
27#include "llvm/IR/Attributes.h"
28#include "llvm/IR/Constant.h"
29#include "llvm/IR/ConstantFold.h"
30#include "llvm/IR/Constants.h"
31#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/GlobalValue.h"
33#include "llvm/IR/GlobalVariable.h"
34#include "llvm/IR/Instruction.h"
35#include "llvm/IR/Instructions.h"
36#include "llvm/IR/IntrinsicInst.h"
37#include "llvm/IR/ValueHandle.h"
38#include "llvm/Support/Casting.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/Debug.h"
41#include "llvm/Support/DebugCounter.h"
42#include "llvm/Support/FileSystem.h"
43#include "llvm/Support/GraphWriter.h"
44#include "llvm/Support/raw_ostream.h"
45#include "llvm/Transforms/Utils/BasicBlockUtils.h"
46#include "llvm/Transforms/Utils/Cloning.h"
47#include "llvm/Transforms/Utils/Local.h"
48#include <cstdint>
49
50#ifdef EXPENSIVE_CHECKS
51#include "llvm/IR/Verifier.h"
52#endif
53
54#include <cassert>
55#include <optional>
56#include <string>
57
58using namespace llvm;
59
60#define DEBUG_TYPE"attributor" "attributor"
61#define VERBOSE_DEBUG_TYPE"attributor" "-verbose" DEBUG_TYPE"attributor" "-verbose"
62
63DEBUG_COUNTER(ManifestDBGCounter, "attributor-manifest",static const unsigned ManifestDBGCounter = DebugCounter::registerCounter
("attributor-manifest", "Determine what attributes are manifested in the IR"
)
64 "Determine what attributes are manifested in the IR")static const unsigned ManifestDBGCounter = DebugCounter::registerCounter
("attributor-manifest", "Determine what attributes are manifested in the IR"
)
;
65
66STATISTIC(NumFnDeleted, "Number of function deleted")static llvm::Statistic NumFnDeleted = {"attributor", "NumFnDeleted"
, "Number of function deleted"}
;
67STATISTIC(NumFnWithExactDefinition,static llvm::Statistic NumFnWithExactDefinition = {"attributor"
, "NumFnWithExactDefinition", "Number of functions with exact definitions"
}
68 "Number of functions with exact definitions")static llvm::Statistic NumFnWithExactDefinition = {"attributor"
, "NumFnWithExactDefinition", "Number of functions with exact definitions"
}
;
69STATISTIC(NumFnWithoutExactDefinition,static llvm::Statistic NumFnWithoutExactDefinition = {"attributor"
, "NumFnWithoutExactDefinition", "Number of functions without exact definitions"
}
70 "Number of functions without exact definitions")static llvm::Statistic NumFnWithoutExactDefinition = {"attributor"
, "NumFnWithoutExactDefinition", "Number of functions without exact definitions"
}
;
71STATISTIC(NumFnShallowWrappersCreated, "Number of shallow wrappers created")static llvm::Statistic NumFnShallowWrappersCreated = {"attributor"
, "NumFnShallowWrappersCreated", "Number of shallow wrappers created"
}
;
72STATISTIC(NumAttributesTimedOut,static llvm::Statistic NumAttributesTimedOut = {"attributor",
"NumAttributesTimedOut", "Number of abstract attributes timed out before fixpoint"
}
73 "Number of abstract attributes timed out before fixpoint")static llvm::Statistic NumAttributesTimedOut = {"attributor",
"NumAttributesTimedOut", "Number of abstract attributes timed out before fixpoint"
}
;
74STATISTIC(NumAttributesValidFixpoint,static llvm::Statistic NumAttributesValidFixpoint = {"attributor"
, "NumAttributesValidFixpoint", "Number of abstract attributes in a valid fixpoint state"
}
75 "Number of abstract attributes in a valid fixpoint state")static llvm::Statistic NumAttributesValidFixpoint = {"attributor"
, "NumAttributesValidFixpoint", "Number of abstract attributes in a valid fixpoint state"
}
;
76STATISTIC(NumAttributesManifested,static llvm::Statistic NumAttributesManifested = {"attributor"
, "NumAttributesManifested", "Number of abstract attributes manifested in IR"
}
77 "Number of abstract attributes manifested in IR")static llvm::Statistic NumAttributesManifested = {"attributor"
, "NumAttributesManifested", "Number of abstract attributes manifested in IR"
}
;
78
79// TODO: Determine a good default value.
80//
81// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
82// (when run with the first 5 abstract attributes). The results also indicate
83// that we never reach 32 iterations but always find a fixpoint sooner.
84//
85// This will become more evolved once we perform two interleaved fixpoint
86// iterations: bottom-up and top-down.
87static cl::opt<unsigned>
88 SetFixpointIterations("attributor-max-iterations", cl::Hidden,
89 cl::desc("Maximal number of fixpoint iterations."),
90 cl::init(32));
91
92static cl::opt<unsigned, true> MaxInitializationChainLengthX(
93 "attributor-max-initialization-chain-length", cl::Hidden,
94 cl::desc(
95 "Maximal number of chained initializations (to avoid stack overflows)"),
96 cl::location(MaxInitializationChainLength), cl::init(1024));
97unsigned llvm::MaxInitializationChainLength;
98
99static cl::opt<bool> VerifyMaxFixpointIterations(
100 "attributor-max-iterations-verify", cl::Hidden,
101 cl::desc("Verify that max-iterations is a tight bound for a fixpoint"),
102 cl::init(false));
103
104static cl::opt<bool> AnnotateDeclarationCallSites(
105 "attributor-annotate-decl-cs", cl::Hidden,
106 cl::desc("Annotate call sites of function declarations."), cl::init(false));
107
108static cl::opt<bool> EnableHeapToStack("enable-heap-to-stack-conversion",
109 cl::init(true), cl::Hidden);
110
111static cl::opt<bool>
112 AllowShallowWrappers("attributor-allow-shallow-wrappers", cl::Hidden,
113 cl::desc("Allow the Attributor to create shallow "
114 "wrappers for non-exact definitions."),
115 cl::init(false));
116
117static cl::opt<bool>
118 AllowDeepWrapper("attributor-allow-deep-wrappers", cl::Hidden,
119 cl::desc("Allow the Attributor to use IP information "
120 "derived from non-exact functions via cloning"),
121 cl::init(false));
122
123// These options can only used for debug builds.
124#ifndef NDEBUG
125static cl::list<std::string>
126 SeedAllowList("attributor-seed-allow-list", cl::Hidden,
127 cl::desc("Comma seperated list of attribute names that are "
128 "allowed to be seeded."),
129 cl::CommaSeparated);
130
131static cl::list<std::string> FunctionSeedAllowList(
132 "attributor-function-seed-allow-list", cl::Hidden,
133 cl::desc("Comma seperated list of function names that are "
134 "allowed to be seeded."),
135 cl::CommaSeparated);
136#endif
137
138static cl::opt<bool>
139 DumpDepGraph("attributor-dump-dep-graph", cl::Hidden,
140 cl::desc("Dump the dependency graph to dot files."),
141 cl::init(false));
142
143static cl::opt<std::string> DepGraphDotFileNamePrefix(
144 "attributor-depgraph-dot-filename-prefix", cl::Hidden,
145 cl::desc("The prefix used for the CallGraph dot file names."));
146
147static cl::opt<bool> ViewDepGraph("attributor-view-dep-graph", cl::Hidden,
148 cl::desc("View the dependency graph."),
149 cl::init(false));
150
151static cl::opt<bool> PrintDependencies("attributor-print-dep", cl::Hidden,
152 cl::desc("Print attribute dependencies"),
153 cl::init(false));
154
155static cl::opt<bool> EnableCallSiteSpecific(
156 "attributor-enable-call-site-specific-deduction", cl::Hidden,
157 cl::desc("Allow the Attributor to do call site specific analysis"),
158 cl::init(false));
159
160static cl::opt<bool>
161 PrintCallGraph("attributor-print-call-graph", cl::Hidden,
162 cl::desc("Print Attributor's internal call graph"),
163 cl::init(false));
164
165static cl::opt<bool> SimplifyAllLoads("attributor-simplify-all-loads",
166 cl::Hidden,
167 cl::desc("Try to simplify all loads."),
168 cl::init(true));
169
170/// Logic operators for the change status enum class.
171///
172///{
173ChangeStatus llvm::operator|(ChangeStatus L, ChangeStatus R) {
174 return L == ChangeStatus::CHANGED ? L : R;
175}
176ChangeStatus &llvm::operator|=(ChangeStatus &L, ChangeStatus R) {
177 L = L | R;
178 return L;
179}
180ChangeStatus llvm::operator&(ChangeStatus L, ChangeStatus R) {
181 return L == ChangeStatus::UNCHANGED ? L : R;
182}
183ChangeStatus &llvm::operator&=(ChangeStatus &L, ChangeStatus R) {
184 L = L & R;
185 return L;
186}
187///}
188
189bool AA::isNoSyncInst(Attributor &A, const Instruction &I,
190 const AbstractAttribute &QueryingAA) {
191 // We are looking for volatile instructions or non-relaxed atomics.
192 if (const auto *CB = dyn_cast<CallBase>(&I)) {
193 if (CB->hasFnAttr(Attribute::NoSync))
194 return true;
195
196 // Non-convergent and readnone imply nosync.
197 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
198 return true;
199
200 if (AANoSync::isNoSyncIntrinsic(&I))
201 return true;
202
203 const auto &NoSyncAA = A.getAAFor<AANoSync>(
204 QueryingAA, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
205 return NoSyncAA.isAssumedNoSync();
206 }
207
208 if (!I.mayReadOrWriteMemory())
209 return true;
210
211 return !I.isVolatile() && !AANoSync::isNonRelaxedAtomic(&I);
212}
213
214bool AA::isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA,
215 const Value &V, bool ForAnalysisOnly) {
216 // TODO: See the AAInstanceInfo class comment.
217 if (!ForAnalysisOnly)
218 return false;
219 auto &InstanceInfoAA = A.getAAFor<AAInstanceInfo>(
220 QueryingAA, IRPosition::value(V), DepClassTy::OPTIONAL);
221 return InstanceInfoAA.isAssumedUniqueForAnalysis();
222}
223
224Constant *AA::getInitialValueForObj(Attributor &A, Value &Obj, Type &Ty,
225 const TargetLibraryInfo *TLI,
226 const DataLayout &DL,
227 AA::RangeTy *RangePtr) {
228 if (isa<AllocaInst>(Obj))
229 return UndefValue::get(&Ty);
230 if (Constant *Init = getInitialValueOfAllocation(&Obj, TLI, &Ty))
231 return Init;
232 auto *GV = dyn_cast<GlobalVariable>(&Obj);
233 if (!GV)
234 return nullptr;
235
236 bool UsedAssumedInformation = false;
237 Constant *Initializer = nullptr;
238 if (A.hasGlobalVariableSimplificationCallback(*GV)) {
239 auto AssumedGV = A.getAssumedInitializerFromCallBack(
240 *GV, /* const AbstractAttribute *AA */ nullptr, UsedAssumedInformation);
241 Initializer = *AssumedGV;
242 if (!Initializer)
243 return nullptr;
244 } else {
245 if (!GV->hasLocalLinkage() && !(GV->isConstant() && GV->hasInitializer()))
246 return nullptr;
247 if (!GV->hasInitializer())
248 return UndefValue::get(&Ty);
249
250 if (!Initializer)
251 Initializer = GV->getInitializer();
252 }
253
254 if (RangePtr && !RangePtr->offsetOrSizeAreUnknown()) {
255 APInt Offset = APInt(64, RangePtr->Offset);
256 return ConstantFoldLoadFromConst(Initializer, &Ty, Offset, DL);
257 }
258
259 return ConstantFoldLoadFromUniformValue(Initializer, &Ty);
260}
261
262bool AA::isValidInScope(const Value &V, const Function *Scope) {
263 if (isa<Constant>(V))
264 return true;
265 if (auto *I = dyn_cast<Instruction>(&V))
266 return I->getFunction() == Scope;
267 if (auto *A = dyn_cast<Argument>(&V))
268 return A->getParent() == Scope;
269 return false;
270}
271
272bool AA::isValidAtPosition(const AA::ValueAndContext &VAC,
273 InformationCache &InfoCache) {
274 if (isa<Constant>(VAC.getValue()) || VAC.getValue() == VAC.getCtxI())
1
Assuming the object is not a 'Constant'
2
Assuming the condition is false
3
Taking false branch
275 return true;
276 const Function *Scope = nullptr;
4
'Scope' initialized to a null pointer value
277 const Instruction *CtxI = VAC.getCtxI();
278 if (CtxI)
5
Assuming 'CtxI' is null
6
Taking false branch
279 Scope = CtxI->getFunction();
280 if (auto *A
7.1
'A' is null
= dyn_cast<Argument>(VAC.getValue()))
7
Assuming the object is not a 'CastReturnType'
8
Taking false branch
281 return A->getParent() == Scope;
282 if (auto *I
9.1
'I' is non-null
= dyn_cast<Instruction>(VAC.getValue())) {
9
Assuming the object is a 'CastReturnType'
10
Taking true branch
283 if (I->getFunction() == Scope) {
11
Assuming the condition is true
12
Taking true branch
284 if (const DominatorTree *DT =
285 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
13
Forming reference to null pointer
286 *Scope))
287 return DT->dominates(I, CtxI);
288 // Local dominance check mostly for the old PM passes.
289 if (CtxI && I->getParent() == CtxI->getParent())
290 return llvm::any_of(
291 make_range(I->getIterator(), I->getParent()->end()),
292 [&](const Instruction &AfterI) { return &AfterI == CtxI; });
293 }
294 }
295 return false;
296}
297
298Value *AA::getWithType(Value &V, Type &Ty) {
299 if (V.getType() == &Ty)
300 return &V;
301 if (isa<PoisonValue>(V))
302 return PoisonValue::get(&Ty);
303 if (isa<UndefValue>(V))
304 return UndefValue::get(&Ty);
305 if (auto *C = dyn_cast<Constant>(&V)) {
306 if (C->isNullValue())
307 return Constant::getNullValue(&Ty);
308 if (C->getType()->isPointerTy() && Ty.isPointerTy())
309 return ConstantExpr::getPointerCast(C, &Ty);
310 if (C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) {
311 if (C->getType()->isIntegerTy() && Ty.isIntegerTy())
312 return ConstantExpr::getTrunc(C, &Ty, /* OnlyIfReduced */ true);
313 if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy())
314 return ConstantExpr::getFPTrunc(C, &Ty, /* OnlyIfReduced */ true);
315 }
316 }
317 return nullptr;
318}
319
320std::optional<Value *>
321AA::combineOptionalValuesInAAValueLatice(const std::optional<Value *> &A,
322 const std::optional<Value *> &B,
323 Type *Ty) {
324 if (A == B)
325 return A;
326 if (!B)
327 return A;
328 if (*B == nullptr)
329 return nullptr;
330 if (!A)
331 return Ty ? getWithType(**B, *Ty) : nullptr;
332 if (*A == nullptr)
333 return nullptr;
334 if (!Ty)
335 Ty = (*A)->getType();
336 if (isa_and_nonnull<UndefValue>(*A))
337 return getWithType(**B, *Ty);
338 if (isa<UndefValue>(*B))
339 return A;
340 if (*A && *B && *A == getWithType(**B, *Ty))
341 return A;
342 return nullptr;
343}
344
345template <bool IsLoad, typename Ty>
346static bool getPotentialCopiesOfMemoryValue(
347 Attributor &A, Ty &I, SmallSetVector<Value *, 4> &PotentialCopies,
348 SmallSetVector<Instruction *, 4> &PotentialValueOrigins,
349 const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
350 bool OnlyExact) {
351 LLVM_DEBUG(dbgs() << "Trying to determine the potential copies of " << Ido { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Trying to determine the potential copies of "
<< I << " (only exact: " << OnlyExact <<
")\n";; } } while (false)
352 << " (only exact: " << OnlyExact << ")\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Trying to determine the potential copies of "
<< I << " (only exact: " << OnlyExact <<
")\n";; } } while (false)
;
353
354 Value &Ptr = *I.getPointerOperand();
355 // Containers to remember the pointer infos and new copies while we are not
356 // sure that we can find all of them. If we abort we want to avoid spurious
357 // dependences and potential copies in the provided container.
358 SmallVector<const AAPointerInfo *> PIs;
359 SmallVector<Value *> NewCopies;
360 SmallVector<Instruction *> NewCopyOrigins;
361
362 const auto *TLI =
363 A.getInfoCache().getTargetLibraryInfoForFunction(*I.getFunction());
364
365 auto Pred = [&](Value &Obj) {
366 LLVM_DEBUG(dbgs() << "Visit underlying object " << Obj << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Visit underlying object " <<
Obj << "\n"; } } while (false)
;
367 if (isa<UndefValue>(&Obj))
368 return true;
369 if (isa<ConstantPointerNull>(&Obj)) {
370 // A null pointer access can be undefined but any offset from null may
371 // be OK. We do not try to optimize the latter.
372 if (!NullPointerIsDefined(I.getFunction(),
373 Ptr.getType()->getPointerAddressSpace()) &&
374 A.getAssumedSimplified(Ptr, QueryingAA, UsedAssumedInformation,
375 AA::Interprocedural) == &Obj)
376 return true;
377 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object is a valid nullptr, giving up.\n"
;; } } while (false)
378 dbgs() << "Underlying object is a valid nullptr, giving up.\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object is a valid nullptr, giving up.\n"
;; } } while (false)
;
379 return false;
380 }
381 // TODO: Use assumed noalias return.
382 if (!isa<AllocaInst>(&Obj) && !isa<GlobalVariable>(&Obj) &&
383 !(IsLoad ? isAllocationFn(&Obj, TLI) : isNoAliasCall(&Obj))) {
384 LLVM_DEBUG(dbgs() << "Underlying object is not supported yet: " << Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object is not supported yet: "
<< Obj << "\n";; } } while (false)
385 << "\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object is not supported yet: "
<< Obj << "\n";; } } while (false)
;
386 return false;
387 }
388 if (auto *GV = dyn_cast<GlobalVariable>(&Obj))
389 if (!GV->hasLocalLinkage() &&
390 !(GV->isConstant() && GV->hasInitializer())) {
391 LLVM_DEBUG(dbgs() << "Underlying object is global with external "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object is global with external "
"linkage, not supported yet: " << Obj << "\n";; }
} while (false)
392 "linkage, not supported yet: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object is global with external "
"linkage, not supported yet: " << Obj << "\n";; }
} while (false)
393 << Obj << "\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object is global with external "
"linkage, not supported yet: " << Obj << "\n";; }
} while (false)
;
394 return false;
395 }
396
397 bool NullOnly = true;
398 bool NullRequired = false;
399 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
400 bool IsExact) {
401 if (!V || *V == nullptr)
402 NullOnly = false;
403 else if (isa<UndefValue>(*V))
404 /* No op */;
405 else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue())
406 NullRequired = !IsExact;
407 else
408 NullOnly = false;
409 };
410
411 auto AdjustWrittenValueType = [&](const AAPointerInfo::Access &Acc,
412 Value &V) {
413 Value *AdjV = AA::getWithType(V, *I.getType());
414 if (!AdjV) {
415 LLVM_DEBUG(dbgs() << "Underlying object written but stored value "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object written but stored value "
"cannot be converted to read type: " << *Acc.getRemoteInst
() << " : " << *I.getType() << "\n";; } } while
(false)
416 "cannot be converted to read type: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object written but stored value "
"cannot be converted to read type: " << *Acc.getRemoteInst
() << " : " << *I.getType() << "\n";; } } while
(false)
417 << *Acc.getRemoteInst() << " : " << *I.getType()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object written but stored value "
"cannot be converted to read type: " << *Acc.getRemoteInst
() << " : " << *I.getType() << "\n";; } } while
(false)
418 << "\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object written but stored value "
"cannot be converted to read type: " << *Acc.getRemoteInst
() << " : " << *I.getType() << "\n";; } } while
(false)
;
419 }
420 return AdjV;
421 };
422
423 auto CheckAccess = [&](const AAPointerInfo::Access &Acc, bool IsExact) {
424 if ((IsLoad && !Acc.isWriteOrAssumption()) || (!IsLoad && !Acc.isRead()))
425 return true;
426 if (IsLoad && Acc.isWrittenValueYetUndetermined())
427 return true;
428 CheckForNullOnlyAndUndef(Acc.getContent(), IsExact);
429 if (OnlyExact && !IsExact && !NullOnly &&
430 !isa_and_nonnull<UndefValue>(Acc.getWrittenValue())) {
431 LLVM_DEBUG(dbgs() << "Non exact access " << *Acc.getRemoteInst()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Non exact access " <<
*Acc.getRemoteInst() << ", abort!\n"; } } while (false
)
432 << ", abort!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Non exact access " <<
*Acc.getRemoteInst() << ", abort!\n"; } } while (false
)
;
433 return false;
434 }
435 if (NullRequired && !NullOnly) {
436 LLVM_DEBUG(dbgs() << "Required all `null` accesses due to non exact "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Required all `null` accesses due to non exact "
"one, however found non-null one: " << *Acc.getRemoteInst
() << ", abort!\n"; } } while (false)
437 "one, however found non-null one: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Required all `null` accesses due to non exact "
"one, however found non-null one: " << *Acc.getRemoteInst
() << ", abort!\n"; } } while (false)
438 << *Acc.getRemoteInst() << ", abort!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Required all `null` accesses due to non exact "
"one, however found non-null one: " << *Acc.getRemoteInst
() << ", abort!\n"; } } while (false)
;
439 return false;
440 }
441 if (IsLoad) {
442 assert(isa<LoadInst>(I) && "Expected load or store instruction only!")(static_cast <bool> (isa<LoadInst>(I) && "Expected load or store instruction only!"
) ? void (0) : __assert_fail ("isa<LoadInst>(I) && \"Expected load or store instruction only!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 442, __extension__
__PRETTY_FUNCTION__))
;
443 if (!Acc.isWrittenValueUnknown()) {
444 Value *V = AdjustWrittenValueType(Acc, *Acc.getWrittenValue());
445 if (!V)
446 return false;
447 NewCopies.push_back(V);
448 NewCopyOrigins.push_back(Acc.getRemoteInst());
449 return true;
450 }
451 auto *SI = dyn_cast<StoreInst>(Acc.getRemoteInst());
452 if (!SI) {
453 LLVM_DEBUG(dbgs() << "Underlying object written through a non-store "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object written through a non-store "
"instruction not supported yet: " << *Acc.getRemoteInst
() << "\n";; } } while (false)
454 "instruction not supported yet: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object written through a non-store "
"instruction not supported yet: " << *Acc.getRemoteInst
() << "\n";; } } while (false)
455 << *Acc.getRemoteInst() << "\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object written through a non-store "
"instruction not supported yet: " << *Acc.getRemoteInst
() << "\n";; } } while (false)
;
456 return false;
457 }
458 Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand());
459 if (!V)
460 return false;
461 NewCopies.push_back(V);
462 NewCopyOrigins.push_back(SI);
463 } else {
464 assert(isa<StoreInst>(I) && "Expected load or store instruction only!")(static_cast <bool> (isa<StoreInst>(I) &&
"Expected load or store instruction only!") ? void (0) : __assert_fail
("isa<StoreInst>(I) && \"Expected load or store instruction only!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 464, __extension__
__PRETTY_FUNCTION__))
;
465 auto *LI = dyn_cast<LoadInst>(Acc.getRemoteInst());
466 if (!LI && OnlyExact) {
467 LLVM_DEBUG(dbgs() << "Underlying object read through a non-load "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object read through a non-load "
"instruction not supported yet: " << *Acc.getRemoteInst
() << "\n";; } } while (false)
468 "instruction not supported yet: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object read through a non-load "
"instruction not supported yet: " << *Acc.getRemoteInst
() << "\n";; } } while (false)
469 << *Acc.getRemoteInst() << "\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying object read through a non-load "
"instruction not supported yet: " << *Acc.getRemoteInst
() << "\n";; } } while (false)
;
470 return false;
471 }
472 NewCopies.push_back(Acc.getRemoteInst());
473 }
474 return true;
475 };
476
477 // If the value has been written to we don't need the initial value of the
478 // object.
479 bool HasBeenWrittenTo = false;
480
481 AA::RangeTy Range;
482 auto &PI = A.getAAFor<AAPointerInfo>(QueryingAA, IRPosition::value(Obj),
483 DepClassTy::NONE);
484 if (!PI.forallInterferingAccesses(A, QueryingAA, I,
485 /* FindInterferingWrites */ IsLoad,
486 /* FindInterferingReads */ !IsLoad,
487 CheckAccess, HasBeenWrittenTo, Range)) {
488 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Failed to verify all interfering accesses for underlying object: "
<< Obj << "\n"; } } while (false)
489 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Failed to verify all interfering accesses for underlying object: "
<< Obj << "\n"; } } while (false)
490 << "Failed to verify all interfering accesses for underlying object: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Failed to verify all interfering accesses for underlying object: "
<< Obj << "\n"; } } while (false)
491 << Obj << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Failed to verify all interfering accesses for underlying object: "
<< Obj << "\n"; } } while (false)
;
492 return false;
493 }
494
495 if (IsLoad && !HasBeenWrittenTo && !Range.isUnassigned()) {
496 const DataLayout &DL = A.getDataLayout();
497 Value *InitialValue =
498 AA::getInitialValueForObj(A, Obj, *I.getType(), TLI, DL, &Range);
499 if (!InitialValue) {
500 LLVM_DEBUG(dbgs() << "Could not determine required initial value of "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Could not determine required initial value of "
"underlying object, abort!\n"; } } while (false)
501 "underlying object, abort!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Could not determine required initial value of "
"underlying object, abort!\n"; } } while (false)
;
502 return false;
503 }
504 CheckForNullOnlyAndUndef(InitialValue, /* IsExact */ true);
505 if (NullRequired && !NullOnly) {
506 LLVM_DEBUG(dbgs() << "Non exact access but initial value that is not "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Non exact access but initial value that is not "
"null or undef, abort!\n"; } } while (false)
507 "null or undef, abort!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Non exact access but initial value that is not "
"null or undef, abort!\n"; } } while (false)
;
508 return false;
509 }
510
511 NewCopies.push_back(InitialValue);
512 NewCopyOrigins.push_back(nullptr);
513 }
514
515 PIs.push_back(&PI);
516
517 return true;
518 };
519
520 const auto &AAUO = A.getAAFor<AAUnderlyingObjects>(
521 QueryingAA, IRPosition::value(Ptr), DepClassTy::OPTIONAL);
522 if (!AAUO.forallUnderlyingObjects(Pred)) {
523 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying objects stored into could not be determined\n"
;; } } while (false)
524 dbgs() << "Underlying objects stored into could not be determined\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Underlying objects stored into could not be determined\n"
;; } } while (false)
;
525 return false;
526 }
527
528 // Only if we were successful collection all potential copies we record
529 // dependences (on non-fix AAPointerInfo AAs). We also only then modify the
530 // given PotentialCopies container.
531 for (const auto *PI : PIs) {
532 if (!PI->getState().isAtFixpoint())
533 UsedAssumedInformation = true;
534 A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL);
535 }
536 PotentialCopies.insert(NewCopies.begin(), NewCopies.end());
537 PotentialValueOrigins.insert(NewCopyOrigins.begin(), NewCopyOrigins.end());
538
539 return true;
540}
541
542bool AA::getPotentiallyLoadedValues(
543 Attributor &A, LoadInst &LI, SmallSetVector<Value *, 4> &PotentialValues,
544 SmallSetVector<Instruction *, 4> &PotentialValueOrigins,
545 const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
546 bool OnlyExact) {
547 return getPotentialCopiesOfMemoryValue</* IsLoad */ true>(
548 A, LI, PotentialValues, PotentialValueOrigins, QueryingAA,
549 UsedAssumedInformation, OnlyExact);
550}
551
552bool AA::getPotentialCopiesOfStoredValue(
553 Attributor &A, StoreInst &SI, SmallSetVector<Value *, 4> &PotentialCopies,
554 const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
555 bool OnlyExact) {
556 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
557 return getPotentialCopiesOfMemoryValue</* IsLoad */ false>(
558 A, SI, PotentialCopies, PotentialValueOrigins, QueryingAA,
559 UsedAssumedInformation, OnlyExact);
560}
561
562static bool isAssumedReadOnlyOrReadNone(Attributor &A, const IRPosition &IRP,
563 const AbstractAttribute &QueryingAA,
564 bool RequireReadNone, bool &IsKnown) {
565
566 IRPosition::Kind Kind = IRP.getPositionKind();
567 if (Kind == IRPosition::IRP_FUNCTION || Kind == IRPosition::IRP_CALL_SITE) {
568 const auto &MemLocAA =
569 A.getAAFor<AAMemoryLocation>(QueryingAA, IRP, DepClassTy::NONE);
570 if (MemLocAA.isAssumedReadNone()) {
571 IsKnown = MemLocAA.isKnownReadNone();
572 if (!IsKnown)
573 A.recordDependence(MemLocAA, QueryingAA, DepClassTy::OPTIONAL);
574 return true;
575 }
576 }
577
578 const auto &MemBehaviorAA =
579 A.getAAFor<AAMemoryBehavior>(QueryingAA, IRP, DepClassTy::NONE);
580 if (MemBehaviorAA.isAssumedReadNone() ||
581 (!RequireReadNone && MemBehaviorAA.isAssumedReadOnly())) {
582 IsKnown = RequireReadNone ? MemBehaviorAA.isKnownReadNone()
583 : MemBehaviorAA.isKnownReadOnly();
584 if (!IsKnown)
585 A.recordDependence(MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL);
586 return true;
587 }
588
589 return false;
590}
591
592bool AA::isAssumedReadOnly(Attributor &A, const IRPosition &IRP,
593 const AbstractAttribute &QueryingAA, bool &IsKnown) {
594 return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA,
595 /* RequireReadNone */ false, IsKnown);
596}
597bool AA::isAssumedReadNone(Attributor &A, const IRPosition &IRP,
598 const AbstractAttribute &QueryingAA, bool &IsKnown) {
599 return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA,
600 /* RequireReadNone */ true, IsKnown);
601}
602
603static bool
604isPotentiallyReachable(Attributor &A, const Instruction &FromI,
605 const Instruction *ToI, const Function &ToFn,
606 const AbstractAttribute &QueryingAA,
607 const AA::InstExclusionSetTy *ExclusionSet,
608 std::function<bool(const Function &F)> GoBackwardsCB) {
609 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
610 dbgs() << "[AA] isPotentiallyReachable @" << ToFn.getName() << " from "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
611 << FromI << " [GBCB: " << bool(GoBackwardsCB) << "][#ExS: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
612 << (ExclusionSet ? std::to_string(ExclusionSet->size()) : "none")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
613 << "]\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
614 if (ExclusionSet)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
615 for (auto *ES : *ExclusionSet)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
616 dbgs() << *ES << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
617 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[AA] isPotentiallyReachable @"
<< ToFn.getName() << " from " << FromI <<
" [GBCB: " << bool(GoBackwardsCB) << "][#ExS: " <<
(ExclusionSet ? std::to_string(ExclusionSet->size()) : "none"
) << "]\n"; if (ExclusionSet) for (auto *ES : *ExclusionSet
) dbgs() << *ES << "\n"; }; } } while (false)
;
618
619 // We know kernels (generally) cannot be called from within the module. Thus,
620 // for reachability we would need to step back from a kernel which would allow
621 // us to reach anything anyway. Even if a kernel is invoked from another
622 // kernel, values like allocas and shared memory are not accessible. We
623 // implicitly check for this situation to avoid costly lookups.
624 if (GoBackwardsCB && &ToFn != FromI.getFunction() &&
625 !GoBackwardsCB(*FromI.getFunction()) && ToFn.hasFnAttribute("kernel") &&
626 FromI.getFunction()->hasFnAttribute("kernel")) {
627 LLVM_DEBUG(dbgs() << "[AA] assume kernel cannot be reached from within the "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] assume kernel cannot be reached from within the "
"module; success\n";; } } while (false)
628 "module; success\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] assume kernel cannot be reached from within the "
"module; success\n";; } } while (false)
;
629 return false;
630 }
631
632 // If we can go arbitrarily backwards we will eventually reach an entry point
633 // that can reach ToI. Only if a set of blocks through which we cannot go is
634 // provided, or once we track internal functions not accessible from the
635 // outside, it makes sense to perform backwards analysis in the absence of a
636 // GoBackwardsCB.
637 if (!GoBackwardsCB && !ExclusionSet) {
638 LLVM_DEBUG(dbgs() << "[AA] check @" << ToFn.getName() << " from " << FromIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] check @" << ToFn
.getName() << " from " << FromI << " is not checked backwards and does not have an "
"exclusion set, abort\n"; } } while (false)
639 << " is not checked backwards and does not have an "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] check @" << ToFn
.getName() << " from " << FromI << " is not checked backwards and does not have an "
"exclusion set, abort\n"; } } while (false)
640 "exclusion set, abort\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] check @" << ToFn
.getName() << " from " << FromI << " is not checked backwards and does not have an "
"exclusion set, abort\n"; } } while (false)
;
641 return true;
642 }
643
644 SmallPtrSet<const Instruction *, 8> Visited;
645 SmallVector<const Instruction *> Worklist;
646 Worklist.push_back(&FromI);
647
648 while (!Worklist.empty()) {
649 const Instruction *CurFromI = Worklist.pop_back_val();
650 if (!Visited.insert(CurFromI).second)
651 continue;
652
653 const Function *FromFn = CurFromI->getFunction();
654 if (FromFn == &ToFn) {
655 if (!ToI)
656 return true;
657 LLVM_DEBUG(dbgs() << "[AA] check " << *ToI << " from " << *CurFromIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] check " << *ToI
<< " from " << *CurFromI << " intraprocedurally\n"
; } } while (false)
658 << " intraprocedurally\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] check " << *ToI
<< " from " << *CurFromI << " intraprocedurally\n"
; } } while (false)
;
659 const auto &ReachabilityAA = A.getAAFor<AAIntraFnReachability>(
660 QueryingAA, IRPosition::function(ToFn), DepClassTy::OPTIONAL);
661 bool Result =
662 ReachabilityAA.isAssumedReachable(A, *CurFromI, *ToI, ExclusionSet);
663 LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] " << *CurFromI <<
" " << (Result ? "can potentially " : "cannot ") <<
"reach " << *ToI << " [Intra]\n"; } } while (false
)
664 << (Result ? "can potentially " : "cannot ") << "reach "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] " << *CurFromI <<
" " << (Result ? "can potentially " : "cannot ") <<
"reach " << *ToI << " [Intra]\n"; } } while (false
)
665 << *ToI << " [Intra]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] " << *CurFromI <<
" " << (Result ? "can potentially " : "cannot ") <<
"reach " << *ToI << " [Intra]\n"; } } while (false
)
;
666 if (Result)
667 return true;
668 }
669
670 bool Result = true;
671 if (!ToFn.isDeclaration() && ToI) {
672 const auto &ToReachabilityAA = A.getAAFor<AAIntraFnReachability>(
673 QueryingAA, IRPosition::function(ToFn), DepClassTy::OPTIONAL);
674 const Instruction &EntryI = ToFn.getEntryBlock().front();
675 Result =
676 ToReachabilityAA.isAssumedReachable(A, EntryI, *ToI, ExclusionSet);
677 LLVM_DEBUG(dbgs() << "[AA] Entry " << EntryI << " of @" << ToFn.getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Entry " << EntryI
<< " of @" << ToFn.getName() << " " <<
(Result ? "can potentially " : "cannot ") << "reach @"
<< *ToI << " [ToFn]\n"; } } while (false)
678 << " " << (Result ? "can potentially " : "cannot ")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Entry " << EntryI
<< " of @" << ToFn.getName() << " " <<
(Result ? "can potentially " : "cannot ") << "reach @"
<< *ToI << " [ToFn]\n"; } } while (false)
679 << "reach @" << *ToI << " [ToFn]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Entry " << EntryI
<< " of @" << ToFn.getName() << " " <<
(Result ? "can potentially " : "cannot ") << "reach @"
<< *ToI << " [ToFn]\n"; } } while (false)
;
680 }
681
682 if (Result) {
683 // The entry of the ToFn can reach the instruction ToI. If the current
684 // instruction is already known to reach the ToFn.
685 const auto &FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
686 QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL);
687 Result = FnReachabilityAA.instructionCanReach(A, *CurFromI, ToFn,
688 ExclusionSet);
689 LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " in @" << FromFn->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] " << *CurFromI <<
" in @" << FromFn->getName() << " " << (
Result ? "can potentially " : "cannot ") << "reach @" <<
ToFn.getName() << " [FromFn]\n"; } } while (false)
690 << " " << (Result ? "can potentially " : "cannot ")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] " << *CurFromI <<
" in @" << FromFn->getName() << " " << (
Result ? "can potentially " : "cannot ") << "reach @" <<
ToFn.getName() << " [FromFn]\n"; } } while (false)
691 << "reach @" << ToFn.getName() << " [FromFn]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] " << *CurFromI <<
" in @" << FromFn->getName() << " " << (
Result ? "can potentially " : "cannot ") << "reach @" <<
ToFn.getName() << " [FromFn]\n"; } } while (false)
;
692 if (Result)
693 return true;
694 }
695
696 // TODO: Check assumed nounwind.
697 const auto &ReachabilityAA = A.getAAFor<AAIntraFnReachability>(
698 QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL);
699 auto ReturnInstCB = [&](Instruction &Ret) {
700 bool Result =
701 ReachabilityAA.isAssumedReachable(A, *CurFromI, Ret, ExclusionSet);
702 LLVM_DEBUG(dbgs() << "[AA][Ret] " << *CurFromI << " "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA][Ret] " << *CurFromI
<< " " << (Result ? "can potentially " : "cannot "
) << "reach " << Ret << " [Intra]\n"; } } while
(false)
703 << (Result ? "can potentially " : "cannot ") << "reach "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA][Ret] " << *CurFromI
<< " " << (Result ? "can potentially " : "cannot "
) << "reach " << Ret << " [Intra]\n"; } } while
(false)
704 << Ret << " [Intra]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA][Ret] " << *CurFromI
<< " " << (Result ? "can potentially " : "cannot "
) << "reach " << Ret << " [Intra]\n"; } } while
(false)
;
705 return !Result;
706 };
707
708 // Check if we can reach returns.
709 bool UsedAssumedInformation = false;
710 if (A.checkForAllInstructions(ReturnInstCB, FromFn, QueryingAA,
711 {Instruction::Ret}, UsedAssumedInformation)) {
712 LLVM_DEBUG(dbgs() << "[AA] No return is reachable, done\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] No return is reachable, done\n"
; } } while (false)
;
713 continue;
714 }
715
716 if (!GoBackwardsCB) {
717 LLVM_DEBUG(dbgs() << "[AA] check @" << ToFn.getName() << " from " << FromIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] check @" << ToFn
.getName() << " from " << FromI << " is not checked backwards, abort\n"
; } } while (false)
718 << " is not checked backwards, abort\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] check @" << ToFn
.getName() << " from " << FromI << " is not checked backwards, abort\n"
; } } while (false)
;
719 return true;
720 }
721
722 // If we do not go backwards from the FromFn we are done here and so far we
723 // could not find a way to reach ToFn/ToI.
724 if (!GoBackwardsCB(*FromFn))
725 continue;
726
727 LLVM_DEBUG(dbgs() << "Stepping backwards to the call sites of @"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Stepping backwards to the call sites of @"
<< FromFn->getName() << "\n"; } } while (false
)
728 << FromFn->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Stepping backwards to the call sites of @"
<< FromFn->getName() << "\n"; } } while (false
)
;
729
730 auto CheckCallSite = [&](AbstractCallSite ACS) {
731 CallBase *CB = ACS.getInstruction();
732 if (!CB)
733 return false;
734
735 if (isa<InvokeInst>(CB))
736 return false;
737
738 Instruction *Inst = CB->getNextNonDebugInstruction();
739 Worklist.push_back(Inst);
740 return true;
741 };
742
743 Result = !A.checkForAllCallSites(CheckCallSite, *FromFn,
744 /* RequireAllCallSites */ true,
745 &QueryingAA, UsedAssumedInformation);
746 if (Result) {
747 LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] stepping back to call sites from "
<< *CurFromI << " in @" << FromFn->getName
() << " failed, give up\n"; } } while (false)
748 << " in @" << FromFn->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] stepping back to call sites from "
<< *CurFromI << " in @" << FromFn->getName
() << " failed, give up\n"; } } while (false)
749 << " failed, give up\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] stepping back to call sites from "
<< *CurFromI << " in @" << FromFn->getName
() << " failed, give up\n"; } } while (false)
;
750 return true;
751 }
752
753 LLVM_DEBUG(dbgs() << "[AA] stepped back to call sites from " << *CurFromIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] stepped back to call sites from "
<< *CurFromI << " in @" << FromFn->getName
() << " worklist size is: " << Worklist.size() <<
"\n"; } } while (false)
754 << " in @" << FromFn->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] stepped back to call sites from "
<< *CurFromI << " in @" << FromFn->getName
() << " worklist size is: " << Worklist.size() <<
"\n"; } } while (false)
755 << " worklist size is: " << Worklist.size() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] stepped back to call sites from "
<< *CurFromI << " in @" << FromFn->getName
() << " worklist size is: " << Worklist.size() <<
"\n"; } } while (false)
;
756 }
757 return false;
758}
759
760bool AA::isPotentiallyReachable(
761 Attributor &A, const Instruction &FromI, const Instruction &ToI,
762 const AbstractAttribute &QueryingAA,
763 const AA::InstExclusionSetTy *ExclusionSet,
764 std::function<bool(const Function &F)> GoBackwardsCB) {
765 const Function *ToFn = ToI.getFunction();
766 return ::isPotentiallyReachable(A, FromI, &ToI, *ToFn, QueryingAA,
767 ExclusionSet, GoBackwardsCB);
768}
769
770bool AA::isPotentiallyReachable(
771 Attributor &A, const Instruction &FromI, const Function &ToFn,
772 const AbstractAttribute &QueryingAA,
773 const AA::InstExclusionSetTy *ExclusionSet,
774 std::function<bool(const Function &F)> GoBackwardsCB) {
775 return ::isPotentiallyReachable(A, FromI, /* ToI */ nullptr, ToFn, QueryingAA,
776 ExclusionSet, GoBackwardsCB);
777}
778
779bool AA::isAssumedThreadLocalObject(Attributor &A, Value &Obj,
780 const AbstractAttribute &QueryingAA) {
781 if (isa<UndefValue>(Obj))
782 return true;
783 if (isa<AllocaInst>(Obj)) {
784 InformationCache &InfoCache = A.getInfoCache();
785 if (!InfoCache.stackIsAccessibleByOtherThreads()) {
786 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; stack objects are thread local.\n"
; } } while (false)
787 dbgs() << "[AA] Object '" << Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; stack objects are thread local.\n"
; } } while (false)
788 << "' is thread local; stack objects are thread local.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; stack objects are thread local.\n"
; } } while (false)
;
789 return true;
790 }
791 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
792 QueryingAA, IRPosition::value(Obj), DepClassTy::OPTIONAL);
793 LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is " << (NoCaptureAA.isAssumedNoCapture() ?
"" : "not") << " thread local; " << (NoCaptureAA
.isAssumedNoCapture() ? "non-" : "") << "captured stack object.\n"
; } } while (false)
794 << (NoCaptureAA.isAssumedNoCapture() ? "" : "not")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is " << (NoCaptureAA.isAssumedNoCapture() ?
"" : "not") << " thread local; " << (NoCaptureAA
.isAssumedNoCapture() ? "non-" : "") << "captured stack object.\n"
; } } while (false)
795 << " thread local; "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is " << (NoCaptureAA.isAssumedNoCapture() ?
"" : "not") << " thread local; " << (NoCaptureAA
.isAssumedNoCapture() ? "non-" : "") << "captured stack object.\n"
; } } while (false)
796 << (NoCaptureAA.isAssumedNoCapture() ? "non-" : "")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is " << (NoCaptureAA.isAssumedNoCapture() ?
"" : "not") << " thread local; " << (NoCaptureAA
.isAssumedNoCapture() ? "non-" : "") << "captured stack object.\n"
; } } while (false)
797 << "captured stack object.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is " << (NoCaptureAA.isAssumedNoCapture() ?
"" : "not") << " thread local; " << (NoCaptureAA
.isAssumedNoCapture() ? "non-" : "") << "captured stack object.\n"
; } } while (false)
;
798 return NoCaptureAA.isAssumedNoCapture();
799 }
800 if (auto *GV = dyn_cast<GlobalVariable>(&Obj)) {
801 if (GV->isConstant()) {
802 LLVM_DEBUG(dbgs() << "[AA] Object '" << Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; constant global\n"; } } while (
false)
803 << "' is thread local; constant global\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; constant global\n"; } } while (
false)
;
804 return true;
805 }
806 if (GV->isThreadLocal()) {
807 LLVM_DEBUG(dbgs() << "[AA] Object '" << Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; thread local global\n"; } } while
(false)
808 << "' is thread local; thread local global\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; thread local global\n"; } } while
(false)
;
809 return true;
810 }
811 }
812
813 if (A.getInfoCache().targetIsGPU()) {
814 if (Obj.getType()->getPointerAddressSpace() ==
815 (int)AA::GPUAddressSpace::Local) {
816 LLVM_DEBUG(dbgs() << "[AA] Object '" << Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; GPU local memory\n"; } } while (
false)
817 << "' is thread local; GPU local memory\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; GPU local memory\n"; } } while (
false)
;
818 return true;
819 }
820 if (Obj.getType()->getPointerAddressSpace() ==
821 (int)AA::GPUAddressSpace::Constant) {
822 LLVM_DEBUG(dbgs() << "[AA] Object '" << Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; GPU constant memory\n"; } } while
(false)
823 << "' is thread local; GPU constant memory\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is thread local; GPU constant memory\n"; } } while
(false)
;
824 return true;
825 }
826 }
827
828 LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is not thread local\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Object '" << Obj
<< "' is not thread local\n"; } } while (false)
;
829 return false;
830}
831
832bool AA::isPotentiallyAffectedByBarrier(Attributor &A, const Instruction &I,
833 const AbstractAttribute &QueryingAA) {
834 if (!I.mayHaveSideEffects() && !I.mayReadFromMemory())
835 return false;
836
837 SmallSetVector<const Value *, 8> Ptrs;
838
839 auto AddLocationPtr = [&](std::optional<MemoryLocation> Loc) {
840 if (!Loc || !Loc->Ptr) {
841 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Access to unknown location; -> requires barriers\n"
; } } while (false)
842 dbgs() << "[AA] Access to unknown location; -> requires barriers\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Access to unknown location; -> requires barriers\n"
; } } while (false)
;
843 return false;
844 }
845 Ptrs.insert(Loc->Ptr);
846 return true;
847 };
848
849 if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&I)) {
850 if (!AddLocationPtr(MemoryLocation::getForDest(MI)))
851 return true;
852 if (const MemTransferInst *MTI = dyn_cast<MemTransferInst>(&I))
853 if (!AddLocationPtr(MemoryLocation::getForSource(MTI)))
854 return true;
855 } else if (!AddLocationPtr(MemoryLocation::getOrNone(&I)))
856 return true;
857
858 return isPotentiallyAffectedByBarrier(A, Ptrs.getArrayRef(), QueryingAA, &I);
859}
860
861bool AA::isPotentiallyAffectedByBarrier(Attributor &A,
862 ArrayRef<const Value *> Ptrs,
863 const AbstractAttribute &QueryingAA,
864 const Instruction *CtxI) {
865 for (const Value *Ptr : Ptrs) {
866 if (!Ptr) {
867 LLVM_DEBUG(dbgs() << "[AA] nullptr; -> requires barriers\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] nullptr; -> requires barriers\n"
; } } while (false)
;
868 return true;
869 }
870
871 auto Pred = [&](Value &Obj) {
872 if (AA::isAssumedThreadLocalObject(A, Obj, QueryingAA))
873 return true;
874 LLVM_DEBUG(dbgs() << "[AA] Access to '" << Obj << "' via '" << *Ptrdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Access to '" <<
Obj << "' via '" << *Ptr << "'; -> requires barrier\n"
; } } while (false)
875 << "'; -> requires barrier\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AA] Access to '" <<
Obj << "' via '" << *Ptr << "'; -> requires barrier\n"
; } } while (false)
;
876 return false;
877 };
878
879 const auto &UnderlyingObjsAA = A.getAAFor<AAUnderlyingObjects>(
880 QueryingAA, IRPosition::value(*Ptr), DepClassTy::OPTIONAL);
881 if (!UnderlyingObjsAA.forallUnderlyingObjects(Pred))
882 return true;
883 }
884 return false;
885}
886
887/// Return true if \p New is equal or worse than \p Old.
888static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
889 if (!Old.isIntAttribute())
890 return true;
891
892 return Old.getValueAsInt() >= New.getValueAsInt();
893}
894
895/// Return true if the information provided by \p Attr was added to the
896/// attribute list \p Attrs. This is only the case if it was not already present
897/// in \p Attrs at the position describe by \p PK and \p AttrIdx.
898static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
899 AttributeList &Attrs, int AttrIdx,
900 bool ForceReplace = false) {
901
902 if (Attr.isEnumAttribute()) {
903 Attribute::AttrKind Kind = Attr.getKindAsEnum();
904 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
905 if (!ForceReplace &&
906 isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind)))
907 return false;
908 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
909 return true;
910 }
911 if (Attr.isStringAttribute()) {
912 StringRef Kind = Attr.getKindAsString();
913 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
914 if (!ForceReplace &&
915 isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind)))
916 return false;
917 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
918 return true;
919 }
920 if (Attr.isIntAttribute()) {
921 Attribute::AttrKind Kind = Attr.getKindAsEnum();
922 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
923 if (!ForceReplace &&
924 isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind)))
925 return false;
926 Attrs = Attrs.removeAttributeAtIndex(Ctx, AttrIdx, Kind);
927 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
928 return true;
929 }
930
931 llvm_unreachable("Expected enum or string attribute!")::llvm::llvm_unreachable_internal("Expected enum or string attribute!"
, "llvm/lib/Transforms/IPO/Attributor.cpp", 931)
;
932}
933
934Argument *IRPosition::getAssociatedArgument() const {
935 if (getPositionKind() == IRP_ARGUMENT)
936 return cast<Argument>(&getAnchorValue());
937
938 // Not an Argument and no argument number means this is not a call site
939 // argument, thus we cannot find a callback argument to return.
940 int ArgNo = getCallSiteArgNo();
941 if (ArgNo < 0)
942 return nullptr;
943
944 // Use abstract call sites to make the connection between the call site
945 // values and the ones in callbacks. If a callback was found that makes use
946 // of the underlying call site operand, we want the corresponding callback
947 // callee argument and not the direct callee argument.
948 std::optional<Argument *> CBCandidateArg;
949 SmallVector<const Use *, 4> CallbackUses;
950 const auto &CB = cast<CallBase>(getAnchorValue());
951 AbstractCallSite::getCallbackUses(CB, CallbackUses);
952 for (const Use *U : CallbackUses) {
953 AbstractCallSite ACS(U);
954 assert(ACS && ACS.isCallbackCall())(static_cast <bool> (ACS && ACS.isCallbackCall(
)) ? void (0) : __assert_fail ("ACS && ACS.isCallbackCall()"
, "llvm/lib/Transforms/IPO/Attributor.cpp", 954, __extension__
__PRETTY_FUNCTION__))
;
955 if (!ACS.getCalledFunction())
956 continue;
957
958 for (unsigned u = 0, e = ACS.getNumArgOperands(); u < e; u++) {
959
960 // Test if the underlying call site operand is argument number u of the
961 // callback callee.
962 if (ACS.getCallArgOperandNo(u) != ArgNo)
963 continue;
964
965 assert(ACS.getCalledFunction()->arg_size() > u &&(static_cast <bool> (ACS.getCalledFunction()->arg_size
() > u && "ACS mapped into var-args arguments!") ?
void (0) : __assert_fail ("ACS.getCalledFunction()->arg_size() > u && \"ACS mapped into var-args arguments!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 966, __extension__
__PRETTY_FUNCTION__))
966 "ACS mapped into var-args arguments!")(static_cast <bool> (ACS.getCalledFunction()->arg_size
() > u && "ACS mapped into var-args arguments!") ?
void (0) : __assert_fail ("ACS.getCalledFunction()->arg_size() > u && \"ACS mapped into var-args arguments!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 966, __extension__
__PRETTY_FUNCTION__))
;
967 if (CBCandidateArg) {
968 CBCandidateArg = nullptr;
969 break;
970 }
971 CBCandidateArg = ACS.getCalledFunction()->getArg(u);
972 }
973 }
974
975 // If we found a unique callback candidate argument, return it.
976 if (CBCandidateArg && *CBCandidateArg)
977 return *CBCandidateArg;
978
979 // If no callbacks were found, or none used the underlying call site operand
980 // exclusively, use the direct callee argument if available.
981 const Function *Callee = CB.getCalledFunction();
982 if (Callee && Callee->arg_size() > unsigned(ArgNo))
983 return Callee->getArg(ArgNo);
984
985 return nullptr;
986}
987
988ChangeStatus AbstractAttribute::update(Attributor &A) {
989 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
990 if (getState().isAtFixpoint())
991 return HasChanged;
992
993 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Update: " <<
*this << "\n"; } } while (false)
;
994
995 HasChanged = updateImpl(A);
996
997 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *thisdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Update " <<
HasChanged << " " << *this << "\n"; } } while
(false)
998 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Update " <<
HasChanged << " " << *this << "\n"; } } while
(false)
;
999
1000 return HasChanged;
1001}
1002
1003ChangeStatus
1004IRAttributeManifest::manifestAttrs(Attributor &A, const IRPosition &IRP,
1005 const ArrayRef<Attribute> &DeducedAttrs,
1006 bool ForceReplace) {
1007 Function *ScopeFn = IRP.getAnchorScope();
1008 IRPosition::Kind PK = IRP.getPositionKind();
1009
1010 // In the following some generic code that will manifest attributes in
1011 // DeducedAttrs if they improve the current IR. Due to the different
1012 // annotation positions we use the underlying AttributeList interface.
1013
1014 AttributeList Attrs;
1015 switch (PK) {
1016 case IRPosition::IRP_INVALID:
1017 case IRPosition::IRP_FLOAT:
1018 return ChangeStatus::UNCHANGED;
1019 case IRPosition::IRP_ARGUMENT:
1020 case IRPosition::IRP_FUNCTION:
1021 case IRPosition::IRP_RETURNED:
1022 Attrs = ScopeFn->getAttributes();
1023 break;
1024 case IRPosition::IRP_CALL_SITE:
1025 case IRPosition::IRP_CALL_SITE_RETURNED:
1026 case IRPosition::IRP_CALL_SITE_ARGUMENT:
1027 Attrs = cast<CallBase>(IRP.getAnchorValue()).getAttributes();
1028 break;
1029 }
1030
1031 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
1032 LLVMContext &Ctx = IRP.getAnchorValue().getContext();
1033 for (const Attribute &Attr : DeducedAttrs) {
1034 if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx(), ForceReplace))
1035 continue;
1036
1037 HasChanged = ChangeStatus::CHANGED;
1038 }
1039
1040 if (HasChanged == ChangeStatus::UNCHANGED)
1041 return HasChanged;
1042
1043 switch (PK) {
1044 case IRPosition::IRP_ARGUMENT:
1045 case IRPosition::IRP_FUNCTION:
1046 case IRPosition::IRP_RETURNED:
1047 ScopeFn->setAttributes(Attrs);
1048 break;
1049 case IRPosition::IRP_CALL_SITE:
1050 case IRPosition::IRP_CALL_SITE_RETURNED:
1051 case IRPosition::IRP_CALL_SITE_ARGUMENT:
1052 cast<CallBase>(IRP.getAnchorValue()).setAttributes(Attrs);
1053 break;
1054 case IRPosition::IRP_INVALID:
1055 case IRPosition::IRP_FLOAT:
1056 break;
1057 }
1058
1059 return HasChanged;
1060}
1061
1062const IRPosition IRPosition::EmptyKey(DenseMapInfo<void *>::getEmptyKey());
1063const IRPosition
1064 IRPosition::TombstoneKey(DenseMapInfo<void *>::getTombstoneKey());
1065
1066SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) {
1067 IRPositions.emplace_back(IRP);
1068
1069 // Helper to determine if operand bundles on a call site are benin or
1070 // potentially problematic. We handle only llvm.assume for now.
1071 auto CanIgnoreOperandBundles = [](const CallBase &CB) {
1072 return (isa<IntrinsicInst>(CB) &&
1073 cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume);
1074 };
1075
1076 const auto *CB = dyn_cast<CallBase>(&IRP.getAnchorValue());
1077 switch (IRP.getPositionKind()) {
1078 case IRPosition::IRP_INVALID:
1079 case IRPosition::IRP_FLOAT:
1080 case IRPosition::IRP_FUNCTION:
1081 return;
1082 case IRPosition::IRP_ARGUMENT:
1083 case IRPosition::IRP_RETURNED:
1084 IRPositions.emplace_back(IRPosition::function(*IRP.getAnchorScope()));
1085 return;
1086 case IRPosition::IRP_CALL_SITE:
1087 assert(CB && "Expected call site!")(static_cast <bool> (CB && "Expected call site!"
) ? void (0) : __assert_fail ("CB && \"Expected call site!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1087, __extension__
__PRETTY_FUNCTION__))
;
1088 // TODO: We need to look at the operand bundles similar to the redirection
1089 // in CallBase.
1090 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
1091 if (const Function *Callee = CB->getCalledFunction())
1092 IRPositions.emplace_back(IRPosition::function(*Callee));
1093 return;
1094 case IRPosition::IRP_CALL_SITE_RETURNED:
1095 assert(CB && "Expected call site!")(static_cast <bool> (CB && "Expected call site!"
) ? void (0) : __assert_fail ("CB && \"Expected call site!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1095, __extension__
__PRETTY_FUNCTION__))
;
1096 // TODO: We need to look at the operand bundles similar to the redirection
1097 // in CallBase.
1098 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1099 if (const Function *Callee = CB->getCalledFunction()) {
1100 IRPositions.emplace_back(IRPosition::returned(*Callee));
1101 IRPositions.emplace_back(IRPosition::function(*Callee));
1102 for (const Argument &Arg : Callee->args())
1103 if (Arg.hasReturnedAttr()) {
1104 IRPositions.emplace_back(
1105 IRPosition::callsite_argument(*CB, Arg.getArgNo()));
1106 IRPositions.emplace_back(
1107 IRPosition::value(*CB->getArgOperand(Arg.getArgNo())));
1108 IRPositions.emplace_back(IRPosition::argument(Arg));
1109 }
1110 }
1111 }
1112 IRPositions.emplace_back(IRPosition::callsite_function(*CB));
1113 return;
1114 case IRPosition::IRP_CALL_SITE_ARGUMENT: {
1115 assert(CB && "Expected call site!")(static_cast <bool> (CB && "Expected call site!"
) ? void (0) : __assert_fail ("CB && \"Expected call site!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1115, __extension__
__PRETTY_FUNCTION__))
;
1116 // TODO: We need to look at the operand bundles similar to the redirection
1117 // in CallBase.
1118 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1119 const Function *Callee = CB->getCalledFunction();
1120 if (Callee) {
1121 if (Argument *Arg = IRP.getAssociatedArgument())
1122 IRPositions.emplace_back(IRPosition::argument(*Arg));
1123 IRPositions.emplace_back(IRPosition::function(*Callee));
1124 }
1125 }
1126 IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue()));
1127 return;
1128 }
1129 }
1130}
1131
1132bool IRPosition::hasAttr(ArrayRef<Attribute::AttrKind> AKs,
1133 bool IgnoreSubsumingPositions, Attributor *A) const {
1134 SmallVector<Attribute, 4> Attrs;
1135 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this)) {
1136 for (Attribute::AttrKind AK : AKs)
1137 if (EquivIRP.getAttrsFromIRAttr(AK, Attrs))
1138 return true;
1139 // The first position returned by the SubsumingPositionIterator is
1140 // always the position itself. If we ignore subsuming positions we
1141 // are done after the first iteration.
1142 if (IgnoreSubsumingPositions)
1143 break;
1144 }
1145 if (A)
1146 for (Attribute::AttrKind AK : AKs)
1147 if (getAttrsFromAssumes(AK, Attrs, *A))
1148 return true;
1149 return false;
1150}
1151
1152void IRPosition::getAttrs(ArrayRef<Attribute::AttrKind> AKs,
1153 SmallVectorImpl<Attribute> &Attrs,
1154 bool IgnoreSubsumingPositions, Attributor *A) const {
1155 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this)) {
1156 for (Attribute::AttrKind AK : AKs)
1157 EquivIRP.getAttrsFromIRAttr(AK, Attrs);
1158 // The first position returned by the SubsumingPositionIterator is
1159 // always the position itself. If we ignore subsuming positions we
1160 // are done after the first iteration.
1161 if (IgnoreSubsumingPositions)
1162 break;
1163 }
1164 if (A)
1165 for (Attribute::AttrKind AK : AKs)
1166 getAttrsFromAssumes(AK, Attrs, *A);
1167}
1168
1169bool IRPosition::getAttrsFromIRAttr(Attribute::AttrKind AK,
1170 SmallVectorImpl<Attribute> &Attrs) const {
1171 if (getPositionKind() == IRP_INVALID || getPositionKind() == IRP_FLOAT)
1172 return false;
1173
1174 AttributeList AttrList;
1175 if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue()))
1176 AttrList = CB->getAttributes();
1177 else
1178 AttrList = getAssociatedFunction()->getAttributes();
1179
1180 bool HasAttr = AttrList.hasAttributeAtIndex(getAttrIdx(), AK);
1181 if (HasAttr)
1182 Attrs.push_back(AttrList.getAttributeAtIndex(getAttrIdx(), AK));
1183 return HasAttr;
1184}
1185
1186bool IRPosition::getAttrsFromAssumes(Attribute::AttrKind AK,
1187 SmallVectorImpl<Attribute> &Attrs,
1188 Attributor &A) const {
1189 assert(getPositionKind() != IRP_INVALID && "Did expect a valid position!")(static_cast <bool> (getPositionKind() != IRP_INVALID &&
"Did expect a valid position!") ? void (0) : __assert_fail (
"getPositionKind() != IRP_INVALID && \"Did expect a valid position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1189, __extension__
__PRETTY_FUNCTION__))
;
1190 Value &AssociatedValue = getAssociatedValue();
1191
1192 const Assume2KnowledgeMap &A2K =
1193 A.getInfoCache().getKnowledgeMap().lookup({&AssociatedValue, AK});
1194
1195 // Check if we found any potential assume use, if not we don't need to create
1196 // explorer iterators.
1197 if (A2K.empty())
1198 return false;
1199
1200 LLVMContext &Ctx = AssociatedValue.getContext();
1201 unsigned AttrsSize = Attrs.size();
1202 MustBeExecutedContextExplorer &Explorer =
1203 A.getInfoCache().getMustBeExecutedContextExplorer();
1204 auto EIt = Explorer.begin(getCtxI()), EEnd = Explorer.end(getCtxI());
1205 for (const auto &It : A2K)
1206 if (Explorer.findInContextOf(It.first, EIt, EEnd))
1207 Attrs.push_back(Attribute::get(Ctx, AK, It.second.Max));
1208 return AttrsSize != Attrs.size();
1209}
1210
1211void IRPosition::verify() {
1212#ifdef EXPENSIVE_CHECKS
1213 switch (getPositionKind()) {
1214 case IRP_INVALID:
1215 assert((CBContext == nullptr) &&(static_cast <bool> ((CBContext == nullptr) && "Invalid position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"Invalid position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1216, __extension__
__PRETTY_FUNCTION__))
1216 "Invalid position must not have CallBaseContext!")(static_cast <bool> ((CBContext == nullptr) && "Invalid position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"Invalid position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1216, __extension__
__PRETTY_FUNCTION__))
;
1217 assert(!Enc.getOpaqueValue() &&(static_cast <bool> (!Enc.getOpaqueValue() && "Expected a nullptr for an invalid position!"
) ? void (0) : __assert_fail ("!Enc.getOpaqueValue() && \"Expected a nullptr for an invalid position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1218, __extension__
__PRETTY_FUNCTION__))
1218 "Expected a nullptr for an invalid position!")(static_cast <bool> (!Enc.getOpaqueValue() && "Expected a nullptr for an invalid position!"
) ? void (0) : __assert_fail ("!Enc.getOpaqueValue() && \"Expected a nullptr for an invalid position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1218, __extension__
__PRETTY_FUNCTION__))
;
1219 return;
1220 case IRP_FLOAT:
1221 assert((!isa<Argument>(&getAssociatedValue())) &&(static_cast <bool> ((!isa<Argument>(&getAssociatedValue
())) && "Expected specialized kind for argument values!"
) ? void (0) : __assert_fail ("(!isa<Argument>(&getAssociatedValue())) && \"Expected specialized kind for argument values!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1222, __extension__
__PRETTY_FUNCTION__))
1222 "Expected specialized kind for argument values!")(static_cast <bool> ((!isa<Argument>(&getAssociatedValue
())) && "Expected specialized kind for argument values!"
) ? void (0) : __assert_fail ("(!isa<Argument>(&getAssociatedValue())) && \"Expected specialized kind for argument values!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1222, __extension__
__PRETTY_FUNCTION__))
;
1223 return;
1224 case IRP_RETURNED:
1225 assert(isa<Function>(getAsValuePtr()) &&(static_cast <bool> (isa<Function>(getAsValuePtr(
)) && "Expected function for a 'returned' position!")
? void (0) : __assert_fail ("isa<Function>(getAsValuePtr()) && \"Expected function for a 'returned' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1226, __extension__
__PRETTY_FUNCTION__))
1226 "Expected function for a 'returned' position!")(static_cast <bool> (isa<Function>(getAsValuePtr(
)) && "Expected function for a 'returned' position!")
? void (0) : __assert_fail ("isa<Function>(getAsValuePtr()) && \"Expected function for a 'returned' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1226, __extension__
__PRETTY_FUNCTION__))
;
1227 assert(getAsValuePtr() == &getAssociatedValue() &&(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1228, __extension__
__PRETTY_FUNCTION__))
1228 "Associated value mismatch!")(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1228, __extension__
__PRETTY_FUNCTION__))
;
1229 return;
1230 case IRP_CALL_SITE_RETURNED:
1231 assert((CBContext == nullptr) &&(static_cast <bool> ((CBContext == nullptr) && "'call site returned' position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"'call site returned' position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1232, __extension__
__PRETTY_FUNCTION__))
1232 "'call site returned' position must not have CallBaseContext!")(static_cast <bool> ((CBContext == nullptr) && "'call site returned' position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"'call site returned' position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1232, __extension__
__PRETTY_FUNCTION__))
;
1233 assert((isa<CallBase>(getAsValuePtr())) &&(static_cast <bool> ((isa<CallBase>(getAsValuePtr
())) && "Expected call base for 'call site returned' position!"
) ? void (0) : __assert_fail ("(isa<CallBase>(getAsValuePtr())) && \"Expected call base for 'call site returned' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1234, __extension__
__PRETTY_FUNCTION__))
1234 "Expected call base for 'call site returned' position!")(static_cast <bool> ((isa<CallBase>(getAsValuePtr
())) && "Expected call base for 'call site returned' position!"
) ? void (0) : __assert_fail ("(isa<CallBase>(getAsValuePtr())) && \"Expected call base for 'call site returned' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1234, __extension__
__PRETTY_FUNCTION__))
;
1235 assert(getAsValuePtr() == &getAssociatedValue() &&(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1236, __extension__
__PRETTY_FUNCTION__))
1236 "Associated value mismatch!")(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1236, __extension__
__PRETTY_FUNCTION__))
;
1237 return;
1238 case IRP_CALL_SITE:
1239 assert((CBContext == nullptr) &&(static_cast <bool> ((CBContext == nullptr) && "'call site function' position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"'call site function' position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1240, __extension__
__PRETTY_FUNCTION__))
1240 "'call site function' position must not have CallBaseContext!")(static_cast <bool> ((CBContext == nullptr) && "'call site function' position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"'call site function' position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1240, __extension__
__PRETTY_FUNCTION__))
;
1241 assert((isa<CallBase>(getAsValuePtr())) &&(static_cast <bool> ((isa<CallBase>(getAsValuePtr
())) && "Expected call base for 'call site function' position!"
) ? void (0) : __assert_fail ("(isa<CallBase>(getAsValuePtr())) && \"Expected call base for 'call site function' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1242, __extension__
__PRETTY_FUNCTION__))
1242 "Expected call base for 'call site function' position!")(static_cast <bool> ((isa<CallBase>(getAsValuePtr
())) && "Expected call base for 'call site function' position!"
) ? void (0) : __assert_fail ("(isa<CallBase>(getAsValuePtr())) && \"Expected call base for 'call site function' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1242, __extension__
__PRETTY_FUNCTION__))
;
1243 assert(getAsValuePtr() == &getAssociatedValue() &&(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1244, __extension__
__PRETTY_FUNCTION__))
1244 "Associated value mismatch!")(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1244, __extension__
__PRETTY_FUNCTION__))
;
1245 return;
1246 case IRP_FUNCTION:
1247 assert(isa<Function>(getAsValuePtr()) &&(static_cast <bool> (isa<Function>(getAsValuePtr(
)) && "Expected function for a 'function' position!")
? void (0) : __assert_fail ("isa<Function>(getAsValuePtr()) && \"Expected function for a 'function' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1248, __extension__
__PRETTY_FUNCTION__))
1248 "Expected function for a 'function' position!")(static_cast <bool> (isa<Function>(getAsValuePtr(
)) && "Expected function for a 'function' position!")
? void (0) : __assert_fail ("isa<Function>(getAsValuePtr()) && \"Expected function for a 'function' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1248, __extension__
__PRETTY_FUNCTION__))
;
1249 assert(getAsValuePtr() == &getAssociatedValue() &&(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1250, __extension__
__PRETTY_FUNCTION__))
1250 "Associated value mismatch!")(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1250, __extension__
__PRETTY_FUNCTION__))
;
1251 return;
1252 case IRP_ARGUMENT:
1253 assert(isa<Argument>(getAsValuePtr()) &&(static_cast <bool> (isa<Argument>(getAsValuePtr(
)) && "Expected argument for a 'argument' position!")
? void (0) : __assert_fail ("isa<Argument>(getAsValuePtr()) && \"Expected argument for a 'argument' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1254, __extension__
__PRETTY_FUNCTION__))
1254 "Expected argument for a 'argument' position!")(static_cast <bool> (isa<Argument>(getAsValuePtr(
)) && "Expected argument for a 'argument' position!")
? void (0) : __assert_fail ("isa<Argument>(getAsValuePtr()) && \"Expected argument for a 'argument' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1254, __extension__
__PRETTY_FUNCTION__))
;
1255 assert(getAsValuePtr() == &getAssociatedValue() &&(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1256, __extension__
__PRETTY_FUNCTION__))
1256 "Associated value mismatch!")(static_cast <bool> (getAsValuePtr() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("getAsValuePtr() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1256, __extension__
__PRETTY_FUNCTION__))
;
1257 return;
1258 case IRP_CALL_SITE_ARGUMENT: {
1259 assert((CBContext == nullptr) &&(static_cast <bool> ((CBContext == nullptr) && "'call site argument' position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"'call site argument' position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1260, __extension__
__PRETTY_FUNCTION__))
1260 "'call site argument' position must not have CallBaseContext!")(static_cast <bool> ((CBContext == nullptr) && "'call site argument' position must not have CallBaseContext!"
) ? void (0) : __assert_fail ("(CBContext == nullptr) && \"'call site argument' position must not have CallBaseContext!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1260, __extension__
__PRETTY_FUNCTION__))
;
1261 Use *U = getAsUsePtr();
1262 (void)U; // Silence unused variable warning.
1263 assert(U && "Expected use for a 'call site argument' position!")(static_cast <bool> (U && "Expected use for a 'call site argument' position!"
) ? void (0) : __assert_fail ("U && \"Expected use for a 'call site argument' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1263, __extension__
__PRETTY_FUNCTION__))
;
1264 assert(isa<CallBase>(U->getUser()) &&(static_cast <bool> (isa<CallBase>(U->getUser(
)) && "Expected call base user for a 'call site argument' position!"
) ? void (0) : __assert_fail ("isa<CallBase>(U->getUser()) && \"Expected call base user for a 'call site argument' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1265, __extension__
__PRETTY_FUNCTION__))
1265 "Expected call base user for a 'call site argument' position!")(static_cast <bool> (isa<CallBase>(U->getUser(
)) && "Expected call base user for a 'call site argument' position!"
) ? void (0) : __assert_fail ("isa<CallBase>(U->getUser()) && \"Expected call base user for a 'call site argument' position!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1265, __extension__
__PRETTY_FUNCTION__))
;
1266 assert(cast<CallBase>(U->getUser())->isArgOperand(U) &&(static_cast <bool> (cast<CallBase>(U->getUser
())->isArgOperand(U) && "Expected call base argument operand for a 'call site argument' "
"position") ? void (0) : __assert_fail ("cast<CallBase>(U->getUser())->isArgOperand(U) && \"Expected call base argument operand for a 'call site argument' \" \"position\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1268, __extension__
__PRETTY_FUNCTION__))
1267 "Expected call base argument operand for a 'call site argument' "(static_cast <bool> (cast<CallBase>(U->getUser
())->isArgOperand(U) && "Expected call base argument operand for a 'call site argument' "
"position") ? void (0) : __assert_fail ("cast<CallBase>(U->getUser())->isArgOperand(U) && \"Expected call base argument operand for a 'call site argument' \" \"position\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1268, __extension__
__PRETTY_FUNCTION__))
1268 "position")(static_cast <bool> (cast<CallBase>(U->getUser
())->isArgOperand(U) && "Expected call base argument operand for a 'call site argument' "
"position") ? void (0) : __assert_fail ("cast<CallBase>(U->getUser())->isArgOperand(U) && \"Expected call base argument operand for a 'call site argument' \" \"position\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1268, __extension__
__PRETTY_FUNCTION__))
;
1269 assert(cast<CallBase>(U->getUser())->getArgOperandNo(U) ==(static_cast <bool> (cast<CallBase>(U->getUser
())->getArgOperandNo(U) == unsigned(getCallSiteArgNo()) &&
"Argument number mismatch!") ? void (0) : __assert_fail ("cast<CallBase>(U->getUser())->getArgOperandNo(U) == unsigned(getCallSiteArgNo()) && \"Argument number mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1271, __extension__
__PRETTY_FUNCTION__))
1270 unsigned(getCallSiteArgNo()) &&(static_cast <bool> (cast<CallBase>(U->getUser
())->getArgOperandNo(U) == unsigned(getCallSiteArgNo()) &&
"Argument number mismatch!") ? void (0) : __assert_fail ("cast<CallBase>(U->getUser())->getArgOperandNo(U) == unsigned(getCallSiteArgNo()) && \"Argument number mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1271, __extension__
__PRETTY_FUNCTION__))
1271 "Argument number mismatch!")(static_cast <bool> (cast<CallBase>(U->getUser
())->getArgOperandNo(U) == unsigned(getCallSiteArgNo()) &&
"Argument number mismatch!") ? void (0) : __assert_fail ("cast<CallBase>(U->getUser())->getArgOperandNo(U) == unsigned(getCallSiteArgNo()) && \"Argument number mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1271, __extension__
__PRETTY_FUNCTION__))
;
1272 assert(U->get() == &getAssociatedValue() && "Associated value mismatch!")(static_cast <bool> (U->get() == &getAssociatedValue
() && "Associated value mismatch!") ? void (0) : __assert_fail
("U->get() == &getAssociatedValue() && \"Associated value mismatch!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1272, __extension__
__PRETTY_FUNCTION__))
;
1273 return;
1274 }
1275 }
1276#endif
1277}
1278
1279std::optional<Constant *>
1280Attributor::getAssumedConstant(const IRPosition &IRP,
1281 const AbstractAttribute &AA,
1282 bool &UsedAssumedInformation) {
1283 // First check all callbacks provided by outside AAs. If any of them returns
1284 // a non-null value that is different from the associated value, or
1285 // std::nullopt, we assume it's simplified.
1286 for (auto &CB : SimplificationCallbacks.lookup(IRP)) {
1287 std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);
1288 if (!SimplifiedV)
1289 return std::nullopt;
1290 if (isa_and_nonnull<Constant>(*SimplifiedV))
1291 return cast<Constant>(*SimplifiedV);
1292 return nullptr;
1293 }
1294 if (auto *C = dyn_cast<Constant>(&IRP.getAssociatedValue()))
1295 return C;
1296 SmallVector<AA::ValueAndContext> Values;
1297 if (getAssumedSimplifiedValues(IRP, &AA, Values,
1298 AA::ValueScope::Interprocedural,
1299 UsedAssumedInformation)) {
1300 if (Values.empty())
1301 return std::nullopt;
1302 if (auto *C = dyn_cast_or_null<Constant>(
1303 AAPotentialValues::getSingleValue(*this, AA, IRP, Values)))
1304 return C;
1305 }
1306 return nullptr;
1307}
1308
1309std::optional<Value *> Attributor::getAssumedSimplified(
1310 const IRPosition &IRP, const AbstractAttribute *AA,
1311 bool &UsedAssumedInformation, AA::ValueScope S) {
1312 // First check all callbacks provided by outside AAs. If any of them returns
1313 // a non-null value that is different from the associated value, or
1314 // std::nullopt, we assume it's simplified.
1315 for (auto &CB : SimplificationCallbacks.lookup(IRP))
1316 return CB(IRP, AA, UsedAssumedInformation);
1317
1318 SmallVector<AA::ValueAndContext> Values;
1319 if (!getAssumedSimplifiedValues(IRP, AA, Values, S, UsedAssumedInformation))
1320 return &IRP.getAssociatedValue();
1321 if (Values.empty())
1322 return std::nullopt;
1323 if (AA)
1324 if (Value *V = AAPotentialValues::getSingleValue(*this, *AA, IRP, Values))
1325 return V;
1326 if (IRP.getPositionKind() == IRPosition::IRP_RETURNED ||
1327 IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED)
1328 return nullptr;
1329 return &IRP.getAssociatedValue();
1330}
1331
1332bool Attributor::getAssumedSimplifiedValues(
1333 const IRPosition &IRP, const AbstractAttribute *AA,
1334 SmallVectorImpl<AA::ValueAndContext> &Values, AA::ValueScope S,
1335 bool &UsedAssumedInformation) {
1336 // First check all callbacks provided by outside AAs. If any of them returns
1337 // a non-null value that is different from the associated value, or
1338 // std::nullopt, we assume it's simplified.
1339 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1340 for (const auto &CB : SimplificationCBs) {
1341 std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);
1342 if (!CBResult.has_value())
1343 continue;
1344 Value *V = *CBResult;
1345 if (!V)
1346 return false;
1347 if ((S & AA::ValueScope::Interprocedural) ||
1348 AA::isValidInScope(*V, IRP.getAnchorScope()))
1349 Values.push_back(AA::ValueAndContext{*V, nullptr});
1350 else
1351 return false;
1352 }
1353 if (!SimplificationCBs.empty())
1354 return true;
1355
1356 // If no high-level/outside simplification occurred, use AAPotentialValues.
1357 const auto &PotentialValuesAA =
1358 getOrCreateAAFor<AAPotentialValues>(IRP, AA, DepClassTy::OPTIONAL);
1359 if (!PotentialValuesAA.getAssumedSimplifiedValues(*this, Values, S))
1360 return false;
1361 UsedAssumedInformation |= !PotentialValuesAA.isAtFixpoint();
1362 return true;
1363}
1364
1365std::optional<Value *> Attributor::translateArgumentToCallSiteContent(
1366 std::optional<Value *> V, CallBase &CB, const AbstractAttribute &AA,
1367 bool &UsedAssumedInformation) {
1368 if (!V)
1369 return V;
1370 if (*V == nullptr || isa<Constant>(*V))
1371 return V;
1372 if (auto *Arg = dyn_cast<Argument>(*V))
1373 if (CB.getCalledFunction() == Arg->getParent())
1374 if (!Arg->hasPointeeInMemoryValueAttr())
1375 return getAssumedSimplified(
1376 IRPosition::callsite_argument(CB, Arg->getArgNo()), AA,
1377 UsedAssumedInformation, AA::Intraprocedural);
1378 return nullptr;
1379}
1380
1381Attributor::~Attributor() {
1382 // The abstract attributes are allocated via the BumpPtrAllocator Allocator,
1383 // thus we cannot delete them. We can, and want to, destruct them though.
1384 for (auto &It : AAMap) {
1385 AbstractAttribute *AA = It.getSecond();
1386 AA->~AbstractAttribute();
1387 }
1388}
1389
1390bool Attributor::isAssumedDead(const AbstractAttribute &AA,
1391 const AAIsDead *FnLivenessAA,
1392 bool &UsedAssumedInformation,
1393 bool CheckBBLivenessOnly, DepClassTy DepClass) {
1394 const IRPosition &IRP = AA.getIRPosition();
1395 if (!Functions.count(IRP.getAnchorScope()))
1396 return false;
1397 return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
1398 CheckBBLivenessOnly, DepClass);
1399}
1400
1401bool Attributor::isAssumedDead(const Use &U,
1402 const AbstractAttribute *QueryingAA,
1403 const AAIsDead *FnLivenessAA,
1404 bool &UsedAssumedInformation,
1405 bool CheckBBLivenessOnly, DepClassTy DepClass) {
1406 Instruction *UserI = dyn_cast<Instruction>(U.getUser());
1407 if (!UserI)
1408 return isAssumedDead(IRPosition::value(*U.get()), QueryingAA, FnLivenessAA,
1409 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1410
1411 if (auto *CB = dyn_cast<CallBase>(UserI)) {
1412 // For call site argument uses we can check if the argument is
1413 // unused/dead.
1414 if (CB->isArgOperand(&U)) {
1415 const IRPosition &CSArgPos =
1416 IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
1417 return isAssumedDead(CSArgPos, QueryingAA, FnLivenessAA,
1418 UsedAssumedInformation, CheckBBLivenessOnly,
1419 DepClass);
1420 }
1421 } else if (ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
1422 const IRPosition &RetPos = IRPosition::returned(*RI->getFunction());
1423 return isAssumedDead(RetPos, QueryingAA, FnLivenessAA,
1424 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1425 } else if (PHINode *PHI = dyn_cast<PHINode>(UserI)) {
1426 BasicBlock *IncomingBB = PHI->getIncomingBlock(U);
1427 return isAssumedDead(*IncomingBB->getTerminator(), QueryingAA, FnLivenessAA,
1428 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1429 } else if (StoreInst *SI = dyn_cast<StoreInst>(UserI)) {
1430 if (!CheckBBLivenessOnly && SI->getPointerOperand() != U.get()) {
1431 const IRPosition IRP = IRPosition::inst(*SI);
1432 const AAIsDead &IsDeadAA =
1433 getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);
1434 if (IsDeadAA.isRemovableStore()) {
1435 if (QueryingAA)
1436 recordDependence(IsDeadAA, *QueryingAA, DepClass);
1437 if (!IsDeadAA.isKnown(AAIsDead::IS_REMOVABLE))
1438 UsedAssumedInformation = true;
1439 return true;
1440 }
1441 }
1442 }
1443
1444 return isAssumedDead(IRPosition::inst(*UserI), QueryingAA, FnLivenessAA,
1445 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1446}
1447
1448bool Attributor::isAssumedDead(const Instruction &I,
1449 const AbstractAttribute *QueryingAA,
1450 const AAIsDead *FnLivenessAA,
1451 bool &UsedAssumedInformation,
1452 bool CheckBBLivenessOnly, DepClassTy DepClass,
1453 bool CheckForDeadStore) {
1454 const IRPosition::CallBaseContext *CBCtx =
1455 QueryingAA ? QueryingAA->getCallBaseContext() : nullptr;
1456
1457 if (ManifestAddedBlocks.contains(I.getParent()))
1458 return false;
1459
1460 const Function &F = *I.getFunction();
1461 if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F)
1462 FnLivenessAA = &getOrCreateAAFor<AAIsDead>(IRPosition::function(F, CBCtx),
1463 QueryingAA, DepClassTy::NONE);
1464
1465 // Don't use recursive reasoning.
1466 if (QueryingAA == FnLivenessAA)
1467 return false;
1468
1469 // If we have a context instruction and a liveness AA we use it.
1470 if (CheckBBLivenessOnly ? FnLivenessAA->isAssumedDead(I.getParent())
1471 : FnLivenessAA->isAssumedDead(&I)) {
1472 if (QueryingAA)
1473 recordDependence(*FnLivenessAA, *QueryingAA, DepClass);
1474 if (!FnLivenessAA->isKnownDead(&I))
1475 UsedAssumedInformation = true;
1476 return true;
1477 }
1478
1479 if (CheckBBLivenessOnly)
1480 return false;
1481
1482 const IRPosition IRP = IRPosition::inst(I, CBCtx);
1483 const AAIsDead &IsDeadAA =
1484 getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);
1485
1486 // Don't use recursive reasoning.
1487 if (QueryingAA == &IsDeadAA)
1488 return false;
1489
1490 if (IsDeadAA.isAssumedDead()) {
1491 if (QueryingAA)
1492 recordDependence(IsDeadAA, *QueryingAA, DepClass);
1493 if (!IsDeadAA.isKnownDead())
1494 UsedAssumedInformation = true;
1495 return true;
1496 }
1497
1498 if (CheckForDeadStore && isa<StoreInst>(I) && IsDeadAA.isRemovableStore()) {
1499 if (QueryingAA)
1500 recordDependence(IsDeadAA, *QueryingAA, DepClass);
1501 if (!IsDeadAA.isKnownDead())
1502 UsedAssumedInformation = true;
1503 return true;
1504 }
1505
1506 return false;
1507}
1508
1509bool Attributor::isAssumedDead(const IRPosition &IRP,
1510 const AbstractAttribute *QueryingAA,
1511 const AAIsDead *FnLivenessAA,
1512 bool &UsedAssumedInformation,
1513 bool CheckBBLivenessOnly, DepClassTy DepClass) {
1514 // Don't check liveness for constants, e.g. functions, used as (floating)
1515 // values since the context instruction and such is here meaningless.
1516 if (IRP.getPositionKind() == IRPosition::IRP_FLOAT &&
1517 isa<Constant>(IRP.getAssociatedValue())) {
1518 return false;
1519 }
1520
1521 Instruction *CtxI = IRP.getCtxI();
1522 if (CtxI &&
1523 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
1524 /* CheckBBLivenessOnly */ true,
1525 CheckBBLivenessOnly ? DepClass : DepClassTy::OPTIONAL))
1526 return true;
1527
1528 if (CheckBBLivenessOnly)
1529 return false;
1530
1531 // If we haven't succeeded we query the specific liveness info for the IRP.
1532 const AAIsDead *IsDeadAA;
1533 if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE)
1534 IsDeadAA = &getOrCreateAAFor<AAIsDead>(
1535 IRPosition::callsite_returned(cast<CallBase>(IRP.getAssociatedValue())),
1536 QueryingAA, DepClassTy::NONE);
1537 else
1538 IsDeadAA = &getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);
1539
1540 // Don't use recursive reasoning.
1541 if (QueryingAA == IsDeadAA)
1542 return false;
1543
1544 if (IsDeadAA->isAssumedDead()) {
1545 if (QueryingAA)
1546 recordDependence(*IsDeadAA, *QueryingAA, DepClass);
1547 if (!IsDeadAA->isKnownDead())
1548 UsedAssumedInformation = true;
1549 return true;
1550 }
1551
1552 return false;
1553}
1554
1555bool Attributor::isAssumedDead(const BasicBlock &BB,
1556 const AbstractAttribute *QueryingAA,
1557 const AAIsDead *FnLivenessAA,
1558 DepClassTy DepClass) {
1559 const Function &F = *BB.getParent();
1560 if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F)
1561 FnLivenessAA = &getOrCreateAAFor<AAIsDead>(IRPosition::function(F),
1562 QueryingAA, DepClassTy::NONE);
1563
1564 // Don't use recursive reasoning.
1565 if (QueryingAA == FnLivenessAA)
1566 return false;
1567
1568 if (FnLivenessAA->isAssumedDead(&BB)) {
1569 if (QueryingAA)
1570 recordDependence(*FnLivenessAA, *QueryingAA, DepClass);
1571 return true;
1572 }
1573
1574 return false;
1575}
1576
1577bool Attributor::checkForAllUses(
1578 function_ref<bool(const Use &, bool &)> Pred,
1579 const AbstractAttribute &QueryingAA, const Value &V,
1580 bool CheckBBLivenessOnly, DepClassTy LivenessDepClass,
1581 bool IgnoreDroppableUses,
1582 function_ref<bool(const Use &OldU, const Use &NewU)> EquivalentUseCB) {
1583
1584 // Check virtual uses first.
1585 for (VirtualUseCallbackTy &CB : VirtualUseCallbacks.lookup(&V))
1586 if (!CB(*this, &QueryingAA))
1587 return false;
1588
1589 // Check the trivial case first as it catches void values.
1590 if (V.use_empty())
1591 return true;
1592
1593 const IRPosition &IRP = QueryingAA.getIRPosition();
1594 SmallVector<const Use *, 16> Worklist;
1595 SmallPtrSet<const Use *, 16> Visited;
1596
1597 auto AddUsers = [&](const Value &V, const Use *OldUse) {
1598 for (const Use &UU : V.uses()) {
1599 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1600 LLVM_DEBUG(dbgs() << "[Attributor] Potential copy was "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Potential copy was "
"rejected by the equivalence call back: " << *UU <<
"!\n"; } } while (false)
1601 "rejected by the equivalence call back: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Potential copy was "
"rejected by the equivalence call back: " << *UU <<
"!\n"; } } while (false)
1602 << *UU << "!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Potential copy was "
"rejected by the equivalence call back: " << *UU <<
"!\n"; } } while (false)
;
1603 return false;
1604 }
1605
1606 Worklist.push_back(&UU);
1607 }
1608 return true;
1609 };
1610
1611 AddUsers(V, /* OldUse */ nullptr);
1612
1613 LLVM_DEBUG(dbgs() << "[Attributor] Got " << Worklist.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Got " <<
Worklist.size() << " initial uses to check\n"; } } while
(false)
1614 << " initial uses to check\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Got " <<
Worklist.size() << " initial uses to check\n"; } } while
(false)
;
1615
1616 const Function *ScopeFn = IRP.getAnchorScope();
1617 const auto *LivenessAA =
1618 ScopeFn ? &getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*ScopeFn),
1619 DepClassTy::NONE)
1620 : nullptr;
1621
1622 while (!Worklist.empty()) {
1623 const Use *U = Worklist.pop_back_val();
1624 if (isa<PHINode>(U->getUser()) && !Visited.insert(U).second)
1625 continue;
1626 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
1627 if (auto *Fn = dyn_cast<Function>(U->getUser()))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
1628 dbgs() << "[Attributor] Check use: " << **U << " in " << Fn->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
1629 << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
1630 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
1631 dbgs() << "[Attributor] Check use: " << **U << " in " << *U->getUser()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
1632 << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
1633 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U->getUser())) dbgs() << "[Attributor] Check use: "
<< **U << " in " << Fn->getName() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
**U << " in " << *U->getUser() << "\n";
}; } } while (false)
;
1634 bool UsedAssumedInformation = false;
1635 if (isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1636 CheckBBLivenessOnly, LivenessDepClass)) {
1637 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Dead use, skip!\n"
; } } while (false)
1638 dbgs() << "[Attributor] Dead use, skip!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Dead use, skip!\n"
; } } while (false)
;
1639 continue;
1640 }
1641 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1642 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Droppable user, skip!\n"
; } } while (false)
1643 dbgs() << "[Attributor] Droppable user, skip!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Droppable user, skip!\n"
; } } while (false)
;
1644 continue;
1645 }
1646
1647 if (auto *SI = dyn_cast<StoreInst>(U->getUser())) {
1648 if (&SI->getOperandUse(0) == U) {
1649 if (!Visited.insert(U).second)
1650 continue;
1651 SmallSetVector<Value *, 4> PotentialCopies;
1652 if (AA::getPotentialCopiesOfStoredValue(
1653 *this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1654 /* OnlyExact */ true)) {
1655 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Value is stored, continue with "
<< PotentialCopies.size() << " potential copies instead!\n"
; } } while (false)
1656 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Value is stored, continue with "
<< PotentialCopies.size() << " potential copies instead!\n"
; } } while (false)
1657 << "[Attributor] Value is stored, continue with "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Value is stored, continue with "
<< PotentialCopies.size() << " potential copies instead!\n"
; } } while (false)
1658 << PotentialCopies.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Value is stored, continue with "
<< PotentialCopies.size() << " potential copies instead!\n"
; } } while (false)
1659 << " potential copies instead!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Value is stored, continue with "
<< PotentialCopies.size() << " potential copies instead!\n"
; } } while (false)
;
1660 for (Value *PotentialCopy : PotentialCopies)
1661 if (!AddUsers(*PotentialCopy, U))
1662 return false;
1663 continue;
1664 }
1665 }
1666 }
1667
1668 bool Follow = false;
1669 if (!Pred(*U, Follow))
1670 return false;
1671 if (!Follow)
1672 continue;
1673
1674 User &Usr = *U->getUser();
1675 AddUsers(Usr, /* OldUse */ nullptr);
1676
1677 auto *RI = dyn_cast<ReturnInst>(&Usr);
1678 if (!RI)
1679 continue;
1680
1681 Function &F = *RI->getFunction();
1682 auto CallSitePred = [&](AbstractCallSite ACS) {
1683 return AddUsers(*ACS.getInstruction(), U);
1684 };
1685 if (!checkForAllCallSites(CallSitePred, F, /* RequireAllCallSites */ true,
1686 &QueryingAA, UsedAssumedInformation)) {
1687 LLVM_DEBUG(dbgs() << "[Attributor] Could not follow return instruction "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Could not follow return instruction "
"to all call sites: " << *RI << "\n"; } } while (
false)
1688 "to all call sites: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Could not follow return instruction "
"to all call sites: " << *RI << "\n"; } } while (
false)
1689 << *RI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Could not follow return instruction "
"to all call sites: " << *RI << "\n"; } } while (
false)
;
1690 return false;
1691 }
1692 }
1693
1694 return true;
1695}
1696
1697bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred,
1698 const AbstractAttribute &QueryingAA,
1699 bool RequireAllCallSites,
1700 bool &UsedAssumedInformation) {
1701 // We can try to determine information from
1702 // the call sites. However, this is only possible all call sites are known,
1703 // hence the function has internal linkage.
1704 const IRPosition &IRP = QueryingAA.getIRPosition();
1705 const Function *AssociatedFunction = IRP.getAssociatedFunction();
1706 if (!AssociatedFunction) {
1707 LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRPdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] No function associated with "
<< IRP << "\n"; } } while (false)
1708 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] No function associated with "
<< IRP << "\n"; } } while (false)
;
1709 return false;
1710 }
1711
1712 return checkForAllCallSites(Pred, *AssociatedFunction, RequireAllCallSites,
1713 &QueryingAA, UsedAssumedInformation);
1714}
1715
1716bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred,
1717 const Function &Fn,
1718 bool RequireAllCallSites,
1719 const AbstractAttribute *QueryingAA,
1720 bool &UsedAssumedInformation,
1721 bool CheckPotentiallyDead) {
1722 if (RequireAllCallSites && !Fn.hasLocalLinkage()) {
1723 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function " <<
Fn.getName() << " has no internal linkage, hence not all call sites are known\n"
; } } while (false)
1724 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function " <<
Fn.getName() << " has no internal linkage, hence not all call sites are known\n"
; } } while (false)
1725 << "[Attributor] Function " << Fn.getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function " <<
Fn.getName() << " has no internal linkage, hence not all call sites are known\n"
; } } while (false)
1726 << " has no internal linkage, hence not all call sites are known\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function " <<
Fn.getName() << " has no internal linkage, hence not all call sites are known\n"
; } } while (false)
;
1727 return false;
1728 }
1729 // Check virtual uses first.
1730 for (VirtualUseCallbackTy &CB : VirtualUseCallbacks.lookup(&Fn))
1731 if (!CB(*this, QueryingAA))
1732 return false;
1733
1734 SmallVector<const Use *, 8> Uses(make_pointer_range(Fn.uses()));
1735 for (unsigned u = 0; u < Uses.size(); ++u) {
1736 const Use &U = *Uses[u];
1737 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
1738 if (auto *Fn = dyn_cast<Function>(U))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
1739 dbgs() << "[Attributor] Check use: " << Fn->getName() << " in "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
1740 << *U.getUser() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
1741 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
1742 dbgs() << "[Attributor] Check use: " << *U << " in " << *U.getUser()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
1743 << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
1744 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { if (auto *Fn = dyn_cast<Function
>(U)) dbgs() << "[Attributor] Check use: " << Fn
->getName() << " in " << *U.getUser() <<
"\n"; else dbgs() << "[Attributor] Check use: " <<
*U << " in " << *U.getUser() << "\n"; }; }
} while (false)
;
1745 if (!CheckPotentiallyDead &&
1746 isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation,
1747 /* CheckBBLivenessOnly */ true)) {
1748 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Dead use, skip!\n"
; } } while (false)
1749 dbgs() << "[Attributor] Dead use, skip!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Dead use, skip!\n"
; } } while (false)
;
1750 continue;
1751 }
1752 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
1753 if (CE->isCast() && CE->getType()->isPointerTy()) {
1754 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[Attributor] Use, is constant cast expression, add "
<< CE->getNumUses() << " uses of that expression instead!\n"
; }; } } while (false)
1755 dbgs() << "[Attributor] Use, is constant cast expression, add "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[Attributor] Use, is constant cast expression, add "
<< CE->getNumUses() << " uses of that expression instead!\n"
; }; } } while (false)
1756 << CE->getNumUses() << " uses of that expression instead!\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[Attributor] Use, is constant cast expression, add "
<< CE->getNumUses() << " uses of that expression instead!\n"
; }; } } while (false)
1757 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { { dbgs() << "[Attributor] Use, is constant cast expression, add "
<< CE->getNumUses() << " uses of that expression instead!\n"
; }; } } while (false)
;
1758 for (const Use &CEU : CE->uses())
1759 Uses.push_back(&CEU);
1760 continue;
1761 }
1762 }
1763
1764 AbstractCallSite ACS(&U);
1765 if (!ACS) {
1766 LLVM_DEBUG(dbgs() << "[Attributor] Function " << Fn.getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function " <<
Fn.getName() << " has non call site use " << *U.
get() << " in " << *U.getUser() << "\n"; } }
while (false)
1767 << " has non call site use " << *U.get() << " in "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function " <<
Fn.getName() << " has non call site use " << *U.
get() << " in " << *U.getUser() << "\n"; } }
while (false)
1768 << *U.getUser() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function " <<
Fn.getName() << " has non call site use " << *U.
get() << " in " << *U.getUser() << "\n"; } }
while (false)
;
1769 // BlockAddress users are allowed.
1770 if (isa<BlockAddress>(U.getUser()))
1771 continue;
1772 return false;
1773 }
1774
1775 const Use *EffectiveUse =
1776 ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U;
1777 if (!ACS.isCallee(EffectiveUse)) {
1778 if (!RequireAllCallSites) {
1779 LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] User " <<
*EffectiveUse->getUser() << " is not a call of " <<
Fn.getName() << ", skip use\n"; } } while (false)
1780 << " is not a call of " << Fn.getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] User " <<
*EffectiveUse->getUser() << " is not a call of " <<
Fn.getName() << ", skip use\n"; } } while (false)
1781 << ", skip use\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] User " <<
*EffectiveUse->getUser() << " is not a call of " <<
Fn.getName() << ", skip use\n"; } } while (false)
;
1782 continue;
1783 }
1784 LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] User " <<
*EffectiveUse->getUser() << " is an invalid use of "
<< Fn.getName() << "\n"; } } while (false)
1785 << " is an invalid use of " << Fn.getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] User " <<
*EffectiveUse->getUser() << " is an invalid use of "
<< Fn.getName() << "\n"; } } while (false)
;
1786 return false;
1787 }
1788
1789 // Make sure the arguments that can be matched between the call site and the
1790 // callee argee on their type. It is unlikely they do not and it doesn't
1791 // make sense for all attributes to know/care about this.
1792 assert(&Fn == ACS.getCalledFunction() && "Expected known callee")(static_cast <bool> (&Fn == ACS.getCalledFunction()
&& "Expected known callee") ? void (0) : __assert_fail
("&Fn == ACS.getCalledFunction() && \"Expected known callee\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 1792, __extension__
__PRETTY_FUNCTION__))
;
1793 unsigned MinArgsParams =
1794 std::min(size_t(ACS.getNumArgOperands()), Fn.arg_size());
1795 for (unsigned u = 0; u < MinArgsParams; ++u) {
1796 Value *CSArgOp = ACS.getCallArgOperand(u);
1797 if (CSArgOp && Fn.getArg(u)->getType() != CSArgOp->getType()) {
1798 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Call site / callee argument type mismatch ["
<< u << "@" << Fn.getName() << ": " <<
*Fn.getArg(u)->getType() << " vs. " << *ACS.getCallArgOperand
(u)->getType() << "\n"; } } while (false)
1799 dbgs() << "[Attributor] Call site / callee argument type mismatch ["do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Call site / callee argument type mismatch ["
<< u << "@" << Fn.getName() << ": " <<
*Fn.getArg(u)->getType() << " vs. " << *ACS.getCallArgOperand
(u)->getType() << "\n"; } } while (false)
1800 << u << "@" << Fn.getName() << ": "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Call site / callee argument type mismatch ["
<< u << "@" << Fn.getName() << ": " <<
*Fn.getArg(u)->getType() << " vs. " << *ACS.getCallArgOperand
(u)->getType() << "\n"; } } while (false)
1801 << *Fn.getArg(u)->getType() << " vs. "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Call site / callee argument type mismatch ["
<< u << "@" << Fn.getName() << ": " <<
*Fn.getArg(u)->getType() << " vs. " << *ACS.getCallArgOperand
(u)->getType() << "\n"; } } while (false)
1802 << *ACS.getCallArgOperand(u)->getType() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Call site / callee argument type mismatch ["
<< u << "@" << Fn.getName() << ": " <<
*Fn.getArg(u)->getType() << " vs. " << *ACS.getCallArgOperand
(u)->getType() << "\n"; } } while (false)
;
1803 return false;
1804 }
1805 }
1806
1807 if (Pred(ACS))
1808 continue;
1809
1810 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Call site callback failed for "
<< *ACS.getInstruction() << "\n"; } } while (false
)
1811 << *ACS.getInstruction() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Call site callback failed for "
<< *ACS.getInstruction() << "\n"; } } while (false
)
;
1812 return false;
1813 }
1814
1815 return true;
1816}
1817
1818bool Attributor::shouldPropagateCallBaseContext(const IRPosition &IRP) {
1819 // TODO: Maintain a cache of Values that are
1820 // on the pathway from a Argument to a Instruction that would effect the
1821 // liveness/return state etc.
1822 return EnableCallSiteSpecific;
1823}
1824
1825bool Attributor::checkForAllReturnedValuesAndReturnInsts(
1826 function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred,
1827 const AbstractAttribute &QueryingAA) {
1828
1829 const IRPosition &IRP = QueryingAA.getIRPosition();
1830 // Since we need to provide return instructions we have to have an exact
1831 // definition.
1832 const Function *AssociatedFunction = IRP.getAssociatedFunction();
1833 if (!AssociatedFunction)
1834 return false;
1835
1836 // If this is a call site query we use the call site specific return values
1837 // and liveness information.
1838 // TODO: use the function scope once we have call site AAReturnedValues.
1839 const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
1840 const auto &AARetVal =
1841 getAAFor<AAReturnedValues>(QueryingAA, QueryIRP, DepClassTy::REQUIRED);
1842 if (!AARetVal.getState().isValidState())
1843 return false;
1844
1845 return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred);
1846}
1847
1848bool Attributor::checkForAllReturnedValues(
1849 function_ref<bool(Value &)> Pred, const AbstractAttribute &QueryingAA) {
1850
1851 const IRPosition &IRP = QueryingAA.getIRPosition();
1852 const Function *AssociatedFunction = IRP.getAssociatedFunction();
1853 if (!AssociatedFunction)
1854 return false;
1855
1856 // TODO: use the function scope once we have call site AAReturnedValues.
1857 const IRPosition &QueryIRP = IRPosition::function(
1858 *AssociatedFunction, QueryingAA.getCallBaseContext());
1859 const auto &AARetVal =
1860 getAAFor<AAReturnedValues>(QueryingAA, QueryIRP, DepClassTy::REQUIRED);
1861 if (!AARetVal.getState().isValidState())
1862 return false;
1863
1864 return AARetVal.checkForAllReturnedValuesAndReturnInsts(
1865 [&](Value &RV, const SmallSetVector<ReturnInst *, 4> &) {
1866 return Pred(RV);
1867 });
1868}
1869
1870static bool checkForAllInstructionsImpl(
1871 Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap,
1872 function_ref<bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA,
1873 const AAIsDead *LivenessAA, const ArrayRef<unsigned> &Opcodes,
1874 bool &UsedAssumedInformation, bool CheckBBLivenessOnly = false,
1875 bool CheckPotentiallyDead = false) {
1876 for (unsigned Opcode : Opcodes) {
1877 // Check if we have instructions with this opcode at all first.
1878 auto *Insts = OpcodeInstMap.lookup(Opcode);
1879 if (!Insts)
1880 continue;
1881
1882 for (Instruction *I : *Insts) {
1883 // Skip dead instructions.
1884 if (A && !CheckPotentiallyDead &&
1885 A->isAssumedDead(IRPosition::inst(*I), QueryingAA, LivenessAA,
1886 UsedAssumedInformation, CheckBBLivenessOnly)) {
1887 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Instruction "
<< *I << " is potentially dead, skip!\n";; } } while
(false)
1888 dbgs() << "[Attributor] Instruction " << *Ido { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Instruction "
<< *I << " is potentially dead, skip!\n";; } } while
(false)
1889 << " is potentially dead, skip!\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] Instruction "
<< *I << " is potentially dead, skip!\n";; } } while
(false)
;
1890 continue;
1891 }
1892
1893 if (!Pred(*I))
1894 return false;
1895 }
1896 }
1897 return true;
1898}
1899
1900bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
1901 const Function *Fn,
1902 const AbstractAttribute &QueryingAA,
1903 const ArrayRef<unsigned> &Opcodes,
1904 bool &UsedAssumedInformation,
1905 bool CheckBBLivenessOnly,
1906 bool CheckPotentiallyDead) {
1907 // Since we need to provide instructions we have to have an exact definition.
1908 if (!Fn || Fn->isDeclaration())
1909 return false;
1910
1911 // TODO: use the function scope once we have call site AAReturnedValues.
1912 const IRPosition &QueryIRP = IRPosition::function(*Fn);
1913 const auto *LivenessAA =
1914 CheckPotentiallyDead
1915 ? nullptr
1916 : &(getAAFor<AAIsDead>(QueryingAA, QueryIRP, DepClassTy::NONE));
1917
1918 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
1919 if (!checkForAllInstructionsImpl(this, OpcodeInstMap, Pred, &QueryingAA,
1920 LivenessAA, Opcodes, UsedAssumedInformation,
1921 CheckBBLivenessOnly, CheckPotentiallyDead))
1922 return false;
1923
1924 return true;
1925}
1926
1927bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
1928 const AbstractAttribute &QueryingAA,
1929 const ArrayRef<unsigned> &Opcodes,
1930 bool &UsedAssumedInformation,
1931 bool CheckBBLivenessOnly,
1932 bool CheckPotentiallyDead) {
1933 const IRPosition &IRP = QueryingAA.getIRPosition();
1934 const Function *AssociatedFunction = IRP.getAssociatedFunction();
1935 return checkForAllInstructions(Pred, AssociatedFunction, QueryingAA, Opcodes,
1936 UsedAssumedInformation, CheckBBLivenessOnly,
1937 CheckPotentiallyDead);
1938}
1939
1940bool Attributor::checkForAllReadWriteInstructions(
1941 function_ref<bool(Instruction &)> Pred, AbstractAttribute &QueryingAA,
1942 bool &UsedAssumedInformation) {
1943
1944 const Function *AssociatedFunction =
1945 QueryingAA.getIRPosition().getAssociatedFunction();
1946 if (!AssociatedFunction)
1947 return false;
1948
1949 // TODO: use the function scope once we have call site AAReturnedValues.
1950 const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
1951 const auto &LivenessAA =
1952 getAAFor<AAIsDead>(QueryingAA, QueryIRP, DepClassTy::NONE);
1953
1954 for (Instruction *I :
1955 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
1956 // Skip dead instructions.
1957 if (isAssumedDead(IRPosition::inst(*I), &QueryingAA, &LivenessAA,
1958 UsedAssumedInformation))
1959 continue;
1960
1961 if (!Pred(*I))
1962 return false;
1963 }
1964
1965 return true;
1966}
1967
1968void Attributor::runTillFixpoint() {
1969 TimeTraceScope TimeScope("Attributor::runTillFixpoint");
1970 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Identified and initialized "
<< DG.SyntheticRoot.Deps.size() << " abstract attributes.\n"
; } } while (false)
1971 << DG.SyntheticRoot.Deps.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Identified and initialized "
<< DG.SyntheticRoot.Deps.size() << " abstract attributes.\n"
; } } while (false)
1972 << " abstract attributes.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Identified and initialized "
<< DG.SyntheticRoot.Deps.size() << " abstract attributes.\n"
; } } while (false)
;
1973
1974 // Now that all abstract attributes are collected and initialized we start
1975 // the abstract analysis.
1976
1977 unsigned IterationCounter = 1;
1978 unsigned MaxIterations =
1979 Configuration.MaxFixpointIterations.value_or(SetFixpointIterations);
1980
1981 SmallVector<AbstractAttribute *, 32> ChangedAAs;
1982 SetVector<AbstractAttribute *> Worklist, InvalidAAs;
1983 Worklist.insert(DG.SyntheticRoot.begin(), DG.SyntheticRoot.end());
1984
1985 do {
1986 // Remember the size to determine new attributes.
1987 size_t NumAAs = DG.SyntheticRoot.Deps.size();
1988 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounterdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n\n[Attributor] #Iteration: "
<< IterationCounter << ", Worklist size: " <<
Worklist.size() << "\n"; } } while (false)
1989 << ", Worklist size: " << Worklist.size() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n\n[Attributor] #Iteration: "
<< IterationCounter << ", Worklist size: " <<
Worklist.size() << "\n"; } } while (false)
;
1990
1991 // For invalid AAs we can fix dependent AAs that have a required dependence,
1992 // thereby folding long dependence chains in a single step without the need
1993 // to run updates.
1994 for (unsigned u = 0; u < InvalidAAs.size(); ++u) {
1995 AbstractAttribute *InvalidAA = InvalidAAs[u];
1996
1997 // Check the dependences to fast track invalidation.
1998 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] InvalidAA: "
<< *InvalidAA << " has " << InvalidAA->
Deps.size() << " required & optional dependences\n"
; } } while (false)
1999 dbgs() << "[Attributor] InvalidAA: " << *InvalidAAdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] InvalidAA: "
<< *InvalidAA << " has " << InvalidAA->
Deps.size() << " required & optional dependences\n"
; } } while (false)
2000 << " has " << InvalidAA->Deps.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] InvalidAA: "
<< *InvalidAA << " has " << InvalidAA->
Deps.size() << " required & optional dependences\n"
; } } while (false)
2001 << " required & optional dependences\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << "[Attributor] InvalidAA: "
<< *InvalidAA << " has " << InvalidAA->
Deps.size() << " required & optional dependences\n"
; } } while (false)
;
2002 for (auto &DepIt : InvalidAA->Deps) {
2003 AbstractAttribute *DepAA = cast<AbstractAttribute>(DepIt.getPointer());
2004 if (DepIt.getInt() == unsigned(DepClassTy::OPTIONAL)) {
2005 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << " - recompute: "
<< *DepAA; } } while (false)
2006 dbgs() << " - recompute: " << *DepAA)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << " - recompute: "
<< *DepAA; } } while (false)
;
2007 Worklist.insert(DepAA);
2008 continue;
2009 }
2010 DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << " - invalidate: "
<< *DepAA; } } while (false)
2011 << " - invalidate: " << *DepAA)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor" "-verbose")) { dbgs() << " - invalidate: "
<< *DepAA; } } while (false)
;
2012 DepAA->getState().indicatePessimisticFixpoint();
2013 assert(DepAA->getState().isAtFixpoint() && "Expected fixpoint state!")(static_cast <bool> (DepAA->getState().isAtFixpoint(
) && "Expected fixpoint state!") ? void (0) : __assert_fail
("DepAA->getState().isAtFixpoint() && \"Expected fixpoint state!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2013, __extension__
__PRETTY_FUNCTION__))
;
2014 if (!DepAA->getState().isValidState())
2015 InvalidAAs.insert(DepAA);
2016 else
2017 ChangedAAs.push_back(DepAA);
2018 }
2019 InvalidAA->Deps.clear();
2020 }
2021
2022 // Add all abstract attributes that are potentially dependent on one that
2023 // changed to the work list.
2024 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2025 for (auto &DepIt : ChangedAA->Deps)
2026 Worklist.insert(cast<AbstractAttribute>(DepIt.getPointer()));
2027 ChangedAA->Deps.clear();
2028 }
2029
2030 LLVM_DEBUG(dbgs() << "[Attributor] #Iteration: " << IterationCounterdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] #Iteration: "
<< IterationCounter << ", Worklist+Dependent size: "
<< Worklist.size() << "\n"; } } while (false)
2031 << ", Worklist+Dependent size: " << Worklist.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] #Iteration: "
<< IterationCounter << ", Worklist+Dependent size: "
<< Worklist.size() << "\n"; } } while (false)
2032 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] #Iteration: "
<< IterationCounter << ", Worklist+Dependent size: "
<< Worklist.size() << "\n"; } } while (false)
;
2033
2034 // Reset the changed and invalid set.
2035 ChangedAAs.clear();
2036 InvalidAAs.clear();
2037
2038 // Update all abstract attribute in the work list and record the ones that
2039 // changed.
2040 for (AbstractAttribute *AA : Worklist) {
2041 const auto &AAState = AA->getState();
2042 if (!AAState.isAtFixpoint())
2043 if (updateAA(*AA) == ChangeStatus::CHANGED)
2044 ChangedAAs.push_back(AA);
2045
2046 // Use the InvalidAAs vector to propagate invalid states fast transitively
2047 // without requiring updates.
2048 if (!AAState.isValidState())
2049 InvalidAAs.insert(AA);
2050 }
2051
2052 // Add attributes to the changed set if they have been created in the last
2053 // iteration.
2054 ChangedAAs.append(DG.SyntheticRoot.begin() + NumAAs,
2055 DG.SyntheticRoot.end());
2056
2057 // Reset the work list and repopulate with the changed abstract attributes.
2058 // Note that dependent ones are added above.
2059 Worklist.clear();
2060 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2061 Worklist.insert(QueryAAsAwaitingUpdate.begin(),
2062 QueryAAsAwaitingUpdate.end());
2063 QueryAAsAwaitingUpdate.clear();
2064
2065 } while (!Worklist.empty() &&
2066 (IterationCounter++ < MaxIterations || VerifyMaxFixpointIterations));
2067
2068 if (IterationCounter > MaxIterations && !Functions.empty()) {
2069 auto Remark = [&](OptimizationRemarkMissed ORM) {
2070 return ORM << "Attributor did not reach a fixpoint after "
2071 << ore::NV("Iterations", MaxIterations) << " iterations.";
2072 };
2073 Function *F = Functions.front();
2074 emitRemark<OptimizationRemarkMissed>(F, "FixedPoint", Remark);
2075 }
2076
2077 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Fixpoint iteration done after: "
<< IterationCounter << "/" << MaxIterations
<< " iterations\n"; } } while (false)
2078 << IterationCounter << "/" << MaxIterationsdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Fixpoint iteration done after: "
<< IterationCounter << "/" << MaxIterations
<< " iterations\n"; } } while (false)
2079 << " iterations\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Fixpoint iteration done after: "
<< IterationCounter << "/" << MaxIterations
<< " iterations\n"; } } while (false)
;
2080
2081 // Reset abstract arguments not settled in a sound fixpoint by now. This
2082 // happens when we stopped the fixpoint iteration early. Note that only the
2083 // ones marked as "changed" *and* the ones transitively depending on them
2084 // need to be reverted to a pessimistic state. Others might not be in a
2085 // fixpoint state but we can use the optimistic results for them anyway.
2086 SmallPtrSet<AbstractAttribute *, 32> Visited;
2087 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2088 AbstractAttribute *ChangedAA = ChangedAAs[u];
2089 if (!Visited.insert(ChangedAA).second)
2090 continue;
2091
2092 AbstractState &State = ChangedAA->getState();
2093 if (!State.isAtFixpoint()) {
2094 State.indicatePessimisticFixpoint();
2095
2096 NumAttributesTimedOut++;
2097 }
2098
2099 for (auto &DepIt : ChangedAA->Deps)
2100 ChangedAAs.push_back(cast<AbstractAttribute>(DepIt.getPointer()));
2101 ChangedAA->Deps.clear();
2102 }
2103
2104 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Visited.empty()) dbgs() << "\n[Attributor] Finalized "
<< Visited.size() << " abstract attributes.\n"; }
; } } while (false)
2105 if (!Visited.empty())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Visited.empty()) dbgs() << "\n[Attributor] Finalized "
<< Visited.size() << " abstract attributes.\n"; }
; } } while (false)
2106 dbgs() << "\n[Attributor] Finalized " << Visited.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Visited.empty()) dbgs() << "\n[Attributor] Finalized "
<< Visited.size() << " abstract attributes.\n"; }
; } } while (false)
2107 << " abstract attributes.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Visited.empty()) dbgs() << "\n[Attributor] Finalized "
<< Visited.size() << " abstract attributes.\n"; }
; } } while (false)
2108 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Visited.empty()) dbgs() << "\n[Attributor] Finalized "
<< Visited.size() << " abstract attributes.\n"; }
; } } while (false)
;
2109
2110 if (VerifyMaxFixpointIterations && IterationCounter != MaxIterations) {
2111 errs() << "\n[Attributor] Fixpoint iteration done after: "
2112 << IterationCounter << "/" << MaxIterations << " iterations\n";
2113 llvm_unreachable("The fixpoint was not reached with exactly the number of "::llvm::llvm_unreachable_internal("The fixpoint was not reached with exactly the number of "
"specified iterations!", "llvm/lib/Transforms/IPO/Attributor.cpp"
, 2114)
2114 "specified iterations!")::llvm::llvm_unreachable_internal("The fixpoint was not reached with exactly the number of "
"specified iterations!", "llvm/lib/Transforms/IPO/Attributor.cpp"
, 2114)
;
2115 }
2116}
2117
2118void Attributor::registerForUpdate(AbstractAttribute &AA) {
2119 assert(AA.isQueryAA() &&(static_cast <bool> (AA.isQueryAA() && "Non-query AAs should not be required to register for updates!"
) ? void (0) : __assert_fail ("AA.isQueryAA() && \"Non-query AAs should not be required to register for updates!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2120, __extension__
__PRETTY_FUNCTION__))
2120 "Non-query AAs should not be required to register for updates!")(static_cast <bool> (AA.isQueryAA() && "Non-query AAs should not be required to register for updates!"
) ? void (0) : __assert_fail ("AA.isQueryAA() && \"Non-query AAs should not be required to register for updates!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2120, __extension__
__PRETTY_FUNCTION__))
;
2121 QueryAAsAwaitingUpdate.insert(&AA);
2122}
2123
2124ChangeStatus Attributor::manifestAttributes() {
2125 TimeTraceScope TimeScope("Attributor::manifestAttributes");
2126 size_t NumFinalAAs = DG.SyntheticRoot.Deps.size();
2127
2128 unsigned NumManifested = 0;
2129 unsigned NumAtFixpoint = 0;
2130 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2131 for (auto &DepAA : DG.SyntheticRoot.Deps) {
2132 AbstractAttribute *AA = cast<AbstractAttribute>(DepAA.getPointer());
2133 AbstractState &State = AA->getState();
2134
2135 // If there is not already a fixpoint reached, we can now take the
2136 // optimistic state. This is correct because we enforced a pessimistic one
2137 // on abstract attributes that were transitively dependent on a changed one
2138 // already above.
2139 if (!State.isAtFixpoint())
2140 State.indicateOptimisticFixpoint();
2141
2142 // We must not manifest Attributes that use Callbase info.
2143 if (AA->hasCallBaseContext())
2144 continue;
2145 // If the state is invalid, we do not try to manifest it.
2146 if (!State.isValidState())
2147 continue;
2148
2149 if (AA->getCtxI() && !isRunOn(*AA->getAnchorScope()))
2150 continue;
2151
2152 // Skip dead code.
2153 bool UsedAssumedInformation = false;
2154 if (isAssumedDead(*AA, nullptr, UsedAssumedInformation,
2155 /* CheckBBLivenessOnly */ true))
2156 continue;
2157 // Check if the manifest debug counter that allows skipping manifestation of
2158 // AAs
2159 if (!DebugCounter::shouldExecute(ManifestDBGCounter))
2160 continue;
2161 // Manifest the state and record if we changed the IR.
2162 ChangeStatus LocalChange = AA->manifest(*this);
2163 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
2164 AA->trackStatistics();
2165 LLVM_DEBUG(dbgs() << "[Attributor] Manifest " << LocalChange << " : " << *AAdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Manifest " <<
LocalChange << " : " << *AA << "\n"; } } while
(false)
2166 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Manifest " <<
LocalChange << " : " << *AA << "\n"; } } while
(false)
;
2167
2168 ManifestChange = ManifestChange | LocalChange;
2169
2170 NumAtFixpoint++;
2171 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2172 }
2173
2174 (void)NumManifested;
2175 (void)NumAtFixpoint;
2176 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifesteddo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Manifested "
<< NumManifested << " arguments while " <<
NumAtFixpoint << " were in a valid fixpoint state\n"; }
} while (false)
2177 << " arguments while " << NumAtFixpointdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Manifested "
<< NumManifested << " arguments while " <<
NumAtFixpoint << " were in a valid fixpoint state\n"; }
} while (false)
2178 << " were in a valid fixpoint state\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Manifested "
<< NumManifested << " arguments while " <<
NumAtFixpoint << " were in a valid fixpoint state\n"; }
} while (false)
;
2179
2180 NumAttributesManifested += NumManifested;
2181 NumAttributesValidFixpoint += NumAtFixpoint;
2182
2183 (void)NumFinalAAs;
2184 if (NumFinalAAs != DG.SyntheticRoot.Deps.size()) {
2185 auto DepIt = DG.SyntheticRoot.Deps.begin();
2186 for (unsigned u = 0; u < NumFinalAAs; ++u)
2187 ++DepIt;
2188 for (unsigned u = NumFinalAAs; u < DG.SyntheticRoot.Deps.size();
2189 ++u, ++DepIt) {
2190 errs() << "Unexpected abstract attribute: "
2191 << cast<AbstractAttribute>(DepIt->getPointer()) << " :: "
2192 << cast<AbstractAttribute>(DepIt->getPointer())
2193 ->getIRPosition()
2194 .getAssociatedValue()
2195 << "\n";
2196 }
2197 llvm_unreachable("Expected the final number of abstract attributes to "::llvm::llvm_unreachable_internal("Expected the final number of abstract attributes to "
"remain unchanged!", "llvm/lib/Transforms/IPO/Attributor.cpp"
, 2198)
2198 "remain unchanged!")::llvm::llvm_unreachable_internal("Expected the final number of abstract attributes to "
"remain unchanged!", "llvm/lib/Transforms/IPO/Attributor.cpp"
, 2198)
;
2199 }
2200 return ManifestChange;
2201}
2202
2203void Attributor::identifyDeadInternalFunctions() {
2204 // Early exit if we don't intend to delete functions.
2205 if (!Configuration.DeleteFns)
2206 return;
2207
2208 // To avoid triggering an assertion in the lazy call graph we will not delete
2209 // any internal library functions. We should modify the assertion though and
2210 // allow internals to be deleted.
2211 const auto *TLI =
2212 isModulePass()
2213 ? nullptr
2214 : getInfoCache().getTargetLibraryInfoForFunction(*Functions.back());
2215 LibFunc LF;
2216
2217 // Identify dead internal functions and delete them. This happens outside
2218 // the other fixpoint analysis as we might treat potentially dead functions
2219 // as live to lower the number of iterations. If they happen to be dead, the
2220 // below fixpoint loop will identify and eliminate them.
2221
2222 SmallVector<Function *, 8> InternalFns;
2223 for (Function *F : Functions)
2224 if (F->hasLocalLinkage() && (isModulePass() || !TLI->getLibFunc(*F, LF)))
2225 InternalFns.push_back(F);
2226
2227 SmallPtrSet<Function *, 8> LiveInternalFns;
2228 bool FoundLiveInternal = true;
2229 while (FoundLiveInternal) {
2230 FoundLiveInternal = false;
2231 for (unsigned u = 0, e = InternalFns.size(); u < e; ++u) {
2232 Function *F = InternalFns[u];
2233 if (!F)
2234 continue;
2235
2236 bool UsedAssumedInformation = false;
2237 if (checkForAllCallSites(
2238 [&](AbstractCallSite ACS) {
2239 Function *Callee = ACS.getInstruction()->getFunction();
2240 return ToBeDeletedFunctions.count(Callee) ||
2241 (Functions.count(Callee) && Callee->hasLocalLinkage() &&
2242 !LiveInternalFns.count(Callee));
2243 },
2244 *F, true, nullptr, UsedAssumedInformation)) {
2245 continue;
2246 }
2247
2248 LiveInternalFns.insert(F);
2249 InternalFns[u] = nullptr;
2250 FoundLiveInternal = true;
2251 }
2252 }
2253
2254 for (unsigned u = 0, e = InternalFns.size(); u < e; ++u)
2255 if (Function *F = InternalFns[u])
2256 ToBeDeletedFunctions.insert(F);
2257}
2258
2259ChangeStatus Attributor::cleanupIR() {
2260 TimeTraceScope TimeScope("Attributor::cleanupIR");
2261 // Delete stuff at the end to avoid invalid references and a nice order.
2262 LLVM_DEBUG(dbgs() << "\n[Attributor] Delete/replace at least "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2263 << ToBeDeletedFunctions.size() << " functions and "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2264 << ToBeDeletedBlocks.size() << " blocks and "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2265 << ToBeDeletedInsts.size() << " instructions and "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2266 << ToBeChangedValues.size() << " values and "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2267 << ToBeChangedUses.size() << " uses. To insert "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2268 << ToBeChangedToUnreachableInsts.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2269 << " unreachables.\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2270 << "Preserve manifest added " << ManifestAddedBlocks.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
2271 << " blocks\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "\n[Attributor] Delete/replace at least "
<< ToBeDeletedFunctions.size() << " functions and "
<< ToBeDeletedBlocks.size() << " blocks and " <<
ToBeDeletedInsts.size() << " instructions and " <<
ToBeChangedValues.size() << " values and " << ToBeChangedUses
.size() << " uses. To insert " << ToBeChangedToUnreachableInsts
.size() << " unreachables.\n" << "Preserve manifest added "
<< ManifestAddedBlocks.size() << " blocks\n"; } }
while (false)
;
2272
2273 SmallVector<WeakTrackingVH, 32> DeadInsts;
2274 SmallVector<Instruction *, 32> TerminatorsToFold;
2275
2276 auto ReplaceUse = [&](Use *U, Value *NewV) {
2277 Value *OldV = U->get();
2278
2279 // If we plan to replace NewV we need to update it at this point.
2280 do {
2281 const auto &Entry = ToBeChangedValues.lookup(NewV);
2282 if (!get<0>(Entry))
2283 break;
2284 NewV = get<0>(Entry);
2285 } while (true);
2286
2287 Instruction *I = dyn_cast<Instruction>(U->getUser());
2288 assert((!I || isRunOn(*I->getFunction())) &&(static_cast <bool> ((!I || isRunOn(*I->getFunction(
))) && "Cannot replace an instruction outside the current SCC!"
) ? void (0) : __assert_fail ("(!I || isRunOn(*I->getFunction())) && \"Cannot replace an instruction outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2289, __extension__
__PRETTY_FUNCTION__))
2289 "Cannot replace an instruction outside the current SCC!")(static_cast <bool> ((!I || isRunOn(*I->getFunction(
))) && "Cannot replace an instruction outside the current SCC!"
) ? void (0) : __assert_fail ("(!I || isRunOn(*I->getFunction())) && \"Cannot replace an instruction outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2289, __extension__
__PRETTY_FUNCTION__))
;
2290
2291 // Do not replace uses in returns if the value is a must-tail call we will
2292 // not delete.
2293 if (auto *RI = dyn_cast_or_null<ReturnInst>(I)) {
2294 if (auto *CI = dyn_cast<CallInst>(OldV->stripPointerCasts()))
2295 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2296 return;
2297 // If we rewrite a return and the new value is not an argument, strip the
2298 // `returned` attribute as it is wrong now.
2299 if (!isa<Argument>(NewV))
2300 for (auto &Arg : RI->getFunction()->args())
2301 Arg.removeAttr(Attribute::Returned);
2302 }
2303
2304 LLVM_DEBUG(dbgs() << "Use " << *NewV << " in " << *U->getUser()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Use " << *NewV <<
" in " << *U->getUser() << " instead of " <<
*OldV << "\n"; } } while (false)
2305 << " instead of " << *OldV << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Use " << *NewV <<
" in " << *U->getUser() << " instead of " <<
*OldV << "\n"; } } while (false)
;
2306 U->set(NewV);
2307
2308 if (Instruction *I = dyn_cast<Instruction>(OldV)) {
2309 CGModifiedFunctions.insert(I->getFunction());
2310 if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) &&
2311 isInstructionTriviallyDead(I))
2312 DeadInsts.push_back(I);
2313 }
2314 if (isa<UndefValue>(NewV) && isa<CallBase>(U->getUser())) {
2315 auto *CB = cast<CallBase>(U->getUser());
2316 if (CB->isArgOperand(U)) {
2317 unsigned Idx = CB->getArgOperandNo(U);
2318 CB->removeParamAttr(Idx, Attribute::NoUndef);
2319 Function *Fn = CB->getCalledFunction();
2320 if (Fn && Fn->arg_size() > Idx)
2321 Fn->removeParamAttr(Idx, Attribute::NoUndef);
2322 }
2323 }
2324 if (isa<Constant>(NewV) && isa<BranchInst>(U->getUser())) {
2325 Instruction *UserI = cast<Instruction>(U->getUser());
2326 if (isa<UndefValue>(NewV)) {
2327 ToBeChangedToUnreachableInsts.insert(UserI);
2328 } else {
2329 TerminatorsToFold.push_back(UserI);
2330 }
2331 }
2332 };
2333
2334 for (auto &It : ToBeChangedUses) {
2335 Use *U = It.first;
2336 Value *NewV = It.second;
2337 ReplaceUse(U, NewV);
2338 }
2339
2340 SmallVector<Use *, 4> Uses;
2341 for (auto &It : ToBeChangedValues) {
2342 Value *OldV = It.first;
2343 auto [NewV, Done] = It.second;
2344 Uses.clear();
2345 for (auto &U : OldV->uses())
2346 if (Done || !U.getUser()->isDroppable())
2347 Uses.push_back(&U);
2348 for (Use *U : Uses) {
2349 if (auto *I = dyn_cast<Instruction>(U->getUser()))
2350 if (!isRunOn(*I->getFunction()))
2351 continue;
2352 ReplaceUse(U, NewV);
2353 }
2354 }
2355
2356 for (const auto &V : InvokeWithDeadSuccessor)
2357 if (InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) {
2358 assert(isRunOn(*II->getFunction()) &&(static_cast <bool> (isRunOn(*II->getFunction()) &&
"Cannot replace an invoke outside the current SCC!") ? void (
0) : __assert_fail ("isRunOn(*II->getFunction()) && \"Cannot replace an invoke outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2359, __extension__
__PRETTY_FUNCTION__))
2359 "Cannot replace an invoke outside the current SCC!")(static_cast <bool> (isRunOn(*II->getFunction()) &&
"Cannot replace an invoke outside the current SCC!") ? void (
0) : __assert_fail ("isRunOn(*II->getFunction()) && \"Cannot replace an invoke outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2359, __extension__
__PRETTY_FUNCTION__))
;
2360 bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind);
2361 bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn);
2362 bool Invoke2CallAllowed =
2363 !AAIsDead::mayCatchAsynchronousExceptions(*II->getFunction());
2364 assert((UnwindBBIsDead || NormalBBIsDead) &&(static_cast <bool> ((UnwindBBIsDead || NormalBBIsDead)
&& "Invoke does not have dead successors!") ? void (
0) : __assert_fail ("(UnwindBBIsDead || NormalBBIsDead) && \"Invoke does not have dead successors!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2365, __extension__
__PRETTY_FUNCTION__))
2365 "Invoke does not have dead successors!")(static_cast <bool> ((UnwindBBIsDead || NormalBBIsDead)
&& "Invoke does not have dead successors!") ? void (
0) : __assert_fail ("(UnwindBBIsDead || NormalBBIsDead) && \"Invoke does not have dead successors!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2365, __extension__
__PRETTY_FUNCTION__))
;
2366 BasicBlock *BB = II->getParent();
2367 BasicBlock *NormalDestBB = II->getNormalDest();
2368 if (UnwindBBIsDead) {
2369 Instruction *NormalNextIP = &NormalDestBB->front();
2370 if (Invoke2CallAllowed) {
2371 changeToCall(II);
2372 NormalNextIP = BB->getTerminator();
2373 }
2374 if (NormalBBIsDead)
2375 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2376 } else {
2377 assert(NormalBBIsDead && "Broken invariant!")(static_cast <bool> (NormalBBIsDead && "Broken invariant!"
) ? void (0) : __assert_fail ("NormalBBIsDead && \"Broken invariant!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2377, __extension__
__PRETTY_FUNCTION__))
;
2378 if (!NormalDestBB->getUniquePredecessor())
2379 NormalDestBB = SplitBlockPredecessors(NormalDestBB, {BB}, ".dead");
2380 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->front());
2381 }
2382 }
2383 for (Instruction *I : TerminatorsToFold) {
2384 assert(isRunOn(*I->getFunction()) &&(static_cast <bool> (isRunOn(*I->getFunction()) &&
"Cannot replace a terminator outside the current SCC!") ? void
(0) : __assert_fail ("isRunOn(*I->getFunction()) && \"Cannot replace a terminator outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2385, __extension__
__PRETTY_FUNCTION__))
2385 "Cannot replace a terminator outside the current SCC!")(static_cast <bool> (isRunOn(*I->getFunction()) &&
"Cannot replace a terminator outside the current SCC!") ? void
(0) : __assert_fail ("isRunOn(*I->getFunction()) && \"Cannot replace a terminator outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2385, __extension__
__PRETTY_FUNCTION__))
;
2386 CGModifiedFunctions.insert(I->getFunction());
2387 ConstantFoldTerminator(I->getParent());
2388 }
2389 for (const auto &V : ToBeChangedToUnreachableInsts)
2390 if (Instruction *I = dyn_cast_or_null<Instruction>(V)) {
2391 LLVM_DEBUG(dbgs() << "[Attributor] Change to unreachable: " << *Ido { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Change to unreachable: "
<< *I << "\n"; } } while (false)
2392 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Change to unreachable: "
<< *I << "\n"; } } while (false)
;
2393 assert(isRunOn(*I->getFunction()) &&(static_cast <bool> (isRunOn(*I->getFunction()) &&
"Cannot replace an instruction outside the current SCC!") ? void
(0) : __assert_fail ("isRunOn(*I->getFunction()) && \"Cannot replace an instruction outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2394, __extension__
__PRETTY_FUNCTION__))
2394 "Cannot replace an instruction outside the current SCC!")(static_cast <bool> (isRunOn(*I->getFunction()) &&
"Cannot replace an instruction outside the current SCC!") ? void
(0) : __assert_fail ("isRunOn(*I->getFunction()) && \"Cannot replace an instruction outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2394, __extension__
__PRETTY_FUNCTION__))
;
2395 CGModifiedFunctions.insert(I->getFunction());
2396 changeToUnreachable(I);
2397 }
2398
2399 for (const auto &V : ToBeDeletedInsts) {
2400 if (Instruction *I = dyn_cast_or_null<Instruction>(V)) {
2401 if (auto *CB = dyn_cast<CallBase>(I)) {
2402 assert((isa<IntrinsicInst>(CB) || isRunOn(*I->getFunction())) &&(static_cast <bool> ((isa<IntrinsicInst>(CB) || isRunOn
(*I->getFunction())) && "Cannot delete an instruction outside the current SCC!"
) ? void (0) : __assert_fail ("(isa<IntrinsicInst>(CB) || isRunOn(*I->getFunction())) && \"Cannot delete an instruction outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2403, __extension__
__PRETTY_FUNCTION__))
2403 "Cannot delete an instruction outside the current SCC!")(static_cast <bool> ((isa<IntrinsicInst>(CB) || isRunOn
(*I->getFunction())) && "Cannot delete an instruction outside the current SCC!"
) ? void (0) : __assert_fail ("(isa<IntrinsicInst>(CB) || isRunOn(*I->getFunction())) && \"Cannot delete an instruction outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2403, __extension__
__PRETTY_FUNCTION__))
;
2404 if (!isa<IntrinsicInst>(CB))
2405 Configuration.CGUpdater.removeCallSite(*CB);
2406 }
2407 I->dropDroppableUses();
2408 CGModifiedFunctions.insert(I->getFunction());
2409 if (!I->getType()->isVoidTy())
2410 I->replaceAllUsesWith(UndefValue::get(I->getType()));
2411 if (!isa<PHINode>(I) && isInstructionTriviallyDead(I))
2412 DeadInsts.push_back(I);
2413 else
2414 I->eraseFromParent();
2415 }
2416 }
2417
2418 llvm::erase_if(DeadInsts, [&](WeakTrackingVH I) { return !I; });
2419
2420 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] DeadInsts size: "
<< DeadInsts.size() << "\n"; for (auto &I : DeadInsts
) if (I) dbgs() << " - " << *I << "\n"; };
} } while (false)
2421 dbgs() << "[Attributor] DeadInsts size: " << DeadInsts.size() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] DeadInsts size: "
<< DeadInsts.size() << "\n"; for (auto &I : DeadInsts
) if (I) dbgs() << " - " << *I << "\n"; };
} } while (false)
2422 for (auto &I : DeadInsts)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] DeadInsts size: "
<< DeadInsts.size() << "\n"; for (auto &I : DeadInsts
) if (I) dbgs() << " - " << *I << "\n"; };
} } while (false)
2423 if (I)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] DeadInsts size: "
<< DeadInsts.size() << "\n"; for (auto &I : DeadInsts
) if (I) dbgs() << " - " << *I << "\n"; };
} } while (false)
2424 dbgs() << " - " << *I << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] DeadInsts size: "
<< DeadInsts.size() << "\n"; for (auto &I : DeadInsts
) if (I) dbgs() << " - " << *I << "\n"; };
} } while (false)
2425 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] DeadInsts size: "
<< DeadInsts.size() << "\n"; for (auto &I : DeadInsts
) if (I) dbgs() << " - " << *I << "\n"; };
} } while (false)
;
2426
2427 RecursivelyDeleteTriviallyDeadInstructions(DeadInsts);
2428
2429 if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2430 SmallVector<BasicBlock *, 8> ToBeDeletedBBs;
2431 ToBeDeletedBBs.reserve(NumDeadBlocks);
2432 for (BasicBlock *BB : ToBeDeletedBlocks) {
2433 assert(isRunOn(*BB->getParent()) &&(static_cast <bool> (isRunOn(*BB->getParent()) &&
"Cannot delete a block outside the current SCC!") ? void (0)
: __assert_fail ("isRunOn(*BB->getParent()) && \"Cannot delete a block outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2434, __extension__
__PRETTY_FUNCTION__))
2434 "Cannot delete a block outside the current SCC!")(static_cast <bool> (isRunOn(*BB->getParent()) &&
"Cannot delete a block outside the current SCC!") ? void (0)
: __assert_fail ("isRunOn(*BB->getParent()) && \"Cannot delete a block outside the current SCC!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2434, __extension__
__PRETTY_FUNCTION__))
;
2435 CGModifiedFunctions.insert(BB->getParent());
2436 // Do not delete BBs added during manifests of AAs.
2437 if (ManifestAddedBlocks.contains(BB))
2438 continue;
2439 ToBeDeletedBBs.push_back(BB);
2440 }
2441 // Actually we do not delete the blocks but squash them into a single
2442 // unreachable but untangling branches that jump here is something we need
2443 // to do in a more generic way.
2444 detachDeadBlocks(ToBeDeletedBBs, nullptr);
2445 }
2446
2447 identifyDeadInternalFunctions();
2448
2449 // Rewrite the functions as requested during manifest.
2450 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2451
2452 for (Function *Fn : CGModifiedFunctions)
2453 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
2454 Configuration.CGUpdater.reanalyzeFunction(*Fn);
2455
2456 for (Function *Fn : ToBeDeletedFunctions) {
2457 if (!Functions.count(Fn))
2458 continue;
2459 Configuration.CGUpdater.removeFunction(*Fn);
2460 }
2461
2462 if (!ToBeChangedUses.empty())
2463 ManifestChange = ChangeStatus::CHANGED;
2464
2465 if (!ToBeChangedToUnreachableInsts.empty())
2466 ManifestChange = ChangeStatus::CHANGED;
2467
2468 if (!ToBeDeletedFunctions.empty())
2469 ManifestChange = ChangeStatus::CHANGED;
2470
2471 if (!ToBeDeletedBlocks.empty())
2472 ManifestChange = ChangeStatus::CHANGED;
2473
2474 if (!ToBeDeletedInsts.empty())
2475 ManifestChange = ChangeStatus::CHANGED;
2476
2477 if (!InvokeWithDeadSuccessor.empty())
2478 ManifestChange = ChangeStatus::CHANGED;
2479
2480 if (!DeadInsts.empty())
2481 ManifestChange = ChangeStatus::CHANGED;
2482
2483 NumFnDeleted += ToBeDeletedFunctions.size();
2484
2485 LLVM_DEBUG(dbgs() << "[Attributor] Deleted " << ToBeDeletedFunctions.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Deleted " <<
ToBeDeletedFunctions.size() << " functions after manifest.\n"
; } } while (false)
2486 << " functions after manifest.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Deleted " <<
ToBeDeletedFunctions.size() << " functions after manifest.\n"
; } } while (false)
;
2487
2488#ifdef EXPENSIVE_CHECKS
2489 for (Function *F : Functions) {
2490 if (ToBeDeletedFunctions.count(F))
2491 continue;
2492 assert(!verifyFunction(*F, &errs()) && "Module verification failed!")(static_cast <bool> (!verifyFunction(*F, &errs()) &&
"Module verification failed!") ? void (0) : __assert_fail ("!verifyFunction(*F, &errs()) && \"Module verification failed!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2492, __extension__
__PRETTY_FUNCTION__))
;
2493 }
2494#endif
2495
2496 return ManifestChange;
2497}
2498
2499ChangeStatus Attributor::run() {
2500 TimeTraceScope TimeScope("Attributor::run");
2501 AttributorCallGraph ACallGraph(*this);
2502
2503 if (PrintCallGraph)
2504 ACallGraph.populateAll();
2505
2506 Phase = AttributorPhase::UPDATE;
2507 runTillFixpoint();
2508
2509 // dump graphs on demand
2510 if (DumpDepGraph)
2511 DG.dumpGraph();
2512
2513 if (ViewDepGraph)
2514 DG.viewGraph();
2515
2516 if (PrintDependencies)
2517 DG.print();
2518
2519 Phase = AttributorPhase::MANIFEST;
2520 ChangeStatus ManifestChange = manifestAttributes();
2521
2522 Phase = AttributorPhase::CLEANUP;
2523 ChangeStatus CleanupChange = cleanupIR();
2524
2525 if (PrintCallGraph)
2526 ACallGraph.print();
2527
2528 return ManifestChange | CleanupChange;
2529}
2530
2531ChangeStatus Attributor::updateAA(AbstractAttribute &AA) {
2532 TimeTraceScope TimeScope("updateAA", [&]() {
2533 return AA.getName() + std::to_string(AA.getIRPosition().getPositionKind());
2534 });
2535 assert(Phase == AttributorPhase::UPDATE &&(static_cast <bool> (Phase == AttributorPhase::UPDATE &&
"We can update AA only in the update stage!") ? void (0) : __assert_fail
("Phase == AttributorPhase::UPDATE && \"We can update AA only in the update stage!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2536, __extension__
__PRETTY_FUNCTION__))
2536 "We can update AA only in the update stage!")(static_cast <bool> (Phase == AttributorPhase::UPDATE &&
"We can update AA only in the update stage!") ? void (0) : __assert_fail
("Phase == AttributorPhase::UPDATE && \"We can update AA only in the update stage!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2536, __extension__
__PRETTY_FUNCTION__))
;
2537
2538 // Use a new dependence vector for this update.
2539 DependenceVector DV;
2540 DependenceStack.push_back(&DV);
2541
2542 auto &AAState = AA.getState();
2543 ChangeStatus CS = ChangeStatus::UNCHANGED;
2544 bool UsedAssumedInformation = false;
2545 if (!isAssumedDead(AA, nullptr, UsedAssumedInformation,
2546 /* CheckBBLivenessOnly */ true))
2547 CS = AA.update(*this);
2548
2549 if (!AA.isQueryAA() && DV.empty() && !AA.getState().isAtFixpoint()) {
2550 // If the AA did not rely on outside information but changed, we run it
2551 // again to see if it found a fixpoint. Most AAs do but we don't require
2552 // them to. Hence, it might take the AA multiple iterations to get to a
2553 // fixpoint even if it does not rely on outside information, which is fine.
2554 ChangeStatus RerunCS = ChangeStatus::UNCHANGED;
2555 if (CS == ChangeStatus::CHANGED)
2556 RerunCS = AA.update(*this);
2557
2558 // If the attribute did not change during the run or rerun, and it still did
2559 // not query any non-fix information, the state will not change and we can
2560 // indicate that right at this point.
2561 if (RerunCS == ChangeStatus::UNCHANGED && !AA.isQueryAA() && DV.empty())
2562 AAState.indicateOptimisticFixpoint();
2563 }
2564
2565 if (!AAState.isAtFixpoint())
2566 rememberDependences();
2567
2568 // Verify the stack was used properly, that is we pop the dependence vector we
2569 // put there earlier.
2570 DependenceVector *PoppedDV = DependenceStack.pop_back_val();
2571 (void)PoppedDV;
2572 assert(PoppedDV == &DV && "Inconsistent usage of the dependence stack!")(static_cast <bool> (PoppedDV == &DV && "Inconsistent usage of the dependence stack!"
) ? void (0) : __assert_fail ("PoppedDV == &DV && \"Inconsistent usage of the dependence stack!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2572, __extension__
__PRETTY_FUNCTION__))
;
2573
2574 return CS;
2575}
2576
2577void Attributor::createShallowWrapper(Function &F) {
2578 assert(!F.isDeclaration() && "Cannot create a wrapper around a declaration!")(static_cast <bool> (!F.isDeclaration() && "Cannot create a wrapper around a declaration!"
) ? void (0) : __assert_fail ("!F.isDeclaration() && \"Cannot create a wrapper around a declaration!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2578, __extension__
__PRETTY_FUNCTION__))
;
2579
2580 Module &M = *F.getParent();
2581 LLVMContext &Ctx = M.getContext();
2582 FunctionType *FnTy = F.getFunctionType();
2583
2584 Function *Wrapper =
2585 Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(), F.getName());
2586 F.setName(""); // set the inside function anonymous
2587 M.getFunctionList().insert(F.getIterator(), Wrapper);
2588
2589 F.setLinkage(GlobalValue::InternalLinkage);
2590
2591 F.replaceAllUsesWith(Wrapper);
2592 assert(F.use_empty() && "Uses remained after wrapper was created!")(static_cast <bool> (F.use_empty() && "Uses remained after wrapper was created!"
) ? void (0) : __assert_fail ("F.use_empty() && \"Uses remained after wrapper was created!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2592, __extension__
__PRETTY_FUNCTION__))
;
2593
2594 // Move the COMDAT section to the wrapper.
2595 // TODO: Check if we need to keep it for F as well.
2596 Wrapper->setComdat(F.getComdat());
2597 F.setComdat(nullptr);
2598
2599 // Copy all metadata and attributes but keep them on F as well.
2600 SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
2601 F.getAllMetadata(MDs);
2602 for (auto MDIt : MDs)
2603 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2604 Wrapper->setAttributes(F.getAttributes());
2605
2606 // Create the call in the wrapper.
2607 BasicBlock *EntryBB = BasicBlock::Create(Ctx, "entry", Wrapper);
2608
2609 SmallVector<Value *, 8> Args;
2610 Argument *FArgIt = F.arg_begin();
2611 for (Argument &Arg : Wrapper->args()) {
2612 Args.push_back(&Arg);
2613 Arg.setName((FArgIt++)->getName());
2614 }
2615
2616 CallInst *CI = CallInst::Create(&F, Args, "", EntryBB);
2617 CI->setTailCall(true);
2618 CI->addFnAttr(Attribute::NoInline);
2619 ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI, EntryBB);
2620
2621 NumFnShallowWrappersCreated++;
2622}
2623
2624bool Attributor::isInternalizable(Function &F) {
2625 if (F.isDeclaration() || F.hasLocalLinkage() ||
2626 GlobalValue::isInterposableLinkage(F.getLinkage()))
2627 return false;
2628 return true;
2629}
2630
2631Function *Attributor::internalizeFunction(Function &F, bool Force) {
2632 if (!AllowDeepWrapper && !Force)
2633 return nullptr;
2634 if (!isInternalizable(F))
2635 return nullptr;
2636
2637 SmallPtrSet<Function *, 2> FnSet = {&F};
2638 DenseMap<Function *, Function *> InternalizedFns;
2639 internalizeFunctions(FnSet, InternalizedFns);
2640
2641 return InternalizedFns[&F];
2642}
2643
2644bool Attributor::internalizeFunctions(SmallPtrSetImpl<Function *> &FnSet,
2645 DenseMap<Function *, Function *> &FnMap) {
2646 for (Function *F : FnSet)
2647 if (!Attributor::isInternalizable(*F))
2648 return false;
2649
2650 FnMap.clear();
2651 // Generate the internalized version of each function.
2652 for (Function *F : FnSet) {
2653 Module &M = *F->getParent();
2654 FunctionType *FnTy = F->getFunctionType();
2655
2656 // Create a copy of the current function
2657 Function *Copied =
2658 Function::Create(FnTy, F->getLinkage(), F->getAddressSpace(),
2659 F->getName() + ".internalized");
2660 ValueToValueMapTy VMap;
2661 auto *NewFArgIt = Copied->arg_begin();
2662 for (auto &Arg : F->args()) {
2663 auto ArgName = Arg.getName();
2664 NewFArgIt->setName(ArgName);
2665 VMap[&Arg] = &(*NewFArgIt++);
2666 }
2667 SmallVector<ReturnInst *, 8> Returns;
2668
2669 // Copy the body of the original function to the new one
2670 CloneFunctionInto(Copied, F, VMap,
2671 CloneFunctionChangeType::LocalChangesOnly, Returns);
2672
2673 // Set the linakage and visibility late as CloneFunctionInto has some
2674 // implicit requirements.
2675 Copied->setVisibility(GlobalValue::DefaultVisibility);
2676 Copied->setLinkage(GlobalValue::PrivateLinkage);
2677
2678 // Copy metadata
2679 SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
2680 F->getAllMetadata(MDs);
2681 for (auto MDIt : MDs)
2682 if (!Copied->hasMetadata())
2683 Copied->addMetadata(MDIt.first, *MDIt.second);
2684
2685 M.getFunctionList().insert(F->getIterator(), Copied);
2686 Copied->setDSOLocal(true);
2687 FnMap[F] = Copied;
2688 }
2689
2690 // Replace all uses of the old function with the new internalized function
2691 // unless the caller is a function that was just internalized.
2692 for (Function *F : FnSet) {
2693 auto &InternalizedFn = FnMap[F];
2694 auto IsNotInternalized = [&](Use &U) -> bool {
2695 if (auto *CB = dyn_cast<CallBase>(U.getUser()))
2696 return !FnMap.lookup(CB->getCaller());
2697 return false;
2698 };
2699 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2700 }
2701
2702 return true;
2703}
2704
2705bool Attributor::isValidFunctionSignatureRewrite(
2706 Argument &Arg, ArrayRef<Type *> ReplacementTypes) {
2707
2708 if (!Configuration.RewriteSignatures)
2709 return false;
2710
2711 Function *Fn = Arg.getParent();
2712 auto CallSiteCanBeChanged = [Fn](AbstractCallSite ACS) {
2713 // Forbid the call site to cast the function return type. If we need to
2714 // rewrite these functions we need to re-create a cast for the new call site
2715 // (if the old had uses).
2716 if (!ACS.getCalledFunction() ||
2717 ACS.getInstruction()->getType() !=
2718 ACS.getCalledFunction()->getReturnType())
2719 return false;
2720 if (ACS.getCalledOperand()->getType() != Fn->getType())
2721 return false;
2722 // Forbid must-tail calls for now.
2723 return !ACS.isCallbackCall() && !ACS.getInstruction()->isMustTailCall();
2724 };
2725
2726 // Avoid var-arg functions for now.
2727 if (Fn->isVarArg()) {
2728 LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite var-args functions\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Cannot rewrite var-args functions\n"
; } } while (false)
;
2729 return false;
2730 }
2731
2732 // Avoid functions with complicated argument passing semantics.
2733 AttributeList FnAttributeList = Fn->getAttributes();
2734 if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) ||
2735 FnAttributeList.hasAttrSomewhere(Attribute::StructRet) ||
2736 FnAttributeList.hasAttrSomewhere(Attribute::InAlloca) ||
2737 FnAttributeList.hasAttrSomewhere(Attribute::Preallocated)) {
2738 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n"
; } } while (false)
2739 dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n"
; } } while (false)
;
2740 return false;
2741 }
2742
2743 // Avoid callbacks for now.
2744 bool UsedAssumedInformation = false;
2745 if (!checkForAllCallSites(CallSiteCanBeChanged, *Fn, true, nullptr,
2746 UsedAssumedInformation)) {
2747 LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Cannot rewrite all call sites\n"
; } } while (false)
;
2748 return false;
2749 }
2750
2751 auto InstPred = [](Instruction &I) {
2752 if (auto *CI = dyn_cast<CallInst>(&I))
2753 return !CI->isMustTailCall();
2754 return true;
2755 };
2756
2757 // Forbid must-tail calls for now.
2758 // TODO:
2759 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
2760 if (!checkForAllInstructionsImpl(nullptr, OpcodeInstMap, InstPred, nullptr,
2761 nullptr, {Instruction::Call},
2762 UsedAssumedInformation)) {
2763 LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite due to instructions\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Cannot rewrite due to instructions\n"
; } } while (false)
;
2764 return false;
2765 }
2766
2767 return true;
2768}
2769
2770bool Attributor::registerFunctionSignatureRewrite(
2771 Argument &Arg, ArrayRef<Type *> ReplacementTypes,
2772 ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB,
2773 ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB) {
2774 LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Register new rewrite of "
<< Arg << " in " << Arg.getParent()->getName
() << " with " << ReplacementTypes.size() <<
" replacements\n"; } } while (false)
2775 << Arg.getParent()->getName() << " with "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Register new rewrite of "
<< Arg << " in " << Arg.getParent()->getName
() << " with " << ReplacementTypes.size() <<
" replacements\n"; } } while (false)
2776 << ReplacementTypes.size() << " replacements\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Register new rewrite of "
<< Arg << " in " << Arg.getParent()->getName
() << " with " << ReplacementTypes.size() <<
" replacements\n"; } } while (false)
;
2777 assert(isValidFunctionSignatureRewrite(Arg, ReplacementTypes) &&(static_cast <bool> (isValidFunctionSignatureRewrite(Arg
, ReplacementTypes) && "Cannot register an invalid rewrite"
) ? void (0) : __assert_fail ("isValidFunctionSignatureRewrite(Arg, ReplacementTypes) && \"Cannot register an invalid rewrite\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2778, __extension__
__PRETTY_FUNCTION__))
2778 "Cannot register an invalid rewrite")(static_cast <bool> (isValidFunctionSignatureRewrite(Arg
, ReplacementTypes) && "Cannot register an invalid rewrite"
) ? void (0) : __assert_fail ("isValidFunctionSignatureRewrite(Arg, ReplacementTypes) && \"Cannot register an invalid rewrite\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2778, __extension__
__PRETTY_FUNCTION__))
;
2779
2780 Function *Fn = Arg.getParent();
2781 SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs =
2782 ArgumentReplacementMap[Fn];
2783 if (ARIs.empty())
2784 ARIs.resize(Fn->arg_size());
2785
2786 // If we have a replacement already with less than or equal new arguments,
2787 // ignore this request.
2788 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.getArgNo()];
2789 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.size()) {
2790 LLVM_DEBUG(dbgs() << "[Attributor] Existing rewrite is preferred\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Existing rewrite is preferred\n"
; } } while (false)
;
2791 return false;
2792 }
2793
2794 // If we have a replacement already but we like the new one better, delete
2795 // the old.
2796 ARI.reset();
2797
2798 LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Register new rewrite of "
<< Arg << " in " << Arg.getParent()->getName
() << " with " << ReplacementTypes.size() <<
" replacements\n"; } } while (false)
2799 << Arg.getParent()->getName() << " with "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Register new rewrite of "
<< Arg << " in " << Arg.getParent()->getName
() << " with " << ReplacementTypes.size() <<
" replacements\n"; } } while (false)
2800 << ReplacementTypes.size() << " replacements\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Register new rewrite of "
<< Arg << " in " << Arg.getParent()->getName
() << " with " << ReplacementTypes.size() <<
" replacements\n"; } } while (false)
;
2801
2802 // Remember the replacement.
2803 ARI.reset(new ArgumentReplacementInfo(*this, Arg, ReplacementTypes,
2804 std::move(CalleeRepairCB),
2805 std::move(ACSRepairCB)));
2806
2807 return true;
2808}
2809
2810bool Attributor::shouldSeedAttribute(AbstractAttribute &AA) {
2811 bool Result = true;
2812#ifndef NDEBUG
2813 if (SeedAllowList.size() != 0)
2814 Result = llvm::is_contained(SeedAllowList, AA.getName());
2815 Function *Fn = AA.getAnchorScope();
2816 if (FunctionSeedAllowList.size() != 0 && Fn)
2817 Result &= llvm::is_contained(FunctionSeedAllowList, Fn->getName());
2818#endif
2819 return Result;
2820}
2821
2822ChangeStatus Attributor::rewriteFunctionSignatures(
2823 SmallSetVector<Function *, 8> &ModifiedFns) {
2824 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2825
2826 for (auto &It : ArgumentReplacementMap) {
2827 Function *OldFn = It.getFirst();
2828
2829 // Deleted functions do not require rewrites.
2830 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
2831 continue;
2832
2833 const SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs =
2834 It.getSecond();
2835 assert(ARIs.size() == OldFn->arg_size() && "Inconsistent state!")(static_cast <bool> (ARIs.size() == OldFn->arg_size(
) && "Inconsistent state!") ? void (0) : __assert_fail
("ARIs.size() == OldFn->arg_size() && \"Inconsistent state!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2835, __extension__
__PRETTY_FUNCTION__))
;
2836
2837 SmallVector<Type *, 16> NewArgumentTypes;
2838 SmallVector<AttributeSet, 16> NewArgumentAttributes;
2839
2840 // Collect replacement argument types and copy over existing attributes.
2841 AttributeList OldFnAttributeList = OldFn->getAttributes();
2842 for (Argument &Arg : OldFn->args()) {
2843 if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2844 ARIs[Arg.getArgNo()]) {
2845 NewArgumentTypes.append(ARI->ReplacementTypes.begin(),
2846 ARI->ReplacementTypes.end());
2847 NewArgumentAttributes.append(ARI->getNumReplacementArgs(),
2848 AttributeSet());
2849 } else {
2850 NewArgumentTypes.push_back(Arg.getType());
2851 NewArgumentAttributes.push_back(
2852 OldFnAttributeList.getParamAttrs(Arg.getArgNo()));
2853 }
2854 }
2855
2856 uint64_t LargestVectorWidth = 0;
2857 for (auto *I : NewArgumentTypes)
2858 if (auto *VT = dyn_cast<llvm::VectorType>(I))
2859 LargestVectorWidth =
2860 std::max(LargestVectorWidth,
2861 VT->getPrimitiveSizeInBits().getKnownMinValue());
2862
2863 FunctionType *OldFnTy = OldFn->getFunctionType();
2864 Type *RetTy = OldFnTy->getReturnType();
2865
2866 // Construct the new function type using the new arguments types.
2867 FunctionType *NewFnTy =
2868 FunctionType::get(RetTy, NewArgumentTypes, OldFnTy->isVarArg());
2869
2870 LLVM_DEBUG(dbgs() << "[Attributor] Function rewrite '" << OldFn->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function rewrite '"
<< OldFn->getName() << "' from " << *OldFn
->getFunctionType() << " to " << *NewFnTy <<
"\n"; } } while (false)
2871 << "' from " << *OldFn->getFunctionType() << " to "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function rewrite '"
<< OldFn->getName() << "' from " << *OldFn
->getFunctionType() << " to " << *NewFnTy <<
"\n"; } } while (false)
2872 << *NewFnTy << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Function rewrite '"
<< OldFn->getName() << "' from " << *OldFn
->getFunctionType() << " to " << *NewFnTy <<
"\n"; } } while (false)
;
2873
2874 // Create the new function body and insert it into the module.
2875 Function *NewFn = Function::Create(NewFnTy, OldFn->getLinkage(),
2876 OldFn->getAddressSpace(), "");
2877 Functions.insert(NewFn);
2878 OldFn->getParent()->getFunctionList().insert(OldFn->getIterator(), NewFn);
2879 NewFn->takeName(OldFn);
2880 NewFn->copyAttributesFrom(OldFn);
2881
2882 // Patch the pointer to LLVM function in debug info descriptor.
2883 NewFn->setSubprogram(OldFn->getSubprogram());
2884 OldFn->setSubprogram(nullptr);
2885
2886 // Recompute the parameter attributes list based on the new arguments for
2887 // the function.
2888 LLVMContext &Ctx = OldFn->getContext();
2889 NewFn->setAttributes(AttributeList::get(
2890 Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(),
2891 NewArgumentAttributes));
2892 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewFn, LargestVectorWidth);
2893
2894 // Since we have now created the new function, splice the body of the old
2895 // function right into the new function, leaving the old rotting hulk of the
2896 // function empty.
2897 NewFn->splice(NewFn->begin(), OldFn);
2898
2899 // Fixup block addresses to reference new function.
2900 SmallVector<BlockAddress *, 8u> BlockAddresses;
2901 for (User *U : OldFn->users())
2902 if (auto *BA = dyn_cast<BlockAddress>(U))
2903 BlockAddresses.push_back(BA);
2904 for (auto *BA : BlockAddresses)
2905 BA->replaceAllUsesWith(BlockAddress::get(NewFn, BA->getBasicBlock()));
2906
2907 // Set of all "call-like" instructions that invoke the old function mapped
2908 // to their new replacements.
2909 SmallVector<std::pair<CallBase *, CallBase *>, 8> CallSitePairs;
2910
2911 // Callback to create a new "call-like" instruction for a given one.
2912 auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) {
2913 CallBase *OldCB = cast<CallBase>(ACS.getInstruction());
2914 const AttributeList &OldCallAttributeList = OldCB->getAttributes();
2915
2916 // Collect the new argument operands for the replacement call site.
2917 SmallVector<Value *, 16> NewArgOperands;
2918 SmallVector<AttributeSet, 16> NewArgOperandAttributes;
2919 for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); ++OldArgNum) {
2920 unsigned NewFirstArgNum = NewArgOperands.size();
2921 (void)NewFirstArgNum; // only used inside assert.
2922 if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2923 ARIs[OldArgNum]) {
2924 if (ARI->ACSRepairCB)
2925 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
2926 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==(static_cast <bool> (ARI->getNumReplacementArgs() + NewFirstArgNum
== NewArgOperands.size() && "ACS repair callback did not provide as many operand as new "
"types were registered!") ? void (0) : __assert_fail ("ARI->getNumReplacementArgs() + NewFirstArgNum == NewArgOperands.size() && \"ACS repair callback did not provide as many operand as new \" \"types were registered!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2929, __extension__
__PRETTY_FUNCTION__))
2927 NewArgOperands.size() &&(static_cast <bool> (ARI->getNumReplacementArgs() + NewFirstArgNum
== NewArgOperands.size() && "ACS repair callback did not provide as many operand as new "
"types were registered!") ? void (0) : __assert_fail ("ARI->getNumReplacementArgs() + NewFirstArgNum == NewArgOperands.size() && \"ACS repair callback did not provide as many operand as new \" \"types were registered!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2929, __extension__
__PRETTY_FUNCTION__))
2928 "ACS repair callback did not provide as many operand as new "(static_cast <bool> (ARI->getNumReplacementArgs() + NewFirstArgNum
== NewArgOperands.size() && "ACS repair callback did not provide as many operand as new "
"types were registered!") ? void (0) : __assert_fail ("ARI->getNumReplacementArgs() + NewFirstArgNum == NewArgOperands.size() && \"ACS repair callback did not provide as many operand as new \" \"types were registered!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2929, __extension__
__PRETTY_FUNCTION__))
2929 "types were registered!")(static_cast <bool> (ARI->getNumReplacementArgs() + NewFirstArgNum
== NewArgOperands.size() && "ACS repair callback did not provide as many operand as new "
"types were registered!") ? void (0) : __assert_fail ("ARI->getNumReplacementArgs() + NewFirstArgNum == NewArgOperands.size() && \"ACS repair callback did not provide as many operand as new \" \"types were registered!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2929, __extension__
__PRETTY_FUNCTION__))
;
2930 // TODO: Exose the attribute set to the ACS repair callback
2931 NewArgOperandAttributes.append(ARI->ReplacementTypes.size(),
2932 AttributeSet());
2933 } else {
2934 NewArgOperands.push_back(ACS.getCallArgOperand(OldArgNum));
2935 NewArgOperandAttributes.push_back(
2936 OldCallAttributeList.getParamAttrs(OldArgNum));
2937 }
2938 }
2939
2940 assert(NewArgOperands.size() == NewArgOperandAttributes.size() &&(static_cast <bool> (NewArgOperands.size() == NewArgOperandAttributes
.size() && "Mismatch # argument operands vs. # argument operand attributes!"
) ? void (0) : __assert_fail ("NewArgOperands.size() == NewArgOperandAttributes.size() && \"Mismatch # argument operands vs. # argument operand attributes!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2941, __extension__
__PRETTY_FUNCTION__))
2941 "Mismatch # argument operands vs. # argument operand attributes!")(static_cast <bool> (NewArgOperands.size() == NewArgOperandAttributes
.size() && "Mismatch # argument operands vs. # argument operand attributes!"
) ? void (0) : __assert_fail ("NewArgOperands.size() == NewArgOperandAttributes.size() && \"Mismatch # argument operands vs. # argument operand attributes!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2941, __extension__
__PRETTY_FUNCTION__))
;
2942 assert(NewArgOperands.size() == NewFn->arg_size() &&(static_cast <bool> (NewArgOperands.size() == NewFn->
arg_size() && "Mismatch # argument operands vs. # function arguments!"
) ? void (0) : __assert_fail ("NewArgOperands.size() == NewFn->arg_size() && \"Mismatch # argument operands vs. # function arguments!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2943, __extension__
__PRETTY_FUNCTION__))
2943 "Mismatch # argument operands vs. # function arguments!")(static_cast <bool> (NewArgOperands.size() == NewFn->
arg_size() && "Mismatch # argument operands vs. # function arguments!"
) ? void (0) : __assert_fail ("NewArgOperands.size() == NewFn->arg_size() && \"Mismatch # argument operands vs. # function arguments!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2943, __extension__
__PRETTY_FUNCTION__))
;
2944
2945 SmallVector<OperandBundleDef, 4> OperandBundleDefs;
2946 OldCB->getOperandBundlesAsDefs(OperandBundleDefs);
2947
2948 // Create a new call or invoke instruction to replace the old one.
2949 CallBase *NewCB;
2950 if (InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) {
2951 NewCB =
2952 InvokeInst::Create(NewFn, II->getNormalDest(), II->getUnwindDest(),
2953 NewArgOperands, OperandBundleDefs, "", OldCB);
2954 } else {
2955 auto *NewCI = CallInst::Create(NewFn, NewArgOperands, OperandBundleDefs,
2956 "", OldCB);
2957 NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
2958 NewCB = NewCI;
2959 }
2960
2961 // Copy over various properties and the new attributes.
2962 NewCB->copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
2963 NewCB->setCallingConv(OldCB->getCallingConv());
2964 NewCB->takeName(OldCB);
2965 NewCB->setAttributes(AttributeList::get(
2966 Ctx, OldCallAttributeList.getFnAttrs(),
2967 OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes));
2968
2969 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewCB->getCaller(),
2970 LargestVectorWidth);
2971
2972 CallSitePairs.push_back({OldCB, NewCB});
2973 return true;
2974 };
2975
2976 // Use the CallSiteReplacementCreator to create replacement call sites.
2977 bool UsedAssumedInformation = false;
2978 bool Success = checkForAllCallSites(CallSiteReplacementCreator, *OldFn,
2979 true, nullptr, UsedAssumedInformation,
2980 /* CheckPotentiallyDead */ true);
2981 (void)Success;
2982 assert(Success && "Assumed call site replacement to succeed!")(static_cast <bool> (Success && "Assumed call site replacement to succeed!"
) ? void (0) : __assert_fail ("Success && \"Assumed call site replacement to succeed!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 2982, __extension__
__PRETTY_FUNCTION__))
;
2983
2984 // Rewire the arguments.
2985 Argument *OldFnArgIt = OldFn->arg_begin();
2986 Argument *NewFnArgIt = NewFn->arg_begin();
2987 for (unsigned OldArgNum = 0; OldArgNum < ARIs.size();
2988 ++OldArgNum, ++OldFnArgIt) {
2989 if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2990 ARIs[OldArgNum]) {
2991 if (ARI->CalleeRepairCB)
2992 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
2993 if (ARI->ReplacementTypes.empty())
2994 OldFnArgIt->replaceAllUsesWith(
2995 PoisonValue::get(OldFnArgIt->getType()));
2996 NewFnArgIt += ARI->ReplacementTypes.size();
2997 } else {
2998 NewFnArgIt->takeName(&*OldFnArgIt);
2999 OldFnArgIt->replaceAllUsesWith(&*NewFnArgIt);
3000 ++NewFnArgIt;
3001 }
3002 }
3003
3004 // Eliminate the instructions *after* we visited all of them.
3005 for (auto &CallSitePair : CallSitePairs) {
3006 CallBase &OldCB = *CallSitePair.first;
3007 CallBase &NewCB = *CallSitePair.second;
3008 assert(OldCB.getType() == NewCB.getType() &&(static_cast <bool> (OldCB.getType() == NewCB.getType()
&& "Cannot handle call sites with different types!")
? void (0) : __assert_fail ("OldCB.getType() == NewCB.getType() && \"Cannot handle call sites with different types!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3009, __extension__
__PRETTY_FUNCTION__))
3009 "Cannot handle call sites with different types!")(static_cast <bool> (OldCB.getType() == NewCB.getType()
&& "Cannot handle call sites with different types!")
? void (0) : __assert_fail ("OldCB.getType() == NewCB.getType() && \"Cannot handle call sites with different types!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3009, __extension__
__PRETTY_FUNCTION__))
;
3010 ModifiedFns.insert(OldCB.getFunction());
3011 Configuration.CGUpdater.replaceCallSite(OldCB, NewCB);
3012 OldCB.replaceAllUsesWith(&NewCB);
3013 OldCB.eraseFromParent();
3014 }
3015
3016 // Replace the function in the call graph (if any).
3017 Configuration.CGUpdater.replaceFunctionWith(*OldFn, *NewFn);
3018
3019 // If the old function was modified and needed to be reanalyzed, the new one
3020 // does now.
3021 if (ModifiedFns.remove(OldFn))
3022 ModifiedFns.insert(NewFn);
3023
3024 Changed = ChangeStatus::CHANGED;
3025 }
3026
3027 return Changed;
3028}
3029
3030void InformationCache::initializeInformationCache(const Function &CF,
3031 FunctionInfo &FI) {
3032 // As we do not modify the function here we can remove the const
3033 // withouth breaking implicit assumptions. At the end of the day, we could
3034 // initialize the cache eagerly which would look the same to the users.
3035 Function &F = const_cast<Function &>(CF);
3036
3037 // Walk all instructions to find interesting instructions that might be
3038 // queried by abstract attributes during their initialization or update.
3039 // This has to happen before we create attributes.
3040
3041 DenseMap<const Value *, std::optional<short>> AssumeUsesMap;
3042
3043 // Add \p V to the assume uses map which track the number of uses outside of
3044 // "visited" assumes. If no outside uses are left the value is added to the
3045 // assume only use vector.
3046 auto AddToAssumeUsesMap = [&](const Value &V) -> void {
3047 SmallVector<const Instruction *> Worklist;
3048 if (auto *I = dyn_cast<Instruction>(&V))
3049 Worklist.push_back(I);
3050 while (!Worklist.empty()) {
3051 const Instruction *I = Worklist.pop_back_val();
3052 std::optional<short> &NumUses = AssumeUsesMap[I];
3053 if (!NumUses)
3054 NumUses = I->getNumUses();
3055 NumUses = *NumUses - /* this assume */ 1;
3056 if (*NumUses != 0)
3057 continue;
3058 AssumeOnlyValues.insert(I);
3059 for (const Value *Op : I->operands())
3060 if (auto *OpI = dyn_cast<Instruction>(Op))
3061 Worklist.push_back(OpI);
3062 }
3063 };
3064
3065 for (Instruction &I : instructions(&F)) {
3066 bool IsInterestingOpcode = false;
3067
3068 // To allow easy access to all instructions in a function with a given
3069 // opcode we store them in the InfoCache. As not all opcodes are interesting
3070 // to concrete attributes we only cache the ones that are as identified in
3071 // the following switch.
3072 // Note: There are no concrete attributes now so this is initially empty.
3073 switch (I.getOpcode()) {
3074 default:
3075 assert(!isa<CallBase>(&I) &&(static_cast <bool> (!isa<CallBase>(&I) &&
"New call base instruction type needs to be known in the " "Attributor."
) ? void (0) : __assert_fail ("!isa<CallBase>(&I) && \"New call base instruction type needs to be known in the \" \"Attributor.\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3077, __extension__
__PRETTY_FUNCTION__))
3076 "New call base instruction type needs to be known in the "(static_cast <bool> (!isa<CallBase>(&I) &&
"New call base instruction type needs to be known in the " "Attributor."
) ? void (0) : __assert_fail ("!isa<CallBase>(&I) && \"New call base instruction type needs to be known in the \" \"Attributor.\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3077, __extension__
__PRETTY_FUNCTION__))
3077 "Attributor.")(static_cast <bool> (!isa<CallBase>(&I) &&
"New call base instruction type needs to be known in the " "Attributor."
) ? void (0) : __assert_fail ("!isa<CallBase>(&I) && \"New call base instruction type needs to be known in the \" \"Attributor.\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3077, __extension__
__PRETTY_FUNCTION__))
;
3078 break;
3079 case Instruction::Call:
3080 // Calls are interesting on their own, additionally:
3081 // For `llvm.assume` calls we also fill the KnowledgeMap as we find them.
3082 // For `must-tail` calls we remember the caller and callee.
3083 if (auto *Assume = dyn_cast<AssumeInst>(&I)) {
3084 AssumeOnlyValues.insert(Assume);
3085 fillMapFromAssume(*Assume, KnowledgeMap);
3086 AddToAssumeUsesMap(*Assume->getArgOperand(0));
3087 } else if (cast<CallInst>(I).isMustTailCall()) {
3088 FI.ContainsMustTailCall = true;
3089 if (const Function *Callee = cast<CallInst>(I).getCalledFunction())
3090 getFunctionInfo(*Callee).CalledViaMustTail = true;
3091 }
3092 [[fallthrough]];
3093 case Instruction::CallBr:
3094 case Instruction::Invoke:
3095 case Instruction::CleanupRet:
3096 case Instruction::CatchSwitch:
3097 case Instruction::AtomicRMW:
3098 case Instruction::AtomicCmpXchg:
3099 case Instruction::Br:
3100 case Instruction::Resume:
3101 case Instruction::Ret:
3102 case Instruction::Load:
3103 // The alignment of a pointer is interesting for loads.
3104 case Instruction::Store:
3105 // The alignment of a pointer is interesting for stores.
3106 case Instruction::Alloca:
3107 case Instruction::AddrSpaceCast:
3108 IsInterestingOpcode = true;
3109 }
3110 if (IsInterestingOpcode) {
3111 auto *&Insts = FI.OpcodeInstMap[I.getOpcode()];
3112 if (!Insts)
3113 Insts = new (Allocator) InstructionVectorTy();
3114 Insts->push_back(&I);
3115 }
3116 if (I.mayReadOrWriteMemory())
3117 FI.RWInsts.push_back(&I);
3118 }
3119
3120 if (F.hasFnAttribute(Attribute::AlwaysInline) &&
3121 isInlineViable(F).isSuccess())
3122 InlineableFunctions.insert(&F);
3123}
3124
3125AAResults *InformationCache::getAAResultsForFunction(const Function &F) {
3126 return AG.getAnalysis<AAManager>(F);
3127}
3128
3129InformationCache::FunctionInfo::~FunctionInfo() {
3130 // The instruction vectors are allocated using a BumpPtrAllocator, we need to
3131 // manually destroy them.
3132 for (auto &It : OpcodeInstMap)
3133 It.getSecond()->~InstructionVectorTy();
3134}
3135
3136void Attributor::recordDependence(const AbstractAttribute &FromAA,
3137 const AbstractAttribute &ToAA,
3138 DepClassTy DepClass) {
3139 if (DepClass == DepClassTy::NONE)
3140 return;
3141 // If we are outside of an update, thus before the actual fixpoint iteration
3142 // started (= when we create AAs), we do not track dependences because we will
3143 // put all AAs into the initial worklist anyway.
3144 if (DependenceStack.empty())
3145 return;
3146 if (FromAA.getState().isAtFixpoint())
3147 return;
3148 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3149}
3150
3151void Attributor::rememberDependences() {
3152 assert(!DependenceStack.empty() && "No dependences to remember!")(static_cast <bool> (!DependenceStack.empty() &&
"No dependences to remember!") ? void (0) : __assert_fail ("!DependenceStack.empty() && \"No dependences to remember!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3152, __extension__
__PRETTY_FUNCTION__))
;
3153
3154 for (DepInfo &DI : *DependenceStack.back()) {
3155 assert((DI.DepClass == DepClassTy::REQUIRED ||(static_cast <bool> ((DI.DepClass == DepClassTy::REQUIRED
|| DI.DepClass == DepClassTy::OPTIONAL) && "Expected required or optional dependence (1 bit)!"
) ? void (0) : __assert_fail ("(DI.DepClass == DepClassTy::REQUIRED || DI.DepClass == DepClassTy::OPTIONAL) && \"Expected required or optional dependence (1 bit)!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3157, __extension__
__PRETTY_FUNCTION__))
3156 DI.DepClass == DepClassTy::OPTIONAL) &&(static_cast <bool> ((DI.DepClass == DepClassTy::REQUIRED
|| DI.DepClass == DepClassTy::OPTIONAL) && "Expected required or optional dependence (1 bit)!"
) ? void (0) : __assert_fail ("(DI.DepClass == DepClassTy::REQUIRED || DI.DepClass == DepClassTy::OPTIONAL) && \"Expected required or optional dependence (1 bit)!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3157, __extension__
__PRETTY_FUNCTION__))
3157 "Expected required or optional dependence (1 bit)!")(static_cast <bool> ((DI.DepClass == DepClassTy::REQUIRED
|| DI.DepClass == DepClassTy::OPTIONAL) && "Expected required or optional dependence (1 bit)!"
) ? void (0) : __assert_fail ("(DI.DepClass == DepClassTy::REQUIRED || DI.DepClass == DepClassTy::OPTIONAL) && \"Expected required or optional dependence (1 bit)!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3157, __extension__
__PRETTY_FUNCTION__))
;
3158 auto &DepAAs = const_cast<AbstractAttribute &>(*DI.FromAA).Deps;
3159 DepAAs.insert(AbstractAttribute::DepTy(
3160 const_cast<AbstractAttribute *>(DI.ToAA), unsigned(DI.DepClass)));
3161 }
3162}
3163
3164void Attributor::identifyDefaultAbstractAttributes(Function &F) {
3165 if (!VisitedFunctions.insert(&F).second)
3166 return;
3167 if (F.isDeclaration())
3168 return;
3169
3170 // In non-module runs we need to look at the call sites of a function to
3171 // determine if it is part of a must-tail call edge. This will influence what
3172 // attributes we can derive.
3173 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(F);
3174 if (!isModulePass() && !FI.CalledViaMustTail) {
3175 for (const Use &U : F.uses())
3176 if (const auto *CB = dyn_cast<CallBase>(U.getUser()))
3177 if (CB->isCallee(&U) && CB->isMustTailCall())
3178 FI.CalledViaMustTail = true;
3179 }
3180
3181 IRPosition FPos = IRPosition::function(F);
3182
3183 // Check for dead BasicBlocks in every function.
3184 // We need dead instruction detection because we do not want to deal with
3185 // broken IR in which SSA rules do not apply.
3186 getOrCreateAAFor<AAIsDead>(FPos);
3187
3188 // Every function might be "will-return".
3189 getOrCreateAAFor<AAWillReturn>(FPos);
3190
3191 // Every function might contain instructions that cause "undefined behavior".
3192 getOrCreateAAFor<AAUndefinedBehavior>(FPos);
3193
3194 // Every function can be nounwind.
3195 getOrCreateAAFor<AANoUnwind>(FPos);
3196
3197 // Every function might be marked "nosync"
3198 getOrCreateAAFor<AANoSync>(FPos);
3199
3200 // Every function might be "no-free".
3201 getOrCreateAAFor<AANoFree>(FPos);
3202
3203 // Every function might be "no-return".
3204 getOrCreateAAFor<AANoReturn>(FPos);
3205
3206 // Every function might be "no-recurse".
3207 getOrCreateAAFor<AANoRecurse>(FPos);
3208
3209 // Every function can be "non-convergent".
3210 if (F.hasFnAttribute(Attribute::Convergent))
3211 getOrCreateAAFor<AANonConvergent>(FPos);
3212
3213 // Every function might be "readnone/readonly/writeonly/...".
3214 getOrCreateAAFor<AAMemoryBehavior>(FPos);
3215
3216 // Every function can be "readnone/argmemonly/inaccessiblememonly/...".
3217 getOrCreateAAFor<AAMemoryLocation>(FPos);
3218
3219 // Every function can track active assumptions.
3220 getOrCreateAAFor<AAAssumptionInfo>(FPos);
3221
3222 // Every function might be applicable for Heap-To-Stack conversion.
3223 if (EnableHeapToStack)
3224 getOrCreateAAFor<AAHeapToStack>(FPos);
3225
3226 // Return attributes are only appropriate if the return type is non void.
3227 Type *ReturnType = F.getReturnType();
3228 if (!ReturnType->isVoidTy()) {
3229 // Argument attribute "returned" --- Create only one per function even
3230 // though it is an argument attribute.
3231 getOrCreateAAFor<AAReturnedValues>(FPos);
3232
3233 IRPosition RetPos = IRPosition::returned(F);
3234
3235 // Every returned value might be dead.
3236 getOrCreateAAFor<AAIsDead>(RetPos);
3237
3238 // Every function might be simplified.
3239 bool UsedAssumedInformation = false;
3240 getAssumedSimplified(RetPos, nullptr, UsedAssumedInformation,
3241 AA::Intraprocedural);
3242
3243 // Every returned value might be marked noundef.
3244 getOrCreateAAFor<AANoUndef>(RetPos);
3245
3246 if (ReturnType->isPointerTy()) {
3247
3248 // Every function with pointer return type might be marked align.
3249 getOrCreateAAFor<AAAlign>(RetPos);
3250
3251 // Every function with pointer return type might be marked nonnull.
3252 getOrCreateAAFor<AANonNull>(RetPos);
3253
3254 // Every function with pointer return type might be marked noalias.
3255 getOrCreateAAFor<AANoAlias>(RetPos);
3256
3257 // Every function with pointer return type might be marked
3258 // dereferenceable.
3259 getOrCreateAAFor<AADereferenceable>(RetPos);
3260 } else if (AttributeFuncs::isNoFPClassCompatibleType(ReturnType)) {
3261 getOrCreateAAFor<AANoFPClass>(RetPos);
3262 }
3263 }
3264
3265 for (Argument &Arg : F.args()) {
3266 IRPosition ArgPos = IRPosition::argument(Arg);
3267
3268 // Every argument might be simplified. We have to go through the Attributor
3269 // interface though as outside AAs can register custom simplification
3270 // callbacks.
3271 bool UsedAssumedInformation = false;
3272 getAssumedSimplified(ArgPos, /* AA */ nullptr, UsedAssumedInformation,
3273 AA::Intraprocedural);
3274
3275 // Every argument might be dead.
3276 getOrCreateAAFor<AAIsDead>(ArgPos);
3277
3278 // Every argument might be marked noundef.
3279 getOrCreateAAFor<AANoUndef>(ArgPos);
3280
3281 if (Arg.getType()->isPointerTy()) {
3282 // Every argument with pointer type might be marked nonnull.
3283 getOrCreateAAFor<AANonNull>(ArgPos);
3284
3285 // Every argument with pointer type might be marked noalias.
3286 getOrCreateAAFor<AANoAlias>(ArgPos);
3287
3288 // Every argument with pointer type might be marked dereferenceable.
3289 getOrCreateAAFor<AADereferenceable>(ArgPos);
3290
3291 // Every argument with pointer type might be marked align.
3292 getOrCreateAAFor<AAAlign>(ArgPos);
3293
3294 // Every argument with pointer type might be marked nocapture.
3295 getOrCreateAAFor<AANoCapture>(ArgPos);
3296
3297 // Every argument with pointer type might be marked
3298 // "readnone/readonly/writeonly/..."
3299 getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3300
3301 // Every argument with pointer type might be marked nofree.
3302 getOrCreateAAFor<AANoFree>(ArgPos);
3303
3304 // Every argument with pointer type might be privatizable (or promotable)
3305 getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3306 } else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) {
3307 getOrCreateAAFor<AANoFPClass>(ArgPos);
3308 }
3309 }
3310
3311 auto CallSitePred = [&](Instruction &I) -> bool {
3312 auto &CB = cast<CallBase>(I);
3313 IRPosition CBInstPos = IRPosition::inst(CB);
3314 IRPosition CBFnPos = IRPosition::callsite_function(CB);
3315
3316 // Call sites might be dead if they do not have side effects and no live
3317 // users. The return value might be dead if there are no live users.
3318 getOrCreateAAFor<AAIsDead>(CBInstPos);
3319
3320 Function *Callee = CB.getCalledFunction();
3321 // TODO: Even if the callee is not known now we might be able to simplify
3322 // the call/callee.
3323 if (!Callee)
3324 return true;
3325
3326 // Every call site can track active assumptions.
3327 getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);
3328
3329 // Skip declarations except if annotations on their call sites were
3330 // explicitly requested.
3331 if (!AnnotateDeclarationCallSites && Callee->isDeclaration() &&
3332 !Callee->hasMetadata(LLVMContext::MD_callback))
3333 return true;
3334
3335 if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3336 IRPosition CBRetPos = IRPosition::callsite_returned(CB);
3337 bool UsedAssumedInformation = false;
3338 getAssumedSimplified(CBRetPos, nullptr, UsedAssumedInformation,
3339 AA::Intraprocedural);
3340
3341 if (AttributeFuncs::isNoFPClassCompatibleType(Callee->getReturnType()))
3342 getOrCreateAAFor<AANoFPClass>(CBInstPos);
3343 }
3344
3345 for (int I = 0, E = CB.arg_size(); I < E; ++I) {
3346
3347 IRPosition CBArgPos = IRPosition::callsite_argument(CB, I);
3348
3349 // Every call site argument might be dead.
3350 getOrCreateAAFor<AAIsDead>(CBArgPos);
3351
3352 // Call site argument might be simplified. We have to go through the
3353 // Attributor interface though as outside AAs can register custom
3354 // simplification callbacks.
3355 bool UsedAssumedInformation = false;
3356 getAssumedSimplified(CBArgPos, /* AA */ nullptr, UsedAssumedInformation,
3357 AA::Intraprocedural);
3358
3359 // Every call site argument might be marked "noundef".
3360 getOrCreateAAFor<AANoUndef>(CBArgPos);
3361
3362 Type *ArgTy = CB.getArgOperand(I)->getType();
3363
3364 if (!ArgTy->isPointerTy()) {
3365 if (AttributeFuncs::isNoFPClassCompatibleType(ArgTy))
3366 getOrCreateAAFor<AANoFPClass>(CBArgPos);
3367
3368 continue;
3369 }
3370
3371 // Call site argument attribute "non-null".
3372 getOrCreateAAFor<AANonNull>(CBArgPos);
3373
3374 // Call site argument attribute "nocapture".
3375 getOrCreateAAFor<AANoCapture>(CBArgPos);
3376
3377 // Call site argument attribute "no-alias".
3378 getOrCreateAAFor<AANoAlias>(CBArgPos);
3379
3380 // Call site argument attribute "dereferenceable".
3381 getOrCreateAAFor<AADereferenceable>(CBArgPos);
3382
3383 // Call site argument attribute "align".
3384 getOrCreateAAFor<AAAlign>(CBArgPos);
3385
3386 // Call site argument attribute
3387 // "readnone/readonly/writeonly/..."
3388 getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);
3389
3390 // Call site argument attribute "nofree".
3391 getOrCreateAAFor<AANoFree>(CBArgPos);
3392 }
3393 return true;
3394 };
3395
3396 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
3397 bool Success;
3398 bool UsedAssumedInformation = false;
3399 Success = checkForAllInstructionsImpl(
3400 nullptr, OpcodeInstMap, CallSitePred, nullptr, nullptr,
3401 {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
3402 (unsigned)Instruction::Call},
3403 UsedAssumedInformation);
3404 (void)Success;
3405 assert(Success && "Expected the check call to be successful!")(static_cast <bool> (Success && "Expected the check call to be successful!"
) ? void (0) : __assert_fail ("Success && \"Expected the check call to be successful!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3405, __extension__
__PRETTY_FUNCTION__))
;
3406
3407 auto LoadStorePred = [&](Instruction &I) -> bool {
3408 if (isa<LoadInst>(I)) {
3409 getOrCreateAAFor<AAAlign>(
3410 IRPosition::value(*cast<LoadInst>(I).getPointerOperand()));
3411 if (SimplifyAllLoads)
3412 getAssumedSimplified(IRPosition::value(I), nullptr,
3413 UsedAssumedInformation, AA::Intraprocedural);
3414 } else {
3415 auto &SI = cast<StoreInst>(I);
3416 getOrCreateAAFor<AAIsDead>(IRPosition::inst(I));
3417 getAssumedSimplified(IRPosition::value(*SI.getValueOperand()), nullptr,
3418 UsedAssumedInformation, AA::Intraprocedural);
3419 getOrCreateAAFor<AAAlign>(IRPosition::value(*SI.getPointerOperand()));
3420 }
3421 return true;
3422 };
3423 Success = checkForAllInstructionsImpl(
3424 nullptr, OpcodeInstMap, LoadStorePred, nullptr, nullptr,
3425 {(unsigned)Instruction::Load, (unsigned)Instruction::Store},
3426 UsedAssumedInformation);
3427 (void)Success;
3428 assert(Success && "Expected the check call to be successful!")(static_cast <bool> (Success && "Expected the check call to be successful!"
) ? void (0) : __assert_fail ("Success && \"Expected the check call to be successful!\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3428, __extension__
__PRETTY_FUNCTION__))
;
3429}
3430
3431/// Helpers to ease debugging through output streams and print calls.
3432///
3433///{
3434raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
3435 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
3436}
3437
3438raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
3439 switch (AP) {
3440 case IRPosition::IRP_INVALID:
3441 return OS << "inv";
3442 case IRPosition::IRP_FLOAT:
3443 return OS << "flt";
3444 case IRPosition::IRP_RETURNED:
3445 return OS << "fn_ret";
3446 case IRPosition::IRP_CALL_SITE_RETURNED:
3447 return OS << "cs_ret";
3448 case IRPosition::IRP_FUNCTION:
3449 return OS << "fn";
3450 case IRPosition::IRP_CALL_SITE:
3451 return OS << "cs";
3452 case IRPosition::IRP_ARGUMENT:
3453 return OS << "arg";
3454 case IRPosition::IRP_CALL_SITE_ARGUMENT:
3455 return OS << "cs_arg";
3456 }
3457 llvm_unreachable("Unknown attribute position!")::llvm::llvm_unreachable_internal("Unknown attribute position!"
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3457)
;
3458}
3459
3460raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
3461 const Value &AV = Pos.getAssociatedValue();
3462 OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
3463 << Pos.getAnchorValue().getName() << "@" << Pos.getCallSiteArgNo() << "]";
3464
3465 if (Pos.hasCallBaseContext())
3466 OS << "[cb_context:" << *Pos.getCallBaseContext() << "]";
3467 return OS << "}";
3468}
3469
3470raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerRangeState &S) {
3471 OS << "range-state(" << S.getBitWidth() << ")<";
3472 S.getKnown().print(OS);
3473 OS << " / ";
3474 S.getAssumed().print(OS);
3475 OS << ">";
3476
3477 return OS << static_cast<const AbstractState &>(S);
3478}
3479
3480raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
3481 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
3482}
3483
3484raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
3485 AA.print(OS);
3486 return OS;
3487}
3488
3489raw_ostream &llvm::operator<<(raw_ostream &OS,
3490 const PotentialConstantIntValuesState &S) {
3491 OS << "set-state(< {";
3492 if (!S.isValidState())
3493 OS << "full-set";
3494 else {
3495 for (const auto &It : S.getAssumedSet())
3496 OS << It << ", ";
3497 if (S.undefIsContained())
3498 OS << "undef ";
3499 }
3500 OS << "} >)";
3501
3502 return OS;
3503}
3504
3505raw_ostream &llvm::operator<<(raw_ostream &OS,
3506 const PotentialLLVMValuesState &S) {
3507 OS << "set-state(< {";
3508 if (!S.isValidState())
3509 OS << "full-set";
3510 else {
3511 for (const auto &It : S.getAssumedSet()) {
3512 if (auto *F = dyn_cast<Function>(It.first.getValue()))
3513 OS << "@" << F->getName() << "[" << int(It.second) << "], ";
3514 else
3515 OS << *It.first.getValue() << "[" << int(It.second) << "], ";
3516 }
3517 if (S.undefIsContained())
3518 OS << "undef ";
3519 }
3520 OS << "} >)";
3521
3522 return OS;
3523}
3524
3525void AbstractAttribute::print(raw_ostream &OS) const {
3526 OS << "[";
3527 OS << getName();
3528 OS << "] for CtxI ";
3529
3530 if (auto *I = getCtxI()) {
3531 OS << "'";
3532 I->print(OS);
3533 OS << "'";
3534 } else
3535 OS << "<<null inst>>";
3536
3537 OS << " at position " << getIRPosition() << " with state " << getAsStr()
3538 << '\n';
3539}
3540
3541void AbstractAttribute::printWithDeps(raw_ostream &OS) const {
3542 print(OS);
3543
3544 for (const auto &DepAA : Deps) {
3545 auto *AA = DepAA.getPointer();
3546 OS << " updates ";
3547 AA->print(OS);
3548 }
3549
3550 OS << '\n';
3551}
3552
3553raw_ostream &llvm::operator<<(raw_ostream &OS,
3554 const AAPointerInfo::Access &Acc) {
3555 OS << " [" << Acc.getKind() << "] " << *Acc.getRemoteInst();
3556 if (Acc.getLocalInst() != Acc.getRemoteInst())
3557 OS << " via " << *Acc.getLocalInst();
3558 if (Acc.getContent()) {
3559 if (*Acc.getContent())
3560 OS << " [" << **Acc.getContent() << "]";
3561 else
3562 OS << " [ <unknown> ]";
3563 }
3564 return OS;
3565}
3566///}
3567
3568/// ----------------------------------------------------------------------------
3569/// Pass (Manager) Boilerplate
3570/// ----------------------------------------------------------------------------
3571
3572static bool runAttributorOnFunctions(InformationCache &InfoCache,
3573 SetVector<Function *> &Functions,
3574 AnalysisGetter &AG,
3575 CallGraphUpdater &CGUpdater,
3576 bool DeleteFns, bool IsModulePass) {
3577 if (Functions.empty())
3578 return false;
3579
3580 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] Run on module with "
<< Functions.size() << " functions:\n"; for (Function
*Fn : Functions) dbgs() << " - " << Fn->getName
() << "\n"; }; } } while (false)
3581 dbgs() << "[Attributor] Run on module with " << Functions.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] Run on module with "
<< Functions.size() << " functions:\n"; for (Function
*Fn : Functions) dbgs() << " - " << Fn->getName
() << "\n"; }; } } while (false)
3582 << " functions:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] Run on module with "
<< Functions.size() << " functions:\n"; for (Function
*Fn : Functions) dbgs() << " - " << Fn->getName
() << "\n"; }; } } while (false)
3583 for (Function *Fn : Functions)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] Run on module with "
<< Functions.size() << " functions:\n"; for (Function
*Fn : Functions) dbgs() << " - " << Fn->getName
() << "\n"; }; } } while (false)
3584 dbgs() << " - " << Fn->getName() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] Run on module with "
<< Functions.size() << " functions:\n"; for (Function
*Fn : Functions) dbgs() << " - " << Fn->getName
() << "\n"; }; } } while (false)
3585 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[Attributor] Run on module with "
<< Functions.size() << " functions:\n"; for (Function
*Fn : Functions) dbgs() << " - " << Fn->getName
() << "\n"; }; } } while (false)
;
3586
3587 // Create an Attributor and initially empty information cache that is filled
3588 // while we identify default attribute opportunities.
3589 AttributorConfig AC(CGUpdater);
3590 AC.IsModulePass = IsModulePass;
3591 AC.DeleteFns = DeleteFns;
3592 Attributor A(Functions, InfoCache, AC);
3593
3594 // Create shallow wrappers for all functions that are not IPO amendable
3595 if (AllowShallowWrappers)
3596 for (Function *F : Functions)
3597 if (!A.isFunctionIPOAmendable(*F))
3598 Attributor::createShallowWrapper(*F);
3599
3600 // Internalize non-exact functions
3601 // TODO: for now we eagerly internalize functions without calculating the
3602 // cost, we need a cost interface to determine whether internalizing
3603 // a function is "beneficial"
3604 if (AllowDeepWrapper) {
3605 unsigned FunSize = Functions.size();
3606 for (unsigned u = 0; u < FunSize; u++) {
3607 Function *F = Functions[u];
3608 if (!F->isDeclaration() && !F->isDefinitionExact() && F->getNumUses() &&
3609 !GlobalValue::isInterposableLinkage(F->getLinkage())) {
3610 Function *NewF = Attributor::internalizeFunction(*F);
3611 assert(NewF && "Could not internalize function.")(static_cast <bool> (NewF && "Could not internalize function."
) ? void (0) : __assert_fail ("NewF && \"Could not internalize function.\""
, "llvm/lib/Transforms/IPO/Attributor.cpp", 3611, __extension__
__PRETTY_FUNCTION__))
;
3612 Functions.insert(NewF);
3613
3614 // Update call graph
3615 CGUpdater.replaceFunctionWith(*F, *NewF);
3616 for (const Use &U : NewF->uses())
3617 if (CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
3618 auto *CallerF = CB->getCaller();
3619 CGUpdater.reanalyzeFunction(*CallerF);
3620 }
3621 }
3622 }
3623 }
3624
3625 for (Function *F : Functions) {
3626 if (F->hasExactDefinition())
3627 NumFnWithExactDefinition++;
3628 else
3629 NumFnWithoutExactDefinition++;
3630
3631 // We look at internal functions only on-demand but if any use is not a
3632 // direct call or outside the current set of analyzed functions, we have
3633 // to do it eagerly.
3634 if (F->hasLocalLinkage()) {
3635 if (llvm::all_of(F->uses(), [&Functions](const Use &U) {
3636 const auto *CB = dyn_cast<CallBase>(U.getUser());
3637 return CB && CB->isCallee(&U) &&
3638 Functions.count(const_cast<Function *>(CB->getCaller()));
3639 }))
3640 continue;
3641 }
3642
3643 // Populate the Attributor with abstract attribute opportunities in the
3644 // function and the information cache with IR information.
3645 A.identifyDefaultAbstractAttributes(*F);
3646 }
3647
3648 ChangeStatus Changed = A.run();
3649
3650 LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Done with " <<
Functions.size() << " functions, result: " << Changed
<< ".\n"; } } while (false)
3651 << " functions, result: " << Changed << ".\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Done with " <<
Functions.size() << " functions, result: " << Changed
<< ".\n"; } } while (false)
;
3652 return Changed == ChangeStatus::CHANGED;
3653}
3654
3655void AADepGraph::viewGraph() { llvm::ViewGraph(this, "Dependency Graph"); }
3656
3657void AADepGraph::dumpGraph() {
3658 static std::atomic<int> CallTimes;
3659 std::string Prefix;
3660
3661 if (!DepGraphDotFileNamePrefix.empty())
3662 Prefix = DepGraphDotFileNamePrefix;
3663 else
3664 Prefix = "dep_graph";
3665 std::string Filename =
3666 Prefix + "_" + std::to_string(CallTimes.load()) + ".dot";
3667
3668 outs() << "Dependency graph dump to " << Filename << ".\n";
3669
3670 std::error_code EC;
3671
3672 raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
3673 if (!EC)
3674 llvm::WriteGraph(File, this);
3675
3676 CallTimes++;
3677}
3678
3679void AADepGraph::print() {
3680 for (auto DepAA : SyntheticRoot.Deps)
3681 cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(outs());
3682}
3683
3684PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
3685 FunctionAnalysisManager &FAM =
3686 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
3687 AnalysisGetter AG(FAM);
3688
3689 SetVector<Function *> Functions;
3690 for (Function &F : M)
3691 Functions.insert(&F);
3692
3693 CallGraphUpdater CGUpdater;
3694 BumpPtrAllocator Allocator;
3695 InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr);
3696 if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
3697 /* DeleteFns */ true, /* IsModulePass */ true)) {
3698 // FIXME: Think about passes we will preserve and add them here.
3699 return PreservedAnalyses::none();
3700 }
3701 return PreservedAnalyses::all();
3702}
3703
3704PreservedAnalyses AttributorCGSCCPass::run(LazyCallGraph::SCC &C,
3705 CGSCCAnalysisManager &AM,
3706 LazyCallGraph &CG,
3707 CGSCCUpdateResult &UR) {
3708 FunctionAnalysisManager &FAM =
3709 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
3710 AnalysisGetter AG(FAM);
3711
3712 SetVector<Function *> Functions;
3713 for (LazyCallGraph::Node &N : C)
3714 Functions.insert(&N.getFunction());
3715
3716 if (Functions.empty())
3717 return PreservedAnalyses::all();
3718
3719 Module &M = *Functions.back()->getParent();
3720 CallGraphUpdater CGUpdater;
3721 CGUpdater.initialize(CG, C, AM, UR);
3722 BumpPtrAllocator Allocator;
3723 InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ &Functions);
3724 if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
3725 /* DeleteFns */ false,
3726 /* IsModulePass */ false)) {
3727 // FIXME: Think about passes we will preserve and add them here.
3728 PreservedAnalyses PA;
3729 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
3730 return PA;
3731 }
3732 return PreservedAnalyses::all();
3733}
3734
3735namespace llvm {
3736
3737template <> struct GraphTraits<AADepGraphNode *> {
3738 using NodeRef = AADepGraphNode *;
3739 using DepTy = PointerIntPair<AADepGraphNode *, 1>;
3740 using EdgeRef = PointerIntPair<AADepGraphNode *, 1>;
3741
3742 static NodeRef getEntryNode(AADepGraphNode *DGN) { return DGN; }
3743 static NodeRef DepGetVal(const DepTy &DT) { return DT.getPointer(); }
3744
3745 using ChildIteratorType =
3746 mapped_iterator<AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)>;
3747 using ChildEdgeIteratorType = AADepGraphNode::DepSetTy::iterator;
3748
3749 static ChildIteratorType child_begin(NodeRef N) { return N->child_begin(); }
3750
3751 static ChildIteratorType child_end(NodeRef N) { return N->child_end(); }
3752};
3753
3754template <>
3755struct GraphTraits<AADepGraph *> : public GraphTraits<AADepGraphNode *> {
3756 static NodeRef getEntryNode(AADepGraph *DG) { return DG->GetEntryNode(); }
3757
3758 using nodes_iterator =
3759 mapped_iterator<AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)>;
3760
3761 static nodes_iterator nodes_begin(AADepGraph *DG) { return DG->begin(); }
3762
3763 static nodes_iterator nodes_end(AADepGraph *DG) { return DG->end(); }
3764};
3765
3766template <> struct DOTGraphTraits<AADepGraph *> : public DefaultDOTGraphTraits {
3767 DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
3768
3769 static std::string getNodeLabel(const AADepGraphNode *Node,
3770 const AADepGraph *DG) {
3771 std::string AAString;
3772 raw_string_ostream O(AAString);
3773 Node->print(O);
3774 return AAString;
3775 }
3776};
3777
3778} // end namespace llvm