Bug Summary

File:build/source/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Warning:line 6801, column 9
Value stored to 'HasChanged' is never read

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 AttributorAttributes.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/AttributorAttributes.cpp
1//===- AttributorAttributes.cpp - Attributes for Attributor 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// See the Attributor.h file comment and the class descriptions in that file for
10// more information.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Transforms/IPO/Attributor.h"
15
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/DenseMapInfo.h"
19#include "llvm/ADT/MapVector.h"
20#include "llvm/ADT/SCCIterator.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SetOperations.h"
23#include "llvm/ADT/SetVector.h"
24#include "llvm/ADT/SmallPtrSet.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/Statistic.h"
27#include "llvm/Analysis/AliasAnalysis.h"
28#include "llvm/Analysis/AssumeBundleQueries.h"
29#include "llvm/Analysis/AssumptionCache.h"
30#include "llvm/Analysis/CaptureTracking.h"
31#include "llvm/Analysis/CycleAnalysis.h"
32#include "llvm/Analysis/InstructionSimplify.h"
33#include "llvm/Analysis/LazyValueInfo.h"
34#include "llvm/Analysis/MemoryBuiltins.h"
35#include "llvm/Analysis/OptimizationRemarkEmitter.h"
36#include "llvm/Analysis/ScalarEvolution.h"
37#include "llvm/Analysis/TargetTransformInfo.h"
38#include "llvm/Analysis/ValueTracking.h"
39#include "llvm/IR/Argument.h"
40#include "llvm/IR/Assumptions.h"
41#include "llvm/IR/BasicBlock.h"
42#include "llvm/IR/Constant.h"
43#include "llvm/IR/Constants.h"
44#include "llvm/IR/DataLayout.h"
45#include "llvm/IR/DerivedTypes.h"
46#include "llvm/IR/GlobalValue.h"
47#include "llvm/IR/IRBuilder.h"
48#include "llvm/IR/InlineAsm.h"
49#include "llvm/IR/InstrTypes.h"
50#include "llvm/IR/Instruction.h"
51#include "llvm/IR/Instructions.h"
52#include "llvm/IR/IntrinsicInst.h"
53#include "llvm/IR/IntrinsicsAMDGPU.h"
54#include "llvm/IR/IntrinsicsNVPTX.h"
55#include "llvm/IR/NoFolder.h"
56#include "llvm/IR/Value.h"
57#include "llvm/IR/ValueHandle.h"
58#include "llvm/Support/Alignment.h"
59#include "llvm/Support/Casting.h"
60#include "llvm/Support/CommandLine.h"
61#include "llvm/Support/ErrorHandling.h"
62#include "llvm/Support/GraphWriter.h"
63#include "llvm/Support/MathExtras.h"
64#include "llvm/Support/raw_ostream.h"
65#include "llvm/Transforms/Utils/Local.h"
66#include "llvm/Transforms/Utils/ValueMapper.h"
67#include <cassert>
68#include <numeric>
69#include <optional>
70
71using namespace llvm;
72
73#define DEBUG_TYPE"attributor" "attributor"
74
75static cl::opt<bool> ManifestInternal(
76 "attributor-manifest-internal", cl::Hidden,
77 cl::desc("Manifest Attributor internal string attributes."),
78 cl::init(false));
79
80static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128),
81 cl::Hidden);
82
83template <>
84unsigned llvm::PotentialConstantIntValuesState::MaxPotentialValues = 0;
85
86template <> unsigned llvm::PotentialLLVMValuesState::MaxPotentialValues = -1;
87
88static cl::opt<unsigned, true> MaxPotentialValues(
89 "attributor-max-potential-values", cl::Hidden,
90 cl::desc("Maximum number of potential values to be "
91 "tracked for each position."),
92 cl::location(llvm::PotentialConstantIntValuesState::MaxPotentialValues),
93 cl::init(7));
94
95static cl::opt<int> MaxPotentialValuesIterations(
96 "attributor-max-potential-values-iterations", cl::Hidden,
97 cl::desc(
98 "Maximum number of iterations we keep dismantling potential values."),
99 cl::init(64));
100
101STATISTIC(NumAAs, "Number of abstract attributes created")static llvm::Statistic NumAAs = {"attributor", "NumAAs", "Number of abstract attributes created"
}
;
102
103// Some helper macros to deal with statistics tracking.
104//
105// Usage:
106// For simple IR attribute tracking overload trackStatistics in the abstract
107// attribute and choose the right STATS_DECLTRACK_********* macro,
108// e.g.,:
109// void trackStatistics() const override {
110// STATS_DECLTRACK_ARG_ATTR(returned)
111// }
112// If there is a single "increment" side one can use the macro
113// STATS_DECLTRACK with a custom message. If there are multiple increment
114// sides, STATS_DECL and STATS_TRACK can also be used separately.
115//
116#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME)("Number of " "TYPE" " marked '" "NAME" "'") \
117 ("Number of " #TYPE " marked '" #NAME "'")
118#define BUILD_STAT_NAME(NAME, TYPE)NumIRTYPE_NAME NumIR##TYPE##_##NAME
119#define STATS_DECL_(NAME, MSG)static llvm::Statistic NAME = {"attributor", "NAME", MSG}; STATISTIC(NAME, MSG)static llvm::Statistic NAME = {"attributor", "NAME", MSG};
120#define STATS_DECL(NAME, TYPE, MSG)static llvm::Statistic NumIRTYPE_NAME = {"attributor", "NumIRTYPE_NAME"
, MSG};;
\
121 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG)static llvm::Statistic NumIRTYPE_NAME = {"attributor", "NumIRTYPE_NAME"
, MSG};
;
122#define STATS_TRACK(NAME, TYPE)++(NumIRTYPE_NAME); ++(BUILD_STAT_NAME(NAME, TYPE)NumIRTYPE_NAME);
123#define STATS_DECLTRACK(NAME, TYPE, MSG){ static llvm::Statistic NumIRTYPE_NAME = {"attributor", "NumIRTYPE_NAME"
, MSG};; ++(NumIRTYPE_NAME); }
\
124 { \
125 STATS_DECL(NAME, TYPE, MSG)static llvm::Statistic NumIRTYPE_NAME = {"attributor", "NumIRTYPE_NAME"
, MSG};;
\
126 STATS_TRACK(NAME, TYPE)++(NumIRTYPE_NAME); \
127 }
128#define STATS_DECLTRACK_ARG_ATTR(NAME){ static llvm::Statistic NumIRArguments_NAME = {"attributor",
"NumIRArguments_NAME", ("Number of " "arguments" " marked '"
"NAME" "'")};; ++(NumIRArguments_NAME); }
\
129 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME)){ static llvm::Statistic NumIRArguments_NAME = {"attributor",
"NumIRArguments_NAME", ("Number of " "arguments" " marked '"
"NAME" "'")};; ++(NumIRArguments_NAME); }
130#define STATS_DECLTRACK_CSARG_ATTR(NAME){ static llvm::Statistic NumIRCSArguments_NAME = {"attributor"
, "NumIRCSArguments_NAME", ("Number of " "call site arguments"
" marked '" "NAME" "'")};; ++(NumIRCSArguments_NAME); }
\
131 STATS_DECLTRACK(NAME, CSArguments, \{ static llvm::Statistic NumIRCSArguments_NAME = {"attributor"
, "NumIRCSArguments_NAME", ("Number of " "call site arguments"
" marked '" "NAME" "'")};; ++(NumIRCSArguments_NAME); }
132 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME)){ static llvm::Statistic NumIRCSArguments_NAME = {"attributor"
, "NumIRCSArguments_NAME", ("Number of " "call site arguments"
" marked '" "NAME" "'")};; ++(NumIRCSArguments_NAME); }
133#define STATS_DECLTRACK_FN_ATTR(NAME){ static llvm::Statistic NumIRFunction_NAME = {"attributor", "NumIRFunction_NAME"
, ("Number of " "functions" " marked '" "NAME" "'")};; ++(NumIRFunction_NAME
); }
\
134 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME)){ static llvm::Statistic NumIRFunction_NAME = {"attributor", "NumIRFunction_NAME"
, ("Number of " "functions" " marked '" "NAME" "'")};; ++(NumIRFunction_NAME
); }
135#define STATS_DECLTRACK_CS_ATTR(NAME){ static llvm::Statistic NumIRCS_NAME = {"attributor", "NumIRCS_NAME"
, ("Number of " "call site" " marked '" "NAME" "'")};; ++(NumIRCS_NAME
); }
\
136 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME)){ static llvm::Statistic NumIRCS_NAME = {"attributor", "NumIRCS_NAME"
, ("Number of " "call site" " marked '" "NAME" "'")};; ++(NumIRCS_NAME
); }
137#define STATS_DECLTRACK_FNRET_ATTR(NAME){ static llvm::Statistic NumIRFunctionReturn_NAME = {"attributor"
, "NumIRFunctionReturn_NAME", ("Number of " "function returns"
" marked '" "NAME" "'")};; ++(NumIRFunctionReturn_NAME); }
\
138 STATS_DECLTRACK(NAME, FunctionReturn, \{ static llvm::Statistic NumIRFunctionReturn_NAME = {"attributor"
, "NumIRFunctionReturn_NAME", ("Number of " "function returns"
" marked '" "NAME" "'")};; ++(NumIRFunctionReturn_NAME); }
139 BUILD_STAT_MSG_IR_ATTR(function returns, NAME)){ static llvm::Statistic NumIRFunctionReturn_NAME = {"attributor"
, "NumIRFunctionReturn_NAME", ("Number of " "function returns"
" marked '" "NAME" "'")};; ++(NumIRFunctionReturn_NAME); }
140#define STATS_DECLTRACK_CSRET_ATTR(NAME){ static llvm::Statistic NumIRCSReturn_NAME = {"attributor", "NumIRCSReturn_NAME"
, ("Number of " "call site returns" " marked '" "NAME" "'")};
; ++(NumIRCSReturn_NAME); }
\
141 STATS_DECLTRACK(NAME, CSReturn, \{ static llvm::Statistic NumIRCSReturn_NAME = {"attributor", "NumIRCSReturn_NAME"
, ("Number of " "call site returns" " marked '" "NAME" "'")};
; ++(NumIRCSReturn_NAME); }
142 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME)){ static llvm::Statistic NumIRCSReturn_NAME = {"attributor", "NumIRCSReturn_NAME"
, ("Number of " "call site returns" " marked '" "NAME" "'")};
; ++(NumIRCSReturn_NAME); }
143#define STATS_DECLTRACK_FLOATING_ATTR(NAME){ static llvm::Statistic NumIRFloating_NAME = {"attributor", "NumIRFloating_NAME"
, ("Number of floating values known to be '" "NAME" "'")};; ++
(NumIRFloating_NAME); }
\
144 STATS_DECLTRACK(NAME, Floating, \{ static llvm::Statistic NumIRFloating_NAME = {"attributor", "NumIRFloating_NAME"
, ("Number of floating values known to be '" #NAME "'")};; ++
(NumIRFloating_NAME); }
145 ("Number of floating values known to be '" #NAME "'")){ static llvm::Statistic NumIRFloating_NAME = {"attributor", "NumIRFloating_NAME"
, ("Number of floating values known to be '" #NAME "'")};; ++
(NumIRFloating_NAME); }
146
147// Specialization of the operator<< for abstract attributes subclasses. This
148// disambiguates situations where multiple operators are applicable.
149namespace llvm {
150#define PIPE_OPERATOR(CLASS) \
151 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
152 return OS << static_cast<const AbstractAttribute &>(AA); \
153 }
154
155PIPE_OPERATOR(AAIsDead)
156PIPE_OPERATOR(AANoUnwind)
157PIPE_OPERATOR(AANoSync)
158PIPE_OPERATOR(AANoRecurse)
159PIPE_OPERATOR(AANonConvergent)
160PIPE_OPERATOR(AAWillReturn)
161PIPE_OPERATOR(AANoReturn)
162PIPE_OPERATOR(AAReturnedValues)
163PIPE_OPERATOR(AANonNull)
164PIPE_OPERATOR(AANoAlias)
165PIPE_OPERATOR(AADereferenceable)
166PIPE_OPERATOR(AAAlign)
167PIPE_OPERATOR(AAInstanceInfo)
168PIPE_OPERATOR(AANoCapture)
169PIPE_OPERATOR(AAValueSimplify)
170PIPE_OPERATOR(AANoFree)
171PIPE_OPERATOR(AAHeapToStack)
172PIPE_OPERATOR(AAIntraFnReachability)
173PIPE_OPERATOR(AAMemoryBehavior)
174PIPE_OPERATOR(AAMemoryLocation)
175PIPE_OPERATOR(AAValueConstantRange)
176PIPE_OPERATOR(AAPrivatizablePtr)
177PIPE_OPERATOR(AAUndefinedBehavior)
178PIPE_OPERATOR(AAPotentialConstantValues)
179PIPE_OPERATOR(AAPotentialValues)
180PIPE_OPERATOR(AANoUndef)
181PIPE_OPERATOR(AANoFPClass)
182PIPE_OPERATOR(AACallEdges)
183PIPE_OPERATOR(AAInterFnReachability)
184PIPE_OPERATOR(AAPointerInfo)
185PIPE_OPERATOR(AAAssumptionInfo)
186PIPE_OPERATOR(AAUnderlyingObjects)
187
188#undef PIPE_OPERATOR
189
190template <>
191ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
192 const DerefState &R) {
193 ChangeStatus CS0 =
194 clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);
195 ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);
196 return CS0 | CS1;
197}
198
199} // namespace llvm
200
201static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
202 bool HeaderOnly, Cycle **CPtr = nullptr) {
203 if (!CI)
204 return true;
205 auto *BB = I->getParent();
206 auto *C = CI->getCycle(BB);
207 if (!C)
208 return false;
209 if (CPtr)
210 *CPtr = C;
211 return !HeaderOnly || BB == C->getHeader();
212}
213
214/// Checks if a type could have padding bytes.
215static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
216 // There is no size information, so be conservative.
217 if (!Ty->isSized())
218 return false;
219
220 // If the alloc size is not equal to the storage size, then there are padding
221 // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
222 if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
223 return false;
224
225 // FIXME: This isn't the right way to check for padding in vectors with
226 // non-byte-size elements.
227 if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))
228 return isDenselyPacked(SeqTy->getElementType(), DL);
229
230 // For array types, check for padding within members.
231 if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))
232 return isDenselyPacked(SeqTy->getElementType(), DL);
233
234 if (!isa<StructType>(Ty))
235 return true;
236
237 // Check for padding within and between elements of a struct.
238 StructType *StructTy = cast<StructType>(Ty);
239 const StructLayout *Layout = DL.getStructLayout(StructTy);
240 uint64_t StartPos = 0;
241 for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
242 Type *ElTy = StructTy->getElementType(I);
243 if (!isDenselyPacked(ElTy, DL))
244 return false;
245 if (StartPos != Layout->getElementOffsetInBits(I))
246 return false;
247 StartPos += DL.getTypeAllocSizeInBits(ElTy);
248 }
249
250 return true;
251}
252
253/// Get pointer operand of memory accessing instruction. If \p I is
254/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
255/// is set to false and the instruction is volatile, return nullptr.
256static const Value *getPointerOperand(const Instruction *I,
257 bool AllowVolatile) {
258 if (!AllowVolatile && I->isVolatile())
259 return nullptr;
260
261 if (auto *LI = dyn_cast<LoadInst>(I)) {
262 return LI->getPointerOperand();
263 }
264
265 if (auto *SI = dyn_cast<StoreInst>(I)) {
266 return SI->getPointerOperand();
267 }
268
269 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) {
270 return CXI->getPointerOperand();
271 }
272
273 if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {
274 return RMWI->getPointerOperand();
275 }
276
277 return nullptr;
278}
279
280/// Helper function to create a pointer of type \p ResTy, based on \p Ptr, and
281/// advanced by \p Offset bytes. To aid later analysis the method tries to build
282/// getelement pointer instructions that traverse the natural type of \p Ptr if
283/// possible. If that fails, the remaining offset is adjusted byte-wise, hence
284/// through a cast to i8*.
285///
286/// TODO: This could probably live somewhere more prominantly if it doesn't
287/// already exist.
288static Value *constructPointer(Type *ResTy, Type *PtrElemTy, Value *Ptr,
289 int64_t Offset, IRBuilder<NoFolder> &IRB,
290 const DataLayout &DL) {
291 assert(Offset >= 0 && "Negative offset not supported yet!")(static_cast <bool> (Offset >= 0 && "Negative offset not supported yet!"
) ? void (0) : __assert_fail ("Offset >= 0 && \"Negative offset not supported yet!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 291, __extension__
__PRETTY_FUNCTION__))
;
292 LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offsetdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Construct pointer: " <<
*Ptr << " + " << Offset << "-bytes as " <<
*ResTy << "\n"; } } while (false)
293 << "-bytes as " << *ResTy << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Construct pointer: " <<
*Ptr << " + " << Offset << "-bytes as " <<
*ResTy << "\n"; } } while (false)
;
294
295 if (Offset) {
296 Type *Ty = PtrElemTy;
297 APInt IntOffset(DL.getIndexTypeSizeInBits(Ptr->getType()), Offset);
298 SmallVector<APInt> IntIndices = DL.getGEPIndicesForOffset(Ty, IntOffset);
299
300 SmallVector<Value *, 4> ValIndices;
301 std::string GEPName = Ptr->getName().str();
302 for (const APInt &Index : IntIndices) {
303 ValIndices.push_back(IRB.getInt(Index));
304 GEPName += "." + std::to_string(Index.getZExtValue());
305 }
306
307 // Create a GEP for the indices collected above.
308 Ptr = IRB.CreateGEP(PtrElemTy, Ptr, ValIndices, GEPName);
309
310 // If an offset is left we use byte-wise adjustment.
311 if (IntOffset != 0) {
312 Ptr = IRB.CreateBitCast(Ptr, IRB.getInt8PtrTy());
313 Ptr = IRB.CreateGEP(IRB.getInt8Ty(), Ptr, IRB.getInt(IntOffset),
314 GEPName + ".b" + Twine(IntOffset.getZExtValue()));
315 }
316 }
317
318 // Ensure the result has the requested type.
319 Ptr = IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr, ResTy,
320 Ptr->getName() + ".cast");
321
322 LLVM_DEBUG(dbgs() << "Constructed pointer: " << *Ptr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Constructed pointer: " <<
*Ptr << "\n"; } } while (false)
;
323 return Ptr;
324}
325
326static const Value *
327stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA,
328 const Value *Val, const DataLayout &DL, APInt &Offset,
329 bool GetMinOffset, bool AllowNonInbounds,
330 bool UseAssumed = false) {
331
332 auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
333 const IRPosition &Pos = IRPosition::value(V);
334 // Only track dependence if we are going to use the assumed info.
335 const AAValueConstantRange &ValueConstantRangeAA =
336 A.getAAFor<AAValueConstantRange>(QueryingAA, Pos,
337 UseAssumed ? DepClassTy::OPTIONAL
338 : DepClassTy::NONE);
339 ConstantRange Range = UseAssumed ? ValueConstantRangeAA.getAssumed()
340 : ValueConstantRangeAA.getKnown();
341 if (Range.isFullSet())
342 return false;
343
344 // We can only use the lower part of the range because the upper part can
345 // be higher than what the value can really be.
346 if (GetMinOffset)
347 ROffset = Range.getSignedMin();
348 else
349 ROffset = Range.getSignedMax();
350 return true;
351 };
352
353 return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
354 /* AllowInvariant */ true,
355 AttributorAnalysis);
356}
357
358static const Value *
359getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA,
360 const Value *Ptr, int64_t &BytesOffset,
361 const DataLayout &DL, bool AllowNonInbounds = false) {
362 APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
363 const Value *Base =
364 stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,
365 /* GetMinOffset */ true, AllowNonInbounds);
366
367 BytesOffset = OffsetAPInt.getSExtValue();
368 return Base;
369}
370
371/// Clamp the information known for all returned values of a function
372/// (identified by \p QueryingAA) into \p S.
373template <typename AAType, typename StateType = typename AAType::StateType>
374static void clampReturnedValueStates(
375 Attributor &A, const AAType &QueryingAA, StateType &S,
376 const IRPosition::CallBaseContext *CBContext = nullptr) {
377 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Clamp return value states for "
<< QueryingAA << " into " << S << "\n"
; } } while (false)
378 << QueryingAA << " into " << S << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Clamp return value states for "
<< QueryingAA << " into " << S << "\n"
; } } while (false)
;
379
380 assert((QueryingAA.getIRPosition().getPositionKind() ==(static_cast <bool> ((QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().
getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) &&
"Can only clamp returned value states for a function returned or call "
"site returned position!") ? void (0) : __assert_fail ("(QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) && \"Can only clamp returned value states for a function returned or call \" \"site returned position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 385, __extension__
__PRETTY_FUNCTION__))
381 IRPosition::IRP_RETURNED ||(static_cast <bool> ((QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().
getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) &&
"Can only clamp returned value states for a function returned or call "
"site returned position!") ? void (0) : __assert_fail ("(QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) && \"Can only clamp returned value states for a function returned or call \" \"site returned position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 385, __extension__
__PRETTY_FUNCTION__))
382 QueryingAA.getIRPosition().getPositionKind() ==(static_cast <bool> ((QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().
getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) &&
"Can only clamp returned value states for a function returned or call "
"site returned position!") ? void (0) : __assert_fail ("(QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) && \"Can only clamp returned value states for a function returned or call \" \"site returned position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 385, __extension__
__PRETTY_FUNCTION__))
383 IRPosition::IRP_CALL_SITE_RETURNED) &&(static_cast <bool> ((QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().
getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) &&
"Can only clamp returned value states for a function returned or call "
"site returned position!") ? void (0) : __assert_fail ("(QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) && \"Can only clamp returned value states for a function returned or call \" \"site returned position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 385, __extension__
__PRETTY_FUNCTION__))
384 "Can only clamp returned value states for a function returned or call "(static_cast <bool> ((QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().
getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) &&
"Can only clamp returned value states for a function returned or call "
"site returned position!") ? void (0) : __assert_fail ("(QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) && \"Can only clamp returned value states for a function returned or call \" \"site returned position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 385, __extension__
__PRETTY_FUNCTION__))
385 "site returned position!")(static_cast <bool> ((QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().
getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) &&
"Can only clamp returned value states for a function returned or call "
"site returned position!") ? void (0) : __assert_fail ("(QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_RETURNED || QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED) && \"Can only clamp returned value states for a function returned or call \" \"site returned position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 385, __extension__
__PRETTY_FUNCTION__))
;
386
387 // Use an optional state as there might not be any return values and we want
388 // to join (IntegerState::operator&) the state of all there are.
389 std::optional<StateType> T;
390
391 // Callback for each possibly returned value.
392 auto CheckReturnValue = [&](Value &RV) -> bool {
393 const IRPosition &RVPos = IRPosition::value(RV, CBContext);
394 const AAType &AA =
395 A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);
396 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV << " AA: " << AA.getAsStr()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] RV: " <<
RV << " AA: " << AA.getAsStr() << " @ " <<
RVPos << "\n"; } } while (false)
397 << " @ " << RVPos << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] RV: " <<
RV << " AA: " << AA.getAsStr() << " @ " <<
RVPos << "\n"; } } while (false)
;
398 const StateType &AAS = AA.getState();
399 if (!T)
400 T = StateType::getBestState(AAS);
401 *T &= AAS;
402 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << Tdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] AA State: " <<
AAS << " RV State: " << T << "\n"; } } while
(false)
403 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] AA State: " <<
AAS << " RV State: " << T << "\n"; } } while
(false)
;
404 return T->isValidState();
405 };
406
407 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA))
408 S.indicatePessimisticFixpoint();
409 else if (T)
410 S ^= *T;
411}
412
413namespace {
414/// Helper class for generic deduction: return value -> returned position.
415template <typename AAType, typename BaseType,
416 typename StateType = typename BaseType::StateType,
417 bool PropagateCallBaseContext = false>
418struct AAReturnedFromReturnedValues : public BaseType {
419 AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
420 : BaseType(IRP, A) {}
421
422 /// See AbstractAttribute::updateImpl(...).
423 ChangeStatus updateImpl(Attributor &A) override {
424 StateType S(StateType::getBestState(this->getState()));
425 clampReturnedValueStates<AAType, StateType>(
426 A, *this, S,
427 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
428 // TODO: If we know we visited all returned values, thus no are assumed
429 // dead, we can take the known information from the state T.
430 return clampStateAndIndicateChange<StateType>(this->getState(), S);
431 }
432};
433
434/// Clamp the information known at all call sites for a given argument
435/// (identified by \p QueryingAA) into \p S.
436template <typename AAType, typename StateType = typename AAType::StateType>
437static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
438 StateType &S) {
439 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Clamp call site argument states for "
<< QueryingAA << " into " << S << "\n"
; } } while (false)
440 << QueryingAA << " into " << S << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Clamp call site argument states for "
<< QueryingAA << " into " << S << "\n"
; } } while (false)
;
441
442 assert(QueryingAA.getIRPosition().getPositionKind() ==(static_cast <bool> (QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_ARGUMENT && "Can only clamp call site argument states for an argument position!"
) ? void (0) : __assert_fail ("QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_ARGUMENT && \"Can only clamp call site argument states for an argument position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 444, __extension__
__PRETTY_FUNCTION__))
443 IRPosition::IRP_ARGUMENT &&(static_cast <bool> (QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_ARGUMENT && "Can only clamp call site argument states for an argument position!"
) ? void (0) : __assert_fail ("QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_ARGUMENT && \"Can only clamp call site argument states for an argument position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 444, __extension__
__PRETTY_FUNCTION__))
444 "Can only clamp call site argument states for an argument position!")(static_cast <bool> (QueryingAA.getIRPosition().getPositionKind
() == IRPosition::IRP_ARGUMENT && "Can only clamp call site argument states for an argument position!"
) ? void (0) : __assert_fail ("QueryingAA.getIRPosition().getPositionKind() == IRPosition::IRP_ARGUMENT && \"Can only clamp call site argument states for an argument position!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 444, __extension__
__PRETTY_FUNCTION__))
;
445
446 // Use an optional state as there might not be any return values and we want
447 // to join (IntegerState::operator&) the state of all there are.
448 std::optional<StateType> T;
449
450 // The argument number which is also the call site argument number.
451 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
452
453 auto CallSiteCheck = [&](AbstractCallSite ACS) {
454 const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
455 // Check if a coresponding argument was found or if it is on not associated
456 // (which can happen for callback calls).
457 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
458 return false;
459
460 const AAType &AA =
461 A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);
462 LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] ACS: " <<
*ACS.getInstruction() << " AA: " << AA.getAsStr(
) << " @" << ACSArgPos << "\n"; } } while (
false)
463 << " AA: " << AA.getAsStr() << " @" << ACSArgPos << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] ACS: " <<
*ACS.getInstruction() << " AA: " << AA.getAsStr(
) << " @" << ACSArgPos << "\n"; } } while (
false)
;
464 const StateType &AAS = AA.getState();
465 if (!T)
466 T = StateType::getBestState(AAS);
467 *T &= AAS;
468 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << Tdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] AA State: " <<
AAS << " CSA State: " << T << "\n"; } } while
(false)
469 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] AA State: " <<
AAS << " CSA State: " << T << "\n"; } } while
(false)
;
470 return T->isValidState();
471 };
472
473 bool UsedAssumedInformation = false;
474 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,
475 UsedAssumedInformation))
476 S.indicatePessimisticFixpoint();
477 else if (T)
478 S ^= *T;
479}
480
481/// This function is the bridge between argument position and the call base
482/// context.
483template <typename AAType, typename BaseType,
484 typename StateType = typename AAType::StateType>
485bool getArgumentStateFromCallBaseContext(Attributor &A,
486 BaseType &QueryingAttribute,
487 IRPosition &Pos, StateType &State) {
488 assert((Pos.getPositionKind() == IRPosition::IRP_ARGUMENT) &&(static_cast <bool> ((Pos.getPositionKind() == IRPosition
::IRP_ARGUMENT) && "Expected an 'argument' position !"
) ? void (0) : __assert_fail ("(Pos.getPositionKind() == IRPosition::IRP_ARGUMENT) && \"Expected an 'argument' position !\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 489, __extension__
__PRETTY_FUNCTION__))
489 "Expected an 'argument' position !")(static_cast <bool> ((Pos.getPositionKind() == IRPosition
::IRP_ARGUMENT) && "Expected an 'argument' position !"
) ? void (0) : __assert_fail ("(Pos.getPositionKind() == IRPosition::IRP_ARGUMENT) && \"Expected an 'argument' position !\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 489, __extension__
__PRETTY_FUNCTION__))
;
490 const CallBase *CBContext = Pos.getCallBaseContext();
491 if (!CBContext)
492 return false;
493
494 int ArgNo = Pos.getCallSiteArgNo();
495 assert(ArgNo >= 0 && "Invalid Arg No!")(static_cast <bool> (ArgNo >= 0 && "Invalid Arg No!"
) ? void (0) : __assert_fail ("ArgNo >= 0 && \"Invalid Arg No!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 495, __extension__
__PRETTY_FUNCTION__))
;
496
497 const auto &AA = A.getAAFor<AAType>(
498 QueryingAttribute, IRPosition::callsite_argument(*CBContext, ArgNo),
499 DepClassTy::REQUIRED);
500 const StateType &CBArgumentState =
501 static_cast<const StateType &>(AA.getState());
502
503 LLVM_DEBUG(dbgs() << "[Attributor] Briding Call site context to argument"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Briding Call site context to argument"
<< "Position:" << Pos << "CB Arg state:" <<
CBArgumentState << "\n"; } } while (false)
504 << "Position:" << Pos << "CB Arg state:" << CBArgumentStatedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Briding Call site context to argument"
<< "Position:" << Pos << "CB Arg state:" <<
CBArgumentState << "\n"; } } while (false)
505 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Briding Call site context to argument"
<< "Position:" << Pos << "CB Arg state:" <<
CBArgumentState << "\n"; } } while (false)
;
506
507 // NOTE: If we want to do call site grouping it should happen here.
508 State ^= CBArgumentState;
509 return true;
510}
511
512/// Helper class for generic deduction: call site argument -> argument position.
513template <typename AAType, typename BaseType,
514 typename StateType = typename AAType::StateType,
515 bool BridgeCallBaseContext = false>
516struct AAArgumentFromCallSiteArguments : public BaseType {
517 AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
518 : BaseType(IRP, A) {}
519
520 /// See AbstractAttribute::updateImpl(...).
521 ChangeStatus updateImpl(Attributor &A) override {
522 StateType S = StateType::getBestState(this->getState());
523
524 if (BridgeCallBaseContext) {
525 bool Success =
526 getArgumentStateFromCallBaseContext<AAType, BaseType, StateType>(
527 A, *this, this->getIRPosition(), S);
528 if (Success)
529 return clampStateAndIndicateChange<StateType>(this->getState(), S);
530 }
531 clampCallSiteArgumentStates<AAType, StateType>(A, *this, S);
532
533 // TODO: If we know we visited all incoming values, thus no are assumed
534 // dead, we can take the known information from the state T.
535 return clampStateAndIndicateChange<StateType>(this->getState(), S);
536 }
537};
538
539/// Helper class for generic replication: function returned -> cs returned.
540template <typename AAType, typename BaseType,
541 typename StateType = typename BaseType::StateType,
542 bool IntroduceCallBaseContext = false>
543struct AACallSiteReturnedFromReturned : public BaseType {
544 AACallSiteReturnedFromReturned(const IRPosition &IRP, Attributor &A)
545 : BaseType(IRP, A) {}
546
547 /// See AbstractAttribute::updateImpl(...).
548 ChangeStatus updateImpl(Attributor &A) override {
549 assert(this->getIRPosition().getPositionKind() ==(static_cast <bool> (this->getIRPosition().getPositionKind
() == IRPosition::IRP_CALL_SITE_RETURNED && "Can only wrap function returned positions for call site returned "
"positions!") ? void (0) : __assert_fail ("this->getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED && \"Can only wrap function returned positions for call site returned \" \"positions!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 552, __extension__
__PRETTY_FUNCTION__))
550 IRPosition::IRP_CALL_SITE_RETURNED &&(static_cast <bool> (this->getIRPosition().getPositionKind
() == IRPosition::IRP_CALL_SITE_RETURNED && "Can only wrap function returned positions for call site returned "
"positions!") ? void (0) : __assert_fail ("this->getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED && \"Can only wrap function returned positions for call site returned \" \"positions!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 552, __extension__
__PRETTY_FUNCTION__))
551 "Can only wrap function returned positions for call site returned "(static_cast <bool> (this->getIRPosition().getPositionKind
() == IRPosition::IRP_CALL_SITE_RETURNED && "Can only wrap function returned positions for call site returned "
"positions!") ? void (0) : __assert_fail ("this->getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED && \"Can only wrap function returned positions for call site returned \" \"positions!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 552, __extension__
__PRETTY_FUNCTION__))
552 "positions!")(static_cast <bool> (this->getIRPosition().getPositionKind
() == IRPosition::IRP_CALL_SITE_RETURNED && "Can only wrap function returned positions for call site returned "
"positions!") ? void (0) : __assert_fail ("this->getIRPosition().getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED && \"Can only wrap function returned positions for call site returned \" \"positions!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 552, __extension__
__PRETTY_FUNCTION__))
;
553 auto &S = this->getState();
554
555 const Function *AssociatedFunction =
556 this->getIRPosition().getAssociatedFunction();
557 if (!AssociatedFunction)
558 return S.indicatePessimisticFixpoint();
559
560 CallBase &CBContext = cast<CallBase>(this->getAnchorValue());
561 if (IntroduceCallBaseContext)
562 LLVM_DEBUG(dbgs() << "[Attributor] Introducing call base context:"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Introducing call base context:"
<< CBContext << "\n"; } } while (false)
563 << CBContext << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Introducing call base context:"
<< CBContext << "\n"; } } while (false)
;
564
565 IRPosition FnPos = IRPosition::returned(
566 *AssociatedFunction, IntroduceCallBaseContext ? &CBContext : nullptr);
567 const AAType &AA = A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);
568 return clampStateAndIndicateChange(S, AA.getState());
569 }
570};
571
572/// Helper function to accumulate uses.
573template <class AAType, typename StateType = typename AAType::StateType>
574static void followUsesInContext(AAType &AA, Attributor &A,
575 MustBeExecutedContextExplorer &Explorer,
576 const Instruction *CtxI,
577 SetVector<const Use *> &Uses,
578 StateType &State) {
579 auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);
580 for (unsigned u = 0; u < Uses.size(); ++u) {
581 const Use *U = Uses[u];
582 if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
583 bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
584 if (Found && AA.followUseInMBEC(A, U, UserI, State))
585 for (const Use &Us : UserI->uses())
586 Uses.insert(&Us);
587 }
588 }
589}
590
591/// Use the must-be-executed-context around \p I to add information into \p S.
592/// The AAType class is required to have `followUseInMBEC` method with the
593/// following signature and behaviour:
594///
595/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)
596/// U - Underlying use.
597/// I - The user of the \p U.
598/// Returns true if the value should be tracked transitively.
599///
600template <class AAType, typename StateType = typename AAType::StateType>
601static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,
602 Instruction &CtxI) {
603
604 // Container for (transitive) uses of the associated value.
605 SetVector<const Use *> Uses;
606 for (const Use &U : AA.getIRPosition().getAssociatedValue().uses())
607 Uses.insert(&U);
608
609 MustBeExecutedContextExplorer &Explorer =
610 A.getInfoCache().getMustBeExecutedContextExplorer();
611
612 followUsesInContext<AAType>(AA, A, Explorer, &CtxI, Uses, S);
613
614 if (S.isAtFixpoint())
615 return;
616
617 SmallVector<const BranchInst *, 4> BrInsts;
618 auto Pred = [&](const Instruction *I) {
619 if (const BranchInst *Br = dyn_cast<BranchInst>(I))
620 if (Br->isConditional())
621 BrInsts.push_back(Br);
622 return true;
623 };
624
625 // Here, accumulate conditional branch instructions in the context. We
626 // explore the child paths and collect the known states. The disjunction of
627 // those states can be merged to its own state. Let ParentState_i be a state
628 // to indicate the known information for an i-th branch instruction in the
629 // context. ChildStates are created for its successors respectively.
630 //
631 // ParentS_1 = ChildS_{1, 1} /\ ChildS_{1, 2} /\ ... /\ ChildS_{1, n_1}
632 // ParentS_2 = ChildS_{2, 1} /\ ChildS_{2, 2} /\ ... /\ ChildS_{2, n_2}
633 // ...
634 // ParentS_m = ChildS_{m, 1} /\ ChildS_{m, 2} /\ ... /\ ChildS_{m, n_m}
635 //
636 // Known State |= ParentS_1 \/ ParentS_2 \/... \/ ParentS_m
637 //
638 // FIXME: Currently, recursive branches are not handled. For example, we
639 // can't deduce that ptr must be dereferenced in below function.
640 //
641 // void f(int a, int c, int *ptr) {
642 // if(a)
643 // if (b) {
644 // *ptr = 0;
645 // } else {
646 // *ptr = 1;
647 // }
648 // else {
649 // if (b) {
650 // *ptr = 0;
651 // } else {
652 // *ptr = 1;
653 // }
654 // }
655 // }
656
657 Explorer.checkForAllContext(&CtxI, Pred);
658 for (const BranchInst *Br : BrInsts) {
659 StateType ParentState;
660
661 // The known state of the parent state is a conjunction of children's
662 // known states so it is initialized with a best state.
663 ParentState.indicateOptimisticFixpoint();
664
665 for (const BasicBlock *BB : Br->successors()) {
666 StateType ChildState;
667
668 size_t BeforeSize = Uses.size();
669 followUsesInContext(AA, A, Explorer, &BB->front(), Uses, ChildState);
670
671 // Erase uses which only appear in the child.
672 for (auto It = Uses.begin() + BeforeSize; It != Uses.end();)
673 It = Uses.erase(It);
674
675 ParentState &= ChildState;
676 }
677
678 // Use only known state.
679 S += ParentState;
680 }
681}
682} // namespace
683
684/// ------------------------ PointerInfo ---------------------------------------
685
686namespace llvm {
687namespace AA {
688namespace PointerInfo {
689
690struct State;
691
692} // namespace PointerInfo
693} // namespace AA
694
695/// Helper for AA::PointerInfo::Access DenseMap/Set usage.
696template <>
697struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {
698 using Access = AAPointerInfo::Access;
699 static inline Access getEmptyKey();
700 static inline Access getTombstoneKey();
701 static unsigned getHashValue(const Access &A);
702 static bool isEqual(const Access &LHS, const Access &RHS);
703};
704
705/// Helper that allows RangeTy as a key in a DenseMap.
706template <> struct DenseMapInfo<AA::RangeTy> {
707 static inline AA::RangeTy getEmptyKey() {
708 auto EmptyKey = DenseMapInfo<int64_t>::getEmptyKey();
709 return AA::RangeTy{EmptyKey, EmptyKey};
710 }
711
712 static inline AA::RangeTy getTombstoneKey() {
713 auto TombstoneKey = DenseMapInfo<int64_t>::getTombstoneKey();
714 return AA::RangeTy{TombstoneKey, TombstoneKey};
715 }
716
717 static unsigned getHashValue(const AA::RangeTy &Range) {
718 return detail::combineHashValue(
719 DenseMapInfo<int64_t>::getHashValue(Range.Offset),
720 DenseMapInfo<int64_t>::getHashValue(Range.Size));
721 }
722
723 static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {
724 return A == B;
725 }
726};
727
728/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign
729/// but the instruction
730struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {
731 using Base = DenseMapInfo<Instruction *>;
732 using Access = AAPointerInfo::Access;
733 static inline Access getEmptyKey();
734 static inline Access getTombstoneKey();
735 static unsigned getHashValue(const Access &A);
736 static bool isEqual(const Access &LHS, const Access &RHS);
737};
738
739} // namespace llvm
740
741/// A type to track pointer/struct usage and accesses for AAPointerInfo.
742struct AA::PointerInfo::State : public AbstractState {
743 /// Return the best possible representable state.
744 static State getBestState(const State &SIS) { return State(); }
745
746 /// Return the worst possible representable state.
747 static State getWorstState(const State &SIS) {
748 State R;
749 R.indicatePessimisticFixpoint();
750 return R;
751 }
752
753 State() = default;
754 State(State &&SIS) = default;
755
756 const State &getAssumed() const { return *this; }
757
758 /// See AbstractState::isValidState().
759 bool isValidState() const override { return BS.isValidState(); }
760
761 /// See AbstractState::isAtFixpoint().
762 bool isAtFixpoint() const override { return BS.isAtFixpoint(); }
763
764 /// See AbstractState::indicateOptimisticFixpoint().
765 ChangeStatus indicateOptimisticFixpoint() override {
766 BS.indicateOptimisticFixpoint();
767 return ChangeStatus::UNCHANGED;
768 }
769
770 /// See AbstractState::indicatePessimisticFixpoint().
771 ChangeStatus indicatePessimisticFixpoint() override {
772 BS.indicatePessimisticFixpoint();
773 return ChangeStatus::CHANGED;
774 }
775
776 State &operator=(const State &R) {
777 if (this == &R)
778 return *this;
779 BS = R.BS;
780 AccessList = R.AccessList;
781 OffsetBins = R.OffsetBins;
782 RemoteIMap = R.RemoteIMap;
783 return *this;
784 }
785
786 State &operator=(State &&R) {
787 if (this == &R)
788 return *this;
789 std::swap(BS, R.BS);
790 std::swap(AccessList, R.AccessList);
791 std::swap(OffsetBins, R.OffsetBins);
792 std::swap(RemoteIMap, R.RemoteIMap);
793 return *this;
794 }
795
796 /// Add a new Access to the state at offset \p Offset and with size \p Size.
797 /// The access is associated with \p I, writes \p Content (if anything), and
798 /// is of kind \p Kind. If an Access already exists for the same \p I and same
799 /// \p RemoteI, the two are combined, potentially losing information about
800 /// offset and size. The resulting access must now be moved from its original
801 /// OffsetBin to the bin for its new offset.
802 ///
803 /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
804 ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges,
805 Instruction &I, std::optional<Value *> Content,
806 AAPointerInfo::AccessKind Kind, Type *Ty,
807 Instruction *RemoteI = nullptr);
808
809 using OffsetBinsTy = DenseMap<RangeTy, SmallSet<unsigned, 4>>;
810
811 using const_bin_iterator = OffsetBinsTy::const_iterator;
812 const_bin_iterator begin() const { return OffsetBins.begin(); }
813 const_bin_iterator end() const { return OffsetBins.end(); }
814
815 const AAPointerInfo::Access &getAccess(unsigned Index) const {
816 return AccessList[Index];
817 }
818
819protected:
820 // Every memory instruction results in an Access object. We maintain a list of
821 // all Access objects that we own, along with the following maps:
822 //
823 // - OffsetBins: RangeTy -> { Access }
824 // - RemoteIMap: RemoteI x LocalI -> Access
825 //
826 // A RemoteI is any instruction that accesses memory. RemoteI is different
827 // from LocalI if and only if LocalI is a call; then RemoteI is some
828 // instruction in the callgraph starting from LocalI. Multiple paths in the
829 // callgraph from LocalI to RemoteI may produce multiple accesses, but these
830 // are all combined into a single Access object. This may result in loss of
831 // information in RangeTy in the Access object.
832 SmallVector<AAPointerInfo::Access> AccessList;
833 OffsetBinsTy OffsetBins;
834 DenseMap<const Instruction *, SmallVector<unsigned>> RemoteIMap;
835
836 /// See AAPointerInfo::forallInterferingAccesses.
837 bool forallInterferingAccesses(
838 AA::RangeTy Range,
839 function_ref<bool(const AAPointerInfo::Access &, bool)> CB) const {
840 if (!isValidState())
841 return false;
842
843 for (const auto &It : OffsetBins) {
844 AA::RangeTy ItRange = It.getFirst();
845 if (!Range.mayOverlap(ItRange))
846 continue;
847 bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();
848 for (auto Index : It.getSecond()) {
849 auto &Access = AccessList[Index];
850 if (!CB(Access, IsExact))
851 return false;
852 }
853 }
854 return true;
855 }
856
857 /// See AAPointerInfo::forallInterferingAccesses.
858 bool forallInterferingAccesses(
859 Instruction &I,
860 function_ref<bool(const AAPointerInfo::Access &, bool)> CB,
861 AA::RangeTy &Range) const {
862 if (!isValidState())
863 return false;
864
865 auto LocalList = RemoteIMap.find(&I);
866 if (LocalList == RemoteIMap.end()) {
867 return true;
868 }
869
870 for (unsigned Index : LocalList->getSecond()) {
871 for (auto &R : AccessList[Index]) {
872 Range &= R;
873 if (Range.offsetAndSizeAreUnknown())
874 break;
875 }
876 }
877 return forallInterferingAccesses(Range, CB);
878 }
879
880private:
881 /// State to track fixpoint and validity.
882 BooleanState BS;
883};
884
885ChangeStatus AA::PointerInfo::State::addAccess(
886 Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I,
887 std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,
888 Instruction *RemoteI) {
889 RemoteI = RemoteI ? RemoteI : &I;
890
891 // Check if we have an access for this instruction, if not, simply add it.
892 auto &LocalList = RemoteIMap[RemoteI];
893 bool AccExists = false;
894 unsigned AccIndex = AccessList.size();
895 for (auto Index : LocalList) {
896 auto &A = AccessList[Index];
897 if (A.getLocalInst() == &I) {
898 AccExists = true;
899 AccIndex = Index;
900 break;
901 }
902 }
903
904 auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {
905 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToAdd.size()) dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n"
;; } } while (false)
906 if (ToAdd.size())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToAdd.size()) dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n"
;; } } while (false)
907 dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToAdd.size()) dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n"
;; } } while (false)
908 )do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToAdd.size()) dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n"
;; } } while (false)
;
909
910 for (auto Key : ToAdd) {
911 LLVM_DEBUG(dbgs() << " key " << Key << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " key " << Key <<
"\n"; } } while (false)
;
912 OffsetBins[Key].insert(AccIndex);
913 }
914 };
915
916 if (!AccExists) {
917 AccessList.emplace_back(&I, RemoteI, Ranges, Content, Kind, Ty);
918 assert((AccessList.size() == AccIndex + 1) &&(static_cast <bool> ((AccessList.size() == AccIndex + 1
) && "New Access should have been at AccIndex") ? void
(0) : __assert_fail ("(AccessList.size() == AccIndex + 1) && \"New Access should have been at AccIndex\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 919, __extension__
__PRETTY_FUNCTION__))
919 "New Access should have been at AccIndex")(static_cast <bool> ((AccessList.size() == AccIndex + 1
) && "New Access should have been at AccIndex") ? void
(0) : __assert_fail ("(AccessList.size() == AccIndex + 1) && \"New Access should have been at AccIndex\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 919, __extension__
__PRETTY_FUNCTION__))
;
920 LocalList.push_back(AccIndex);
921 AddToBins(AccessList[AccIndex].getRanges());
922 return ChangeStatus::CHANGED;
923 }
924
925 // Combine the new Access with the existing Access, and then update the
926 // mapping in the offset bins.
927 AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);
928 auto &Current = AccessList[AccIndex];
929 auto Before = Current;
930 Current &= Acc;
931 if (Current == Before)
932 return ChangeStatus::UNCHANGED;
933
934 auto &ExistingRanges = Before.getRanges();
935 auto &NewRanges = Current.getRanges();
936
937 // Ranges that are in the old access but not the new access need to be removed
938 // from the offset bins.
939 AAPointerInfo::RangeList ToRemove;
940 AAPointerInfo::RangeList::set_difference(ExistingRanges, NewRanges, ToRemove);
941 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToRemove.size()) dbgs() << "[AAPointerInfo] Removing access from old offset bins\n"
;; } } while (false)
942 if (ToRemove.size())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToRemove.size()) dbgs() << "[AAPointerInfo] Removing access from old offset bins\n"
;; } } while (false)
943 dbgs() << "[AAPointerInfo] Removing access from old offset bins\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToRemove.size()) dbgs() << "[AAPointerInfo] Removing access from old offset bins\n"
;; } } while (false)
944 )do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToRemove.size()) dbgs() << "[AAPointerInfo] Removing access from old offset bins\n"
;; } } while (false)
;
945
946 for (auto Key : ToRemove) {
947 LLVM_DEBUG(dbgs() << " key " << Key << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " key " << Key <<
"\n"; } } while (false)
;
948 assert(OffsetBins.count(Key) && "Existing Access must be in some bin.")(static_cast <bool> (OffsetBins.count(Key) && "Existing Access must be in some bin."
) ? void (0) : __assert_fail ("OffsetBins.count(Key) && \"Existing Access must be in some bin.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 948, __extension__
__PRETTY_FUNCTION__))
;
949 auto &Bin = OffsetBins[Key];
950 assert(Bin.count(AccIndex) &&(static_cast <bool> (Bin.count(AccIndex) && "Expected bin to actually contain the Access."
) ? void (0) : __assert_fail ("Bin.count(AccIndex) && \"Expected bin to actually contain the Access.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 951, __extension__
__PRETTY_FUNCTION__))
951 "Expected bin to actually contain the Access.")(static_cast <bool> (Bin.count(AccIndex) && "Expected bin to actually contain the Access."
) ? void (0) : __assert_fail ("Bin.count(AccIndex) && \"Expected bin to actually contain the Access.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 951, __extension__
__PRETTY_FUNCTION__))
;
952 Bin.erase(AccIndex);
953 }
954
955 // Ranges that are in the new access but not the old access need to be added
956 // to the offset bins.
957 AAPointerInfo::RangeList ToAdd;
958 AAPointerInfo::RangeList::set_difference(NewRanges, ExistingRanges, ToAdd);
959 AddToBins(ToAdd);
960 return ChangeStatus::CHANGED;
961}
962
963namespace {
964
965/// A helper containing a list of offsets computed for a Use. Ideally this
966/// list should be strictly ascending, but we ensure that only when we
967/// actually translate the list of offsets to a RangeList.
968struct OffsetInfo {
969 using VecTy = SmallVector<int64_t>;
970 using const_iterator = VecTy::const_iterator;
971 VecTy Offsets;
972
973 const_iterator begin() const { return Offsets.begin(); }
974 const_iterator end() const { return Offsets.end(); }
975
976 bool operator==(const OffsetInfo &RHS) const {
977 return Offsets == RHS.Offsets;
978 }
979
980 bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }
981
982 void insert(int64_t Offset) { Offsets.push_back(Offset); }
983 bool isUnassigned() const { return Offsets.size() == 0; }
984
985 bool isUnknown() const {
986 if (isUnassigned())
987 return false;
988 if (Offsets.size() == 1)
989 return Offsets.front() == AA::RangeTy::Unknown;
990 return false;
991 }
992
993 void setUnknown() {
994 Offsets.clear();
995 Offsets.push_back(AA::RangeTy::Unknown);
996 }
997
998 void addToAll(int64_t Inc) {
999 for (auto &Offset : Offsets) {
1000 Offset += Inc;
1001 }
1002 }
1003
1004 /// Copy offsets from \p R into the current list.
1005 ///
1006 /// Ideally all lists should be strictly ascending, but we defer that to the
1007 /// actual use of the list. So we just blindly append here.
1008 void merge(const OffsetInfo &R) { Offsets.append(R.Offsets); }
1009};
1010
1011#ifndef NDEBUG
1012static raw_ostream &operator<<(raw_ostream &OS, const OffsetInfo &OI) {
1013 ListSeparator LS;
1014 OS << "[";
1015 for (auto Offset : OI) {
1016 OS << LS << Offset;
1017 }
1018 OS << "]";
1019 return OS;
1020}
1021#endif // NDEBUG
1022
1023struct AAPointerInfoImpl
1024 : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1025 using BaseTy = StateWrapper<AA::PointerInfo::State, AAPointerInfo>;
1026 AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
1027
1028 /// See AbstractAttribute::getAsStr().
1029 const std::string getAsStr() const override {
1030 return std::string("PointerInfo ") +
1031 (isValidState() ? (std::string("#") +
1032 std::to_string(OffsetBins.size()) + " bins")
1033 : "<invalid>");
1034 }
1035
1036 /// See AbstractAttribute::manifest(...).
1037 ChangeStatus manifest(Attributor &A) override {
1038 return AAPointerInfo::manifest(A);
1039 }
1040
1041 bool forallInterferingAccesses(
1042 AA::RangeTy Range,
1043 function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
1044 const override {
1045 return State::forallInterferingAccesses(Range, CB);
1046 }
1047
1048 bool forallInterferingAccesses(
1049 Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
1050 bool FindInterferingWrites, bool FindInterferingReads,
1051 function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
1052 AA::RangeTy &Range) const override {
1053 HasBeenWrittenTo = false;
1054
1055 SmallPtrSet<const Access *, 8> DominatingWrites;
1056 SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;
1057
1058 Function &Scope = *I.getFunction();
1059 const auto &NoSyncAA = A.getAAFor<AANoSync>(
1060 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1061 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
1062 IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);
1063 bool AllInSameNoSyncFn = NoSyncAA.isAssumedNoSync();
1064 bool InstIsExecutedByInitialThreadOnly =
1065 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);
1066 bool InstIsExecutedInAlignedRegion =
1067 ExecDomainAA && ExecDomainAA->isExecutedInAlignedRegion(A, I);
1068 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1069 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1070
1071 InformationCache &InfoCache = A.getInfoCache();
1072 bool IsThreadLocalObj =
1073 AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);
1074
1075 // Helper to determine if we need to consider threading, which we cannot
1076 // right now. However, if the function is (assumed) nosync or the thread
1077 // executing all instructions is the main thread only we can ignore
1078 // threading. Also, thread-local objects do not require threading reasoning.
1079 // Finally, we can ignore threading if either access is executed in an
1080 // aligned region.
1081 auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
1082 if (IsThreadLocalObj || AllInSameNoSyncFn)
1083 return true;
1084 const auto *FnExecDomainAA =
1085 I.getFunction() == &Scope
1086 ? ExecDomainAA
1087 : A.lookupAAFor<AAExecutionDomain>(
1088 IRPosition::function(*I.getFunction()), &QueryingAA,
1089 DepClassTy::NONE);
1090 if (!FnExecDomainAA)
1091 return false;
1092 if (InstIsExecutedInAlignedRegion ||
1093 FnExecDomainAA->isExecutedInAlignedRegion(A, I)) {
1094 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1095 return true;
1096 }
1097 if (InstIsExecutedByInitialThreadOnly &&
1098 FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
1099 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1100 return true;
1101 }
1102 return false;
1103 };
1104
1105 // Helper to determine if the access is executed by the same thread as the
1106 // given instruction, for now it is sufficient to avoid any potential
1107 // threading effects as we cannot deal with them anyway.
1108 auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
1109 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1110 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1111 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1112 };
1113
1114 // TODO: Use inter-procedural reachability and dominance.
1115 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
1116 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1117
1118 const bool UseDominanceReasoning =
1119 FindInterferingWrites && NoRecurseAA.isKnownNoRecurse();
1120 const DominatorTree *DT =
1121 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);
1122
1123 // Helper to check if a value has "kernel lifetime", that is it will not
1124 // outlive a GPU kernel. This is true for shared, constant, and local
1125 // globals on AMD and NVIDIA GPUs.
1126 auto HasKernelLifetime = [&](Value *V, Module &M) {
1127 Triple T(M.getTargetTriple());
1128 if (!(T.isAMDGPU() || T.isNVPTX()))
1129 return false;
1130 switch (AA::GPUAddressSpace(V->getType()->getPointerAddressSpace())) {
1131 case AA::GPUAddressSpace::Shared:
1132 case AA::GPUAddressSpace::Constant:
1133 case AA::GPUAddressSpace::Local:
1134 return true;
1135 default:
1136 return false;
1137 };
1138 };
1139
1140 // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
1141 // to determine if we should look at reachability from the callee. For
1142 // certain pointers we know the lifetime and we do not have to step into the
1143 // callee to determine reachability as the pointer would be dead in the
1144 // callee. See the conditional initialization below.
1145 std::function<bool(const Function &)> IsLiveInCalleeCB;
1146
1147 if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {
1148 // If the alloca containing function is not recursive the alloca
1149 // must be dead in the callee.
1150 const Function *AIFn = AI->getFunction();
1151 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
1152 *this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL);
1153 if (NoRecurseAA.isAssumedNoRecurse()) {
1154 IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
1155 }
1156 } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {
1157 // If the global has kernel lifetime we can stop if we reach a kernel
1158 // as it is "dead" in the (unknown) callees.
1159 if (HasKernelLifetime(GV, *GV->getParent()))
1160 IsLiveInCalleeCB = [](const Function &Fn) {
1161 return !Fn.hasFnAttribute("kernel");
1162 };
1163 }
1164
1165 // Set of accesses/instructions that will overwrite the result and are
1166 // therefore blockers in the reachability traversal.
1167 AA::InstExclusionSetTy ExclusionSet;
1168
1169 auto AccessCB = [&](const Access &Acc, bool Exact) {
1170 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
1171 if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))
1172 ExclusionSet.insert(Acc.getRemoteInst());
1173 }
1174
1175 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1176 (!FindInterferingReads || !Acc.isRead()))
1177 return true;
1178
1179 bool Dominates = FindInterferingWrites && DT && Exact &&
1180 Acc.isMustAccess() &&
1181 (Acc.getRemoteInst()->getFunction() == &Scope) &&
1182 DT->dominates(Acc.getRemoteInst(), &I);
1183 if (Dominates)
1184 DominatingWrites.insert(&Acc);
1185
1186 // Track if all interesting accesses are in the same `nosync` function as
1187 // the given instruction.
1188 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;
1189
1190 InterferingAccesses.push_back({&Acc, Exact});
1191 return true;
1192 };
1193 if (!State::forallInterferingAccesses(I, AccessCB, Range))
1194 return false;
1195
1196 HasBeenWrittenTo = !DominatingWrites.empty();
1197
1198 // Dominating writes form a chain, find the least/lowest member.
1199 Instruction *LeastDominatingWriteInst = nullptr;
1200 for (const Access *Acc : DominatingWrites) {
1201 if (!LeastDominatingWriteInst) {
1202 LeastDominatingWriteInst = Acc->getRemoteInst();
1203 } else if (DT->dominates(LeastDominatingWriteInst,
1204 Acc->getRemoteInst())) {
1205 LeastDominatingWriteInst = Acc->getRemoteInst();
1206 }
1207 }
1208
1209 // Helper to determine if we can skip a specific write access.
1210 auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
1211 if (!CanIgnoreThreading(Acc))
1212 return false;
1213
1214 // Check read (RAW) dependences and write (WAR) dependences as necessary.
1215 // If we successfully excluded all effects we are interested in, the
1216 // access can be skipped.
1217 bool ReadChecked = !FindInterferingReads;
1218 bool WriteChecked = !FindInterferingWrites;
1219
1220 // If the instruction cannot reach the access, the former does not
1221 // interfere with what the access reads.
1222 if (!ReadChecked) {
1223 if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,
1224 &ExclusionSet, IsLiveInCalleeCB))
1225 ReadChecked = true;
1226 }
1227 // If the instruction cannot be reach from the access, the latter does not
1228 // interfere with what the instruction reads.
1229 if (!WriteChecked) {
1230 if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,
1231 &ExclusionSet, IsLiveInCalleeCB))
1232 WriteChecked = true;
1233 }
1234
1235 // If we still might be affected by the write of the access but there are
1236 // dominating writes in the function of the instruction
1237 // (HasBeenWrittenTo), we can try to reason that the access is overwritten
1238 // by them. This would have happend above if they are all in the same
1239 // function, so we only check the inter-procedural case. Effectively, we
1240 // want to show that there is no call after the dominting write that might
1241 // reach the access, and when it returns reach the instruction with the
1242 // updated value. To this end, we iterate all call sites, check if they
1243 // might reach the instruction without going through another access
1244 // (ExclusionSet) and at the same time might reach the access. However,
1245 // that is all part of AAInterFnReachability.
1246 if (!WriteChecked && HasBeenWrittenTo &&
1247 Acc.getRemoteInst()->getFunction() != &Scope) {
1248
1249 const auto &FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
1250 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1251
1252 // Without going backwards in the call tree, can we reach the access
1253 // from the least dominating write. Do not allow to pass the instruction
1254 // itself either.
1255 bool Inserted = ExclusionSet.insert(&I).second;
1256
1257 if (!FnReachabilityAA.instructionCanReach(
1258 A, *LeastDominatingWriteInst,
1259 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1260 WriteChecked = true;
1261
1262 if (Inserted)
1263 ExclusionSet.erase(&I);
1264 }
1265
1266 if (ReadChecked && WriteChecked)
1267 return true;
1268
1269 if (!DT || !UseDominanceReasoning)
1270 return false;
1271 if (!DominatingWrites.count(&Acc))
1272 return false;
1273 return LeastDominatingWriteInst != Acc.getRemoteInst();
1274 };
1275
1276 // Run the user callback on all accesses we cannot skip and return if
1277 // that succeeded for all or not.
1278 for (auto &It : InterferingAccesses) {
1279 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1280 !CanSkipAccess(*It.first, It.second)) {
1281 if (!UserCB(*It.first, It.second))
1282 return false;
1283 }
1284 }
1285 return true;
1286 }
1287
1288 ChangeStatus translateAndAddStateFromCallee(Attributor &A,
1289 const AAPointerInfo &OtherAA,
1290 CallBase &CB) {
1291 using namespace AA::PointerInfo;
1292 if (!OtherAA.getState().isValidState() || !isValidState())
1293 return indicatePessimisticFixpoint();
1294
1295 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1296 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1297
1298 // Combine the accesses bin by bin.
1299 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1300 const auto &State = OtherAAImpl.getState();
1301 for (const auto &It : State) {
1302 for (auto Index : It.getSecond()) {
1303 const auto &RAcc = State.getAccess(Index);
1304 if (IsByval && !RAcc.isRead())
1305 continue;
1306 bool UsedAssumedInformation = false;
1307 AccessKind AK = RAcc.getKind();
1308 auto Content = A.translateArgumentToCallSiteContent(
1309 RAcc.getContent(), CB, *this, UsedAssumedInformation);
1310 AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1311 AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1312
1313 Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,
1314 RAcc.getType(), RAcc.getRemoteInst());
1315 }
1316 }
1317 return Changed;
1318 }
1319
1320 ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
1321 const OffsetInfo &Offsets, CallBase &CB) {
1322 using namespace AA::PointerInfo;
1323 if (!OtherAA.getState().isValidState() || !isValidState())
1324 return indicatePessimisticFixpoint();
1325
1326 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1327
1328 // Combine the accesses bin by bin.
1329 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1330 const auto &State = OtherAAImpl.getState();
1331 for (const auto &It : State) {
1332 for (auto Index : It.getSecond()) {
1333 const auto &RAcc = State.getAccess(Index);
1334 for (auto Offset : Offsets) {
1335 auto NewRanges = Offset == AA::RangeTy::Unknown
1336 ? AA::RangeTy::getUnknown()
1337 : RAcc.getRanges();
1338 if (!NewRanges.isUnknown()) {
1339 NewRanges.addToAllOffsets(Offset);
1340 }
1341 Changed |=
1342 addAccess(A, NewRanges, CB, RAcc.getContent(), RAcc.getKind(),
1343 RAcc.getType(), RAcc.getRemoteInst());
1344 }
1345 }
1346 }
1347 return Changed;
1348 }
1349
1350 /// Statistic tracking for all AAPointerInfo implementations.
1351 /// See AbstractAttribute::trackStatistics().
1352 void trackPointerInfoStatistics(const IRPosition &IRP) const {}
1353
1354 /// Dump the state into \p O.
1355 void dumpState(raw_ostream &O) {
1356 for (auto &It : OffsetBins) {
1357 O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
1358 << "] : " << It.getSecond().size() << "\n";
1359 for (auto AccIndex : It.getSecond()) {
1360 auto &Acc = AccessList[AccIndex];
1361 O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
1362 if (Acc.getLocalInst() != Acc.getRemoteInst())
1363 O << " --> " << *Acc.getRemoteInst()
1364 << "\n";
1365 if (!Acc.isWrittenValueYetUndetermined()) {
1366 if (isa_and_nonnull<Function>(Acc.getWrittenValue()))
1367 O << " - c: func " << Acc.getWrittenValue()->getName()
1368 << "\n";
1369 else if (Acc.getWrittenValue())
1370 O << " - c: " << *Acc.getWrittenValue() << "\n";
1371 else
1372 O << " - c: <unknown>\n";
1373 }
1374 }
1375 }
1376 }
1377};
1378
1379struct AAPointerInfoFloating : public AAPointerInfoImpl {
1380 using AccessKind = AAPointerInfo::AccessKind;
1381 AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
1382 : AAPointerInfoImpl(IRP, A) {}
1383
1384 /// Deal with an access and signal if it was handled successfully.
1385 bool handleAccess(Attributor &A, Instruction &I,
1386 std::optional<Value *> Content, AccessKind Kind,
1387 SmallVectorImpl<int64_t> &Offsets, ChangeStatus &Changed,
1388 Type &Ty) {
1389 using namespace AA::PointerInfo;
1390 auto Size = AA::RangeTy::Unknown;
1391 const DataLayout &DL = A.getDataLayout();
1392 TypeSize AccessSize = DL.getTypeStoreSize(&Ty);
1393 if (!AccessSize.isScalable())
1394 Size = AccessSize.getFixedValue();
1395
1396 // Make a strictly ascending list of offsets as required by addAccess()
1397 llvm::sort(Offsets);
1398 auto *Last = std::unique(Offsets.begin(), Offsets.end());
1399 Offsets.erase(Last, Offsets.end());
1400
1401 VectorType *VT = dyn_cast<VectorType>(&Ty);
1402 if (!VT || VT->getElementCount().isScalable() ||
1403 !Content.value_or(nullptr) || !isa<Constant>(*Content) ||
1404 (*Content)->getType() != VT ||
1405 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1406 Changed = Changed | addAccess(A, {Offsets, Size}, I, Content, Kind, &Ty);
1407 } else {
1408 // Handle vector stores with constant content element-wise.
1409 // TODO: We could look for the elements or create instructions
1410 // representing them.
1411 // TODO: We need to push the Content into the range abstraction
1412 // (AA::RangeTy) to allow different content values for different
1413 // ranges. ranges. Hence, support vectors storing different values.
1414 Type *ElementType = VT->getElementType();
1415 int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();
1416 auto *ConstContent = cast<Constant>(*Content);
1417 Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());
1418 SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());
1419
1420 for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1421 Value *ElementContent = ConstantExpr::getExtractElement(
1422 ConstContent, ConstantInt::get(Int32Ty, i));
1423
1424 // Add the element access.
1425 Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,
1426 ElementContent, Kind, ElementType);
1427
1428 // Advance the offsets for the next element.
1429 for (auto &ElementOffset : ElementOffsets)
1430 ElementOffset += ElementSize;
1431 }
1432 }
1433 return true;
1434 };
1435
1436 /// See AbstractAttribute::updateImpl(...).
1437 ChangeStatus updateImpl(Attributor &A) override;
1438
1439 /// If the indices to \p GEP can be traced to constants, incorporate all
1440 /// of these into \p UsrOI.
1441 ///
1442 /// \return true iff \p UsrOI is updated.
1443 bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
1444 OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
1445 const GEPOperator *GEP);
1446
1447 /// See AbstractAttribute::trackStatistics()
1448 void trackStatistics() const override {
1449 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1450 }
1451};
1452
1453bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
1454 const DataLayout &DL,
1455 OffsetInfo &UsrOI,
1456 const OffsetInfo &PtrOI,
1457 const GEPOperator *GEP) {
1458 unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
1459 MapVector<Value *, APInt> VariableOffsets;
1460 APInt ConstantOffset(BitWidth, 0);
1461
1462 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&(static_cast <bool> (!UsrOI.isUnknown() && !PtrOI
.isUnknown() && "Don't look for constant values if the offset has already been "
"determined to be unknown.") ? void (0) : __assert_fail ("!UsrOI.isUnknown() && !PtrOI.isUnknown() && \"Don't look for constant values if the offset has already been \" \"determined to be unknown.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1464, __extension__
__PRETTY_FUNCTION__))
1463 "Don't look for constant values if the offset has already been "(static_cast <bool> (!UsrOI.isUnknown() && !PtrOI
.isUnknown() && "Don't look for constant values if the offset has already been "
"determined to be unknown.") ? void (0) : __assert_fail ("!UsrOI.isUnknown() && !PtrOI.isUnknown() && \"Don't look for constant values if the offset has already been \" \"determined to be unknown.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1464, __extension__
__PRETTY_FUNCTION__))
1464 "determined to be unknown.")(static_cast <bool> (!UsrOI.isUnknown() && !PtrOI
.isUnknown() && "Don't look for constant values if the offset has already been "
"determined to be unknown.") ? void (0) : __assert_fail ("!UsrOI.isUnknown() && !PtrOI.isUnknown() && \"Don't look for constant values if the offset has already been \" \"determined to be unknown.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1464, __extension__
__PRETTY_FUNCTION__))
;
1465
1466 if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
1467 UsrOI.setUnknown();
1468 return true;
1469 }
1470
1471 LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] GEP offset is "
<< (VariableOffsets.empty() ? "" : "not") << " constant "
<< *GEP << "\n"; } } while (false)
1472 << (VariableOffsets.empty() ? "" : "not") << " constant "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] GEP offset is "
<< (VariableOffsets.empty() ? "" : "not") << " constant "
<< *GEP << "\n"; } } while (false)
1473 << *GEP << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] GEP offset is "
<< (VariableOffsets.empty() ? "" : "not") << " constant "
<< *GEP << "\n"; } } while (false)
;
1474
1475 auto Union = PtrOI;
1476 Union.addToAll(ConstantOffset.getSExtValue());
1477
1478 // Each VI in VariableOffsets has a set of potential constant values. Every
1479 // combination of elements, picked one each from these sets, is separately
1480 // added to the original set of offsets, thus resulting in more offsets.
1481 for (const auto &VI : VariableOffsets) {
1482 auto &PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
1483 *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);
1484 if (!PotentialConstantsAA.isValidState()) {
1485 UsrOI.setUnknown();
1486 return true;
1487 }
1488
1489 // UndefValue is treated as a zero, which leaves Union as is.
1490 if (PotentialConstantsAA.undefIsContained())
1491 continue;
1492
1493 // We need at least one constant in every set to compute an actual offset.
1494 // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
1495 // don't actually exist. In other words, the absence of constant values
1496 // implies that the operation can be assumed dead for now.
1497 auto &AssumedSet = PotentialConstantsAA.getAssumedSet();
1498 if (AssumedSet.empty())
1499 return false;
1500
1501 OffsetInfo Product;
1502 for (const auto &ConstOffset : AssumedSet) {
1503 auto CopyPerOffset = Union;
1504 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1505 VI.second.getZExtValue());
1506 Product.merge(CopyPerOffset);
1507 }
1508 Union = Product;
1509 }
1510
1511 UsrOI = std::move(Union);
1512 return true;
1513}
1514
1515ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
1516 using namespace AA::PointerInfo;
1517 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1518 const DataLayout &DL = A.getDataLayout();
1519 Value &AssociatedValue = getAssociatedValue();
1520
1521 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1522 OffsetInfoMap[&AssociatedValue].insert(0);
1523
1524 auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
1525 // One does not simply walk into a map and assign a reference to a possibly
1526 // new location. That can cause an invalidation before the assignment
1527 // happens, like so:
1528 //
1529 // OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
1530 //
1531 // The RHS is a reference that may be invalidated by an insertion caused by
1532 // the LHS. So we ensure that the side-effect of the LHS happens first.
1533 auto &UsrOI = OffsetInfoMap[Usr];
1534 auto &PtrOI = OffsetInfoMap[CurPtr];
1535 assert(!PtrOI.isUnassigned() &&(static_cast <bool> (!PtrOI.isUnassigned() && "Cannot pass through if the input Ptr was not visited!"
) ? void (0) : __assert_fail ("!PtrOI.isUnassigned() && \"Cannot pass through if the input Ptr was not visited!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1536, __extension__
__PRETTY_FUNCTION__))
1536 "Cannot pass through if the input Ptr was not visited!")(static_cast <bool> (!PtrOI.isUnassigned() && "Cannot pass through if the input Ptr was not visited!"
) ? void (0) : __assert_fail ("!PtrOI.isUnassigned() && \"Cannot pass through if the input Ptr was not visited!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1536, __extension__
__PRETTY_FUNCTION__))
;
1537 UsrOI = PtrOI;
1538 Follow = true;
1539 return true;
1540 };
1541
1542 const auto *F = getAnchorScope();
1543 const auto *CI =
1544 F ? A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(*F)
1545 : nullptr;
1546 const auto *TLI =
1547 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
1548
1549 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1550 Value *CurPtr = U.get();
1551 User *Usr = U.getUser();
1552 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usrdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Analyze " <<
*CurPtr << " in " << *Usr << "\n"; } } while
(false)
1553 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Analyze " <<
*CurPtr << " in " << *Usr << "\n"; } } while
(false)
;
1554 assert(OffsetInfoMap.count(CurPtr) &&(static_cast <bool> (OffsetInfoMap.count(CurPtr) &&
"The current pointer offset should have been seeded!") ? void
(0) : __assert_fail ("OffsetInfoMap.count(CurPtr) && \"The current pointer offset should have been seeded!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1555, __extension__
__PRETTY_FUNCTION__))
1555 "The current pointer offset should have been seeded!")(static_cast <bool> (OffsetInfoMap.count(CurPtr) &&
"The current pointer offset should have been seeded!") ? void
(0) : __assert_fail ("OffsetInfoMap.count(CurPtr) && \"The current pointer offset should have been seeded!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1555, __extension__
__PRETTY_FUNCTION__))
;
1556
1557 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
1558 if (CE->isCast())
1559 return HandlePassthroughUser(Usr, CurPtr, Follow);
1560 if (CE->isCompare())
1561 return true;
1562 if (!isa<GEPOperator>(CE)) {
1563 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CEdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled constant user "
<< *CE << "\n"; } } while (false)
1564 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled constant user "
<< *CE << "\n"; } } while (false)
;
1565 return false;
1566 }
1567 }
1568 if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {
1569 // Note the order here, the Usr access might change the map, CurPtr is
1570 // already in it though.
1571 auto &UsrOI = OffsetInfoMap[Usr];
1572 auto &PtrOI = OffsetInfoMap[CurPtr];
1573
1574 if (UsrOI.isUnknown())
1575 return true;
1576
1577 if (PtrOI.isUnknown()) {
1578 Follow = true;
1579 UsrOI.setUnknown();
1580 return true;
1581 }
1582
1583 Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
1584 return true;
1585 }
1586 if (isa<PtrToIntInst>(Usr))
1587 return false;
1588 if (isa<CastInst>(Usr) || isa<SelectInst>(Usr) || isa<ReturnInst>(Usr))
1589 return HandlePassthroughUser(Usr, CurPtr, Follow);
1590
1591 // For PHIs we need to take care of the recurrence explicitly as the value
1592 // might change while we iterate through a loop. For now, we give up if
1593 // the PHI is not invariant.
1594 if (isa<PHINode>(Usr)) {
1595 // Note the order here, the Usr access might change the map, CurPtr is
1596 // already in it though.
1597 bool IsFirstPHIUser = !OffsetInfoMap.count(Usr);
1598 auto &UsrOI = OffsetInfoMap[Usr];
1599 auto &PtrOI = OffsetInfoMap[CurPtr];
1600
1601 // Check if the PHI operand has already an unknown offset as we can't
1602 // improve on that anymore.
1603 if (PtrOI.isUnknown()) {
1604 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand offset unknown "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
1605 << *CurPtr << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand offset unknown "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1606 Follow = !UsrOI.isUnknown();
1607 UsrOI.setUnknown();
1608 return true;
1609 }
1610
1611 // Check if the PHI is invariant (so far).
1612 if (UsrOI == PtrOI) {
1613 assert(!PtrOI.isUnassigned() &&(static_cast <bool> (!PtrOI.isUnassigned() && "Cannot assign if the current Ptr was not visited!"
) ? void (0) : __assert_fail ("!PtrOI.isUnassigned() && \"Cannot assign if the current Ptr was not visited!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1614, __extension__
__PRETTY_FUNCTION__))
1614 "Cannot assign if the current Ptr was not visited!")(static_cast <bool> (!PtrOI.isUnassigned() && "Cannot assign if the current Ptr was not visited!"
) ? void (0) : __assert_fail ("!PtrOI.isUnassigned() && \"Cannot assign if the current Ptr was not visited!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1614, __extension__
__PRETTY_FUNCTION__))
;
1615 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI is invariant (so far)"
; } } while (false)
;
1616 return true;
1617 }
1618
1619 // Check if the PHI operand can be traced back to AssociatedValue.
1620 APInt Offset(
1621 DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),
1622 0);
1623 Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
1624 DL, Offset, /* AllowNonInbounds */ true);
1625 auto It = OffsetInfoMap.find(CurPtrBase);
1626 if (It == OffsetInfoMap.end()) {
1627 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand is too complex "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
1628 << *CurPtr << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand is too complex "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1629 UsrOI.setUnknown();
1630 Follow = true;
1631 return true;
1632 }
1633
1634 // Check if the PHI operand is not dependent on the PHI itself. Every
1635 // recurrence is a cyclic net of PHIs in the data flow, and has an
1636 // equivalent Cycle in the control flow. One of those PHIs must be in the
1637 // header of that control flow Cycle. This is independent of the choice of
1638 // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
1639 // every Cycle header; if such a node is marked unknown, this will
1640 // eventually propagate through the whole net of PHIs in the recurrence.
1641 if (mayBeInCycle(CI, cast<Instruction>(Usr), /* HeaderOnly */ true)) {
1642 auto BaseOI = It->getSecond();
1643 BaseOI.addToAll(Offset.getZExtValue());
1644 if (IsFirstPHIUser || BaseOI == UsrOI) {
1645 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtrdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI is invariant "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
1646 << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI is invariant "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1647 return HandlePassthroughUser(Usr, CurPtr, Follow);
1648 }
1649
1650 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
1651 dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
1652 << *CurPtr << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1653 UsrOI.setUnknown();
1654 Follow = true;
1655 return true;
1656 }
1657
1658 UsrOI.merge(PtrOI);
1659 Follow = true;
1660 return true;
1661 }
1662
1663 if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {
1664 // If the access is to a pointer that may or may not be the associated
1665 // value, e.g. due to a PHI, we cannot assume it will be read.
1666 AccessKind AK = AccessKind::AK_R;
1667 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1668 AK = AccessKind(AK | AccessKind::AK_MUST);
1669 else
1670 AK = AccessKind(AK | AccessKind::AK_MAY);
1671 if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,
1672 OffsetInfoMap[CurPtr].Offsets, Changed,
1673 *LoadI->getType()))
1674 return false;
1675
1676 auto IsAssumption = [](Instruction &I) {
1677 if (auto *II = dyn_cast<IntrinsicInst>(&I))
1678 return II->isAssumeLikeIntrinsic();
1679 return false;
1680 };
1681
1682 auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
1683 // Check if the assumption and the load are executed together without
1684 // memory modification.
1685 do {
1686 if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
1687 return true;
1688 FromI = FromI->getNextNonDebugInstruction();
1689 } while (FromI && FromI != ToI);
1690 return false;
1691 };
1692
1693 BasicBlock *BB = LoadI->getParent();
1694 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1695 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1696 return false;
1697 BasicBlock *IntrBB = IntrI.getParent();
1698 if (IntrI.getParent() == BB) {
1699 if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(), &IntrI))
1700 return false;
1701 } else {
1702 auto PredIt = pred_begin(IntrBB);
1703 if (PredIt == pred_end(IntrBB))
1704 return false;
1705 if ((*PredIt) != BB)
1706 return false;
1707 if (++PredIt != pred_end(IntrBB))
1708 return false;
1709 for (auto *SuccBB : successors(BB)) {
1710 if (SuccBB == IntrBB)
1711 continue;
1712 if (isa<UnreachableInst>(SuccBB->getTerminator()))
1713 continue;
1714 return false;
1715 }
1716 if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(),
1717 BB->getTerminator()))
1718 return false;
1719 if (IsImpactedInRange(&IntrBB->front(), &IntrI))
1720 return false;
1721 }
1722 return true;
1723 };
1724
1725 std::pair<Value *, IntrinsicInst *> Assumption;
1726 for (const Use &LoadU : LoadI->uses()) {
1727 if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {
1728 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1729 continue;
1730 for (const Use &CmpU : CmpI->uses()) {
1731 if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {
1732 if (!IsValidAssume(*IntrI))
1733 continue;
1734 int Idx = CmpI->getOperandUse(0) == LoadU;
1735 Assumption = {CmpI->getOperand(Idx), IntrI};
1736 break;
1737 }
1738 }
1739 }
1740 if (Assumption.first)
1741 break;
1742 }
1743
1744 // Check if we found an assumption associated with this load.
1745 if (!Assumption.first || !Assumption.second)
1746 return true;
1747
1748 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Assumption found "
<< *Assumption.second << ": " << *LoadI <<
" == " << *Assumption.first << "\n"; } } while (
false)
1749 << *Assumption.second << ": " << *LoadIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Assumption found "
<< *Assumption.second << ": " << *LoadI <<
" == " << *Assumption.first << "\n"; } } while (
false)
1750 << " == " << *Assumption.first << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Assumption found "
<< *Assumption.second << ": " << *LoadI <<
" == " << *Assumption.first << "\n"; } } while (
false)
;
1751
1752 return handleAccess(
1753 A, *Assumption.second, Assumption.first, AccessKind::AK_ASSUMPTION,
1754 OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());
1755 }
1756
1757 auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
1758 ArrayRef<Value *> OtherOps, AccessKind AK) {
1759 for (auto *OtherOp : OtherOps) {
1760 if (OtherOp == CurPtr) {
1761 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Escaping use in store like instruction "
<< I << "\n"; } } while (false)
1762 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Escaping use in store like instruction "
<< I << "\n"; } } while (false)
1763 << "[AAPointerInfo] Escaping use in store like instruction " << Ido { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Escaping use in store like instruction "
<< I << "\n"; } } while (false)
1764 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Escaping use in store like instruction "
<< I << "\n"; } } while (false)
;
1765 return false;
1766 }
1767 }
1768
1769 // If the access is to a pointer that may or may not be the associated
1770 // value, e.g. due to a PHI, we cannot assume it will be written.
1771 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1772 AK = AccessKind(AK | AccessKind::AK_MUST);
1773 else
1774 AK = AccessKind(AK | AccessKind::AK_MAY);
1775 bool UsedAssumedInformation = false;
1776 std::optional<Value *> Content = nullptr;
1777 if (ValueOp)
1778 Content = A.getAssumedSimplified(
1779 *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
1780 return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1781 Changed, ValueTy);
1782 };
1783
1784 if (auto *StoreI = dyn_cast<StoreInst>(Usr))
1785 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1786 *StoreI->getValueOperand()->getType(),
1787 {StoreI->getValueOperand()}, AccessKind::AK_W);
1788 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
1789 return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
1790 {RMWI->getValOperand()}, AccessKind::AK_RW);
1791 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
1792 return HandleStoreLike(
1793 *CXI, nullptr, *CXI->getNewValOperand()->getType(),
1794 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1795 AccessKind::AK_RW);
1796
1797 if (auto *CB = dyn_cast<CallBase>(Usr)) {
1798 if (CB->isLifetimeStartOrEnd())
1799 return true;
1800 if (getFreedOperand(CB, TLI) == U)
1801 return true;
1802 if (CB->isArgOperand(&U)) {
1803 unsigned ArgNo = CB->getArgOperandNo(&U);
1804 const auto &CSArgPI = A.getAAFor<AAPointerInfo>(
1805 *this, IRPosition::callsite_argument(*CB, ArgNo),
1806 DepClassTy::REQUIRED);
1807 Changed = translateAndAddState(A, CSArgPI, OffsetInfoMap[CurPtr], *CB) |
1808 Changed;
1809 return isValidState();
1810 }
1811 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CBdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Call user not handled "
<< *CB << "\n"; } } while (false)
1812 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Call user not handled "
<< *CB << "\n"; } } while (false)
;
1813 // TODO: Allow some call uses
1814 return false;
1815 }
1816
1817 LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] User not handled "
<< *Usr << "\n"; } } while (false)
;
1818 return false;
1819 };
1820 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
1821 assert(OffsetInfoMap.count(OldU) && "Old use should be known already!")(static_cast <bool> (OffsetInfoMap.count(OldU) &&
"Old use should be known already!") ? void (0) : __assert_fail
("OffsetInfoMap.count(OldU) && \"Old use should be known already!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 1821, __extension__
__PRETTY_FUNCTION__))
;
1822 if (OffsetInfoMap.count(NewU)) {
1823 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!(OffsetInfoMap[NewU] == OffsetInfoMap
[OldU])) { dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
<< OffsetInfoMap[NewU] << " vs " << OffsetInfoMap
[OldU] << "\n"; } }; } } while (false)
1824 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!(OffsetInfoMap[NewU] == OffsetInfoMap
[OldU])) { dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
<< OffsetInfoMap[NewU] << " vs " << OffsetInfoMap
[OldU] << "\n"; } }; } } while (false)
1825 dbgs() << "[AAPointerInfo] Equivalent use callback failed: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!(OffsetInfoMap[NewU] == OffsetInfoMap
[OldU])) { dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
<< OffsetInfoMap[NewU] << " vs " << OffsetInfoMap
[OldU] << "\n"; } }; } } while (false)
1826 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!(OffsetInfoMap[NewU] == OffsetInfoMap
[OldU])) { dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
<< OffsetInfoMap[NewU] << " vs " << OffsetInfoMap
[OldU] << "\n"; } }; } } while (false)
1827 << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!(OffsetInfoMap[NewU] == OffsetInfoMap
[OldU])) { dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
<< OffsetInfoMap[NewU] << " vs " << OffsetInfoMap
[OldU] << "\n"; } }; } } while (false)
1828 }do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!(OffsetInfoMap[NewU] == OffsetInfoMap
[OldU])) { dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
<< OffsetInfoMap[NewU] << " vs " << OffsetInfoMap
[OldU] << "\n"; } }; } } while (false)
1829 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!(OffsetInfoMap[NewU] == OffsetInfoMap
[OldU])) { dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
<< OffsetInfoMap[NewU] << " vs " << OffsetInfoMap
[OldU] << "\n"; } }; } } while (false)
;
1830 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1831 }
1832 OffsetInfoMap[NewU] = OffsetInfoMap[OldU];
1833 return true;
1834 };
1835 if (!A.checkForAllUses(UsePred, *this, AssociatedValue,
1836 /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,
1837 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
1838 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n"
; } } while (false)
;
1839 return indicatePessimisticFixpoint();
1840 }
1841
1842 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1843 dbgs() << "Accesses by bin after update:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1844 dumpState(dbgs());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1845 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
;
1846
1847 return Changed;
1848}
1849
1850struct AAPointerInfoReturned final : AAPointerInfoImpl {
1851 AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
1852 : AAPointerInfoImpl(IRP, A) {}
1853
1854 /// See AbstractAttribute::updateImpl(...).
1855 ChangeStatus updateImpl(Attributor &A) override {
1856 return indicatePessimisticFixpoint();
1857 }
1858
1859 /// See AbstractAttribute::trackStatistics()
1860 void trackStatistics() const override {
1861 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1862 }
1863};
1864
1865struct AAPointerInfoArgument final : AAPointerInfoFloating {
1866 AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
1867 : AAPointerInfoFloating(IRP, A) {}
1868
1869 /// See AbstractAttribute::initialize(...).
1870 void initialize(Attributor &A) override {
1871 AAPointerInfoFloating::initialize(A);
1872 if (getAnchorScope()->isDeclaration())
1873 indicatePessimisticFixpoint();
1874 }
1875
1876 /// See AbstractAttribute::trackStatistics()
1877 void trackStatistics() const override {
1878 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1879 }
1880};
1881
1882struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1883 AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
1884 : AAPointerInfoFloating(IRP, A) {}
1885
1886 /// See AbstractAttribute::updateImpl(...).
1887 ChangeStatus updateImpl(Attributor &A) override {
1888 using namespace AA::PointerInfo;
1889 // We handle memory intrinsics explicitly, at least the first (=
1890 // destination) and second (=source) arguments as we know how they are
1891 // accessed.
1892 if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
1893 ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
1894 int64_t LengthVal = AA::RangeTy::Unknown;
1895 if (Length)
1896 LengthVal = Length->getSExtValue();
1897 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1898 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1899 if (ArgNo > 1) {
1900 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
<< *MI << "\n"; } } while (false)
1901 << *MI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
<< *MI << "\n"; } } while (false)
;
1902 return indicatePessimisticFixpoint();
1903 } else {
1904 auto Kind =
1905 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1906 Changed =
1907 Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);
1908 }
1909 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1910 dbgs() << "Accesses by bin after update:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1911 dumpState(dbgs());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1912 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
;
1913
1914 return Changed;
1915 }
1916
1917 // TODO: Once we have call site specific value information we can provide
1918 // call site specific liveness information and then it makes
1919 // sense to specialize attributes for call sites arguments instead of
1920 // redirecting requests to the callee argument.
1921 Argument *Arg = getAssociatedArgument();
1922 if (Arg) {
1923 const IRPosition &ArgPos = IRPosition::argument(*Arg);
1924 auto &ArgAA =
1925 A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
1926 if (ArgAA.getState().isValidState())
1927 return translateAndAddStateFromCallee(A, ArgAA,
1928 *cast<CallBase>(getCtxI()));
1929 if (!Arg->getParent()->isDeclaration())
1930 return indicatePessimisticFixpoint();
1931 }
1932
1933 const auto &NoCaptureAA =
1934 A.getAAFor<AANoCapture>(*this, getIRPosition(), DepClassTy::OPTIONAL);
1935
1936 if (!NoCaptureAA.isAssumedNoCapture())
1937 return indicatePessimisticFixpoint();
1938
1939 bool IsKnown = false;
1940 if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
1941 return ChangeStatus::UNCHANGED;
1942 bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);
1943 auto Kind =
1944 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
1945 return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,
1946 nullptr);
1947 }
1948
1949 /// See AbstractAttribute::trackStatistics()
1950 void trackStatistics() const override {
1951 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1952 }
1953};
1954
1955struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
1956 AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
1957 : AAPointerInfoFloating(IRP, A) {}
1958
1959 /// See AbstractAttribute::trackStatistics()
1960 void trackStatistics() const override {
1961 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1962 }
1963};
1964} // namespace
1965
1966/// -----------------------NoUnwind Function Attribute--------------------------
1967
1968namespace {
1969struct AANoUnwindImpl : AANoUnwind {
1970 AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}
1971
1972 const std::string getAsStr() const override {
1973 return getAssumed() ? "nounwind" : "may-unwind";
1974 }
1975
1976 /// See AbstractAttribute::updateImpl(...).
1977 ChangeStatus updateImpl(Attributor &A) override {
1978 auto Opcodes = {
1979 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
1980 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
1981 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
1982
1983 auto CheckForNoUnwind = [&](Instruction &I) {
1984 if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
1985 return true;
1986
1987 if (const auto *CB = dyn_cast<CallBase>(&I)) {
1988 const auto &NoUnwindAA = A.getAAFor<AANoUnwind>(
1989 *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);
1990 return NoUnwindAA.isAssumedNoUnwind();
1991 }
1992 return false;
1993 };
1994
1995 bool UsedAssumedInformation = false;
1996 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
1997 UsedAssumedInformation))
1998 return indicatePessimisticFixpoint();
1999
2000 return ChangeStatus::UNCHANGED;
2001 }
2002};
2003
2004struct AANoUnwindFunction final : public AANoUnwindImpl {
2005 AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
2006 : AANoUnwindImpl(IRP, A) {}
2007
2008 /// See AbstractAttribute::trackStatistics()
2009 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind){ static llvm::Statistic NumIRFunction_nounwind = {"attributor"
, "NumIRFunction_nounwind", ("Number of " "functions" " marked '"
"nounwind" "'")};; ++(NumIRFunction_nounwind); }
}
2010};
2011
2012/// NoUnwind attribute deduction for a call sites.
2013struct AANoUnwindCallSite final : AANoUnwindImpl {
2014 AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
2015 : AANoUnwindImpl(IRP, A) {}
2016
2017 /// See AbstractAttribute::initialize(...).
2018 void initialize(Attributor &A) override {
2019 AANoUnwindImpl::initialize(A);
2020 Function *F = getAssociatedFunction();
2021 if (!F || F->isDeclaration())
2022 indicatePessimisticFixpoint();
2023 }
2024
2025 /// See AbstractAttribute::updateImpl(...).
2026 ChangeStatus updateImpl(Attributor &A) override {
2027 // TODO: Once we have call site specific value information we can provide
2028 // call site specific liveness information and then it makes
2029 // sense to specialize attributes for call sites arguments instead of
2030 // redirecting requests to the callee argument.
2031 Function *F = getAssociatedFunction();
2032 const IRPosition &FnPos = IRPosition::function(*F);
2033 auto &FnAA = A.getAAFor<AANoUnwind>(*this, FnPos, DepClassTy::REQUIRED);
2034 return clampStateAndIndicateChange(getState(), FnAA.getState());
2035 }
2036
2037 /// See AbstractAttribute::trackStatistics()
2038 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind){ static llvm::Statistic NumIRCS_nounwind = {"attributor", "NumIRCS_nounwind"
, ("Number of " "call site" " marked '" "nounwind" "'")};; ++
(NumIRCS_nounwind); }
; }
2039};
2040} // namespace
2041
2042/// --------------------- Function Return Values -------------------------------
2043
2044namespace {
2045/// "Attribute" that collects all potential returned values and the return
2046/// instructions that they arise from.
2047///
2048/// If there is a unique returned value R, the manifest method will:
2049/// - mark R with the "returned" attribute, if R is an argument.
2050class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
2051
2052 /// Mapping of values potentially returned by the associated function to the
2053 /// return instructions that might return them.
2054 MapVector<Value *, SmallSetVector<ReturnInst *, 4>> ReturnedValues;
2055
2056 /// State flags
2057 ///
2058 ///{
2059 bool IsFixed = false;
2060 bool IsValidState = true;
2061 ///}
2062
2063public:
2064 AAReturnedValuesImpl(const IRPosition &IRP, Attributor &A)
2065 : AAReturnedValues(IRP, A) {}
2066
2067 /// See AbstractAttribute::initialize(...).
2068 void initialize(Attributor &A) override {
2069 // Reset the state.
2070 IsFixed = false;
2071 IsValidState = true;
2072 ReturnedValues.clear();
2073
2074 Function *F = getAssociatedFunction();
2075 if (!F || F->isDeclaration()) {
2076 indicatePessimisticFixpoint();
2077 return;
2078 }
2079 assert(!F->getReturnType()->isVoidTy() &&(static_cast <bool> (!F->getReturnType()->isVoidTy
() && "Did not expect a void return type!") ? void (0
) : __assert_fail ("!F->getReturnType()->isVoidTy() && \"Did not expect a void return type!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2080, __extension__
__PRETTY_FUNCTION__))
2080 "Did not expect a void return type!")(static_cast <bool> (!F->getReturnType()->isVoidTy
() && "Did not expect a void return type!") ? void (0
) : __assert_fail ("!F->getReturnType()->isVoidTy() && \"Did not expect a void return type!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2080, __extension__
__PRETTY_FUNCTION__))
;
2081
2082 // The map from instruction opcodes to those instructions in the function.
2083 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
2084
2085 // Look through all arguments, if one is marked as returned we are done.
2086 for (Argument &Arg : F->args()) {
2087 if (Arg.hasReturnedAttr()) {
2088 auto &ReturnInstSet = ReturnedValues[&Arg];
2089 if (auto *Insts = OpcodeInstMap.lookup(Instruction::Ret))
2090 for (Instruction *RI : *Insts)
2091 ReturnInstSet.insert(cast<ReturnInst>(RI));
2092
2093 indicateOptimisticFixpoint();
2094 return;
2095 }
2096 }
2097
2098 if (!A.isFunctionIPOAmendable(*F))
2099 indicatePessimisticFixpoint();
2100 }
2101
2102 /// See AbstractAttribute::manifest(...).
2103 ChangeStatus manifest(Attributor &A) override;
2104
2105 /// See AbstractAttribute::getState(...).
2106 AbstractState &getState() override { return *this; }
2107
2108 /// See AbstractAttribute::getState(...).
2109 const AbstractState &getState() const override { return *this; }
2110
2111 /// See AbstractAttribute::updateImpl(Attributor &A).
2112 ChangeStatus updateImpl(Attributor &A) override;
2113
2114 llvm::iterator_range<iterator> returned_values() override {
2115 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
2116 }
2117
2118 llvm::iterator_range<const_iterator> returned_values() const override {
2119 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
2120 }
2121
2122 /// Return the number of potential return values, -1 if unknown.
2123 size_t getNumReturnValues() const override {
2124 return isValidState() ? ReturnedValues.size() : -1;
2125 }
2126
2127 /// Return an assumed unique return value if a single candidate is found. If
2128 /// there cannot be one, return a nullptr. If it is not clear yet, return
2129 /// std::nullopt.
2130 std::optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
2131
2132 /// See AbstractState::checkForAllReturnedValues(...).
2133 bool checkForAllReturnedValuesAndReturnInsts(
2134 function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred)
2135 const override;
2136
2137 /// Pretty print the attribute similar to the IR representation.
2138 const std::string getAsStr() const override;
2139
2140 /// See AbstractState::isAtFixpoint().
2141 bool isAtFixpoint() const override { return IsFixed; }
2142
2143 /// See AbstractState::isValidState().
2144 bool isValidState() const override { return IsValidState; }
2145
2146 /// See AbstractState::indicateOptimisticFixpoint(...).
2147 ChangeStatus indicateOptimisticFixpoint() override {
2148 IsFixed = true;
2149 return ChangeStatus::UNCHANGED;
2150 }
2151
2152 ChangeStatus indicatePessimisticFixpoint() override {
2153 IsFixed = true;
2154 IsValidState = false;
2155 return ChangeStatus::CHANGED;
2156 }
2157};
2158
2159ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
2160 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2161
2162 // Bookkeeping.
2163 assert(isValidState())(static_cast <bool> (isValidState()) ? void (0) : __assert_fail
("isValidState()", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 2163, __extension__ __PRETTY_FUNCTION__))
;
2164 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,{ static llvm::Statistic NumIRFunctionReturn_KnownReturnValues
= {"attributor", "NumIRFunctionReturn_KnownReturnValues", "Number of function with known return values"
};; ++(NumIRFunctionReturn_KnownReturnValues); }
2165 "Number of function with known return values"){ static llvm::Statistic NumIRFunctionReturn_KnownReturnValues
= {"attributor", "NumIRFunctionReturn_KnownReturnValues", "Number of function with known return values"
};; ++(NumIRFunctionReturn_KnownReturnValues); }
;
2166
2167 // Check if we have an assumed unique return value that we could manifest.
2168 std::optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
2169
2170 if (!UniqueRV || !*UniqueRV)
2171 return Changed;
2172
2173 // Bookkeeping.
2174 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,{ static llvm::Statistic NumIRFunctionReturn_UniqueReturnValue
= {"attributor", "NumIRFunctionReturn_UniqueReturnValue", "Number of function with unique return"
};; ++(NumIRFunctionReturn_UniqueReturnValue); }
2175 "Number of function with unique return"){ static llvm::Statistic NumIRFunctionReturn_UniqueReturnValue
= {"attributor", "NumIRFunctionReturn_UniqueReturnValue", "Number of function with unique return"
};; ++(NumIRFunctionReturn_UniqueReturnValue); }
;
2176 // If the assumed unique return value is an argument, annotate it.
2177 if (auto *UniqueRVArg = dyn_cast<Argument>(*UniqueRV)) {
2178 if (UniqueRVArg->getType()->canLosslesslyBitCastTo(
2179 getAssociatedFunction()->getReturnType())) {
2180 getIRPosition() = IRPosition::argument(*UniqueRVArg);
2181 Changed = IRAttribute::manifest(A);
2182 }
2183 }
2184 return Changed;
2185}
2186
2187const std::string AAReturnedValuesImpl::getAsStr() const {
2188 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
2189 (isValidState() ? std::to_string(getNumReturnValues()) : "?") + ")";
2190}
2191
2192std::optional<Value *>
2193AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
2194 // If checkForAllReturnedValues provides a unique value, ignoring potential
2195 // undef values that can also be present, it is assumed to be the actual
2196 // return value and forwarded to the caller of this method. If there are
2197 // multiple, a nullptr is returned indicating there cannot be a unique
2198 // returned value.
2199 std::optional<Value *> UniqueRV;
2200 Type *Ty = getAssociatedFunction()->getReturnType();
2201
2202 auto Pred = [&](Value &RV) -> bool {
2203 UniqueRV = AA::combineOptionalValuesInAAValueLatice(UniqueRV, &RV, Ty);
2204 return UniqueRV != std::optional<Value *>(nullptr);
2205 };
2206
2207 if (!A.checkForAllReturnedValues(Pred, *this))
2208 UniqueRV = nullptr;
2209
2210 return UniqueRV;
2211}
2212
2213bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
2214 function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred)
2215 const {
2216 if (!isValidState())
2217 return false;
2218
2219 // Check all returned values but ignore call sites as long as we have not
2220 // encountered an overdefined one during an update.
2221 for (const auto &It : ReturnedValues) {
2222 Value *RV = It.first;
2223 if (!Pred(*RV, It.second))
2224 return false;
2225 }
2226
2227 return true;
2228}
2229
2230ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
2231 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2232
2233 SmallVector<AA::ValueAndContext> Values;
2234 bool UsedAssumedInformation = false;
2235 auto ReturnInstCB = [&](Instruction &I) {
2236 ReturnInst &Ret = cast<ReturnInst>(I);
2237 Values.clear();
2238 if (!A.getAssumedSimplifiedValues(IRPosition::value(*Ret.getReturnValue()),
2239 *this, Values, AA::Intraprocedural,
2240 UsedAssumedInformation))
2241 Values.push_back({*Ret.getReturnValue(), Ret});
2242
2243 for (auto &VAC : Values) {
2244 assert(AA::isValidInScope(*VAC.getValue(), Ret.getFunction()) &&(static_cast <bool> (AA::isValidInScope(*VAC.getValue()
, Ret.getFunction()) && "Assumed returned value should be valid in function scope!"
) ? void (0) : __assert_fail ("AA::isValidInScope(*VAC.getValue(), Ret.getFunction()) && \"Assumed returned value should be valid in function scope!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2245, __extension__
__PRETTY_FUNCTION__))
2245 "Assumed returned value should be valid in function scope!")(static_cast <bool> (AA::isValidInScope(*VAC.getValue()
, Ret.getFunction()) && "Assumed returned value should be valid in function scope!"
) ? void (0) : __assert_fail ("AA::isValidInScope(*VAC.getValue(), Ret.getFunction()) && \"Assumed returned value should be valid in function scope!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2245, __extension__
__PRETTY_FUNCTION__))
;
2246 if (ReturnedValues[VAC.getValue()].insert(&Ret))
2247 Changed = ChangeStatus::CHANGED;
2248 }
2249 return true;
2250 };
2251
2252 // Discover returned values from all live returned instructions in the
2253 // associated function.
2254 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
2255 UsedAssumedInformation))
2256 return indicatePessimisticFixpoint();
2257 return Changed;
2258}
2259
2260struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
2261 AAReturnedValuesFunction(const IRPosition &IRP, Attributor &A)
2262 : AAReturnedValuesImpl(IRP, A) {}
2263
2264 /// See AbstractAttribute::trackStatistics()
2265 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned){ static llvm::Statistic NumIRArguments_returned = {"attributor"
, "NumIRArguments_returned", ("Number of " "arguments" " marked '"
"returned" "'")};; ++(NumIRArguments_returned); }
}
2266};
2267
2268/// Returned values information for a call sites.
2269struct AAReturnedValuesCallSite final : AAReturnedValuesImpl {
2270 AAReturnedValuesCallSite(const IRPosition &IRP, Attributor &A)
2271 : AAReturnedValuesImpl(IRP, A) {}
2272
2273 /// See AbstractAttribute::initialize(...).
2274 void initialize(Attributor &A) override {
2275 // TODO: Once we have call site specific value information we can provide
2276 // call site specific liveness information and then it makes
2277 // sense to specialize attributes for call sites instead of
2278 // redirecting requests to the callee.
2279 llvm_unreachable("Abstract attributes for returned values are not "::llvm::llvm_unreachable_internal("Abstract attributes for returned values are not "
"supported for call sites yet!", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 2280)
2280 "supported for call sites yet!")::llvm::llvm_unreachable_internal("Abstract attributes for returned values are not "
"supported for call sites yet!", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 2280)
;
2281 }
2282
2283 /// See AbstractAttribute::updateImpl(...).
2284 ChangeStatus updateImpl(Attributor &A) override {
2285 return indicatePessimisticFixpoint();
2286 }
2287
2288 /// See AbstractAttribute::trackStatistics()
2289 void trackStatistics() const override {}
2290};
2291} // namespace
2292
2293/// ------------------------ NoSync Function Attribute -------------------------
2294
2295bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
2296 switch (CB.getIntrinsicID()) {
2297 case Intrinsic::nvvm_barrier0:
2298 case Intrinsic::nvvm_barrier0_and:
2299 case Intrinsic::nvvm_barrier0_or:
2300 case Intrinsic::nvvm_barrier0_popc:
2301 return true;
2302 case Intrinsic::amdgcn_s_barrier:
2303 if (ExecutedAligned)
2304 return true;
2305 break;
2306 default:
2307 break;
2308 }
2309 return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));
2310}
2311
2312bool AANoSync::isNonRelaxedAtomic(const Instruction *I) {
2313 if (!I->isAtomic())
2314 return false;
2315
2316 if (auto *FI = dyn_cast<FenceInst>(I))
2317 // All legal orderings for fence are stronger than monotonic.
2318 return FI->getSyncScopeID() != SyncScope::SingleThread;
2319 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
2320 // Unordered is not a legal ordering for cmpxchg.
2321 return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
2322 AI->getFailureOrdering() != AtomicOrdering::Monotonic);
2323 }
2324
2325 AtomicOrdering Ordering;
2326 switch (I->getOpcode()) {
2327 case Instruction::AtomicRMW:
2328 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
2329 break;
2330 case Instruction::Store:
2331 Ordering = cast<StoreInst>(I)->getOrdering();
2332 break;
2333 case Instruction::Load:
2334 Ordering = cast<LoadInst>(I)->getOrdering();
2335 break;
2336 default:
2337 llvm_unreachable(::llvm::llvm_unreachable_internal("New atomic operations need to be known in the attributor."
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2338)
2338 "New atomic operations need to be known in the attributor.")::llvm::llvm_unreachable_internal("New atomic operations need to be known in the attributor."
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2338)
;
2339 }
2340
2341 return (Ordering != AtomicOrdering::Unordered &&
2342 Ordering != AtomicOrdering::Monotonic);
2343}
2344
2345/// Return true if this intrinsic is nosync. This is only used for intrinsics
2346/// which would be nosync except that they have a volatile flag. All other
2347/// intrinsics are simply annotated with the nosync attribute in Intrinsics.td.
2348bool AANoSync::isNoSyncIntrinsic(const Instruction *I) {
2349 if (auto *MI = dyn_cast<MemIntrinsic>(I))
2350 return !MI->isVolatile();
2351 return false;
2352}
2353
2354namespace {
2355struct AANoSyncImpl : AANoSync {
2356 AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}
2357
2358 const std::string getAsStr() const override {
2359 return getAssumed() ? "nosync" : "may-sync";
2360 }
2361
2362 /// See AbstractAttribute::updateImpl(...).
2363 ChangeStatus updateImpl(Attributor &A) override;
2364};
2365
2366ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
2367
2368 auto CheckRWInstForNoSync = [&](Instruction &I) {
2369 return AA::isNoSyncInst(A, I, *this);
2370 };
2371
2372 auto CheckForNoSync = [&](Instruction &I) {
2373 // At this point we handled all read/write effects and they are all
2374 // nosync, so they can be skipped.
2375 if (I.mayReadOrWriteMemory())
2376 return true;
2377
2378 // non-convergent and readnone imply nosync.
2379 return !cast<CallBase>(I).isConvergent();
2380 };
2381
2382 bool UsedAssumedInformation = false;
2383 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
2384 UsedAssumedInformation) ||
2385 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
2386 UsedAssumedInformation))
2387 return indicatePessimisticFixpoint();
2388
2389 return ChangeStatus::UNCHANGED;
2390}
2391
2392struct AANoSyncFunction final : public AANoSyncImpl {
2393 AANoSyncFunction(const IRPosition &IRP, Attributor &A)
2394 : AANoSyncImpl(IRP, A) {}
2395
2396 /// See AbstractAttribute::trackStatistics()
2397 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync){ static llvm::Statistic NumIRFunction_nosync = {"attributor"
, "NumIRFunction_nosync", ("Number of " "functions" " marked '"
"nosync" "'")};; ++(NumIRFunction_nosync); }
}
2398};
2399
2400/// NoSync attribute deduction for a call sites.
2401struct AANoSyncCallSite final : AANoSyncImpl {
2402 AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
2403 : AANoSyncImpl(IRP, A) {}
2404
2405 /// See AbstractAttribute::initialize(...).
2406 void initialize(Attributor &A) override {
2407 AANoSyncImpl::initialize(A);
2408 Function *F = getAssociatedFunction();
2409 if (!F || F->isDeclaration())
2410 indicatePessimisticFixpoint();
2411 }
2412
2413 /// See AbstractAttribute::updateImpl(...).
2414 ChangeStatus updateImpl(Attributor &A) override {
2415 // TODO: Once we have call site specific value information we can provide
2416 // call site specific liveness information and then it makes
2417 // sense to specialize attributes for call sites arguments instead of
2418 // redirecting requests to the callee argument.
2419 Function *F = getAssociatedFunction();
2420 const IRPosition &FnPos = IRPosition::function(*F);
2421 auto &FnAA = A.getAAFor<AANoSync>(*this, FnPos, DepClassTy::REQUIRED);
2422 return clampStateAndIndicateChange(getState(), FnAA.getState());
2423 }
2424
2425 /// See AbstractAttribute::trackStatistics()
2426 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync){ static llvm::Statistic NumIRCS_nosync = {"attributor", "NumIRCS_nosync"
, ("Number of " "call site" " marked '" "nosync" "'")};; ++(NumIRCS_nosync
); }
; }
2427};
2428} // namespace
2429
2430/// ------------------------ No-Free Attributes ----------------------------
2431
2432namespace {
2433struct AANoFreeImpl : public AANoFree {
2434 AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}
2435
2436 /// See AbstractAttribute::updateImpl(...).
2437 ChangeStatus updateImpl(Attributor &A) override {
2438 auto CheckForNoFree = [&](Instruction &I) {
2439 const auto &CB = cast<CallBase>(I);
2440 if (CB.hasFnAttr(Attribute::NoFree))
2441 return true;
2442
2443 const auto &NoFreeAA = A.getAAFor<AANoFree>(
2444 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
2445 return NoFreeAA.isAssumedNoFree();
2446 };
2447
2448 bool UsedAssumedInformation = false;
2449 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
2450 UsedAssumedInformation))
2451 return indicatePessimisticFixpoint();
2452 return ChangeStatus::UNCHANGED;
2453 }
2454
2455 /// See AbstractAttribute::getAsStr().
2456 const std::string getAsStr() const override {
2457 return getAssumed() ? "nofree" : "may-free";
2458 }
2459};
2460
2461struct AANoFreeFunction final : public AANoFreeImpl {
2462 AANoFreeFunction(const IRPosition &IRP, Attributor &A)
2463 : AANoFreeImpl(IRP, A) {}
2464
2465 /// See AbstractAttribute::trackStatistics()
2466 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree){ static llvm::Statistic NumIRFunction_nofree = {"attributor"
, "NumIRFunction_nofree", ("Number of " "functions" " marked '"
"nofree" "'")};; ++(NumIRFunction_nofree); }
}
2467};
2468
2469/// NoFree attribute deduction for a call sites.
2470struct AANoFreeCallSite final : AANoFreeImpl {
2471 AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
2472 : AANoFreeImpl(IRP, A) {}
2473
2474 /// See AbstractAttribute::initialize(...).
2475 void initialize(Attributor &A) override {
2476 AANoFreeImpl::initialize(A);
2477 Function *F = getAssociatedFunction();
2478 if (!F || F->isDeclaration())
2479 indicatePessimisticFixpoint();
2480 }
2481
2482 /// See AbstractAttribute::updateImpl(...).
2483 ChangeStatus updateImpl(Attributor &A) override {
2484 // TODO: Once we have call site specific value information we can provide
2485 // call site specific liveness information and then it makes
2486 // sense to specialize attributes for call sites arguments instead of
2487 // redirecting requests to the callee argument.
2488 Function *F = getAssociatedFunction();
2489 const IRPosition &FnPos = IRPosition::function(*F);
2490 auto &FnAA = A.getAAFor<AANoFree>(*this, FnPos, DepClassTy::REQUIRED);
2491 return clampStateAndIndicateChange(getState(), FnAA.getState());
2492 }
2493
2494 /// See AbstractAttribute::trackStatistics()
2495 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree){ static llvm::Statistic NumIRCS_nofree = {"attributor", "NumIRCS_nofree"
, ("Number of " "call site" " marked '" "nofree" "'")};; ++(NumIRCS_nofree
); }
; }
2496};
2497
2498/// NoFree attribute for floating values.
2499struct AANoFreeFloating : AANoFreeImpl {
2500 AANoFreeFloating(const IRPosition &IRP, Attributor &A)
2501 : AANoFreeImpl(IRP, A) {}
2502
2503 /// See AbstractAttribute::trackStatistics()
2504 void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree){ static llvm::Statistic NumIRFloating_nofree = {"attributor"
, "NumIRFloating_nofree", ("Number of floating values known to be '"
"nofree" "'")};; ++(NumIRFloating_nofree); }
}
2505
2506 /// See Abstract Attribute::updateImpl(...).
2507 ChangeStatus updateImpl(Attributor &A) override {
2508 const IRPosition &IRP = getIRPosition();
2509
2510 const auto &NoFreeAA = A.getAAFor<AANoFree>(
2511 *this, IRPosition::function_scope(IRP), DepClassTy::OPTIONAL);
2512 if (NoFreeAA.isAssumedNoFree())
2513 return ChangeStatus::UNCHANGED;
2514
2515 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2516 auto Pred = [&](const Use &U, bool &Follow) -> bool {
2517 Instruction *UserI = cast<Instruction>(U.getUser());
2518 if (auto *CB = dyn_cast<CallBase>(UserI)) {
2519 if (CB->isBundleOperand(&U))
2520 return false;
2521 if (!CB->isArgOperand(&U))
2522 return true;
2523 unsigned ArgNo = CB->getArgOperandNo(&U);
2524
2525 const auto &NoFreeArg = A.getAAFor<AANoFree>(
2526 *this, IRPosition::callsite_argument(*CB, ArgNo),
2527 DepClassTy::REQUIRED);
2528 return NoFreeArg.isAssumedNoFree();
2529 }
2530
2531 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
2532 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
2533 Follow = true;
2534 return true;
2535 }
2536 if (isa<StoreInst>(UserI) || isa<LoadInst>(UserI) ||
2537 isa<ReturnInst>(UserI))
2538 return true;
2539
2540 // Unknown user.
2541 return false;
2542 };
2543 if (!A.checkForAllUses(Pred, *this, AssociatedValue))
2544 return indicatePessimisticFixpoint();
2545
2546 return ChangeStatus::UNCHANGED;
2547 }
2548};
2549
2550/// NoFree attribute for a call site argument.
2551struct AANoFreeArgument final : AANoFreeFloating {
2552 AANoFreeArgument(const IRPosition &IRP, Attributor &A)
2553 : AANoFreeFloating(IRP, A) {}
2554
2555 /// See AbstractAttribute::trackStatistics()
2556 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree){ static llvm::Statistic NumIRArguments_nofree = {"attributor"
, "NumIRArguments_nofree", ("Number of " "arguments" " marked '"
"nofree" "'")};; ++(NumIRArguments_nofree); }
}
2557};
2558
2559/// NoFree attribute for call site arguments.
2560struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2561 AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
2562 : AANoFreeFloating(IRP, A) {}
2563
2564 /// See AbstractAttribute::updateImpl(...).
2565 ChangeStatus updateImpl(Attributor &A) override {
2566 // TODO: Once we have call site specific value information we can provide
2567 // call site specific liveness information and then it makes
2568 // sense to specialize attributes for call sites arguments instead of
2569 // redirecting requests to the callee argument.
2570 Argument *Arg = getAssociatedArgument();
2571 if (!Arg)
2572 return indicatePessimisticFixpoint();
2573 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2574 auto &ArgAA = A.getAAFor<AANoFree>(*this, ArgPos, DepClassTy::REQUIRED);
2575 return clampStateAndIndicateChange(getState(), ArgAA.getState());
2576 }
2577
2578 /// See AbstractAttribute::trackStatistics()
2579 void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nofree){ static llvm::Statistic NumIRCSArguments_nofree = {"attributor"
, "NumIRCSArguments_nofree", ("Number of " "call site arguments"
" marked '" "nofree" "'")};; ++(NumIRCSArguments_nofree); }
};
2580};
2581
2582/// NoFree attribute for function return value.
2583struct AANoFreeReturned final : AANoFreeFloating {
2584 AANoFreeReturned(const IRPosition &IRP, Attributor &A)
2585 : AANoFreeFloating(IRP, A) {
2586 llvm_unreachable("NoFree is not applicable to function returns!")::llvm::llvm_unreachable_internal("NoFree is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2586)
;
2587 }
2588
2589 /// See AbstractAttribute::initialize(...).
2590 void initialize(Attributor &A) override {
2591 llvm_unreachable("NoFree is not applicable to function returns!")::llvm::llvm_unreachable_internal("NoFree is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2591)
;
2592 }
2593
2594 /// See AbstractAttribute::updateImpl(...).
2595 ChangeStatus updateImpl(Attributor &A) override {
2596 llvm_unreachable("NoFree is not applicable to function returns!")::llvm::llvm_unreachable_internal("NoFree is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2596)
;
2597 }
2598
2599 /// See AbstractAttribute::trackStatistics()
2600 void trackStatistics() const override {}
2601};
2602
2603/// NoFree attribute deduction for a call site return value.
2604struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2605 AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
2606 : AANoFreeFloating(IRP, A) {}
2607
2608 ChangeStatus manifest(Attributor &A) override {
2609 return ChangeStatus::UNCHANGED;
2610 }
2611 /// See AbstractAttribute::trackStatistics()
2612 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree){ static llvm::Statistic NumIRCSReturn_nofree = {"attributor"
, "NumIRCSReturn_nofree", ("Number of " "call site returns" " marked '"
"nofree" "'")};; ++(NumIRCSReturn_nofree); }
}
2613};
2614} // namespace
2615
2616/// ------------------------ NonNull Argument Attribute ------------------------
2617namespace {
2618static int64_t getKnownNonNullAndDerefBytesForUse(
2619 Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
2620 const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
2621 TrackUse = false;
2622
2623 const Value *UseV = U->get();
2624 if (!UseV->getType()->isPointerTy())
2625 return 0;
2626
2627 // We need to follow common pointer manipulation uses to the accesses they
2628 // feed into. We can try to be smart to avoid looking through things we do not
2629 // like for now, e.g., non-inbounds GEPs.
2630 if (isa<CastInst>(I)) {
2631 TrackUse = true;
2632 return 0;
2633 }
2634
2635 if (isa<GetElementPtrInst>(I)) {
2636 TrackUse = true;
2637 return 0;
2638 }
2639
2640 Type *PtrTy = UseV->getType();
2641 const Function *F = I->getFunction();
2642 bool NullPointerIsDefined =
2643 F ? llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()) : true;
2644 const DataLayout &DL = A.getInfoCache().getDL();
2645 if (const auto *CB = dyn_cast<CallBase>(I)) {
2646 if (CB->isBundleOperand(U)) {
2647 if (RetainedKnowledge RK = getKnowledgeFromUse(
2648 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2649 IsNonNull |=
2650 (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);
2651 return RK.ArgValue;
2652 }
2653 return 0;
2654 }
2655
2656 if (CB->isCallee(U)) {
2657 IsNonNull |= !NullPointerIsDefined;
2658 return 0;
2659 }
2660
2661 unsigned ArgNo = CB->getArgOperandNo(U);
2662 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
2663 // As long as we only use known information there is no need to track
2664 // dependences here.
2665 auto &DerefAA =
2666 A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
2667 IsNonNull |= DerefAA.isKnownNonNull();
2668 return DerefAA.getKnownDereferenceableBytes();
2669 }
2670
2671 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
2672 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
2673 return 0;
2674
2675 int64_t Offset;
2676 const Value *Base =
2677 getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);
2678 if (Base && Base == &AssociatedValue) {
2679 int64_t DerefBytes = Loc->Size.getValue() + Offset;
2680 IsNonNull |= !NullPointerIsDefined;
2681 return std::max(int64_t(0), DerefBytes);
2682 }
2683
2684 /// Corner case when an offset is 0.
2685 Base = GetPointerBaseWithConstantOffset(Loc->Ptr, Offset, DL,
2686 /*AllowNonInbounds*/ true);
2687 if (Base && Base == &AssociatedValue && Offset == 0) {
2688 int64_t DerefBytes = Loc->Size.getValue();
2689 IsNonNull |= !NullPointerIsDefined;
2690 return std::max(int64_t(0), DerefBytes);
2691 }
2692
2693 return 0;
2694}
2695
2696struct AANonNullImpl : AANonNull {
2697 AANonNullImpl(const IRPosition &IRP, Attributor &A)
2698 : AANonNull(IRP, A),
2699 NullIsDefined(NullPointerIsDefined(
2700 getAnchorScope(),
2701 getAssociatedValue().getType()->getPointerAddressSpace())) {}
2702
2703 /// See AbstractAttribute::initialize(...).
2704 void initialize(Attributor &A) override {
2705 Value &V = *getAssociatedValue().stripPointerCasts();
2706 if (!NullIsDefined &&
2707 hasAttr({Attribute::NonNull, Attribute::Dereferenceable},
2708 /* IgnoreSubsumingPositions */ false, &A)) {
2709 indicateOptimisticFixpoint();
2710 return;
2711 }
2712
2713 if (isa<ConstantPointerNull>(V)) {
2714 indicatePessimisticFixpoint();
2715 return;
2716 }
2717
2718 AANonNull::initialize(A);
2719
2720 bool CanBeNull, CanBeFreed;
2721 if (V.getPointerDereferenceableBytes(A.getDataLayout(), CanBeNull,
2722 CanBeFreed)) {
2723 if (!CanBeNull) {
2724 indicateOptimisticFixpoint();
2725 return;
2726 }
2727 }
2728
2729 if (isa<GlobalValue>(V)) {
2730 indicatePessimisticFixpoint();
2731 return;
2732 }
2733
2734 if (Instruction *CtxI = getCtxI())
2735 followUsesInMBEC(*this, A, getState(), *CtxI);
2736 }
2737
2738 /// See followUsesInMBEC
2739 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
2740 AANonNull::StateType &State) {
2741 bool IsNonNull = false;
2742 bool TrackUse = false;
2743 getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,
2744 IsNonNull, TrackUse);
2745 State.setKnown(IsNonNull);
2746 return TrackUse;
2747 }
2748
2749 /// See AbstractAttribute::getAsStr().
2750 const std::string getAsStr() const override {
2751 return getAssumed() ? "nonnull" : "may-null";
2752 }
2753
2754 /// Flag to determine if the underlying value can be null and still allow
2755 /// valid accesses.
2756 const bool NullIsDefined;
2757};
2758
2759/// NonNull attribute for a floating value.
2760struct AANonNullFloating : public AANonNullImpl {
2761 AANonNullFloating(const IRPosition &IRP, Attributor &A)
2762 : AANonNullImpl(IRP, A) {}
2763
2764 /// See AbstractAttribute::updateImpl(...).
2765 ChangeStatus updateImpl(Attributor &A) override {
2766 const DataLayout &DL = A.getDataLayout();
2767
2768 bool Stripped;
2769 bool UsedAssumedInformation = false;
2770 SmallVector<AA::ValueAndContext> Values;
2771 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
2772 AA::AnyScope, UsedAssumedInformation)) {
2773 Values.push_back({getAssociatedValue(), getCtxI()});
2774 Stripped = false;
2775 } else {
2776 Stripped = Values.size() != 1 ||
2777 Values.front().getValue() != &getAssociatedValue();
2778 }
2779
2780 DominatorTree *DT = nullptr;
2781 AssumptionCache *AC = nullptr;
2782 InformationCache &InfoCache = A.getInfoCache();
2783 if (const Function *Fn = getAnchorScope()) {
2784 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*Fn);
2785 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*Fn);
2786 }
2787
2788 AANonNull::StateType T;
2789 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
2790 const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V),
2791 DepClassTy::REQUIRED);
2792 if (!Stripped && this == &AA) {
2793 if (!isKnownNonZero(&V, DL, 0, AC, CtxI, DT))
2794 T.indicatePessimisticFixpoint();
2795 } else {
2796 // Use abstract attribute information.
2797 const AANonNull::StateType &NS = AA.getState();
2798 T ^= NS;
2799 }
2800 return T.isValidState();
2801 };
2802
2803 for (const auto &VAC : Values)
2804 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
2805 return indicatePessimisticFixpoint();
2806
2807 return clampStateAndIndicateChange(getState(), T);
2808 }
2809
2810 /// See AbstractAttribute::trackStatistics()
2811 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull){ static llvm::Statistic NumIRFunctionReturn_nonnull = {"attributor"
, "NumIRFunctionReturn_nonnull", ("Number of " "function returns"
" marked '" "nonnull" "'")};; ++(NumIRFunctionReturn_nonnull
); }
}
2812};
2813
2814/// NonNull attribute for function return value.
2815struct AANonNullReturned final
2816 : AAReturnedFromReturnedValues<AANonNull, AANonNull> {
2817 AANonNullReturned(const IRPosition &IRP, Attributor &A)
2818 : AAReturnedFromReturnedValues<AANonNull, AANonNull>(IRP, A) {}
2819
2820 /// See AbstractAttribute::getAsStr().
2821 const std::string getAsStr() const override {
2822 return getAssumed() ? "nonnull" : "may-null";
2823 }
2824
2825 /// See AbstractAttribute::trackStatistics()
2826 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull){ static llvm::Statistic NumIRFunctionReturn_nonnull = {"attributor"
, "NumIRFunctionReturn_nonnull", ("Number of " "function returns"
" marked '" "nonnull" "'")};; ++(NumIRFunctionReturn_nonnull
); }
}
2827};
2828
2829/// NonNull attribute for function argument.
2830struct AANonNullArgument final
2831 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2832 AANonNullArgument(const IRPosition &IRP, Attributor &A)
2833 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}
2834
2835 /// See AbstractAttribute::trackStatistics()
2836 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull){ static llvm::Statistic NumIRArguments_nonnull = {"attributor"
, "NumIRArguments_nonnull", ("Number of " "arguments" " marked '"
"nonnull" "'")};; ++(NumIRArguments_nonnull); }
}
2837};
2838
2839struct AANonNullCallSiteArgument final : AANonNullFloating {
2840 AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
2841 : AANonNullFloating(IRP, A) {}
2842
2843 /// See AbstractAttribute::trackStatistics()
2844 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull){ static llvm::Statistic NumIRCSArguments_nonnull = {"attributor"
, "NumIRCSArguments_nonnull", ("Number of " "call site arguments"
" marked '" "nonnull" "'")};; ++(NumIRCSArguments_nonnull); }
}
2845};
2846
2847/// NonNull attribute for a call site return position.
2848struct AANonNullCallSiteReturned final
2849 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl> {
2850 AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
2851 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl>(IRP, A) {}
2852
2853 /// See AbstractAttribute::trackStatistics()
2854 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull){ static llvm::Statistic NumIRCSReturn_nonnull = {"attributor"
, "NumIRCSReturn_nonnull", ("Number of " "call site returns" " marked '"
"nonnull" "'")};; ++(NumIRCSReturn_nonnull); }
}
2855};
2856} // namespace
2857
2858/// ------------------------ No-Recurse Attributes ----------------------------
2859
2860namespace {
2861struct AANoRecurseImpl : public AANoRecurse {
2862 AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}
2863
2864 /// See AbstractAttribute::getAsStr()
2865 const std::string getAsStr() const override {
2866 return getAssumed() ? "norecurse" : "may-recurse";
2867 }
2868};
2869
2870struct AANoRecurseFunction final : AANoRecurseImpl {
2871 AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
2872 : AANoRecurseImpl(IRP, A) {}
2873
2874 /// See AbstractAttribute::updateImpl(...).
2875 ChangeStatus updateImpl(Attributor &A) override {
2876
2877 // If all live call sites are known to be no-recurse, we are as well.
2878 auto CallSitePred = [&](AbstractCallSite ACS) {
2879 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
2880 *this, IRPosition::function(*ACS.getInstruction()->getFunction()),
2881 DepClassTy::NONE);
2882 return NoRecurseAA.isKnownNoRecurse();
2883 };
2884 bool UsedAssumedInformation = false;
2885 if (A.checkForAllCallSites(CallSitePred, *this, true,
2886 UsedAssumedInformation)) {
2887 // If we know all call sites and all are known no-recurse, we are done.
2888 // If all known call sites, which might not be all that exist, are known
2889 // to be no-recurse, we are not done but we can continue to assume
2890 // no-recurse. If one of the call sites we have not visited will become
2891 // live, another update is triggered.
2892 if (!UsedAssumedInformation)
2893 indicateOptimisticFixpoint();
2894 return ChangeStatus::UNCHANGED;
2895 }
2896
2897 const AAInterFnReachability &EdgeReachability =
2898 A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),
2899 DepClassTy::REQUIRED);
2900 if (EdgeReachability.canReach(A, *getAnchorScope()))
2901 return indicatePessimisticFixpoint();
2902 return ChangeStatus::UNCHANGED;
2903 }
2904
2905 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse){ static llvm::Statistic NumIRFunction_norecurse = {"attributor"
, "NumIRFunction_norecurse", ("Number of " "functions" " marked '"
"norecurse" "'")};; ++(NumIRFunction_norecurse); }
}
2906};
2907
2908/// NoRecurse attribute deduction for a call sites.
2909struct AANoRecurseCallSite final : AANoRecurseImpl {
2910 AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
2911 : AANoRecurseImpl(IRP, A) {}
2912
2913 /// See AbstractAttribute::initialize(...).
2914 void initialize(Attributor &A) override {
2915 AANoRecurseImpl::initialize(A);
2916 Function *F = getAssociatedFunction();
2917 if (!F || F->isDeclaration())
2918 indicatePessimisticFixpoint();
2919 }
2920
2921 /// See AbstractAttribute::updateImpl(...).
2922 ChangeStatus updateImpl(Attributor &A) override {
2923 // TODO: Once we have call site specific value information we can provide
2924 // call site specific liveness information and then it makes
2925 // sense to specialize attributes for call sites arguments instead of
2926 // redirecting requests to the callee argument.
2927 Function *F = getAssociatedFunction();
2928 const IRPosition &FnPos = IRPosition::function(*F);
2929 auto &FnAA = A.getAAFor<AANoRecurse>(*this, FnPos, DepClassTy::REQUIRED);
2930 return clampStateAndIndicateChange(getState(), FnAA.getState());
2931 }
2932
2933 /// See AbstractAttribute::trackStatistics()
2934 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse){ static llvm::Statistic NumIRCS_norecurse = {"attributor", "NumIRCS_norecurse"
, ("Number of " "call site" " marked '" "norecurse" "'")};; ++
(NumIRCS_norecurse); }
; }
2935};
2936} // namespace
2937
2938/// ------------------------ No-Convergent Attribute --------------------------
2939
2940namespace {
2941struct AANonConvergentImpl : public AANonConvergent {
2942 AANonConvergentImpl(const IRPosition &IRP, Attributor &A)
2943 : AANonConvergent(IRP, A) {}
2944
2945 /// See AbstractAttribute::getAsStr()
2946 const std::string getAsStr() const override {
2947 return getAssumed() ? "non-convergent" : "may-be-convergent";
2948 }
2949};
2950
2951struct AANonConvergentFunction final : AANonConvergentImpl {
2952 AANonConvergentFunction(const IRPosition &IRP, Attributor &A)
2953 : AANonConvergentImpl(IRP, A) {}
2954
2955 /// See AbstractAttribute::updateImpl(...).
2956 ChangeStatus updateImpl(Attributor &A) override {
2957 // If all function calls are known to not be convergent, we are not convergent.
2958 auto CalleeIsNotConvergent = [&](Instruction &Inst) {
2959 CallBase &CB = cast<CallBase>(Inst);
2960 Function *Callee = CB.getCalledFunction();
2961 if (!Callee || Callee->isIntrinsic()) {
2962 return false;
2963 }
2964 if (Callee->isDeclaration()) {
2965 return !Callee->hasFnAttribute(Attribute::Convergent);
2966 }
2967 const auto &ConvergentAA = A.getAAFor<AANonConvergent>(
2968 *this, IRPosition::function(*Callee), DepClassTy::REQUIRED);
2969 return ConvergentAA.isAssumedNotConvergent();
2970 };
2971
2972 bool UsedAssumedInformation = false;
2973 if (!A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *this,
2974 UsedAssumedInformation)) {
2975 return indicatePessimisticFixpoint();
2976 }
2977 return ChangeStatus::UNCHANGED;
2978 }
2979
2980 ChangeStatus manifest(Attributor &A) override {
2981 if (isKnownNotConvergent() && hasAttr(Attribute::Convergent)) {
2982 removeAttrs({Attribute::Convergent});
2983 return ChangeStatus::CHANGED;
2984 }
2985 return ChangeStatus::UNCHANGED;
2986 }
2987
2988 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(convergent){ static llvm::Statistic NumIRFunction_convergent = {"attributor"
, "NumIRFunction_convergent", ("Number of " "functions" " marked '"
"convergent" "'")};; ++(NumIRFunction_convergent); }
}
2989};
2990} // namespace
2991
2992/// -------------------- Undefined-Behavior Attributes ------------------------
2993
2994namespace {
2995struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
2996 AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
2997 : AAUndefinedBehavior(IRP, A) {}
2998
2999 /// See AbstractAttribute::updateImpl(...).
3000 // through a pointer (i.e. also branches etc.)
3001 ChangeStatus updateImpl(Attributor &A) override {
3002 const size_t UBPrevSize = KnownUBInsts.size();
3003 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
3004
3005 auto InspectMemAccessInstForUB = [&](Instruction &I) {
3006 // Lang ref now states volatile store is not UB, let's skip them.
3007 if (I.isVolatile() && I.mayWriteToMemory())
3008 return true;
3009
3010 // Skip instructions that are already saved.
3011 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3012 return true;
3013
3014 // If we reach here, we know we have an instruction
3015 // that accesses memory through a pointer operand,
3016 // for which getPointerOperand() should give it to us.
3017 Value *PtrOp =
3018 const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));
3019 assert(PtrOp &&(static_cast <bool> (PtrOp && "Expected pointer operand of memory accessing instruction"
) ? void (0) : __assert_fail ("PtrOp && \"Expected pointer operand of memory accessing instruction\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3020, __extension__
__PRETTY_FUNCTION__))
3020 "Expected pointer operand of memory accessing instruction")(static_cast <bool> (PtrOp && "Expected pointer operand of memory accessing instruction"
) ? void (0) : __assert_fail ("PtrOp && \"Expected pointer operand of memory accessing instruction\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3020, __extension__
__PRETTY_FUNCTION__))
;
3021
3022 // Either we stopped and the appropriate action was taken,
3023 // or we got back a simplified value to continue.
3024 std::optional<Value *> SimplifiedPtrOp =
3025 stopOnUndefOrAssumed(A, PtrOp, &I);
3026 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
3027 return true;
3028 const Value *PtrOpVal = *SimplifiedPtrOp;
3029
3030 // A memory access through a pointer is considered UB
3031 // only if the pointer has constant null value.
3032 // TODO: Expand it to not only check constant values.
3033 if (!isa<ConstantPointerNull>(PtrOpVal)) {
3034 AssumedNoUBInsts.insert(&I);
3035 return true;
3036 }
3037 const Type *PtrTy = PtrOpVal->getType();
3038
3039 // Because we only consider instructions inside functions,
3040 // assume that a parent function exists.
3041 const Function *F = I.getFunction();
3042
3043 // A memory access using constant null pointer is only considered UB
3044 // if null pointer is _not_ defined for the target platform.
3045 if (llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()))
3046 AssumedNoUBInsts.insert(&I);
3047 else
3048 KnownUBInsts.insert(&I);
3049 return true;
3050 };
3051
3052 auto InspectBrInstForUB = [&](Instruction &I) {
3053 // A conditional branch instruction is considered UB if it has `undef`
3054 // condition.
3055
3056 // Skip instructions that are already saved.
3057 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3058 return true;
3059
3060 // We know we have a branch instruction.
3061 auto *BrInst = cast<BranchInst>(&I);
3062
3063 // Unconditional branches are never considered UB.
3064 if (BrInst->isUnconditional())
3065 return true;
3066
3067 // Either we stopped and the appropriate action was taken,
3068 // or we got back a simplified value to continue.
3069 std::optional<Value *> SimplifiedCond =
3070 stopOnUndefOrAssumed(A, BrInst->getCondition(), BrInst);
3071 if (!SimplifiedCond || !*SimplifiedCond)
3072 return true;
3073 AssumedNoUBInsts.insert(&I);
3074 return true;
3075 };
3076
3077 auto InspectCallSiteForUB = [&](Instruction &I) {
3078 // Check whether a callsite always cause UB or not
3079
3080 // Skip instructions that are already saved.
3081 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3082 return true;
3083
3084 // Check nonnull and noundef argument attribute violation for each
3085 // callsite.
3086 CallBase &CB = cast<CallBase>(I);
3087 Function *Callee = CB.getCalledFunction();
3088 if (!Callee)
3089 return true;
3090 for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
3091 // If current argument is known to be simplified to null pointer and the
3092 // corresponding argument position is known to have nonnull attribute,
3093 // the argument is poison. Furthermore, if the argument is poison and
3094 // the position is known to have noundef attriubte, this callsite is
3095 // considered UB.
3096 if (idx >= Callee->arg_size())
3097 break;
3098 Value *ArgVal = CB.getArgOperand(idx);
3099 if (!ArgVal)
3100 continue;
3101 // Here, we handle three cases.
3102 // (1) Not having a value means it is dead. (we can replace the value
3103 // with undef)
3104 // (2) Simplified to undef. The argument violate noundef attriubte.
3105 // (3) Simplified to null pointer where known to be nonnull.
3106 // The argument is a poison value and violate noundef attribute.
3107 IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
3108 auto &NoUndefAA =
3109 A.getAAFor<AANoUndef>(*this, CalleeArgumentIRP, DepClassTy::NONE);
3110 if (!NoUndefAA.isKnownNoUndef())
3111 continue;
3112 bool UsedAssumedInformation = false;
3113 std::optional<Value *> SimplifiedVal =
3114 A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,
3115 UsedAssumedInformation, AA::Interprocedural);
3116 if (UsedAssumedInformation)
3117 continue;
3118 if (SimplifiedVal && !*SimplifiedVal)
3119 return true;
3120 if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {
3121 KnownUBInsts.insert(&I);
3122 continue;
3123 }
3124 if (!ArgVal->getType()->isPointerTy() ||
3125 !isa<ConstantPointerNull>(**SimplifiedVal))
3126 continue;
3127 auto &NonNullAA =
3128 A.getAAFor<AANonNull>(*this, CalleeArgumentIRP, DepClassTy::NONE);
3129 if (NonNullAA.isKnownNonNull())
3130 KnownUBInsts.insert(&I);
3131 }
3132 return true;
3133 };
3134
3135 auto InspectReturnInstForUB = [&](Instruction &I) {
3136 auto &RI = cast<ReturnInst>(I);
3137 // Either we stopped and the appropriate action was taken,
3138 // or we got back a simplified return value to continue.
3139 std::optional<Value *> SimplifiedRetValue =
3140 stopOnUndefOrAssumed(A, RI.getReturnValue(), &I);
3141 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3142 return true;
3143
3144 // Check if a return instruction always cause UB or not
3145 // Note: It is guaranteed that the returned position of the anchor
3146 // scope has noundef attribute when this is called.
3147 // We also ensure the return position is not "assumed dead"
3148 // because the returned value was then potentially simplified to
3149 // `undef` in AAReturnedValues without removing the `noundef`
3150 // attribute yet.
3151
3152 // When the returned position has noundef attriubte, UB occurs in the
3153 // following cases.
3154 // (1) Returned value is known to be undef.
3155 // (2) The value is known to be a null pointer and the returned
3156 // position has nonnull attribute (because the returned value is
3157 // poison).
3158 if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {
3159 auto &NonNullAA = A.getAAFor<AANonNull>(
3160 *this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE);
3161 if (NonNullAA.isKnownNonNull())
3162 KnownUBInsts.insert(&I);
3163 }
3164
3165 return true;
3166 };
3167
3168 bool UsedAssumedInformation = false;
3169 A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
3170 {Instruction::Load, Instruction::Store,
3171 Instruction::AtomicCmpXchg,
3172 Instruction::AtomicRMW},
3173 UsedAssumedInformation,
3174 /* CheckBBLivenessOnly */ true);
3175 A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},
3176 UsedAssumedInformation,
3177 /* CheckBBLivenessOnly */ true);
3178 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
3179 UsedAssumedInformation);
3180
3181 // If the returned position of the anchor scope has noundef attriubte, check
3182 // all returned instructions.
3183 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3184 const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
3185 if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
3186 auto &RetPosNoUndefAA =
3187 A.getAAFor<AANoUndef>(*this, ReturnIRP, DepClassTy::NONE);
3188 if (RetPosNoUndefAA.isKnownNoUndef())
3189 A.checkForAllInstructions(InspectReturnInstForUB, *this,
3190 {Instruction::Ret}, UsedAssumedInformation,
3191 /* CheckBBLivenessOnly */ true);
3192 }
3193 }
3194
3195 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3196 UBPrevSize != KnownUBInsts.size())
3197 return ChangeStatus::CHANGED;
3198 return ChangeStatus::UNCHANGED;
3199 }
3200
3201 bool isKnownToCauseUB(Instruction *I) const override {
3202 return KnownUBInsts.count(I);
3203 }
3204
3205 bool isAssumedToCauseUB(Instruction *I) const override {
3206 // In simple words, if an instruction is not in the assumed to _not_
3207 // cause UB, then it is assumed UB (that includes those
3208 // in the KnownUBInsts set). The rest is boilerplate
3209 // is to ensure that it is one of the instructions we test
3210 // for UB.
3211
3212 switch (I->getOpcode()) {
3213 case Instruction::Load:
3214 case Instruction::Store:
3215 case Instruction::AtomicCmpXchg:
3216 case Instruction::AtomicRMW:
3217 return !AssumedNoUBInsts.count(I);
3218 case Instruction::Br: {
3219 auto *BrInst = cast<BranchInst>(I);
3220 if (BrInst->isUnconditional())
3221 return false;
3222 return !AssumedNoUBInsts.count(I);
3223 } break;
3224 default:
3225 return false;
3226 }
3227 return false;
3228 }
3229
3230 ChangeStatus manifest(Attributor &A) override {
3231 if (KnownUBInsts.empty())
3232 return ChangeStatus::UNCHANGED;
3233 for (Instruction *I : KnownUBInsts)
3234 A.changeToUnreachableAfterManifest(I);
3235 return ChangeStatus::CHANGED;
3236 }
3237
3238 /// See AbstractAttribute::getAsStr()
3239 const std::string getAsStr() const override {
3240 return getAssumed() ? "undefined-behavior" : "no-ub";
3241 }
3242
3243 /// Note: The correctness of this analysis depends on the fact that the
3244 /// following 2 sets will stop changing after some point.
3245 /// "Change" here means that their size changes.
3246 /// The size of each set is monotonically increasing
3247 /// (we only add items to them) and it is upper bounded by the number of
3248 /// instructions in the processed function (we can never save more
3249 /// elements in either set than this number). Hence, at some point,
3250 /// they will stop increasing.
3251 /// Consequently, at some point, both sets will have stopped
3252 /// changing, effectively making the analysis reach a fixpoint.
3253
3254 /// Note: These 2 sets are disjoint and an instruction can be considered
3255 /// one of 3 things:
3256 /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
3257 /// the KnownUBInsts set.
3258 /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
3259 /// has a reason to assume it).
3260 /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
3261 /// could not find a reason to assume or prove that it can cause UB,
3262 /// hence it assumes it doesn't. We have a set for these instructions
3263 /// so that we don't reprocess them in every update.
3264 /// Note however that instructions in this set may cause UB.
3265
3266protected:
3267 /// A set of all live instructions _known_ to cause UB.
3268 SmallPtrSet<Instruction *, 8> KnownUBInsts;
3269
3270private:
3271 /// A set of all the (live) instructions that are assumed to _not_ cause UB.
3272 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3273
3274 // Should be called on updates in which if we're processing an instruction
3275 // \p I that depends on a value \p V, one of the following has to happen:
3276 // - If the value is assumed, then stop.
3277 // - If the value is known but undef, then consider it UB.
3278 // - Otherwise, do specific processing with the simplified value.
3279 // We return std::nullopt in the first 2 cases to signify that an appropriate
3280 // action was taken and the caller should stop.
3281 // Otherwise, we return the simplified value that the caller should
3282 // use for specific processing.
3283 std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
3284 Instruction *I) {
3285 bool UsedAssumedInformation = false;
3286 std::optional<Value *> SimplifiedV =
3287 A.getAssumedSimplified(IRPosition::value(*V), *this,
3288 UsedAssumedInformation, AA::Interprocedural);
3289 if (!UsedAssumedInformation) {
3290 // Don't depend on assumed values.
3291 if (!SimplifiedV) {
3292 // If it is known (which we tested above) but it doesn't have a value,
3293 // then we can assume `undef` and hence the instruction is UB.
3294 KnownUBInsts.insert(I);
3295 return std::nullopt;
3296 }
3297 if (!*SimplifiedV)
3298 return nullptr;
3299 V = *SimplifiedV;
3300 }
3301 if (isa<UndefValue>(V)) {
3302 KnownUBInsts.insert(I);
3303 return std::nullopt;
3304 }
3305 return V;
3306 }
3307};
3308
3309struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3310 AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
3311 : AAUndefinedBehaviorImpl(IRP, A) {}
3312
3313 /// See AbstractAttribute::trackStatistics()
3314 void trackStatistics() const override {
3315 STATS_DECL(UndefinedBehaviorInstruction, Instruction,static llvm::Statistic NumIRInstruction_UndefinedBehaviorInstruction
= {"attributor", "NumIRInstruction_UndefinedBehaviorInstruction"
, "Number of instructions known to have UB"};;
3316 "Number of instructions known to have UB")static llvm::Statistic NumIRInstruction_UndefinedBehaviorInstruction
= {"attributor", "NumIRInstruction_UndefinedBehaviorInstruction"
, "Number of instructions known to have UB"};;
;
3317 BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction)NumIRInstruction_UndefinedBehaviorInstruction +=
3318 KnownUBInsts.size();
3319 }
3320};
3321} // namespace
3322
3323/// ------------------------ Will-Return Attributes ----------------------------
3324
3325namespace {
3326// Helper function that checks whether a function has any cycle which we don't
3327// know if it is bounded or not.
3328// Loops with maximum trip count are considered bounded, any other cycle not.
3329static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
3330 ScalarEvolution *SE =
3331 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
3332 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
3333 // If either SCEV or LoopInfo is not available for the function then we assume
3334 // any cycle to be unbounded cycle.
3335 // We use scc_iterator which uses Tarjan algorithm to find all the maximal
3336 // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
3337 if (!SE || !LI) {
3338 for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
3339 if (SCCI.hasCycle())
3340 return true;
3341 return false;
3342 }
3343
3344 // If there's irreducible control, the function may contain non-loop cycles.
3345 if (mayContainIrreducibleControl(F, LI))
3346 return true;
3347
3348 // Any loop that does not have a max trip count is considered unbounded cycle.
3349 for (auto *L : LI->getLoopsInPreorder()) {
3350 if (!SE->getSmallConstantMaxTripCount(L))
3351 return true;
3352 }
3353 return false;
3354}
3355
3356struct AAWillReturnImpl : public AAWillReturn {
3357 AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
3358 : AAWillReturn(IRP, A) {}
3359
3360 /// See AbstractAttribute::initialize(...).
3361 void initialize(Attributor &A) override {
3362 AAWillReturn::initialize(A);
3363
3364 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ true)) {
3365 indicateOptimisticFixpoint();
3366 return;
3367 }
3368 }
3369
3370 /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
3371 bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
3372 // Check for `mustprogress` in the scope and the associated function which
3373 // might be different if this is a call site.
3374 if ((!getAnchorScope() || !getAnchorScope()->mustProgress()) &&
3375 (!getAssociatedFunction() || !getAssociatedFunction()->mustProgress()))
3376 return false;
3377
3378 bool IsKnown;
3379 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3380 return IsKnown || !KnownOnly;
3381 return false;
3382 }
3383
3384 /// See AbstractAttribute::updateImpl(...).
3385 ChangeStatus updateImpl(Attributor &A) override {
3386 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3387 return ChangeStatus::UNCHANGED;
3388
3389 auto CheckForWillReturn = [&](Instruction &I) {
3390 IRPosition IPos = IRPosition::callsite_function(cast<CallBase>(I));
3391 const auto &WillReturnAA =
3392 A.getAAFor<AAWillReturn>(*this, IPos, DepClassTy::REQUIRED);
3393 if (WillReturnAA.isKnownWillReturn())
3394 return true;
3395 if (!WillReturnAA.isAssumedWillReturn())
3396 return false;
3397 const auto &NoRecurseAA =
3398 A.getAAFor<AANoRecurse>(*this, IPos, DepClassTy::REQUIRED);
3399 return NoRecurseAA.isAssumedNoRecurse();
3400 };
3401
3402 bool UsedAssumedInformation = false;
3403 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
3404 UsedAssumedInformation))
3405 return indicatePessimisticFixpoint();
3406
3407 return ChangeStatus::UNCHANGED;
3408 }
3409
3410 /// See AbstractAttribute::getAsStr()
3411 const std::string getAsStr() const override {
3412 return getAssumed() ? "willreturn" : "may-noreturn";
3413 }
3414};
3415
3416struct AAWillReturnFunction final : AAWillReturnImpl {
3417 AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
3418 : AAWillReturnImpl(IRP, A) {}
3419
3420 /// See AbstractAttribute::initialize(...).
3421 void initialize(Attributor &A) override {
3422 AAWillReturnImpl::initialize(A);
3423
3424 Function *F = getAnchorScope();
3425 if (!F || F->isDeclaration() || mayContainUnboundedCycle(*F, A))
3426 indicatePessimisticFixpoint();
3427 }
3428
3429 /// See AbstractAttribute::trackStatistics()
3430 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn){ static llvm::Statistic NumIRFunction_willreturn = {"attributor"
, "NumIRFunction_willreturn", ("Number of " "functions" " marked '"
"willreturn" "'")};; ++(NumIRFunction_willreturn); }
}
3431};
3432
3433/// WillReturn attribute deduction for a call sites.
3434struct AAWillReturnCallSite final : AAWillReturnImpl {
3435 AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)
3436 : AAWillReturnImpl(IRP, A) {}
3437
3438 /// See AbstractAttribute::initialize(...).
3439 void initialize(Attributor &A) override {
3440 AAWillReturnImpl::initialize(A);
3441 Function *F = getAssociatedFunction();
3442 if (!F || !A.isFunctionIPOAmendable(*F))
3443 indicatePessimisticFixpoint();
3444 }
3445
3446 /// See AbstractAttribute::updateImpl(...).
3447 ChangeStatus updateImpl(Attributor &A) override {
3448 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3449 return ChangeStatus::UNCHANGED;
3450
3451 // TODO: Once we have call site specific value information we can provide
3452 // call site specific liveness information and then it makes
3453 // sense to specialize attributes for call sites arguments instead of
3454 // redirecting requests to the callee argument.
3455 Function *F = getAssociatedFunction();
3456 const IRPosition &FnPos = IRPosition::function(*F);
3457 auto &FnAA = A.getAAFor<AAWillReturn>(*this, FnPos, DepClassTy::REQUIRED);
3458 return clampStateAndIndicateChange(getState(), FnAA.getState());
3459 }
3460
3461 /// See AbstractAttribute::trackStatistics()
3462 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn){ static llvm::Statistic NumIRCS_willreturn = {"attributor", "NumIRCS_willreturn"
, ("Number of " "call site" " marked '" "willreturn" "'")};; ++
(NumIRCS_willreturn); }
; }
3463};
3464} // namespace
3465
3466/// -------------------AAIntraFnReachability Attribute--------------------------
3467
3468/// All information associated with a reachability query. This boilerplate code
3469/// is used by both AAIntraFnReachability and AAInterFnReachability, with
3470/// different \p ToTy values.
3471template <typename ToTy> struct ReachabilityQueryInfo {
3472 enum class Reachable {
3473 No,
3474 Yes,
3475 };
3476
3477 /// Start here,
3478 const Instruction *From = nullptr;
3479 /// reach this place,
3480 const ToTy *To = nullptr;
3481 /// without going through any of these instructions,
3482 const AA::InstExclusionSetTy *ExclusionSet = nullptr;
3483 /// and remember if it worked:
3484 Reachable Result = Reachable::No;
3485
3486 ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
3487 : From(From), To(To) {}
3488
3489 /// Constructor replacement to ensure unique and stable sets are used for the
3490 /// cache.
3491 ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To,
3492 const AA::InstExclusionSetTy *ES, bool MakeUnique)
3493 : From(&From), To(&To), ExclusionSet(ES) {
3494
3495 if (!ES || ES->empty()) {
3496 ExclusionSet = nullptr;
3497 } else if (MakeUnique) {
3498 ExclusionSet = A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3499 }
3500 }
3501
3502 ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
3503 : From(RQI.From), To(RQI.To), ExclusionSet(RQI.ExclusionSet) {}
3504};
3505
3506namespace llvm {
3507template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
3508 using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;
3509 using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;
3510
3511 static ReachabilityQueryInfo<ToTy> EmptyKey;
3512 static ReachabilityQueryInfo<ToTy> TombstoneKey;
3513
3514 static inline ReachabilityQueryInfo<ToTy> *getEmptyKey() { return &EmptyKey; }
3515 static inline ReachabilityQueryInfo<ToTy> *getTombstoneKey() {
3516 return &TombstoneKey;
3517 }
3518 static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
3519 unsigned H = PairDMI ::getHashValue({RQI->From, RQI->To});
3520 H += InstSetDMI::getHashValue(RQI->ExclusionSet);
3521 return H;
3522 }
3523 static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
3524 const ReachabilityQueryInfo<ToTy> *RHS) {
3525 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3526 return false;
3527 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3528 }
3529};
3530
3531#define DefineKeys(ToTy) \
3532 template <> \
3533 ReachabilityQueryInfo<ToTy> \
3534 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::EmptyKey = \
3535 ReachabilityQueryInfo<ToTy>( \
3536 DenseMapInfo<const Instruction *>::getEmptyKey(), \
3537 DenseMapInfo<const ToTy *>::getEmptyKey()); \
3538 template <> \
3539 ReachabilityQueryInfo<ToTy> \
3540 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::TombstoneKey = \
3541 ReachabilityQueryInfo<ToTy>( \
3542 DenseMapInfo<const Instruction *>::getTombstoneKey(), \
3543 DenseMapInfo<const ToTy *>::getTombstoneKey());
3544
3545DefineKeys(Instruction) DefineKeys(Function)
3546#undef DefineKeys
3547
3548} // namespace llvm
3549
3550namespace {
3551
3552template <typename BaseTy, typename ToTy>
3553struct CachedReachabilityAA : public BaseTy {
3554 using RQITy = ReachabilityQueryInfo<ToTy>;
3555
3556 CachedReachabilityAA<BaseTy, ToTy>(const IRPosition &IRP, Attributor &A)
3557 : BaseTy(IRP, A) {}
3558
3559 /// See AbstractAttribute::isQueryAA.
3560 bool isQueryAA() const override { return true; }
3561
3562 /// See AbstractAttribute::updateImpl(...).
3563 ChangeStatus updateImpl(Attributor &A) override {
3564 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3565 InUpdate = true;
3566 for (unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3567 RQITy *RQI = QueryVector[u];
3568 if (RQI->Result == RQITy::Reachable::No && isReachableImpl(A, *RQI))
3569 Changed = ChangeStatus::CHANGED;
3570 }
3571 InUpdate = false;
3572 return Changed;
3573 }
3574
3575 virtual bool isReachableImpl(Attributor &A, RQITy &RQI) = 0;
3576
3577 bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
3578 RQITy &RQI, bool UsedExclusionSet) {
3579 RQI.Result = Result;
3580
3581 // Remove the temporary RQI from the cache.
3582 if (!InUpdate)
3583 QueryCache.erase(&RQI);
3584
3585 // Insert a plain RQI (w/o exclusion set) if that makes sense. Two options:
3586 // 1) If it is reachable, it doesn't matter if we have an exclusion set for this query.
3587 // 2) We did not use the exclusion set, potentially because there is none.
3588 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3589 RQITy PlainRQI(RQI.From, RQI.To);
3590 if (!QueryCache.count(&PlainRQI)) {
3591 RQITy *RQIPtr = new (A.Allocator) RQITy(RQI.From, RQI.To);
3592 RQIPtr->Result = Result;
3593 QueryVector.push_back(RQIPtr);
3594 QueryCache.insert(RQIPtr);
3595 }
3596 }
3597
3598 // Check if we need to insert a new permanent RQI with the exclusion set.
3599 if (!InUpdate && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3600 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&(static_cast <bool> ((!RQI.ExclusionSet || !RQI.ExclusionSet
->empty()) && "Did not expect empty set!") ? void (
0) : __assert_fail ("(!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) && \"Did not expect empty set!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3601, __extension__
__PRETTY_FUNCTION__))
3601 "Did not expect empty set!")(static_cast <bool> ((!RQI.ExclusionSet || !RQI.ExclusionSet
->empty()) && "Did not expect empty set!") ? void (
0) : __assert_fail ("(!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) && \"Did not expect empty set!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3601, __extension__
__PRETTY_FUNCTION__))
;
3602 RQITy *RQIPtr = new (A.Allocator)
3603 RQITy(A, *RQI.From, *RQI.To, RQI.ExclusionSet, true);
3604 assert(RQIPtr->Result == RQITy::Reachable::No && "Already reachable?")(static_cast <bool> (RQIPtr->Result == RQITy::Reachable
::No && "Already reachable?") ? void (0) : __assert_fail
("RQIPtr->Result == RQITy::Reachable::No && \"Already reachable?\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3604, __extension__
__PRETTY_FUNCTION__))
;
3605 RQIPtr->Result = Result;
3606 assert(!QueryCache.count(RQIPtr))(static_cast <bool> (!QueryCache.count(RQIPtr)) ? void (
0) : __assert_fail ("!QueryCache.count(RQIPtr)", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 3606, __extension__ __PRETTY_FUNCTION__))
;
3607 QueryVector.push_back(RQIPtr);
3608 QueryCache.insert(RQIPtr);
3609 }
3610
3611 if (Result == RQITy::Reachable::No && !InUpdate)
3612 A.registerForUpdate(*this);
3613 return Result == RQITy::Reachable::Yes;
3614 }
3615
3616 const std::string getAsStr() const override {
3617 // TODO: Return the number of reachable queries.
3618 return "#queries(" + std::to_string(QueryVector.size()) + ")";
3619 }
3620
3621 bool checkQueryCache(Attributor &A, RQITy &StackRQI,
3622 typename RQITy::Reachable &Result) {
3623 if (!this->getState().isValidState()) {
3624 Result = RQITy::Reachable::Yes;
3625 return true;
3626 }
3627
3628 // If we have an exclusion set we might be able to find our answer by
3629 // ignoring it first.
3630 if (StackRQI.ExclusionSet) {
3631 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3632 auto It = QueryCache.find(&PlainRQI);
3633 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3634 Result = RQITy::Reachable::No;
3635 return true;
3636 }
3637 }
3638
3639 auto It = QueryCache.find(&StackRQI);
3640 if (It != QueryCache.end()) {
3641 Result = (*It)->Result;
3642 return true;
3643 }
3644
3645 // Insert a temporary for recursive queries. We will replace it with a
3646 // permanent entry later.
3647 QueryCache.insert(&StackRQI);
3648 return false;
3649 }
3650
3651private:
3652 bool InUpdate = false;
3653 SmallVector<RQITy *> QueryVector;
3654 DenseSet<RQITy *> QueryCache;
3655};
3656
3657struct AAIntraFnReachabilityFunction final
3658 : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3659 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3660 AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
3661 : Base(IRP, A) {}
3662
3663 bool isAssumedReachable(
3664 Attributor &A, const Instruction &From, const Instruction &To,
3665 const AA::InstExclusionSetTy *ExclusionSet) const override {
3666 auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
3667 if (&From == &To)
3668 return true;
3669
3670 RQITy StackRQI(A, From, To, ExclusionSet, false);
3671 typename RQITy::Reachable Result;
3672 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
3673 return NonConstThis->isReachableImpl(A, StackRQI);
3674 return Result == RQITy::Reachable::Yes;
3675 }
3676
3677 ChangeStatus updateImpl(Attributor &A) override {
3678 // We only depend on liveness. DeadEdges is all we care about, check if any
3679 // of them changed.
3680 auto &LivenessAA =
3681 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3682 if (llvm::all_of(DeadEdges, [&](const auto &DeadEdge) {
3683 return LivenessAA.isEdgeDead(DeadEdge.first, DeadEdge.second);
3684 })) {
3685 return ChangeStatus::UNCHANGED;
3686 }
3687 DeadEdges.clear();
3688 return Base::updateImpl(A);
3689 }
3690
3691 bool isReachableImpl(Attributor &A, RQITy &RQI) override {
3692 const Instruction *Origin = RQI.From;
3693 bool UsedExclusionSet = false;
3694
3695 auto WillReachInBlock = [&](const Instruction &From, const Instruction &To,
3696 const AA::InstExclusionSetTy *ExclusionSet) {
3697 const Instruction *IP = &From;
3698 while (IP && IP != &To) {
3699 if (ExclusionSet && IP != Origin && ExclusionSet->count(IP)) {
3700 UsedExclusionSet = true;
3701 break;
3702 }
3703 IP = IP->getNextNode();
3704 }
3705 return IP == &To;
3706 };
3707
3708 const BasicBlock *FromBB = RQI.From->getParent();
3709 const BasicBlock *ToBB = RQI.To->getParent();
3710 assert(FromBB->getParent() == ToBB->getParent() &&(static_cast <bool> (FromBB->getParent() == ToBB->
getParent() && "Not an intra-procedural query!") ? void
(0) : __assert_fail ("FromBB->getParent() == ToBB->getParent() && \"Not an intra-procedural query!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3711, __extension__
__PRETTY_FUNCTION__))
3711 "Not an intra-procedural query!")(static_cast <bool> (FromBB->getParent() == ToBB->
getParent() && "Not an intra-procedural query!") ? void
(0) : __assert_fail ("FromBB->getParent() == ToBB->getParent() && \"Not an intra-procedural query!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3711, __extension__
__PRETTY_FUNCTION__))
;
3712
3713 // Check intra-block reachability, however, other reaching paths are still
3714 // possible.
3715 if (FromBB == ToBB &&
3716 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3717 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet);
3718
3719 // Check if reaching the ToBB block is sufficient or if even that would not
3720 // ensure reaching the target. In the latter case we are done.
3721 if (!WillReachInBlock(ToBB->front(), *RQI.To, RQI.ExclusionSet))
3722 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);
3723
3724 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3725 if (RQI.ExclusionSet)
3726 for (auto *I : *RQI.ExclusionSet)
3727 ExclusionBlocks.insert(I->getParent());
3728
3729 // Check if we make it out of the FromBB block at all.
3730 if (ExclusionBlocks.count(FromBB) &&
3731 !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
3732 RQI.ExclusionSet))
3733 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);
3734
3735 SmallPtrSet<const BasicBlock *, 16> Visited;
3736 SmallVector<const BasicBlock *, 16> Worklist;
3737 Worklist.push_back(FromBB);
3738
3739 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3740 auto &LivenessAA =
3741 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3742 while (!Worklist.empty()) {
3743 const BasicBlock *BB = Worklist.pop_back_val();
3744 if (!Visited.insert(BB).second)
3745 continue;
3746 for (const BasicBlock *SuccBB : successors(BB)) {
3747 if (LivenessAA.isEdgeDead(BB, SuccBB)) {
3748 LocalDeadEdges.insert({BB, SuccBB});
3749 continue;
3750 }
3751 // We checked before if we just need to reach the ToBB block.
3752 if (SuccBB == ToBB)
3753 return rememberResult(A, RQITy::Reachable::Yes, RQI,
3754 UsedExclusionSet);
3755 if (ExclusionBlocks.count(SuccBB)) {
3756 UsedExclusionSet = true;
3757 continue;
3758 }
3759 Worklist.push_back(SuccBB);
3760 }
3761 }
3762
3763 DeadEdges.insert(LocalDeadEdges.begin(), LocalDeadEdges.end());
3764 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);
3765 }
3766
3767 /// See AbstractAttribute::trackStatistics()
3768 void trackStatistics() const override {}
3769
3770private:
3771 // Set of assumed dead edges we used in the last query. If any changes we
3772 // update the state.
3773 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3774};
3775} // namespace
3776
3777/// ------------------------ NoAlias Argument Attribute ------------------------
3778
3779namespace {
3780struct AANoAliasImpl : AANoAlias {
3781 AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
3782 assert(getAssociatedType()->isPointerTy() &&(static_cast <bool> (getAssociatedType()->isPointerTy
() && "Noalias is a pointer attribute") ? void (0) : __assert_fail
("getAssociatedType()->isPointerTy() && \"Noalias is a pointer attribute\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3783, __extension__
__PRETTY_FUNCTION__))
3783 "Noalias is a pointer attribute")(static_cast <bool> (getAssociatedType()->isPointerTy
() && "Noalias is a pointer attribute") ? void (0) : __assert_fail
("getAssociatedType()->isPointerTy() && \"Noalias is a pointer attribute\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3783, __extension__
__PRETTY_FUNCTION__))
;
3784 }
3785
3786 const std::string getAsStr() const override {
3787 return getAssumed() ? "noalias" : "may-alias";
3788 }
3789};
3790
3791/// NoAlias attribute for a floating value.
3792struct AANoAliasFloating final : AANoAliasImpl {
3793 AANoAliasFloating(const IRPosition &IRP, Attributor &A)
3794 : AANoAliasImpl(IRP, A) {}
3795
3796 /// See AbstractAttribute::initialize(...).
3797 void initialize(Attributor &A) override {
3798 AANoAliasImpl::initialize(A);
3799 Value *Val = &getAssociatedValue();
3800 do {
3801 CastInst *CI = dyn_cast<CastInst>(Val);
3802 if (!CI)
3803 break;
3804 Value *Base = CI->getOperand(0);
3805 if (!Base->hasOneUse())
3806 break;
3807 Val = Base;
3808 } while (true);
3809
3810 if (!Val->getType()->isPointerTy()) {
3811 indicatePessimisticFixpoint();
3812 return;
3813 }
3814
3815 if (isa<AllocaInst>(Val))
3816 indicateOptimisticFixpoint();
3817 else if (isa<ConstantPointerNull>(Val) &&
3818 !NullPointerIsDefined(getAnchorScope(),
3819 Val->getType()->getPointerAddressSpace()))
3820 indicateOptimisticFixpoint();
3821 else if (Val != &getAssociatedValue()) {
3822 const auto &ValNoAliasAA = A.getAAFor<AANoAlias>(
3823 *this, IRPosition::value(*Val), DepClassTy::OPTIONAL);
3824 if (ValNoAliasAA.isKnownNoAlias())
3825 indicateOptimisticFixpoint();
3826 }
3827 }
3828
3829 /// See AbstractAttribute::updateImpl(...).
3830 ChangeStatus updateImpl(Attributor &A) override {
3831 // TODO: Implement this.
3832 return indicatePessimisticFixpoint();
3833 }
3834
3835 /// See AbstractAttribute::trackStatistics()
3836 void trackStatistics() const override {
3837 STATS_DECLTRACK_FLOATING_ATTR(noalias){ static llvm::Statistic NumIRFloating_noalias = {"attributor"
, "NumIRFloating_noalias", ("Number of floating values known to be '"
"noalias" "'")};; ++(NumIRFloating_noalias); }
3838 }
3839};
3840
3841/// NoAlias attribute for an argument.
3842struct AANoAliasArgument final
3843 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3844 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3845 AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
3846
3847 /// See AbstractAttribute::initialize(...).
3848 void initialize(Attributor &A) override {
3849 Base::initialize(A);
3850 // See callsite argument attribute and callee argument attribute.
3851 if (hasAttr({Attribute::ByVal}))
3852 indicateOptimisticFixpoint();
3853 }
3854
3855 /// See AbstractAttribute::update(...).
3856 ChangeStatus updateImpl(Attributor &A) override {
3857 // We have to make sure no-alias on the argument does not break
3858 // synchronization when this is a callback argument, see also [1] below.
3859 // If synchronization cannot be affected, we delegate to the base updateImpl
3860 // function, otherwise we give up for now.
3861
3862 // If the function is no-sync, no-alias cannot break synchronization.
3863 const auto &NoSyncAA =
3864 A.getAAFor<AANoSync>(*this, IRPosition::function_scope(getIRPosition()),
3865 DepClassTy::OPTIONAL);
3866 if (NoSyncAA.isAssumedNoSync())
3867 return Base::updateImpl(A);
3868
3869 // If the argument is read-only, no-alias cannot break synchronization.
3870 bool IsKnown;
3871 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3872 return Base::updateImpl(A);
3873
3874 // If the argument is never passed through callbacks, no-alias cannot break
3875 // synchronization.
3876 bool UsedAssumedInformation = false;
3877 if (A.checkForAllCallSites(
3878 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,
3879 true, UsedAssumedInformation))
3880 return Base::updateImpl(A);
3881
3882 // TODO: add no-alias but make sure it doesn't break synchronization by
3883 // introducing fake uses. See:
3884 // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
3885 // International Workshop on OpenMP 2018,
3886 // http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf
3887
3888 return indicatePessimisticFixpoint();
3889 }
3890
3891 /// See AbstractAttribute::trackStatistics()
3892 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias){ static llvm::Statistic NumIRArguments_noalias = {"attributor"
, "NumIRArguments_noalias", ("Number of " "arguments" " marked '"
"noalias" "'")};; ++(NumIRArguments_noalias); }
}
3893};
3894
3895struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3896 AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
3897 : AANoAliasImpl(IRP, A) {}
3898
3899 /// See AbstractAttribute::initialize(...).
3900 void initialize(Attributor &A) override {
3901 // See callsite argument attribute and callee argument attribute.
3902 const auto &CB = cast<CallBase>(getAnchorValue());
3903 if (CB.paramHasAttr(getCallSiteArgNo(), Attribute::NoAlias))
3904 indicateOptimisticFixpoint();
3905 Value &Val = getAssociatedValue();
3906 if (isa<ConstantPointerNull>(Val) &&
3907 !NullPointerIsDefined(getAnchorScope(),
3908 Val.getType()->getPointerAddressSpace()))
3909 indicateOptimisticFixpoint();
3910 }
3911
3912 /// Determine if the underlying value may alias with the call site argument
3913 /// \p OtherArgNo of \p ICS (= the underlying call site).
3914 bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
3915 const AAMemoryBehavior &MemBehaviorAA,
3916 const CallBase &CB, unsigned OtherArgNo) {
3917 // We do not need to worry about aliasing with the underlying IRP.
3918 if (this->getCalleeArgNo() == (int)OtherArgNo)
3919 return false;
3920
3921 // If it is not a pointer or pointer vector we do not alias.
3922 const Value *ArgOp = CB.getArgOperand(OtherArgNo);
3923 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
3924 return false;
3925
3926 auto &CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
3927 *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);
3928
3929 // If the argument is readnone, there is no read-write aliasing.
3930 if (CBArgMemBehaviorAA.isAssumedReadNone()) {
3931 A.recordDependence(CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3932 return false;
3933 }
3934
3935 // If the argument is readonly and the underlying value is readonly, there
3936 // is no read-write aliasing.
3937 bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
3938 if (CBArgMemBehaviorAA.isAssumedReadOnly() && IsReadOnly) {
3939 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3940 A.recordDependence(CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3941 return false;
3942 }
3943
3944 // We have to utilize actual alias analysis queries so we need the object.
3945 if (!AAR)
3946 AAR = A.getInfoCache().getAAResultsForFunction(*getAnchorScope());
3947
3948 // Try to rule it out at the call site.
3949 bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);
3950 LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[NoAliasCSArg] Check alias between "
"callsite arguments: " << getAssociatedValue() <<
" " << *ArgOp << " => " << (IsAliasing ?
"" : "no-") << "alias \n"; } } while (false)
3951 "callsite arguments: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[NoAliasCSArg] Check alias between "
"callsite arguments: " << getAssociatedValue() <<
" " << *ArgOp << " => " << (IsAliasing ?
"" : "no-") << "alias \n"; } } while (false)
3952 << getAssociatedValue() << " " << *ArgOp << " => "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[NoAliasCSArg] Check alias between "
"callsite arguments: " << getAssociatedValue() <<
" " << *ArgOp << " => " << (IsAliasing ?
"" : "no-") << "alias \n"; } } while (false)
3953 << (IsAliasing ? "" : "no-") << "alias \n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[NoAliasCSArg] Check alias between "
"callsite arguments: " << getAssociatedValue() <<
" " << *ArgOp << " => " << (IsAliasing ?
"" : "no-") << "alias \n"; } } while (false)
;
3954
3955 return IsAliasing;
3956 }
3957
3958 bool
3959 isKnownNoAliasDueToNoAliasPreservation(Attributor &A, AAResults *&AAR,
3960 const AAMemoryBehavior &MemBehaviorAA,
3961 const AANoAlias &NoAliasAA) {
3962 // We can deduce "noalias" if the following conditions hold.
3963 // (i) Associated value is assumed to be noalias in the definition.
3964 // (ii) Associated value is assumed to be no-capture in all the uses
3965 // possibly executed before this callsite.
3966 // (iii) There is no other pointer argument which could alias with the
3967 // value.
3968
3969 bool AssociatedValueIsNoAliasAtDef = NoAliasAA.isAssumedNoAlias();
3970 if (!AssociatedValueIsNoAliasAtDef) {
3971 LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAlias] " << getAssociatedValue
() << " is not no-alias at the definition\n"; } } while
(false)
3972 << " is not no-alias at the definition\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAlias] " << getAssociatedValue
() << " is not no-alias at the definition\n"; } } while
(false)
;
3973 return false;
3974 }
3975
3976 auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
3977 const auto &DerefAA = A.getAAFor<AADereferenceable>(
3978 *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
3979 return DerefAA.getAssumedDereferenceableBytes();
3980 };
3981
3982 A.recordDependence(NoAliasAA, *this, DepClassTy::OPTIONAL);
3983
3984 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3985 const Function *ScopeFn = VIRP.getAnchorScope();
3986 auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, VIRP, DepClassTy::NONE);
3987 // Check whether the value is captured in the scope using AANoCapture.
3988 // Look at CFG and check only uses possibly executed before this
3989 // callsite.
3990 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
3991 Instruction *UserI = cast<Instruction>(U.getUser());
3992
3993 // If UserI is the curr instruction and there is a single potential use of
3994 // the value in UserI we allow the use.
3995 // TODO: We should inspect the operands and allow those that cannot alias
3996 // with the value.
3997 if (UserI == getCtxI() && UserI->getNumOperands() == 1)
3998 return true;
3999
4000 if (ScopeFn) {
4001 if (auto *CB = dyn_cast<CallBase>(UserI)) {
4002 if (CB->isArgOperand(&U)) {
4003
4004 unsigned ArgNo = CB->getArgOperandNo(&U);
4005
4006 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
4007 *this, IRPosition::callsite_argument(*CB, ArgNo),
4008 DepClassTy::OPTIONAL);
4009
4010 if (NoCaptureAA.isAssumedNoCapture())
4011 return true;
4012 }
4013 }
4014
4015 if (!AA::isPotentiallyReachable(
4016 A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,
4017 [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
4018 return true;
4019 }
4020
4021 // TODO: We should track the capturing uses in AANoCapture but the problem
4022 // is CGSCC runs. For those we would need to "allow" AANoCapture for
4023 // a value in the module slice.
4024 switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
4025 case UseCaptureKind::NO_CAPTURE:
4026 return true;
4027 case UseCaptureKind::MAY_CAPTURE:
4028 LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] Unknown user: "
<< *UserI << "\n"; } } while (false)
4029 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] Unknown user: "
<< *UserI << "\n"; } } while (false)
;
4030 return false;
4031 case UseCaptureKind::PASSTHROUGH:
4032 Follow = true;
4033 return true;
4034 }
4035 llvm_unreachable("unknown UseCaptureKind")::llvm::llvm_unreachable_internal("unknown UseCaptureKind", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 4035)
;
4036 };
4037
4038 if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
4039 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
4040 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] " <<
getAssociatedValue() << " cannot be noalias as it is potentially captured\n"
; } } while (false)
4041 dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] " <<
getAssociatedValue() << " cannot be noalias as it is potentially captured\n"
; } } while (false)
4042 << " cannot be noalias as it is potentially captured\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] " <<
getAssociatedValue() << " cannot be noalias as it is potentially captured\n"
; } } while (false)
;
4043 return false;
4044 }
4045 }
4046 A.recordDependence(NoCaptureAA, *this, DepClassTy::OPTIONAL);
4047
4048 // Check there is no other pointer argument which could alias with the
4049 // value passed at this call site.
4050 // TODO: AbstractCallSite
4051 const auto &CB = cast<CallBase>(getAnchorValue());
4052 for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
4053 if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
4054 return false;
4055
4056 return true;
4057 }
4058
4059 /// See AbstractAttribute::updateImpl(...).
4060 ChangeStatus updateImpl(Attributor &A) override {
4061 // If the argument is readnone we are done as there are no accesses via the
4062 // argument.
4063 auto &MemBehaviorAA =
4064 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
4065 if (MemBehaviorAA.isAssumedReadNone()) {
4066 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
4067 return ChangeStatus::UNCHANGED;
4068 }
4069
4070 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
4071 const auto &NoAliasAA =
4072 A.getAAFor<AANoAlias>(*this, VIRP, DepClassTy::NONE);
4073
4074 AAResults *AAR = nullptr;
4075 if (isKnownNoAliasDueToNoAliasPreservation(A, AAR, MemBehaviorAA,
4076 NoAliasAA)) {
4077 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n"
; } } while (false)
4078 dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n"
; } } while (false)
;
4079 return ChangeStatus::UNCHANGED;
4080 }
4081
4082 return indicatePessimisticFixpoint();
4083 }
4084
4085 /// See AbstractAttribute::trackStatistics()
4086 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias){ static llvm::Statistic NumIRCSArguments_noalias = {"attributor"
, "NumIRCSArguments_noalias", ("Number of " "call site arguments"
" marked '" "noalias" "'")};; ++(NumIRCSArguments_noalias); }
}
4087};
4088
4089/// NoAlias attribute for function return value.
4090struct AANoAliasReturned final : AANoAliasImpl {
4091 AANoAliasReturned(const IRPosition &IRP, Attributor &A)
4092 : AANoAliasImpl(IRP, A) {}
4093
4094 /// See AbstractAttribute::initialize(...).
4095 void initialize(Attributor &A) override {
4096 AANoAliasImpl::initialize(A);
4097 Function *F = getAssociatedFunction();
4098 if (!F || F->isDeclaration())
4099 indicatePessimisticFixpoint();
4100 }
4101
4102 /// See AbstractAttribute::updateImpl(...).
4103 ChangeStatus updateImpl(Attributor &A) override {
4104
4105 auto CheckReturnValue = [&](Value &RV) -> bool {
4106 if (Constant *C = dyn_cast<Constant>(&RV))
4107 if (C->isNullValue() || isa<UndefValue>(C))
4108 return true;
4109
4110 /// For now, we can only deduce noalias if we have call sites.
4111 /// FIXME: add more support.
4112 if (!isa<CallBase>(&RV))
4113 return false;
4114
4115 const IRPosition &RVPos = IRPosition::value(RV);
4116 const auto &NoAliasAA =
4117 A.getAAFor<AANoAlias>(*this, RVPos, DepClassTy::REQUIRED);
4118 if (!NoAliasAA.isAssumedNoAlias())
4119 return false;
4120
4121 const auto &NoCaptureAA =
4122 A.getAAFor<AANoCapture>(*this, RVPos, DepClassTy::REQUIRED);
4123 return NoCaptureAA.isAssumedNoCaptureMaybeReturned();
4124 };
4125
4126 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
4127 return indicatePessimisticFixpoint();
4128
4129 return ChangeStatus::UNCHANGED;
4130 }
4131
4132 /// See AbstractAttribute::trackStatistics()
4133 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias){ static llvm::Statistic NumIRFunctionReturn_noalias = {"attributor"
, "NumIRFunctionReturn_noalias", ("Number of " "function returns"
" marked '" "noalias" "'")};; ++(NumIRFunctionReturn_noalias
); }
}
4134};
4135
4136/// NoAlias attribute deduction for a call site return value.
4137struct AANoAliasCallSiteReturned final : AANoAliasImpl {
4138 AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
4139 : AANoAliasImpl(IRP, A) {}
4140
4141 /// See AbstractAttribute::initialize(...).
4142 void initialize(Attributor &A) override {
4143 AANoAliasImpl::initialize(A);
4144 Function *F = getAssociatedFunction();
4145 if (!F || F->isDeclaration())
4146 indicatePessimisticFixpoint();
4147 }
4148
4149 /// See AbstractAttribute::updateImpl(...).
4150 ChangeStatus updateImpl(Attributor &A) override {
4151 // TODO: Once we have call site specific value information we can provide
4152 // call site specific liveness information and then it makes
4153 // sense to specialize attributes for call sites arguments instead of
4154 // redirecting requests to the callee argument.
4155 Function *F = getAssociatedFunction();
4156 const IRPosition &FnPos = IRPosition::returned(*F);
4157 auto &FnAA = A.getAAFor<AANoAlias>(*this, FnPos, DepClassTy::REQUIRED);
4158 return clampStateAndIndicateChange(getState(), FnAA.getState());
4159 }
4160
4161 /// See AbstractAttribute::trackStatistics()
4162 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias){ static llvm::Statistic NumIRCSReturn_noalias = {"attributor"
, "NumIRCSReturn_noalias", ("Number of " "call site returns" " marked '"
"noalias" "'")};; ++(NumIRCSReturn_noalias); }
; }
4163};
4164} // namespace
4165
4166/// -------------------AAIsDead Function Attribute-----------------------
4167
4168namespace {
4169struct AAIsDeadValueImpl : public AAIsDead {
4170 AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4171
4172 /// See AbstractAttribute::initialize(...).
4173 void initialize(Attributor &A) override {
4174 if (auto *Scope = getAnchorScope())
4175 if (!A.isRunOn(*Scope))
4176 indicatePessimisticFixpoint();
4177 }
4178
4179 /// See AAIsDead::isAssumedDead().
4180 bool isAssumedDead() const override { return isAssumed(IS_DEAD); }
4181
4182 /// See AAIsDead::isKnownDead().
4183 bool isKnownDead() const override { return isKnown(IS_DEAD); }
4184
4185 /// See AAIsDead::isAssumedDead(BasicBlock *).
4186 bool isAssumedDead(const BasicBlock *BB) const override { return false; }
4187
4188 /// See AAIsDead::isKnownDead(BasicBlock *).
4189 bool isKnownDead(const BasicBlock *BB) const override { return false; }
4190
4191 /// See AAIsDead::isAssumedDead(Instruction *I).
4192 bool isAssumedDead(const Instruction *I) const override {
4193 return I == getCtxI() && isAssumedDead();
4194 }
4195
4196 /// See AAIsDead::isKnownDead(Instruction *I).
4197 bool isKnownDead(const Instruction *I) const override {
4198 return isAssumedDead(I) && isKnownDead();
4199 }
4200
4201 /// See AbstractAttribute::getAsStr().
4202 const std::string getAsStr() const override {
4203 return isAssumedDead() ? "assumed-dead" : "assumed-live";
4204 }
4205
4206 /// Check if all uses are assumed dead.
4207 bool areAllUsesAssumedDead(Attributor &A, Value &V) {
4208 // Callers might not check the type, void has no uses.
4209 if (V.getType()->isVoidTy() || V.use_empty())
4210 return true;
4211
4212 // If we replace a value with a constant there are no uses left afterwards.
4213 if (!isa<Constant>(V)) {
4214 if (auto *I = dyn_cast<Instruction>(&V))
4215 if (!A.isRunOn(*I->getFunction()))
4216 return false;
4217 bool UsedAssumedInformation = false;
4218 std::optional<Constant *> C =
4219 A.getAssumedConstant(V, *this, UsedAssumedInformation);
4220 if (!C || *C)
4221 return true;
4222 }
4223
4224 auto UsePred = [&](const Use &U, bool &Follow) { return false; };
4225 // Explicitly set the dependence class to required because we want a long
4226 // chain of N dependent instructions to be considered live as soon as one is
4227 // without going through N update cycles. This is not required for
4228 // correctness.
4229 return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,
4230 DepClassTy::REQUIRED,
4231 /* IgnoreDroppableUses */ false);
4232 }
4233
4234 /// Determine if \p I is assumed to be side-effect free.
4235 bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
4236 if (!I || wouldInstructionBeTriviallyDead(I))
4237 return true;
4238
4239 auto *CB = dyn_cast<CallBase>(I);
4240 if (!CB || isa<IntrinsicInst>(CB))
4241 return false;
4242
4243 const IRPosition &CallIRP = IRPosition::callsite_function(*CB);
4244 const auto &NoUnwindAA =
4245 A.getAndUpdateAAFor<AANoUnwind>(*this, CallIRP, DepClassTy::NONE);
4246 if (!NoUnwindAA.isAssumedNoUnwind())
4247 return false;
4248 if (!NoUnwindAA.isKnownNoUnwind())
4249 A.recordDependence(NoUnwindAA, *this, DepClassTy::OPTIONAL);
4250
4251 bool IsKnown;
4252 return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);
4253 }
4254};
4255
4256struct AAIsDeadFloating : public AAIsDeadValueImpl {
4257 AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
4258 : AAIsDeadValueImpl(IRP, A) {}
4259
4260 /// See AbstractAttribute::initialize(...).
4261 void initialize(Attributor &A) override {
4262 AAIsDeadValueImpl::initialize(A);
4263
4264 if (isa<UndefValue>(getAssociatedValue())) {
4265 indicatePessimisticFixpoint();
4266 return;
4267 }
4268
4269 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4270 if (!isAssumedSideEffectFree(A, I)) {
4271 if (!isa_and_nonnull<StoreInst>(I))
4272 indicatePessimisticFixpoint();
4273 else
4274 removeAssumedBits(HAS_NO_EFFECT);
4275 }
4276 }
4277
4278 bool isDeadStore(Attributor &A, StoreInst &SI,
4279 SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
4280 // Lang ref now states volatile store is not UB/dead, let's skip them.
4281 if (SI.isVolatile())
4282 return false;
4283
4284 // If we are collecting assumes to be deleted we are in the manifest stage.
4285 // It's problematic to collect the potential copies again now so we use the
4286 // cached ones.
4287 bool UsedAssumedInformation = false;
4288 if (!AssumeOnlyInst) {
4289 PotentialCopies.clear();
4290 if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,
4291 UsedAssumedInformation)) {
4292 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Could not determine potential copies of store!\n"
; } } while (false)
4293 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Could not determine potential copies of store!\n"
; } } while (false)
4294 << "[AAIsDead] Could not determine potential copies of store!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Could not determine potential copies of store!\n"
; } } while (false)
;
4295 return false;
4296 }
4297 }
4298 LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Store has " <<
PotentialCopies.size() << " potential copies.\n"; } } while
(false)
4299 << " potential copies.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Store has " <<
PotentialCopies.size() << " potential copies.\n"; } } while
(false)
;
4300
4301 InformationCache &InfoCache = A.getInfoCache();
4302 return llvm::all_of(PotentialCopies, [&](Value *V) {
4303 if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,
4304 UsedAssumedInformation))
4305 return true;
4306 if (auto *LI = dyn_cast<LoadInst>(V)) {
4307 if (llvm::all_of(LI->uses(), [&](const Use &U) {
4308 auto &UserI = cast<Instruction>(*U.getUser());
4309 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4310 if (AssumeOnlyInst)
4311 AssumeOnlyInst->insert(&UserI);
4312 return true;
4313 }
4314 return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);
4315 })) {
4316 return true;
4317 }
4318 }
4319 LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *Vdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Potential copy "
<< *V << " is assumed live!\n"; } } while (false
)
4320 << " is assumed live!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Potential copy "
<< *V << " is assumed live!\n"; } } while (false
)
;
4321 return false;
4322 });
4323 }
4324
4325 /// See AbstractAttribute::getAsStr().
4326 const std::string getAsStr() const override {
4327 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4328 if (isa_and_nonnull<StoreInst>(I))
4329 if (isValidState())
4330 return "assumed-dead-store";
4331 return AAIsDeadValueImpl::getAsStr();
4332 }
4333
4334 /// See AbstractAttribute::updateImpl(...).
4335 ChangeStatus updateImpl(Attributor &A) override {
4336 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4337 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
4338 if (!isDeadStore(A, *SI))
4339 return indicatePessimisticFixpoint();
4340 } else {
4341 if (!isAssumedSideEffectFree(A, I))
4342 return indicatePessimisticFixpoint();
4343 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4344 return indicatePessimisticFixpoint();
4345 }
4346 return ChangeStatus::UNCHANGED;
4347 }
4348
4349 bool isRemovableStore() const override {
4350 return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());
4351 }
4352
4353 /// See AbstractAttribute::manifest(...).
4354 ChangeStatus manifest(Attributor &A) override {
4355 Value &V = getAssociatedValue();
4356 if (auto *I = dyn_cast<Instruction>(&V)) {
4357 // If we get here we basically know the users are all dead. We check if
4358 // isAssumedSideEffectFree returns true here again because it might not be
4359 // the case and only the users are dead but the instruction (=call) is
4360 // still needed.
4361 if (auto *SI = dyn_cast<StoreInst>(I)) {
4362 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4363 bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);
4364 (void)IsDead;
4365 assert(IsDead && "Store was assumed to be dead!")(static_cast <bool> (IsDead && "Store was assumed to be dead!"
) ? void (0) : __assert_fail ("IsDead && \"Store was assumed to be dead!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4365, __extension__
__PRETTY_FUNCTION__))
;
4366 A.deleteAfterManifest(*I);
4367 for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
4368 Instruction *AOI = AssumeOnlyInst[i];
4369 for (auto *Usr : AOI->users())
4370 AssumeOnlyInst.insert(cast<Instruction>(Usr));
4371 A.deleteAfterManifest(*AOI);
4372 }
4373 return ChangeStatus::CHANGED;
4374 }
4375 if (isAssumedSideEffectFree(A, I) && !isa<InvokeInst>(I)) {
4376 A.deleteAfterManifest(*I);
4377 return ChangeStatus::CHANGED;
4378 }
4379 }
4380 return ChangeStatus::UNCHANGED;
4381 }
4382
4383 /// See AbstractAttribute::trackStatistics()
4384 void trackStatistics() const override {
4385 STATS_DECLTRACK_FLOATING_ATTR(IsDead){ static llvm::Statistic NumIRFloating_IsDead = {"attributor"
, "NumIRFloating_IsDead", ("Number of floating values known to be '"
"IsDead" "'")};; ++(NumIRFloating_IsDead); }
4386 }
4387
4388private:
4389 // The potential copies of a dead store, used for deletion during manifest.
4390 SmallSetVector<Value *, 4> PotentialCopies;
4391};
4392
4393struct AAIsDeadArgument : public AAIsDeadFloating {
4394 AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
4395 : AAIsDeadFloating(IRP, A) {}
4396
4397 /// See AbstractAttribute::initialize(...).
4398 void initialize(Attributor &A) override {
4399 AAIsDeadFloating::initialize(A);
4400 if (!A.isFunctionIPOAmendable(*getAnchorScope()))
4401 indicatePessimisticFixpoint();
4402 }
4403
4404 /// See AbstractAttribute::manifest(...).
4405 ChangeStatus manifest(Attributor &A) override {
4406 Argument &Arg = *getAssociatedArgument();
4407 if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
4408 if (A.registerFunctionSignatureRewrite(
4409 Arg, /* ReplacementTypes */ {},
4410 Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{},
4411 Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) {
4412 return ChangeStatus::CHANGED;
4413 }
4414 return ChangeStatus::UNCHANGED;
4415 }
4416
4417 /// See AbstractAttribute::trackStatistics()
4418 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead){ static llvm::Statistic NumIRArguments_IsDead = {"attributor"
, "NumIRArguments_IsDead", ("Number of " "arguments" " marked '"
"IsDead" "'")};; ++(NumIRArguments_IsDead); }
}
4419};
4420
4421struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
4422 AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
4423 : AAIsDeadValueImpl(IRP, A) {}
4424
4425 /// See AbstractAttribute::initialize(...).
4426 void initialize(Attributor &A) override {
4427 AAIsDeadValueImpl::initialize(A);
4428 if (isa<UndefValue>(getAssociatedValue()))
4429 indicatePessimisticFixpoint();
4430 }
4431
4432 /// See AbstractAttribute::updateImpl(...).
4433 ChangeStatus updateImpl(Attributor &A) override {
4434 // TODO: Once we have call site specific value information we can provide
4435 // call site specific liveness information and then it makes
4436 // sense to specialize attributes for call sites arguments instead of
4437 // redirecting requests to the callee argument.
4438 Argument *Arg = getAssociatedArgument();
4439 if (!Arg)
4440 return indicatePessimisticFixpoint();
4441 const IRPosition &ArgPos = IRPosition::argument(*Arg);
4442 auto &ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);
4443 return clampStateAndIndicateChange(getState(), ArgAA.getState());
4444 }
4445
4446 /// See AbstractAttribute::manifest(...).
4447 ChangeStatus manifest(Attributor &A) override {
4448 CallBase &CB = cast<CallBase>(getAnchorValue());
4449 Use &U = CB.getArgOperandUse(getCallSiteArgNo());
4450 assert(!isa<UndefValue>(U.get()) &&(static_cast <bool> (!isa<UndefValue>(U.get()) &&
"Expected undef values to be filtered out!") ? void (0) : __assert_fail
("!isa<UndefValue>(U.get()) && \"Expected undef values to be filtered out!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4451, __extension__
__PRETTY_FUNCTION__))
4451 "Expected undef values to be filtered out!")(static_cast <bool> (!isa<UndefValue>(U.get()) &&
"Expected undef values to be filtered out!") ? void (0) : __assert_fail
("!isa<UndefValue>(U.get()) && \"Expected undef values to be filtered out!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4451, __extension__
__PRETTY_FUNCTION__))
;
4452 UndefValue &UV = *UndefValue::get(U->getType());
4453 if (A.changeUseAfterManifest(U, UV))
4454 return ChangeStatus::CHANGED;
4455 return ChangeStatus::UNCHANGED;
4456 }
4457
4458 /// See AbstractAttribute::trackStatistics()
4459 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead){ static llvm::Statistic NumIRCSArguments_IsDead = {"attributor"
, "NumIRCSArguments_IsDead", ("Number of " "call site arguments"
" marked '" "IsDead" "'")};; ++(NumIRCSArguments_IsDead); }
}
4460};
4461
4462struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
4463 AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
4464 : AAIsDeadFloating(IRP, A) {}
4465
4466 /// See AAIsDead::isAssumedDead().
4467 bool isAssumedDead() const override {
4468 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4469 }
4470
4471 /// See AbstractAttribute::initialize(...).
4472 void initialize(Attributor &A) override {
4473 AAIsDeadFloating::initialize(A);
4474 if (isa<UndefValue>(getAssociatedValue())) {
4475 indicatePessimisticFixpoint();
4476 return;
4477 }
4478
4479 // We track this separately as a secondary state.
4480 IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());
4481 }
4482
4483 /// See AbstractAttribute::updateImpl(...).
4484 ChangeStatus updateImpl(Attributor &A) override {
4485 ChangeStatus Changed = ChangeStatus::UNCHANGED;
4486 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {
4487 IsAssumedSideEffectFree = false;
4488 Changed = ChangeStatus::CHANGED;
4489 }
4490 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4491 return indicatePessimisticFixpoint();
4492 return Changed;
4493 }
4494
4495 /// See AbstractAttribute::trackStatistics()
4496 void trackStatistics() const override {
4497 if (IsAssumedSideEffectFree)
4498 STATS_DECLTRACK_CSRET_ATTR(IsDead){ static llvm::Statistic NumIRCSReturn_IsDead = {"attributor"
, "NumIRCSReturn_IsDead", ("Number of " "call site returns" " marked '"
"IsDead" "'")};; ++(NumIRCSReturn_IsDead); }
4499 else
4500 STATS_DECLTRACK_CSRET_ATTR(UnusedResult){ static llvm::Statistic NumIRCSReturn_UnusedResult = {"attributor"
, "NumIRCSReturn_UnusedResult", ("Number of " "call site returns"
" marked '" "UnusedResult" "'")};; ++(NumIRCSReturn_UnusedResult
); }
4501 }
4502
4503 /// See AbstractAttribute::getAsStr().
4504 const std::string getAsStr() const override {
4505 return isAssumedDead()
4506 ? "assumed-dead"
4507 : (getAssumed() ? "assumed-dead-users" : "assumed-live");
4508 }
4509
4510private:
4511 bool IsAssumedSideEffectFree = true;
4512};
4513
4514struct AAIsDeadReturned : public AAIsDeadValueImpl {
4515 AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
4516 : AAIsDeadValueImpl(IRP, A) {}
4517
4518 /// See AbstractAttribute::updateImpl(...).
4519 ChangeStatus updateImpl(Attributor &A) override {
4520
4521 bool UsedAssumedInformation = false;
4522 A.checkForAllInstructions([](Instruction &) { return true; }, *this,
4523 {Instruction::Ret}, UsedAssumedInformation);
4524
4525 auto PredForCallSite = [&](AbstractCallSite ACS) {
4526 if (ACS.isCallbackCall() || !ACS.getInstruction())
4527 return false;
4528 return areAllUsesAssumedDead(A, *ACS.getInstruction());
4529 };
4530
4531 if (!A.checkForAllCallSites(PredForCallSite, *this, true,
4532 UsedAssumedInformation))
4533 return indicatePessimisticFixpoint();
4534
4535 return ChangeStatus::UNCHANGED;
4536 }
4537
4538 /// See AbstractAttribute::manifest(...).
4539 ChangeStatus manifest(Attributor &A) override {
4540 // TODO: Rewrite the signature to return void?
4541 bool AnyChange = false;
4542 UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());
4543 auto RetInstPred = [&](Instruction &I) {
4544 ReturnInst &RI = cast<ReturnInst>(I);
4545 if (!isa<UndefValue>(RI.getReturnValue()))
4546 AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
4547 return true;
4548 };
4549 bool UsedAssumedInformation = false;
4550 A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
4551 UsedAssumedInformation);
4552 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4553 }
4554
4555 /// See AbstractAttribute::trackStatistics()
4556 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead){ static llvm::Statistic NumIRFunctionReturn_IsDead = {"attributor"
, "NumIRFunctionReturn_IsDead", ("Number of " "function returns"
" marked '" "IsDead" "'")};; ++(NumIRFunctionReturn_IsDead);
}
}
4557};
4558
4559struct AAIsDeadFunction : public AAIsDead {
4560 AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4561
4562 /// See AbstractAttribute::initialize(...).
4563 void initialize(Attributor &A) override {
4564 Function *F = getAnchorScope();
4565 if (!F || F->isDeclaration() || !A.isRunOn(*F)) {
4566 indicatePessimisticFixpoint();
4567 return;
4568 }
4569 if (!isAssumedDeadInternalFunction(A)) {
4570 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4571 assumeLive(A, F->getEntryBlock());
4572 }
4573 }
4574
4575 bool isAssumedDeadInternalFunction(Attributor &A) {
4576 if (!getAnchorScope()->hasLocalLinkage())
4577 return false;
4578 bool UsedAssumedInformation = false;
4579 return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,
4580 true, UsedAssumedInformation);
4581 }
4582
4583 /// See AbstractAttribute::getAsStr().
4584 const std::string getAsStr() const override {
4585 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
4586 std::to_string(getAnchorScope()->size()) + "][#TBEP " +
4587 std::to_string(ToBeExploredFrom.size()) + "][#KDE " +
4588 std::to_string(KnownDeadEnds.size()) + "]";
4589 }
4590
4591 /// See AbstractAttribute::manifest(...).
4592 ChangeStatus manifest(Attributor &A) override {
4593 assert(getState().isValidState() &&(static_cast <bool> (getState().isValidState() &&
"Attempted to manifest an invalid state!") ? void (0) : __assert_fail
("getState().isValidState() && \"Attempted to manifest an invalid state!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4594, __extension__
__PRETTY_FUNCTION__))
4594 "Attempted to manifest an invalid state!")(static_cast <bool> (getState().isValidState() &&
"Attempted to manifest an invalid state!") ? void (0) : __assert_fail
("getState().isValidState() && \"Attempted to manifest an invalid state!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4594, __extension__
__PRETTY_FUNCTION__))
;
4595
4596 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
4597 Function &F = *getAnchorScope();
4598
4599 if (AssumedLiveBlocks.empty()) {
4600 A.deleteAfterManifest(F);
4601 return ChangeStatus::CHANGED;
4602 }
4603
4604 // Flag to determine if we can change an invoke to a call assuming the
4605 // callee is nounwind. This is not possible if the personality of the
4606 // function allows to catch asynchronous exceptions.
4607 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
4608
4609 KnownDeadEnds.set_union(ToBeExploredFrom);
4610 for (const Instruction *DeadEndI : KnownDeadEnds) {
4611 auto *CB = dyn_cast<CallBase>(DeadEndI);
4612 if (!CB)
4613 continue;
4614 const auto &NoReturnAA = A.getAndUpdateAAFor<AANoReturn>(
4615 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
4616 bool MayReturn = !NoReturnAA.isAssumedNoReturn();
4617 if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))
4618 continue;
4619
4620 if (auto *II = dyn_cast<InvokeInst>(DeadEndI))
4621 A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));
4622 else
4623 A.changeToUnreachableAfterManifest(
4624 const_cast<Instruction *>(DeadEndI->getNextNode()));
4625 HasChanged = ChangeStatus::CHANGED;
4626 }
4627
4628 STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.")static llvm::Statistic NumIRBasicBlock_AAIsDead = {"attributor"
, "NumIRBasicBlock_AAIsDead", "Number of dead basic blocks deleted."
};;
;
4629 for (BasicBlock &BB : F)
4630 if (!AssumedLiveBlocks.count(&BB)) {
4631 A.deleteAfterManifest(BB);
4632 ++BUILD_STAT_NAME(AAIsDead, BasicBlock)NumIRBasicBlock_AAIsDead;
4633 HasChanged = ChangeStatus::CHANGED;
4634 }
4635
4636 return HasChanged;
4637 }
4638
4639 /// See AbstractAttribute::updateImpl(...).
4640 ChangeStatus updateImpl(Attributor &A) override;
4641
4642 bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
4643 assert(From->getParent() == getAnchorScope() &&(static_cast <bool> (From->getParent() == getAnchorScope
() && To->getParent() == getAnchorScope() &&
"Used AAIsDead of the wrong function") ? void (0) : __assert_fail
("From->getParent() == getAnchorScope() && To->getParent() == getAnchorScope() && \"Used AAIsDead of the wrong function\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4645, __extension__
__PRETTY_FUNCTION__))
4644 To->getParent() == getAnchorScope() &&(static_cast <bool> (From->getParent() == getAnchorScope
() && To->getParent() == getAnchorScope() &&
"Used AAIsDead of the wrong function") ? void (0) : __assert_fail
("From->getParent() == getAnchorScope() && To->getParent() == getAnchorScope() && \"Used AAIsDead of the wrong function\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4645, __extension__
__PRETTY_FUNCTION__))
4645 "Used AAIsDead of the wrong function")(static_cast <bool> (From->getParent() == getAnchorScope
() && To->getParent() == getAnchorScope() &&
"Used AAIsDead of the wrong function") ? void (0) : __assert_fail
("From->getParent() == getAnchorScope() && To->getParent() == getAnchorScope() && \"Used AAIsDead of the wrong function\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4645, __extension__
__PRETTY_FUNCTION__))
;
4646 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4647 }
4648
4649 /// See AbstractAttribute::trackStatistics()
4650 void trackStatistics() const override {}
4651
4652 /// Returns true if the function is assumed dead.
4653 bool isAssumedDead() const override { return false; }
4654
4655 /// See AAIsDead::isKnownDead().
4656 bool isKnownDead() const override { return false; }
4657
4658 /// See AAIsDead::isAssumedDead(BasicBlock *).
4659 bool isAssumedDead(const BasicBlock *BB) const override {
4660 assert(BB->getParent() == getAnchorScope() &&(static_cast <bool> (BB->getParent() == getAnchorScope
() && "BB must be in the same anchor scope function."
) ? void (0) : __assert_fail ("BB->getParent() == getAnchorScope() && \"BB must be in the same anchor scope function.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4661, __extension__
__PRETTY_FUNCTION__))
4661 "BB must be in the same anchor scope function.")(static_cast <bool> (BB->getParent() == getAnchorScope
() && "BB must be in the same anchor scope function."
) ? void (0) : __assert_fail ("BB->getParent() == getAnchorScope() && \"BB must be in the same anchor scope function.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4661, __extension__
__PRETTY_FUNCTION__))
;
4662
4663 if (!getAssumed())
4664 return false;
4665 return !AssumedLiveBlocks.count(BB);
4666 }
4667
4668 /// See AAIsDead::isKnownDead(BasicBlock *).
4669 bool isKnownDead(const BasicBlock *BB) const override {
4670 return getKnown() && isAssumedDead(BB);
4671 }
4672
4673 /// See AAIsDead::isAssumed(Instruction *I).
4674 bool isAssumedDead(const Instruction *I) const override {
4675 assert(I->getParent()->getParent() == getAnchorScope() &&(static_cast <bool> (I->getParent()->getParent() ==
getAnchorScope() && "Instruction must be in the same anchor scope function."
) ? void (0) : __assert_fail ("I->getParent()->getParent() == getAnchorScope() && \"Instruction must be in the same anchor scope function.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4676, __extension__
__PRETTY_FUNCTION__))
4676 "Instruction must be in the same anchor scope function.")(static_cast <bool> (I->getParent()->getParent() ==
getAnchorScope() && "Instruction must be in the same anchor scope function."
) ? void (0) : __assert_fail ("I->getParent()->getParent() == getAnchorScope() && \"Instruction must be in the same anchor scope function.\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4676, __extension__
__PRETTY_FUNCTION__))
;
4677
4678 if (!getAssumed())
4679 return false;
4680
4681 // If it is not in AssumedLiveBlocks then it for sure dead.
4682 // Otherwise, it can still be after noreturn call in a live block.
4683 if (!AssumedLiveBlocks.count(I->getParent()))
4684 return true;
4685
4686 // If it is not after a liveness barrier it is live.
4687 const Instruction *PrevI = I->getPrevNode();
4688 while (PrevI) {
4689 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4690 return true;
4691 PrevI = PrevI->getPrevNode();
4692 }
4693 return false;
4694 }
4695
4696 /// See AAIsDead::isKnownDead(Instruction *I).
4697 bool isKnownDead(const Instruction *I) const override {
4698 return getKnown() && isAssumedDead(I);
4699 }
4700
4701 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
4702 /// that internal function called from \p BB should now be looked at.
4703 bool assumeLive(Attributor &A, const BasicBlock &BB) {
4704 if (!AssumedLiveBlocks.insert(&BB).second)
4705 return false;
4706
4707 // We assume that all of BB is (probably) live now and if there are calls to
4708 // internal functions we will assume that those are now live as well. This
4709 // is a performance optimization for blocks with calls to a lot of internal
4710 // functions. It can however cause dead functions to be treated as live.
4711 for (const Instruction &I : BB)
4712 if (const auto *CB = dyn_cast<CallBase>(&I))
4713 if (const Function *F = CB->getCalledFunction())
4714 if (F->hasLocalLinkage())
4715 A.markLiveInternalFunction(*F);
4716 return true;
4717 }
4718
4719 /// Collection of instructions that need to be explored again, e.g., we
4720 /// did assume they do not transfer control to (one of their) successors.
4721 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4722
4723 /// Collection of instructions that are known to not transfer control.
4724 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4725
4726 /// Collection of all assumed live edges
4727 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4728
4729 /// Collection of all assumed live BasicBlocks.
4730 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4731};
4732
4733static bool
4734identifyAliveSuccessors(Attributor &A, const CallBase &CB,
4735 AbstractAttribute &AA,
4736 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4737 const IRPosition &IPos = IRPosition::callsite_function(CB);
4738
4739 const auto &NoReturnAA =
4740 A.getAndUpdateAAFor<AANoReturn>(AA, IPos, DepClassTy::OPTIONAL);
4741 if (NoReturnAA.isAssumedNoReturn())
4742 return !NoReturnAA.isKnownNoReturn();
4743 if (CB.isTerminator())
4744 AliveSuccessors.push_back(&CB.getSuccessor(0)->front());
4745 else
4746 AliveSuccessors.push_back(CB.getNextNode());
4747 return false;
4748}
4749
4750static bool
4751identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
4752 AbstractAttribute &AA,
4753 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4754 bool UsedAssumedInformation =
4755 identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);
4756
4757 // First, determine if we can change an invoke to a call assuming the
4758 // callee is nounwind. This is not possible if the personality of the
4759 // function allows to catch asynchronous exceptions.
4760 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {
4761 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4762 } else {
4763 const IRPosition &IPos = IRPosition::callsite_function(II);
4764 const auto &AANoUnw =
4765 A.getAndUpdateAAFor<AANoUnwind>(AA, IPos, DepClassTy::OPTIONAL);
4766 if (AANoUnw.isAssumedNoUnwind()) {
4767 UsedAssumedInformation |= !AANoUnw.isKnownNoUnwind();
4768 } else {
4769 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4770 }
4771 }
4772 return UsedAssumedInformation;
4773}
4774
4775static bool
4776identifyAliveSuccessors(Attributor &A, const BranchInst &BI,
4777 AbstractAttribute &AA,
4778 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4779 bool UsedAssumedInformation = false;
4780 if (BI.getNumSuccessors() == 1) {
4781 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4782 } else {
4783 std::optional<Constant *> C =
4784 A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);
4785 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4786 // No value yet, assume both edges are dead.
4787 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4788 const BasicBlock *SuccBB =
4789 BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());
4790 AliveSuccessors.push_back(&SuccBB->front());
4791 } else {
4792 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4793 AliveSuccessors.push_back(&BI.getSuccessor(1)->front());
4794 UsedAssumedInformation = false;
4795 }
4796 }
4797 return UsedAssumedInformation;
4798}
4799
4800static bool
4801identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
4802 AbstractAttribute &AA,
4803 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4804 bool UsedAssumedInformation = false;
4805 std::optional<Constant *> C =
4806 A.getAssumedConstant(*SI.getCondition(), AA, UsedAssumedInformation);
4807 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4808 // No value yet, assume all edges are dead.
4809 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4810 for (const auto &CaseIt : SI.cases()) {
4811 if (CaseIt.getCaseValue() == *C) {
4812 AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());
4813 return UsedAssumedInformation;
4814 }
4815 }
4816 AliveSuccessors.push_back(&SI.getDefaultDest()->front());
4817 return UsedAssumedInformation;
4818 } else {
4819 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4820 AliveSuccessors.push_back(&SuccBB->front());
4821 }
4822 return UsedAssumedInformation;
4823}
4824
4825ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
4826 ChangeStatus Change = ChangeStatus::UNCHANGED;
4827
4828 if (AssumedLiveBlocks.empty()) {
4829 if (isAssumedDeadInternalFunction(A))
4830 return ChangeStatus::UNCHANGED;
4831
4832 Function *F = getAnchorScope();
4833 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4834 assumeLive(A, F->getEntryBlock());
4835 Change = ChangeStatus::CHANGED;
4836 }
4837
4838 LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Live [" <<
AssumedLiveBlocks.size() << "/" << getAnchorScope
()->size() << "] BBs and " << ToBeExploredFrom
.size() << " exploration points and " << KnownDeadEnds
.size() << " known dead ends\n"; } } while (false)
4839 << getAnchorScope()->size() << "] BBs and "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Live [" <<
AssumedLiveBlocks.size() << "/" << getAnchorScope
()->size() << "] BBs and " << ToBeExploredFrom
.size() << " exploration points and " << KnownDeadEnds
.size() << " known dead ends\n"; } } while (false)
4840 << ToBeExploredFrom.size() << " exploration points and "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Live [" <<
AssumedLiveBlocks.size() << "/" << getAnchorScope
()->size() << "] BBs and " << ToBeExploredFrom
.size() << " exploration points and " << KnownDeadEnds
.size() << " known dead ends\n"; } } while (false)
4841 << KnownDeadEnds.size() << " known dead ends\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Live [" <<
AssumedLiveBlocks.size() << "/" << getAnchorScope
()->size() << "] BBs and " << ToBeExploredFrom
.size() << " exploration points and " << KnownDeadEnds
.size() << " known dead ends\n"; } } while (false)
;
4842
4843 // Copy and clear the list of instructions we need to explore from. It is
4844 // refilled with instructions the next update has to look at.
4845 SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
4846 ToBeExploredFrom.end());
4847 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4848
4849 SmallVector<const Instruction *, 8> AliveSuccessors;
4850 while (!Worklist.empty()) {
4851 const Instruction *I = Worklist.pop_back_val();
4852 LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Exploration inst: "
<< *I << "\n"; } } while (false)
;
4853
4854 // Fast forward for uninteresting instructions. We could look for UB here
4855 // though.
4856 while (!I->isTerminator() && !isa<CallBase>(I))
4857 I = I->getNextNode();
4858
4859 AliveSuccessors.clear();
4860
4861 bool UsedAssumedInformation = false;
4862 switch (I->getOpcode()) {
4863 // TODO: look for (assumed) UB to backwards propagate "deadness".
4864 default:
4865 assert(I->isTerminator() &&(static_cast <bool> (I->isTerminator() && "Expected non-terminators to be handled already!"
) ? void (0) : __assert_fail ("I->isTerminator() && \"Expected non-terminators to be handled already!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4866, __extension__
__PRETTY_FUNCTION__))
4866 "Expected non-terminators to be handled already!")(static_cast <bool> (I->isTerminator() && "Expected non-terminators to be handled already!"
) ? void (0) : __assert_fail ("I->isTerminator() && \"Expected non-terminators to be handled already!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4866, __extension__
__PRETTY_FUNCTION__))
;
4867 for (const BasicBlock *SuccBB : successors(I->getParent()))
4868 AliveSuccessors.push_back(&SuccBB->front());
4869 break;
4870 case Instruction::Call:
4871 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),
4872 *this, AliveSuccessors);
4873 break;
4874 case Instruction::Invoke:
4875 UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),
4876 *this, AliveSuccessors);
4877 break;
4878 case Instruction::Br:
4879 UsedAssumedInformation = identifyAliveSuccessors(A, cast<BranchInst>(*I),
4880 *this, AliveSuccessors);
4881 break;
4882 case Instruction::Switch:
4883 UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),
4884 *this, AliveSuccessors);
4885 break;
4886 }
4887
4888 if (UsedAssumedInformation) {
4889 NewToBeExploredFrom.insert(I);
4890 } else if (AliveSuccessors.empty() ||
4891 (I->isTerminator() &&
4892 AliveSuccessors.size() < I->getNumSuccessors())) {
4893 if (KnownDeadEnds.insert(I))
4894 Change = ChangeStatus::CHANGED;
4895 }
4896
4897 LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] #AliveSuccessors: "
<< AliveSuccessors.size() << " UsedAssumedInformation: "
<< UsedAssumedInformation << "\n"; } } while (false
)
4898 << AliveSuccessors.size() << " UsedAssumedInformation: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] #AliveSuccessors: "
<< AliveSuccessors.size() << " UsedAssumedInformation: "
<< UsedAssumedInformation << "\n"; } } while (false
)
4899 << UsedAssumedInformation << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] #AliveSuccessors: "
<< AliveSuccessors.size() << " UsedAssumedInformation: "
<< UsedAssumedInformation << "\n"; } } while (false
)
;
4900
4901 for (const Instruction *AliveSuccessor : AliveSuccessors) {
4902 if (!I->isTerminator()) {
4903 assert(AliveSuccessors.size() == 1 &&(static_cast <bool> (AliveSuccessors.size() == 1 &&
"Non-terminator expected to have a single successor!") ? void
(0) : __assert_fail ("AliveSuccessors.size() == 1 && \"Non-terminator expected to have a single successor!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4904, __extension__
__PRETTY_FUNCTION__))
4904 "Non-terminator expected to have a single successor!")(static_cast <bool> (AliveSuccessors.size() == 1 &&
"Non-terminator expected to have a single successor!") ? void
(0) : __assert_fail ("AliveSuccessors.size() == 1 && \"Non-terminator expected to have a single successor!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 4904, __extension__
__PRETTY_FUNCTION__))
;
4905 Worklist.push_back(AliveSuccessor);
4906 } else {
4907 // record the assumed live edge
4908 auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());
4909 if (AssumedLiveEdges.insert(Edge).second)
4910 Change = ChangeStatus::CHANGED;
4911 if (assumeLive(A, *AliveSuccessor->getParent()))
4912 Worklist.push_back(AliveSuccessor);
4913 }
4914 }
4915 }
4916
4917 // Check if the content of ToBeExploredFrom changed, ignore the order.
4918 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4919 llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {
4920 return !ToBeExploredFrom.count(I);
4921 })) {
4922 Change = ChangeStatus::CHANGED;
4923 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4924 }
4925
4926 // If we know everything is live there is no need to query for liveness.
4927 // Instead, indicating a pessimistic fixpoint will cause the state to be
4928 // "invalid" and all queries to be answered conservatively without lookups.
4929 // To be in this state we have to (1) finished the exploration and (3) not
4930 // discovered any non-trivial dead end and (2) not ruled unreachable code
4931 // dead.
4932 if (ToBeExploredFrom.empty() &&
4933 getAnchorScope()->size() == AssumedLiveBlocks.size() &&
4934 llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {
4935 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4936 }))
4937 return indicatePessimisticFixpoint();
4938 return Change;
4939}
4940
4941/// Liveness information for a call sites.
4942struct AAIsDeadCallSite final : AAIsDeadFunction {
4943 AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
4944 : AAIsDeadFunction(IRP, A) {}
4945
4946 /// See AbstractAttribute::initialize(...).
4947 void initialize(Attributor &A) override {
4948 // TODO: Once we have call site specific value information we can provide
4949 // call site specific liveness information and then it makes
4950 // sense to specialize attributes for call sites instead of
4951 // redirecting requests to the callee.
4952 llvm_unreachable("Abstract attributes for liveness are not "::llvm::llvm_unreachable_internal("Abstract attributes for liveness are not "
"supported for call sites yet!", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 4953)
4953 "supported for call sites yet!")::llvm::llvm_unreachable_internal("Abstract attributes for liveness are not "
"supported for call sites yet!", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 4953)
;
4954 }
4955
4956 /// See AbstractAttribute::updateImpl(...).
4957 ChangeStatus updateImpl(Attributor &A) override {
4958 return indicatePessimisticFixpoint();
4959 }
4960
4961 /// See AbstractAttribute::trackStatistics()
4962 void trackStatistics() const override {}
4963};
4964} // namespace
4965
4966/// -------------------- Dereferenceable Argument Attribute --------------------
4967
4968namespace {
4969struct AADereferenceableImpl : AADereferenceable {
4970 AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
4971 : AADereferenceable(IRP, A) {}
4972 using StateType = DerefState;
4973
4974 /// See AbstractAttribute::initialize(...).
4975 void initialize(Attributor &A) override {
4976 Value &V = *getAssociatedValue().stripPointerCasts();
4977 SmallVector<Attribute, 4> Attrs;
4978 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4979 Attrs, /* IgnoreSubsumingPositions */ false, &A);
4980 for (const Attribute &Attr : Attrs)
4981 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4982
4983 const IRPosition &IRP = this->getIRPosition();
4984 NonNullAA = &A.getAAFor<AANonNull>(*this, IRP, DepClassTy::NONE);
4985
4986 bool CanBeNull, CanBeFreed;
4987 takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(
4988 A.getDataLayout(), CanBeNull, CanBeFreed));
4989
4990 bool IsFnInterface = IRP.isFnInterfaceKind();
4991 Function *FnScope = IRP.getAnchorScope();
4992 if (IsFnInterface && (!FnScope || !A.isFunctionIPOAmendable(*FnScope))) {
4993 indicatePessimisticFixpoint();
4994 return;
4995 }
4996
4997 if (Instruction *CtxI = getCtxI())
4998 followUsesInMBEC(*this, A, getState(), *CtxI);
4999 }
5000
5001 /// See AbstractAttribute::getState()
5002 /// {
5003 StateType &getState() override { return *this; }
5004 const StateType &getState() const override { return *this; }
5005 /// }
5006
5007 /// Helper function for collecting accessed bytes in must-be-executed-context
5008 void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
5009 DerefState &State) {
5010 const Value *UseV = U->get();
5011 if (!UseV->getType()->isPointerTy())
5012 return;
5013
5014 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
5015 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
5016 return;
5017
5018 int64_t Offset;
5019 const Value *Base = GetPointerBaseWithConstantOffset(
5020 Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);
5021 if (Base && Base == &getAssociatedValue())
5022 State.addAccessedBytes(Offset, Loc->Size.getValue());
5023 }
5024
5025 /// See followUsesInMBEC
5026 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5027 AADereferenceable::StateType &State) {
5028 bool IsNonNull = false;
5029 bool TrackUse = false;
5030 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
5031 A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);
5032 LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytesdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AADereferenceable] Deref bytes: "
<< DerefBytes << " for instruction " << *I
<< "\n"; } } while (false)
5033 << " for instruction " << *I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AADereferenceable] Deref bytes: "
<< DerefBytes << " for instruction " << *I
<< "\n"; } } while (false)
;
5034
5035 addAccessedBytesForUse(A, U, I, State);
5036 State.takeKnownDerefBytesMaximum(DerefBytes);
5037 return TrackUse;
5038 }
5039
5040 /// See AbstractAttribute::manifest(...).
5041 ChangeStatus manifest(Attributor &A) override {
5042 ChangeStatus Change = AADereferenceable::manifest(A);
5043 if (isAssumedNonNull() && hasAttr(Attribute::DereferenceableOrNull)) {
5044 removeAttrs({Attribute::DereferenceableOrNull});
5045 return ChangeStatus::CHANGED;
5046 }
5047 return Change;
5048 }
5049
5050 void getDeducedAttributes(LLVMContext &Ctx,
5051 SmallVectorImpl<Attribute> &Attrs) const override {
5052 // TODO: Add *_globally support
5053 if (isAssumedNonNull())
5054 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5055 Ctx, getAssumedDereferenceableBytes()));
5056 else
5057 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5058 Ctx, getAssumedDereferenceableBytes()));
5059 }
5060
5061 /// See AbstractAttribute::getAsStr().
5062 const std::string getAsStr() const override {
5063 if (!getAssumedDereferenceableBytes())
5064 return "unknown-dereferenceable";
5065 return std::string("dereferenceable") +
5066 (isAssumedNonNull() ? "" : "_or_null") +
5067 (isAssumedGlobal() ? "_globally" : "") + "<" +
5068 std::to_string(getKnownDereferenceableBytes()) + "-" +
5069 std::to_string(getAssumedDereferenceableBytes()) + ">";
5070 }
5071};
5072
5073/// Dereferenceable attribute for a floating value.
5074struct AADereferenceableFloating : AADereferenceableImpl {
5075 AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
5076 : AADereferenceableImpl(IRP, A) {}
5077
5078 /// See AbstractAttribute::updateImpl(...).
5079 ChangeStatus updateImpl(Attributor &A) override {
5080
5081 bool Stripped;
5082 bool UsedAssumedInformation = false;
5083 SmallVector<AA::ValueAndContext> Values;
5084 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5085 AA::AnyScope, UsedAssumedInformation)) {
5086 Values.push_back({getAssociatedValue(), getCtxI()});
5087 Stripped = false;
5088 } else {
5089 Stripped = Values.size() != 1 ||
5090 Values.front().getValue() != &getAssociatedValue();
5091 }
5092
5093 const DataLayout &DL = A.getDataLayout();
5094 DerefState T;
5095
5096 auto VisitValueCB = [&](const Value &V) -> bool {
5097 unsigned IdxWidth =
5098 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
5099 APInt Offset(IdxWidth, 0);
5100 const Value *Base = stripAndAccumulateOffsets(
5101 A, *this, &V, DL, Offset, /* GetMinOffset */ false,
5102 /* AllowNonInbounds */ true);
5103
5104 const auto &AA = A.getAAFor<AADereferenceable>(
5105 *this, IRPosition::value(*Base), DepClassTy::REQUIRED);
5106 int64_t DerefBytes = 0;
5107 if (!Stripped && this == &AA) {
5108 // Use IR information if we did not strip anything.
5109 // TODO: track globally.
5110 bool CanBeNull, CanBeFreed;
5111 DerefBytes =
5112 Base->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);
5113 T.GlobalState.indicatePessimisticFixpoint();
5114 } else {
5115 const DerefState &DS = AA.getState();
5116 DerefBytes = DS.DerefBytesState.getAssumed();
5117 T.GlobalState &= DS.GlobalState;
5118 }
5119
5120 // For now we do not try to "increase" dereferenceability due to negative
5121 // indices as we first have to come up with code to deal with loops and
5122 // for overflows of the dereferenceable bytes.
5123 int64_t OffsetSExt = Offset.getSExtValue();
5124 if (OffsetSExt < 0)
5125 OffsetSExt = 0;
5126
5127 T.takeAssumedDerefBytesMinimum(
5128 std::max(int64_t(0), DerefBytes - OffsetSExt));
5129
5130 if (this == &AA) {
5131 if (!Stripped) {
5132 // If nothing was stripped IR information is all we got.
5133 T.takeKnownDerefBytesMaximum(
5134 std::max(int64_t(0), DerefBytes - OffsetSExt));
5135 T.indicatePessimisticFixpoint();
5136 } else if (OffsetSExt > 0) {
5137 // If something was stripped but there is circular reasoning we look
5138 // for the offset. If it is positive we basically decrease the
5139 // dereferenceable bytes in a circular loop now, which will simply
5140 // drive them down to the known value in a very slow way which we
5141 // can accelerate.
5142 T.indicatePessimisticFixpoint();
5143 }
5144 }
5145
5146 return T.isValidState();
5147 };
5148
5149 for (const auto &VAC : Values)
5150 if (!VisitValueCB(*VAC.getValue()))
5151 return indicatePessimisticFixpoint();
5152
5153 return clampStateAndIndicateChange(getState(), T);
5154 }
5155
5156 /// See AbstractAttribute::trackStatistics()
5157 void trackStatistics() const override {
5158 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable){ static llvm::Statistic NumIRFloating_dereferenceable = {"attributor"
, "NumIRFloating_dereferenceable", ("Number of floating values known to be '"
"dereferenceable" "'")};; ++(NumIRFloating_dereferenceable);
}
5159 }
5160};
5161
5162/// Dereferenceable attribute for a return value.
5163struct AADereferenceableReturned final
5164 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5165 AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
5166 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>(
5167 IRP, A) {}
5168
5169 /// See AbstractAttribute::trackStatistics()
5170 void trackStatistics() const override {
5171 STATS_DECLTRACK_FNRET_ATTR(dereferenceable){ static llvm::Statistic NumIRFunctionReturn_dereferenceable =
{"attributor", "NumIRFunctionReturn_dereferenceable", ("Number of "
"function returns" " marked '" "dereferenceable" "'")};; ++(
NumIRFunctionReturn_dereferenceable); }
5172 }
5173};
5174
5175/// Dereferenceable attribute for an argument
5176struct AADereferenceableArgument final
5177 : AAArgumentFromCallSiteArguments<AADereferenceable,
5178 AADereferenceableImpl> {
5179 using Base =
5180 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5181 AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
5182 : Base(IRP, A) {}
5183
5184 /// See AbstractAttribute::trackStatistics()
5185 void trackStatistics() const override {
5186 STATS_DECLTRACK_ARG_ATTR(dereferenceable){ static llvm::Statistic NumIRArguments_dereferenceable = {"attributor"
, "NumIRArguments_dereferenceable", ("Number of " "arguments"
" marked '" "dereferenceable" "'")};; ++(NumIRArguments_dereferenceable
); }
5187 }
5188};
5189
5190/// Dereferenceable attribute for a call site argument.
5191struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5192 AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
5193 : AADereferenceableFloating(IRP, A) {}
5194
5195 /// See AbstractAttribute::trackStatistics()
5196 void trackStatistics() const override {
5197 STATS_DECLTRACK_CSARG_ATTR(dereferenceable){ static llvm::Statistic NumIRCSArguments_dereferenceable = {
"attributor", "NumIRCSArguments_dereferenceable", ("Number of "
"call site arguments" " marked '" "dereferenceable" "'")};; ++
(NumIRCSArguments_dereferenceable); }
5198 }
5199};
5200
5201/// Dereferenceable attribute deduction for a call site return value.
5202struct AADereferenceableCallSiteReturned final
5203 : AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl> {
5204 using Base =
5205 AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl>;
5206 AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
5207 : Base(IRP, A) {}
5208
5209 /// See AbstractAttribute::trackStatistics()
5210 void trackStatistics() const override {
5211 STATS_DECLTRACK_CS_ATTR(dereferenceable){ static llvm::Statistic NumIRCS_dereferenceable = {"attributor"
, "NumIRCS_dereferenceable", ("Number of " "call site" " marked '"
"dereferenceable" "'")};; ++(NumIRCS_dereferenceable); }
;
5212 }
5213};
5214} // namespace
5215
5216// ------------------------ Align Argument Attribute ------------------------
5217
5218namespace {
5219static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
5220 Value &AssociatedValue, const Use *U,
5221 const Instruction *I, bool &TrackUse) {
5222 // We need to follow common pointer manipulation uses to the accesses they
5223 // feed into.
5224 if (isa<CastInst>(I)) {
5225 // Follow all but ptr2int casts.
5226 TrackUse = !isa<PtrToIntInst>(I);
5227 return 0;
5228 }
5229 if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
5230 if (GEP->hasAllConstantIndices())
5231 TrackUse = true;
5232 return 0;
5233 }
5234
5235 MaybeAlign MA;
5236 if (const auto *CB = dyn_cast<CallBase>(I)) {
5237 if (CB->isBundleOperand(U) || CB->isCallee(U))
5238 return 0;
5239
5240 unsigned ArgNo = CB->getArgOperandNo(U);
5241 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
5242 // As long as we only use known information there is no need to track
5243 // dependences here.
5244 auto &AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);
5245 MA = MaybeAlign(AlignAA.getKnownAlign());
5246 }
5247
5248 const DataLayout &DL = A.getDataLayout();
5249 const Value *UseV = U->get();
5250 if (auto *SI = dyn_cast<StoreInst>(I)) {
5251 if (SI->getPointerOperand() == UseV)
5252 MA = SI->getAlign();
5253 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
5254 if (LI->getPointerOperand() == UseV)
5255 MA = LI->getAlign();
5256 }
5257
5258 if (!MA || *MA <= QueryingAA.getKnownAlign())
5259 return 0;
5260
5261 unsigned Alignment = MA->value();
5262 int64_t Offset;
5263
5264 if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
5265 if (Base == &AssociatedValue) {
5266 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5267 // So we can say that the maximum power of two which is a divisor of
5268 // gcd(Offset, Alignment) is an alignment.
5269
5270 uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);
5271 Alignment = llvm::bit_floor(gcd);
5272 }
5273 }
5274
5275 return Alignment;
5276}
5277
5278struct AAAlignImpl : AAAlign {
5279 AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}
5280
5281 /// See AbstractAttribute::initialize(...).
5282 void initialize(Attributor &A) override {
5283 SmallVector<Attribute, 4> Attrs;
5284 getAttrs({Attribute::Alignment}, Attrs);
5285 for (const Attribute &Attr : Attrs)
5286 takeKnownMaximum(Attr.getValueAsInt());
5287
5288 Value &V = *getAssociatedValue().stripPointerCasts();
5289 takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());
5290
5291 if (getIRPosition().isFnInterfaceKind() &&
5292 (!getAnchorScope() ||
5293 !A.isFunctionIPOAmendable(*getAssociatedFunction()))) {
5294 indicatePessimisticFixpoint();
5295 return;
5296 }
5297
5298 if (Instruction *CtxI = getCtxI())
5299 followUsesInMBEC(*this, A, getState(), *CtxI);
5300 }
5301
5302 /// See AbstractAttribute::manifest(...).
5303 ChangeStatus manifest(Attributor &A) override {
5304 ChangeStatus LoadStoreChanged = ChangeStatus::UNCHANGED;
5305
5306 // Check for users that allow alignment annotations.
5307 Value &AssociatedValue = getAssociatedValue();
5308 for (const Use &U : AssociatedValue.uses()) {
5309 if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
5310 if (SI->getPointerOperand() == &AssociatedValue)
5311 if (SI->getAlign() < getAssumedAlign()) {
5312 STATS_DECLTRACK(AAAlign, Store,{ static llvm::Statistic NumIRStore_AAAlign = {"attributor", "NumIRStore_AAAlign"
, "Number of times alignment added to a store"};; ++(NumIRStore_AAAlign
); }
5313 "Number of times alignment added to a store"){ static llvm::Statistic NumIRStore_AAAlign = {"attributor", "NumIRStore_AAAlign"
, "Number of times alignment added to a store"};; ++(NumIRStore_AAAlign
); }
;
5314 SI->setAlignment(getAssumedAlign());
5315 LoadStoreChanged = ChangeStatus::CHANGED;
5316 }
5317 } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
5318 if (LI->getPointerOperand() == &AssociatedValue)
5319 if (LI->getAlign() < getAssumedAlign()) {
5320 LI->setAlignment(getAssumedAlign());
5321 STATS_DECLTRACK(AAAlign, Load,{ static llvm::Statistic NumIRLoad_AAAlign = {"attributor", "NumIRLoad_AAAlign"
, "Number of times alignment added to a load"};; ++(NumIRLoad_AAAlign
); }
5322 "Number of times alignment added to a load"){ static llvm::Statistic NumIRLoad_AAAlign = {"attributor", "NumIRLoad_AAAlign"
, "Number of times alignment added to a load"};; ++(NumIRLoad_AAAlign
); }
;
5323 LoadStoreChanged = ChangeStatus::CHANGED;
5324 }
5325 }
5326 }
5327
5328 ChangeStatus Changed = AAAlign::manifest(A);
5329
5330 Align InheritAlign =
5331 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5332 if (InheritAlign >= getAssumedAlign())
5333 return LoadStoreChanged;
5334 return Changed | LoadStoreChanged;
5335 }
5336
5337 // TODO: Provide a helper to determine the implied ABI alignment and check in
5338 // the existing manifest method and a new one for AAAlignImpl that value
5339 // to avoid making the alignment explicit if it did not improve.
5340
5341 /// See AbstractAttribute::getDeducedAttributes
5342 void getDeducedAttributes(LLVMContext &Ctx,
5343 SmallVectorImpl<Attribute> &Attrs) const override {
5344 if (getAssumedAlign() > 1)
5345 Attrs.emplace_back(
5346 Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
5347 }
5348
5349 /// See followUsesInMBEC
5350 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5351 AAAlign::StateType &State) {
5352 bool TrackUse = false;
5353
5354 unsigned int KnownAlign =
5355 getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
5356 State.takeKnownMaximum(KnownAlign);
5357
5358 return TrackUse;
5359 }
5360
5361 /// See AbstractAttribute::getAsStr().
5362 const std::string getAsStr() const override {
5363 return "align<" + std::to_string(getKnownAlign().value()) + "-" +
5364 std::to_string(getAssumedAlign().value()) + ">";
5365 }
5366};
5367
5368/// Align attribute for a floating value.
5369struct AAAlignFloating : AAAlignImpl {
5370 AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}
5371
5372 /// See AbstractAttribute::updateImpl(...).
5373 ChangeStatus updateImpl(Attributor &A) override {
5374 const DataLayout &DL = A.getDataLayout();
5375
5376 bool Stripped;
5377 bool UsedAssumedInformation = false;
5378 SmallVector<AA::ValueAndContext> Values;
5379 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5380 AA::AnyScope, UsedAssumedInformation)) {
5381 Values.push_back({getAssociatedValue(), getCtxI()});
5382 Stripped = false;
5383 } else {
5384 Stripped = Values.size() != 1 ||
5385 Values.front().getValue() != &getAssociatedValue();
5386 }
5387
5388 StateType T;
5389 auto VisitValueCB = [&](Value &V) -> bool {
5390 if (isa<UndefValue>(V) || isa<ConstantPointerNull>(V))
5391 return true;
5392 const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),
5393 DepClassTy::REQUIRED);
5394 if (!Stripped && this == &AA) {
5395 int64_t Offset;
5396 unsigned Alignment = 1;
5397 if (const Value *Base =
5398 GetPointerBaseWithConstantOffset(&V, Offset, DL)) {
5399 // TODO: Use AAAlign for the base too.
5400 Align PA = Base->getPointerAlignment(DL);
5401 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5402 // So we can say that the maximum power of two which is a divisor of
5403 // gcd(Offset, Alignment) is an alignment.
5404
5405 uint32_t gcd =
5406 std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));
5407 Alignment = llvm::bit_floor(gcd);
5408 } else {
5409 Alignment = V.getPointerAlignment(DL).value();
5410 }
5411 // Use only IR information if we did not strip anything.
5412 T.takeKnownMaximum(Alignment);
5413 T.indicatePessimisticFixpoint();
5414 } else {
5415 // Use abstract attribute information.
5416 const AAAlign::StateType &DS = AA.getState();
5417 T ^= DS;
5418 }
5419 return T.isValidState();
5420 };
5421
5422 for (const auto &VAC : Values) {
5423 if (!VisitValueCB(*VAC.getValue()))
5424 return indicatePessimisticFixpoint();
5425 }
5426
5427 // TODO: If we know we visited all incoming values, thus no are assumed
5428 // dead, we can take the known information from the state T.
5429 return clampStateAndIndicateChange(getState(), T);
5430 }
5431
5432 /// See AbstractAttribute::trackStatistics()
5433 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align){ static llvm::Statistic NumIRFloating_align = {"attributor",
"NumIRFloating_align", ("Number of floating values known to be '"
"align" "'")};; ++(NumIRFloating_align); }
}
5434};
5435
5436/// Align attribute for function return value.
5437struct AAAlignReturned final
5438 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5439 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5440 AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5441
5442 /// See AbstractAttribute::initialize(...).
5443 void initialize(Attributor &A) override {
5444 Base::initialize(A);
5445 Function *F = getAssociatedFunction();
5446 if (!F || F->isDeclaration())
5447 indicatePessimisticFixpoint();
5448 }
5449
5450 /// See AbstractAttribute::trackStatistics()
5451 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned){ static llvm::Statistic NumIRFunctionReturn_aligned = {"attributor"
, "NumIRFunctionReturn_aligned", ("Number of " "function returns"
" marked '" "aligned" "'")};; ++(NumIRFunctionReturn_aligned
); }
}
5452};
5453
5454/// Align attribute for function argument.
5455struct AAAlignArgument final
5456 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5457 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5458 AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5459
5460 /// See AbstractAttribute::manifest(...).
5461 ChangeStatus manifest(Attributor &A) override {
5462 // If the associated argument is involved in a must-tail call we give up
5463 // because we would need to keep the argument alignments of caller and
5464 // callee in-sync. Just does not seem worth the trouble right now.
5465 if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5466 return ChangeStatus::UNCHANGED;
5467 return Base::manifest(A);
5468 }
5469
5470 /// See AbstractAttribute::trackStatistics()
5471 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned){ static llvm::Statistic NumIRArguments_aligned = {"attributor"
, "NumIRArguments_aligned", ("Number of " "arguments" " marked '"
"aligned" "'")};; ++(NumIRArguments_aligned); }
}
5472};
5473
5474struct AAAlignCallSiteArgument final : AAAlignFloating {
5475 AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
5476 : AAAlignFloating(IRP, A) {}
5477
5478 /// See AbstractAttribute::manifest(...).
5479 ChangeStatus manifest(Attributor &A) override {
5480 // If the associated argument is involved in a must-tail call we give up
5481 // because we would need to keep the argument alignments of caller and
5482 // callee in-sync. Just does not seem worth the trouble right now.
5483 if (Argument *Arg = getAssociatedArgument())
5484 if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5485 return ChangeStatus::UNCHANGED;
5486 ChangeStatus Changed = AAAlignImpl::manifest(A);
5487 Align InheritAlign =
5488 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5489 if (InheritAlign >= getAssumedAlign())
5490 Changed = ChangeStatus::UNCHANGED;
5491 return Changed;
5492 }
5493
5494 /// See AbstractAttribute::updateImpl(Attributor &A).
5495 ChangeStatus updateImpl(Attributor &A) override {
5496 ChangeStatus Changed = AAAlignFloating::updateImpl(A);
5497 if (Argument *Arg = getAssociatedArgument()) {
5498 // We only take known information from the argument
5499 // so we do not need to track a dependence.
5500 const auto &ArgAlignAA = A.getAAFor<AAAlign>(
5501 *this, IRPosition::argument(*Arg), DepClassTy::NONE);
5502 takeKnownMaximum(ArgAlignAA.getKnownAlign().value());
5503 }
5504 return Changed;
5505 }
5506
5507 /// See AbstractAttribute::trackStatistics()
5508 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned){ static llvm::Statistic NumIRCSArguments_aligned = {"attributor"
, "NumIRCSArguments_aligned", ("Number of " "call site arguments"
" marked '" "aligned" "'")};; ++(NumIRCSArguments_aligned); }
}
5509};
5510
5511/// Align attribute deduction for a call site return value.
5512struct AAAlignCallSiteReturned final
5513 : AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl> {
5514 using Base = AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl>;
5515 AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
5516 : Base(IRP, A) {}
5517
5518 /// See AbstractAttribute::initialize(...).
5519 void initialize(Attributor &A) override {
5520 Base::initialize(A);
5521 Function *F = getAssociatedFunction();
5522 if (!F || F->isDeclaration())
5523 indicatePessimisticFixpoint();
5524 }
5525
5526 /// See AbstractAttribute::trackStatistics()
5527 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align){ static llvm::Statistic NumIRCS_align = {"attributor", "NumIRCS_align"
, ("Number of " "call site" " marked '" "align" "'")};; ++(NumIRCS_align
); }
; }
5528};
5529} // namespace
5530
5531/// ------------------ Function No-Return Attribute ----------------------------
5532namespace {
5533struct AANoReturnImpl : public AANoReturn {
5534 AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}
5535
5536 /// See AbstractAttribute::initialize(...).
5537 void initialize(Attributor &A) override {
5538 AANoReturn::initialize(A);
5539 Function *F = getAssociatedFunction();
5540 if (!F || F->isDeclaration())
5541 indicatePessimisticFixpoint();
5542 }
5543
5544 /// See AbstractAttribute::getAsStr().
5545 const std::string getAsStr() const override {
5546 return getAssumed() ? "noreturn" : "may-return";
5547 }
5548
5549 /// See AbstractAttribute::updateImpl(Attributor &A).
5550 ChangeStatus updateImpl(Attributor &A) override {
5551 auto CheckForNoReturn = [](Instruction &) { return false; };
5552 bool UsedAssumedInformation = false;
5553 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
5554 {(unsigned)Instruction::Ret},
5555 UsedAssumedInformation))
5556 return indicatePessimisticFixpoint();
5557 return ChangeStatus::UNCHANGED;
5558 }
5559};
5560
5561struct AANoReturnFunction final : AANoReturnImpl {
5562 AANoReturnFunction(const IRPosition &IRP, Attributor &A)
5563 : AANoReturnImpl(IRP, A) {}
5564
5565 /// See AbstractAttribute::trackStatistics()
5566 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn){ static llvm::Statistic NumIRFunction_noreturn = {"attributor"
, "NumIRFunction_noreturn", ("Number of " "functions" " marked '"
"noreturn" "'")};; ++(NumIRFunction_noreturn); }
}
5567};
5568
5569/// NoReturn attribute deduction for a call sites.
5570struct AANoReturnCallSite final : AANoReturnImpl {
5571 AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
5572 : AANoReturnImpl(IRP, A) {}
5573
5574 /// See AbstractAttribute::initialize(...).
5575 void initialize(Attributor &A) override {
5576 AANoReturnImpl::initialize(A);
5577 if (Function *F = getAssociatedFunction()) {
5578 const IRPosition &FnPos = IRPosition::function(*F);
5579 auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos, DepClassTy::REQUIRED);
5580 if (!FnAA.isAssumedNoReturn())
5581 indicatePessimisticFixpoint();
5582 }
5583 }
5584
5585 /// See AbstractAttribute::updateImpl(...).
5586 ChangeStatus updateImpl(Attributor &A) override {
5587 // TODO: Once we have call site specific value information we can provide
5588 // call site specific liveness information and then it makes
5589 // sense to specialize attributes for call sites arguments instead of
5590 // redirecting requests to the callee argument.
5591 Function *F = getAssociatedFunction();
5592 const IRPosition &FnPos = IRPosition::function(*F);
5593 auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos, DepClassTy::REQUIRED);
5594 return clampStateAndIndicateChange(getState(), FnAA.getState());
5595 }
5596
5597 /// See AbstractAttribute::trackStatistics()
5598 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn){ static llvm::Statistic NumIRCS_noreturn = {"attributor", "NumIRCS_noreturn"
, ("Number of " "call site" " marked '" "noreturn" "'")};; ++
(NumIRCS_noreturn); }
; }
5599};
5600} // namespace
5601
5602/// ----------------------- Instance Info ---------------------------------
5603
5604namespace {
5605/// A class to hold the state of for no-capture attributes.
5606struct AAInstanceInfoImpl : public AAInstanceInfo {
5607 AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
5608 : AAInstanceInfo(IRP, A) {}
5609
5610 /// See AbstractAttribute::initialize(...).
5611 void initialize(Attributor &A) override {
5612 Value &V = getAssociatedValue();
5613 if (auto *C = dyn_cast<Constant>(&V)) {
5614 if (C->isThreadDependent())
5615 indicatePessimisticFixpoint();
5616 else
5617 indicateOptimisticFixpoint();
5618 return;
5619 }
5620 if (auto *CB = dyn_cast<CallBase>(&V))
5621 if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
5622 !CB->mayReadFromMemory()) {
5623 indicateOptimisticFixpoint();
5624 return;
5625 }
5626 if (auto *I = dyn_cast<Instruction>(&V)) {
5627 const auto *CI =
5628 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5629 *I->getFunction());
5630 if (mayBeInCycle(CI, I, /* HeaderOnly */ false)) {
5631 indicatePessimisticFixpoint();
5632 return;
5633 }
5634 }
5635 }
5636
5637 /// See AbstractAttribute::updateImpl(...).
5638 ChangeStatus updateImpl(Attributor &A) override {
5639 ChangeStatus Changed = ChangeStatus::UNCHANGED;
5640
5641 Value &V = getAssociatedValue();
5642 const Function *Scope = nullptr;
5643 if (auto *I = dyn_cast<Instruction>(&V))
5644 Scope = I->getFunction();
5645 if (auto *A = dyn_cast<Argument>(&V)) {
5646 Scope = A->getParent();
5647 if (!Scope->hasLocalLinkage())
5648 return Changed;
5649 }
5650 if (!Scope)
5651 return indicateOptimisticFixpoint();
5652
5653 auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
5654 *this, IRPosition::function(*Scope), DepClassTy::OPTIONAL);
5655 if (NoRecurseAA.isAssumedNoRecurse())
5656 return Changed;
5657
5658 auto UsePred = [&](const Use &U, bool &Follow) {
5659 const Instruction *UserI = dyn_cast<Instruction>(U.getUser());
5660 if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||
5661 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
5662 Follow = true;
5663 return true;
5664 }
5665 if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||
5666 (isa<StoreInst>(UserI) &&
5667 cast<StoreInst>(UserI)->getValueOperand() != U.get()))
5668 return true;
5669 if (auto *CB = dyn_cast<CallBase>(UserI)) {
5670 // This check is not guaranteeing uniqueness but for now that we cannot
5671 // end up with two versions of \p U thinking it was one.
5672 if (!CB->getCalledFunction() ||
5673 !CB->getCalledFunction()->hasLocalLinkage())
5674 return true;
5675 if (!CB->isArgOperand(&U))
5676 return false;
5677 const auto &ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
5678 *this, IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U)),
5679 DepClassTy::OPTIONAL);
5680 if (!ArgInstanceInfoAA.isAssumedUniqueForAnalysis())
5681 return false;
5682 // If this call base might reach the scope again we might forward the
5683 // argument back here. This is very conservative.
5684 if (AA::isPotentiallyReachable(
5685 A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,
5686 [Scope](const Function &Fn) { return &Fn != Scope; }))
5687 return false;
5688 return true;
5689 }
5690 return false;
5691 };
5692
5693 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
5694 if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {
5695 auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
5696 if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&
5697 AA::isDynamicallyUnique(A, *this, *Ptr))
5698 return true;
5699 }
5700 return false;
5701 };
5702
5703 if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,
5704 DepClassTy::OPTIONAL,
5705 /* IgnoreDroppableUses */ true, EquivalentUseCB))
5706 return indicatePessimisticFixpoint();
5707
5708 return Changed;
5709 }
5710
5711 /// See AbstractState::getAsStr().
5712 const std::string getAsStr() const override {
5713 return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
5714 }
5715
5716 /// See AbstractAttribute::trackStatistics()
5717 void trackStatistics() const override {}
5718};
5719
5720/// InstanceInfo attribute for floating values.
5721struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5722 AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
5723 : AAInstanceInfoImpl(IRP, A) {}
5724};
5725
5726/// NoCapture attribute for function arguments.
5727struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5728 AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
5729 : AAInstanceInfoFloating(IRP, A) {}
5730};
5731
5732/// InstanceInfo attribute for call site arguments.
5733struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5734 AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
5735 : AAInstanceInfoImpl(IRP, A) {}
5736
5737 /// See AbstractAttribute::updateImpl(...).
5738 ChangeStatus updateImpl(Attributor &A) override {
5739 // TODO: Once we have call site specific value information we can provide
5740 // call site specific liveness information and then it makes
5741 // sense to specialize attributes for call sites arguments instead of
5742 // redirecting requests to the callee argument.
5743 Argument *Arg = getAssociatedArgument();
5744 if (!Arg)
5745 return indicatePessimisticFixpoint();
5746 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5747 auto &ArgAA =
5748 A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);
5749 return clampStateAndIndicateChange(getState(), ArgAA.getState());
5750 }
5751};
5752
5753/// InstanceInfo attribute for function return value.
5754struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5755 AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
5756 : AAInstanceInfoImpl(IRP, A) {
5757 llvm_unreachable("InstanceInfo is not applicable to function returns!")::llvm::llvm_unreachable_internal("InstanceInfo is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 5757)
;
5758 }
5759
5760 /// See AbstractAttribute::initialize(...).
5761 void initialize(Attributor &A) override {
5762 llvm_unreachable("InstanceInfo is not applicable to function returns!")::llvm::llvm_unreachable_internal("InstanceInfo is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 5762)
;
5763 }
5764
5765 /// See AbstractAttribute::updateImpl(...).
5766 ChangeStatus updateImpl(Attributor &A) override {
5767 llvm_unreachable("InstanceInfo is not applicable to function returns!")::llvm::llvm_unreachable_internal("InstanceInfo is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 5767)
;
5768 }
5769};
5770
5771/// InstanceInfo attribute deduction for a call site return value.
5772struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5773 AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
5774 : AAInstanceInfoFloating(IRP, A) {}
5775};
5776} // namespace
5777
5778/// ----------------------- Variable Capturing ---------------------------------
5779
5780namespace {
5781/// A class to hold the state of for no-capture attributes.
5782struct AANoCaptureImpl : public AANoCapture {
5783 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5784
5785 /// See AbstractAttribute::initialize(...).
5786 void initialize(Attributor &A) override {
5787 if (hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ true)) {
5788 indicateOptimisticFixpoint();
5789 return;
5790 }
5791 Function *AnchorScope = getAnchorScope();
5792 if (isFnInterfaceKind() &&
5793 (!AnchorScope || !A.isFunctionIPOAmendable(*AnchorScope))) {
5794 indicatePessimisticFixpoint();
5795 return;
5796 }
5797
5798 // You cannot "capture" null in the default address space.
5799 if (isa<ConstantPointerNull>(getAssociatedValue()) &&
5800 getAssociatedValue().getType()->getPointerAddressSpace() == 0) {
5801 indicateOptimisticFixpoint();
5802 return;
5803 }
5804
5805 const Function *F =
5806 isArgumentPosition() ? getAssociatedFunction() : AnchorScope;
5807
5808 // Check what state the associated function can actually capture.
5809 if (F)
5810 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
5811 else
5812 indicatePessimisticFixpoint();
5813 }
5814
5815 /// See AbstractAttribute::updateImpl(...).
5816 ChangeStatus updateImpl(Attributor &A) override;
5817
5818 /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
5819 void getDeducedAttributes(LLVMContext &Ctx,
5820 SmallVectorImpl<Attribute> &Attrs) const override {
5821 if (!isAssumedNoCaptureMaybeReturned())
5822 return;
5823
5824 if (isArgumentPosition()) {
5825 if (isAssumedNoCapture())
5826 Attrs.emplace_back(Attribute::get(Ctx, Attribute::NoCapture));
5827 else if (ManifestInternal)
5828 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
5829 }
5830 }
5831
5832 /// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
5833 /// depending on the ability of the function associated with \p IRP to capture
5834 /// state in memory and through "returning/throwing", respectively.
5835 static void determineFunctionCaptureCapabilities(const IRPosition &IRP,
5836 const Function &F,
5837 BitIntegerState &State) {
5838 // TODO: Once we have memory behavior attributes we should use them here.
5839
5840 // If we know we cannot communicate or write to memory, we do not care about
5841 // ptr2int anymore.
5842 if (F.onlyReadsMemory() && F.doesNotThrow() &&
5843 F.getReturnType()->isVoidTy()) {
5844 State.addKnownBits(NO_CAPTURE);
5845 return;
5846 }
5847
5848 // A function cannot capture state in memory if it only reads memory, it can
5849 // however return/throw state and the state might be influenced by the
5850 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5851 if (F.onlyReadsMemory())
5852 State.addKnownBits(NOT_CAPTURED_IN_MEM);
5853
5854 // A function cannot communicate state back if it does not through
5855 // exceptions and doesn not return values.
5856 if (F.doesNotThrow() && F.getReturnType()->isVoidTy())
5857 State.addKnownBits(NOT_CAPTURED_IN_RET);
5858
5859 // Check existing "returned" attributes.
5860 int ArgNo = IRP.getCalleeArgNo();
5861 if (F.doesNotThrow() && ArgNo >= 0) {
5862 for (unsigned u = 0, e = F.arg_size(); u < e; ++u)
5863 if (F.hasParamAttribute(u, Attribute::Returned)) {
5864 if (u == unsigned(ArgNo))
5865 State.removeAssumedBits(NOT_CAPTURED_IN_RET);
5866 else if (F.onlyReadsMemory())
5867 State.addKnownBits(NO_CAPTURE);
5868 else
5869 State.addKnownBits(NOT_CAPTURED_IN_RET);
5870 break;
5871 }
5872 }
5873 }
5874
5875 /// See AbstractState::getAsStr().
5876 const std::string getAsStr() const override {
5877 if (isKnownNoCapture())
5878 return "known not-captured";
5879 if (isAssumedNoCapture())
5880 return "assumed not-captured";
5881 if (isKnownNoCaptureMaybeReturned())
5882 return "known not-captured-maybe-returned";
5883 if (isAssumedNoCaptureMaybeReturned())
5884 return "assumed not-captured-maybe-returned";
5885 return "assumed-captured";
5886 }
5887
5888 /// Check the use \p U and update \p State accordingly. Return true if we
5889 /// should continue to update the state.
5890 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
5891 bool &Follow) {
5892 Instruction *UInst = cast<Instruction>(U.getUser());
5893 LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoCapture] Check use: "
<< *U.get() << " in " << *UInst << "\n"
; } } while (false)
5894 << *UInst << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoCapture] Check use: "
<< *U.get() << " in " << *UInst << "\n"
; } } while (false)
;
5895
5896 // Deal with ptr2int by following uses.
5897 if (isa<PtrToIntInst>(UInst)) {
5898 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " - ptr2int assume the worst!\n"
; } } while (false)
;
5899 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5900 /* Return */ true);
5901 }
5902
5903 // For stores we already checked if we can follow them, if they make it
5904 // here we give up.
5905 if (isa<StoreInst>(UInst))
5906 return isCapturedIn(State, /* Memory */ true, /* Integer */ false,
5907 /* Return */ false);
5908
5909 // Explicitly catch return instructions.
5910 if (isa<ReturnInst>(UInst)) {
5911 if (UInst->getFunction() == getAnchorScope())
5912 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5913 /* Return */ true);
5914 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5915 /* Return */ true);
5916 }
5917
5918 // For now we only use special logic for call sites. However, the tracker
5919 // itself knows about a lot of other non-capturing cases already.
5920 auto *CB = dyn_cast<CallBase>(UInst);
5921 if (!CB || !CB->isArgOperand(&U))
5922 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5923 /* Return */ true);
5924
5925 unsigned ArgNo = CB->getArgOperandNo(&U);
5926 const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
5927 // If we have a abstract no-capture attribute for the argument we can use
5928 // it to justify a non-capture attribute here. This allows recursion!
5929 auto &ArgNoCaptureAA =
5930 A.getAAFor<AANoCapture>(*this, CSArgPos, DepClassTy::REQUIRED);
5931 if (ArgNoCaptureAA.isAssumedNoCapture())
5932 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5933 /* Return */ false);
5934 if (ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
5935 Follow = true;
5936 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5937 /* Return */ false);
5938 }
5939
5940 // Lastly, we could not find a reason no-capture can be assumed so we don't.
5941 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5942 /* Return */ true);
5943 }
5944
5945 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
5946 /// \p CapturedInRet, then return true if we should continue updating the
5947 /// state.
5948 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
5949 bool CapturedInInt, bool CapturedInRet) {
5950 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " - captures [Mem " <<
CapturedInMem << "|Int " << CapturedInInt <<
"|Ret " << CapturedInRet << "]\n"; } } while (false
)
5951 << CapturedInInt << "|Ret " << CapturedInRet << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " - captures [Mem " <<
CapturedInMem << "|Int " << CapturedInInt <<
"|Ret " << CapturedInRet << "]\n"; } } while (false
)
;
5952 if (CapturedInMem)
5953 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
5954 if (CapturedInInt)
5955 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
5956 if (CapturedInRet)
5957 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
5958 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
5959 }
5960};
5961
5962ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
5963 const IRPosition &IRP = getIRPosition();
5964 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
5965 : &IRP.getAssociatedValue();
5966 if (!V)
5967 return indicatePessimisticFixpoint();
5968
5969 const Function *F =
5970 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
5971 assert(F && "Expected a function!")(static_cast <bool> (F && "Expected a function!"
) ? void (0) : __assert_fail ("F && \"Expected a function!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 5971, __extension__
__PRETTY_FUNCTION__))
;
5972 const IRPosition &FnPos = IRPosition::function(*F);
5973
5974 AANoCapture::StateType T;
5975
5976 // Readonly means we cannot capture through memory.
5977 bool IsKnown;
5978 if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
5979 T.addKnownBits(NOT_CAPTURED_IN_MEM);
5980 if (IsKnown)
5981 addKnownBits(NOT_CAPTURED_IN_MEM);
5982 }
5983
5984 // Make sure all returned values are different than the underlying value.
5985 // TODO: we could do this in a more sophisticated way inside
5986 // AAReturnedValues, e.g., track all values that escape through returns
5987 // directly somehow.
5988 auto CheckReturnedArgs = [&](const AAReturnedValues &RVAA) {
5989 if (!RVAA.getState().isValidState())
5990 return false;
5991 bool SeenConstant = false;
5992 for (const auto &It : RVAA.returned_values()) {
5993 if (isa<Constant>(It.first)) {
5994 if (SeenConstant)
5995 return false;
5996 SeenConstant = true;
5997 } else if (!isa<Argument>(It.first) ||
5998 It.first == getAssociatedArgument())
5999 return false;
6000 }
6001 return true;
6002 };
6003
6004 const auto &NoUnwindAA =
6005 A.getAAFor<AANoUnwind>(*this, FnPos, DepClassTy::OPTIONAL);
6006 if (NoUnwindAA.isAssumedNoUnwind()) {
6007 bool IsVoidTy = F->getReturnType()->isVoidTy();
6008 const AAReturnedValues *RVAA =
6009 IsVoidTy ? nullptr
6010 : &A.getAAFor<AAReturnedValues>(*this, FnPos,
6011
6012 DepClassTy::OPTIONAL);
6013 if (IsVoidTy || CheckReturnedArgs(*RVAA)) {
6014 T.addKnownBits(NOT_CAPTURED_IN_RET);
6015 if (T.isKnown(NOT_CAPTURED_IN_MEM))
6016 return ChangeStatus::UNCHANGED;
6017 if (NoUnwindAA.isKnownNoUnwind() &&
6018 (IsVoidTy || RVAA->getState().isAtFixpoint())) {
6019 addKnownBits(NOT_CAPTURED_IN_RET);
6020 if (isKnown(NOT_CAPTURED_IN_MEM))
6021 return indicateOptimisticFixpoint();
6022 }
6023 }
6024 }
6025
6026 auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
6027 const auto &DerefAA = A.getAAFor<AADereferenceable>(
6028 *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
6029 return DerefAA.getAssumedDereferenceableBytes();
6030 };
6031
6032 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
6033 switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
6034 case UseCaptureKind::NO_CAPTURE:
6035 return true;
6036 case UseCaptureKind::MAY_CAPTURE:
6037 return checkUse(A, T, U, Follow);
6038 case UseCaptureKind::PASSTHROUGH:
6039 Follow = true;
6040 return true;
6041 }
6042 llvm_unreachable("Unexpected use capture kind!")::llvm::llvm_unreachable_internal("Unexpected use capture kind!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6042)
;
6043 };
6044
6045 if (!A.checkForAllUses(UseCheck, *this, *V))
6046 return indicatePessimisticFixpoint();
6047
6048 AANoCapture::StateType &S = getState();
6049 auto Assumed = S.getAssumed();
6050 S.intersectAssumedBits(T.getAssumed());
6051 if (!isAssumedNoCaptureMaybeReturned())
6052 return indicatePessimisticFixpoint();
6053 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
6054 : ChangeStatus::CHANGED;
6055}
6056
6057/// NoCapture attribute for function arguments.
6058struct AANoCaptureArgument final : AANoCaptureImpl {
6059 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
6060 : AANoCaptureImpl(IRP, A) {}
6061
6062 /// See AbstractAttribute::trackStatistics()
6063 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture){ static llvm::Statistic NumIRArguments_nocapture = {"attributor"
, "NumIRArguments_nocapture", ("Number of " "arguments" " marked '"
"nocapture" "'")};; ++(NumIRArguments_nocapture); }
}
6064};
6065
6066/// NoCapture attribute for call site arguments.
6067struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6068 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
6069 : AANoCaptureImpl(IRP, A) {}
6070
6071 /// See AbstractAttribute::initialize(...).
6072 void initialize(Attributor &A) override {
6073 if (Argument *Arg = getAssociatedArgument())
6074 if (Arg->hasByValAttr())
6075 indicateOptimisticFixpoint();
6076 AANoCaptureImpl::initialize(A);
6077 }
6078
6079 /// See AbstractAttribute::updateImpl(...).
6080 ChangeStatus updateImpl(Attributor &A) override {
6081 // TODO: Once we have call site specific value information we can provide
6082 // call site specific liveness information and then it makes
6083 // sense to specialize attributes for call sites arguments instead of
6084 // redirecting requests to the callee argument.
6085 Argument *Arg = getAssociatedArgument();
6086 if (!Arg)
6087 return indicatePessimisticFixpoint();
6088 const IRPosition &ArgPos = IRPosition::argument(*Arg);
6089 auto &ArgAA = A.getAAFor<AANoCapture>(*this, ArgPos, DepClassTy::REQUIRED);
6090 return clampStateAndIndicateChange(getState(), ArgAA.getState());
6091 }
6092
6093 /// See AbstractAttribute::trackStatistics()
6094 void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nocapture){ static llvm::Statistic NumIRCSArguments_nocapture = {"attributor"
, "NumIRCSArguments_nocapture", ("Number of " "call site arguments"
" marked '" "nocapture" "'")};; ++(NumIRCSArguments_nocapture
); }
};
6095};
6096
6097/// NoCapture attribute for floating values.
6098struct AANoCaptureFloating final : AANoCaptureImpl {
6099 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
6100 : AANoCaptureImpl(IRP, A) {}
6101
6102 /// See AbstractAttribute::trackStatistics()
6103 void trackStatistics() const override {
6104 STATS_DECLTRACK_FLOATING_ATTR(nocapture){ static llvm::Statistic NumIRFloating_nocapture = {"attributor"
, "NumIRFloating_nocapture", ("Number of floating values known to be '"
"nocapture" "'")};; ++(NumIRFloating_nocapture); }
6105 }
6106};
6107
6108/// NoCapture attribute for function return value.
6109struct AANoCaptureReturned final : AANoCaptureImpl {
6110 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
6111 : AANoCaptureImpl(IRP, A) {
6112 llvm_unreachable("NoCapture is not applicable to function returns!")::llvm::llvm_unreachable_internal("NoCapture is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6112)
;
6113 }
6114
6115 /// See AbstractAttribute::initialize(...).
6116 void initialize(Attributor &A) override {
6117 llvm_unreachable("NoCapture is not applicable to function returns!")::llvm::llvm_unreachable_internal("NoCapture is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6117)
;
6118 }
6119
6120 /// See AbstractAttribute::updateImpl(...).
6121 ChangeStatus updateImpl(Attributor &A) override {
6122 llvm_unreachable("NoCapture is not applicable to function returns!")::llvm::llvm_unreachable_internal("NoCapture is not applicable to function returns!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6122)
;
6123 }
6124
6125 /// See AbstractAttribute::trackStatistics()
6126 void trackStatistics() const override {}
6127};
6128
6129/// NoCapture attribute deduction for a call site return value.
6130struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6131 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
6132 : AANoCaptureImpl(IRP, A) {}
6133
6134 /// See AbstractAttribute::initialize(...).
6135 void initialize(Attributor &A) override {
6136 const Function *F = getAnchorScope();
6137 // Check what state the associated function can actually capture.
6138 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
6139 }
6140
6141 /// See AbstractAttribute::trackStatistics()
6142 void trackStatistics() const override {
6143 STATS_DECLTRACK_CSRET_ATTR(nocapture){ static llvm::Statistic NumIRCSReturn_nocapture = {"attributor"
, "NumIRCSReturn_nocapture", ("Number of " "call site returns"
" marked '" "nocapture" "'")};; ++(NumIRCSReturn_nocapture);
}
6144 }
6145};
6146} // namespace
6147
6148/// ------------------ Value Simplify Attribute ----------------------------
6149
6150bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6151 // FIXME: Add a typecast support.
6152 SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
6153 SimplifiedAssociatedValue, Other, Ty);
6154 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6155 return false;
6156
6157 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (SimplifiedAssociatedValue) dbgs() <<
"[ValueSimplify] is assumed to be " << **SimplifiedAssociatedValue
<< "\n"; else dbgs() << "[ValueSimplify] is assumed to be <none>\n"
; }; } } while (false)
6158 if (SimplifiedAssociatedValue)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (SimplifiedAssociatedValue) dbgs() <<
"[ValueSimplify] is assumed to be " << **SimplifiedAssociatedValue
<< "\n"; else dbgs() << "[ValueSimplify] is assumed to be <none>\n"
; }; } } while (false)
6159 dbgs() << "[ValueSimplify] is assumed to be "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (SimplifiedAssociatedValue) dbgs() <<
"[ValueSimplify] is assumed to be " << **SimplifiedAssociatedValue
<< "\n"; else dbgs() << "[ValueSimplify] is assumed to be <none>\n"
; }; } } while (false)
6160 << **SimplifiedAssociatedValue << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (SimplifiedAssociatedValue) dbgs() <<
"[ValueSimplify] is assumed to be " << **SimplifiedAssociatedValue
<< "\n"; else dbgs() << "[ValueSimplify] is assumed to be <none>\n"
; }; } } while (false)
6161 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (SimplifiedAssociatedValue) dbgs() <<
"[ValueSimplify] is assumed to be " << **SimplifiedAssociatedValue
<< "\n"; else dbgs() << "[ValueSimplify] is assumed to be <none>\n"
; }; } } while (false)
6162 dbgs() << "[ValueSimplify] is assumed to be <none>\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (SimplifiedAssociatedValue) dbgs() <<
"[ValueSimplify] is assumed to be " << **SimplifiedAssociatedValue
<< "\n"; else dbgs() << "[ValueSimplify] is assumed to be <none>\n"
; }; } } while (false)
6163 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (SimplifiedAssociatedValue) dbgs() <<
"[ValueSimplify] is assumed to be " << **SimplifiedAssociatedValue
<< "\n"; else dbgs() << "[ValueSimplify] is assumed to be <none>\n"
; }; } } while (false)
;
6164 return true;
6165}
6166
6167namespace {
6168struct AAValueSimplifyImpl : AAValueSimplify {
6169 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6170 : AAValueSimplify(IRP, A) {}
6171
6172 /// See AbstractAttribute::initialize(...).
6173 void initialize(Attributor &A) override {
6174 if (getAssociatedValue().getType()->isVoidTy())
6175 indicatePessimisticFixpoint();
6176 if (A.hasSimplificationCallback(getIRPosition()))
6177 indicatePessimisticFixpoint();
6178 }
6179
6180 /// See AbstractAttribute::getAsStr().
6181 const std::string getAsStr() const override {
6182 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6183 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6184 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6185 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6186 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
;
6187 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6188 : "not-simple";
6189 }
6190
6191 /// See AbstractAttribute::trackStatistics()
6192 void trackStatistics() const override {}
6193
6194 /// See AAValueSimplify::getAssumedSimplifiedValue()
6195 std::optional<Value *>
6196 getAssumedSimplifiedValue(Attributor &A) const override {
6197 return SimplifiedAssociatedValue;
6198 }
6199
6200 /// Ensure the return value is \p V with type \p Ty, if not possible return
6201 /// nullptr. If \p Check is true we will only verify such an operation would
6202 /// suceed and return a non-nullptr value if that is the case. No IR is
6203 /// generated or modified.
6204 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6205 bool Check) {
6206 if (auto *TypedV = AA::getWithType(V, Ty))
6207 return TypedV;
6208 if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
6209 return Check ? &V
6210 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(&V, &Ty,
6211 "", CtxI);
6212 return nullptr;
6213 }
6214
6215 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6216 /// If \p Check is true we will only verify such an operation would suceed and
6217 /// return a non-nullptr value if that is the case. No IR is generated or
6218 /// modified.
6219 static Value *reproduceInst(Attributor &A,
6220 const AbstractAttribute &QueryingAA,
6221 Instruction &I, Type &Ty, Instruction *CtxI,
6222 bool Check, ValueToValueMapTy &VMap) {
6223 assert(CtxI && "Cannot reproduce an instruction without context!")(static_cast <bool> (CtxI && "Cannot reproduce an instruction without context!"
) ? void (0) : __assert_fail ("CtxI && \"Cannot reproduce an instruction without context!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6223, __extension__
__PRETTY_FUNCTION__))
;
6224 if (Check && (I.mayReadFromMemory() ||
6225 !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
6226 /* TLI */ nullptr)))
6227 return nullptr;
6228 for (Value *Op : I.operands()) {
6229 Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
6230 if (!NewOp) {
6231 assert(Check && "Manifest of new value unexpectedly failed!")(static_cast <bool> (Check && "Manifest of new value unexpectedly failed!"
) ? void (0) : __assert_fail ("Check && \"Manifest of new value unexpectedly failed!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6231, __extension__
__PRETTY_FUNCTION__))
;
6232 return nullptr;
6233 }
6234 if (!Check)
6235 VMap[Op] = NewOp;
6236 }
6237 if (Check)
6238 return &I;
6239
6240 Instruction *CloneI = I.clone();
6241 // TODO: Try to salvage debug information here.
6242 CloneI->setDebugLoc(DebugLoc());
6243 VMap[&I] = CloneI;
6244 CloneI->insertBefore(CtxI);
6245 RemapInstruction(CloneI, VMap);
6246 return CloneI;
6247 }
6248
6249 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6250 /// If \p Check is true we will only verify such an operation would suceed and
6251 /// return a non-nullptr value if that is the case. No IR is generated or
6252 /// modified.
6253 static Value *reproduceValue(Attributor &A,
6254 const AbstractAttribute &QueryingAA, Value &V,
6255 Type &Ty, Instruction *CtxI, bool Check,
6256 ValueToValueMapTy &VMap) {
6257 if (const auto &NewV = VMap.lookup(&V))
6258 return NewV;
6259 bool UsedAssumedInformation = false;
6260 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6261 V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6262 if (!SimpleV.has_value())
6263 return PoisonValue::get(&Ty);
6264 Value *EffectiveV = &V;
6265 if (*SimpleV)
6266 EffectiveV = *SimpleV;
6267 if (auto *C = dyn_cast<Constant>(EffectiveV))
6268 return C;
6269 if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
6270 A.getInfoCache()))
6271 return ensureType(A, *EffectiveV, Ty, CtxI, Check);
6272 if (auto *I = dyn_cast<Instruction>(EffectiveV))
6273 if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
6274 return ensureType(A, *NewV, Ty, CtxI, Check);
6275 return nullptr;
6276 }
6277
6278 /// Return a value we can use as replacement for the associated one, or
6279 /// nullptr if we don't have one that makes sense.
6280 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6281 Value *NewV = SimplifiedAssociatedValue
6282 ? *SimplifiedAssociatedValue
6283 : UndefValue::get(getAssociatedType());
6284 if (NewV && NewV != &getAssociatedValue()) {
6285 ValueToValueMapTy VMap;
6286 // First verify we can reprduce the value with the required type at the
6287 // context location before we actually start modifying the IR.
6288 if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6289 /* CheckOnly */ true, VMap))
6290 return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6291 /* CheckOnly */ false, VMap);
6292 }
6293 return nullptr;
6294 }
6295
6296 /// Helper function for querying AAValueSimplify and updating candidate.
6297 /// \param IRP The value position we are trying to unify with SimplifiedValue
6298 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6299 const IRPosition &IRP, bool Simplify = true) {
6300 bool UsedAssumedInformation = false;
6301 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6302 if (Simplify)
6303 QueryingValueSimplified = A.getAssumedSimplified(
6304 IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6305 return unionAssumed(QueryingValueSimplified);
6306 }
6307
6308 /// Returns a candidate is found or not
6309 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6310 if (!getAssociatedValue().getType()->isIntegerTy())
6311 return false;
6312
6313 // This will also pass the call base context.
6314 const auto &AA =
6315 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6316
6317 std::optional<Constant *> COpt = AA.getAssumedConstant(A);
6318
6319 if (!COpt) {
6320 SimplifiedAssociatedValue = std::nullopt;
6321 A.recordDependence(AA, *this, DepClassTy::OPTIONAL);
6322 return true;
6323 }
6324 if (auto *C = *COpt) {
6325 SimplifiedAssociatedValue = C;
6326 A.recordDependence(AA, *this, DepClassTy::OPTIONAL);
6327 return true;
6328 }
6329 return false;
6330 }
6331
6332 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6333 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6334 return true;
6335 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6336 return true;
6337 return false;
6338 }
6339
6340 /// See AbstractAttribute::manifest(...).
6341 ChangeStatus manifest(Attributor &A) override {
6342 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6343 for (auto &U : getAssociatedValue().uses()) {
6344 // Check if we need to adjust the insertion point to make sure the IR is
6345 // valid.
6346 Instruction *IP = dyn_cast<Instruction>(U.getUser());
6347 if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
6348 IP = PHI->getIncomingBlock(U)->getTerminator();
6349 if (auto *NewV = manifestReplacementValue(A, IP)) {
6350 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[ValueSimplify] " <<
getAssociatedValue() << " -> " << *NewV <<
" :: " << *this << "\n"; } } while (false)
6351 << " -> " << *NewV << " :: " << *this << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[ValueSimplify] " <<
getAssociatedValue() << " -> " << *NewV <<
" :: " << *this << "\n"; } } while (false)
;
6352 if (A.changeUseAfterManifest(U, *NewV))
6353 Changed = ChangeStatus::CHANGED;
6354 }
6355 }
6356
6357 return Changed | AAValueSimplify::manifest(A);
6358 }
6359
6360 /// See AbstractState::indicatePessimisticFixpoint(...).
6361 ChangeStatus indicatePessimisticFixpoint() override {
6362 SimplifiedAssociatedValue = &getAssociatedValue();
6363 return AAValueSimplify::indicatePessimisticFixpoint();
6364 }
6365};
6366
6367struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6368 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6369 : AAValueSimplifyImpl(IRP, A) {}
6370
6371 void initialize(Attributor &A) override {
6372 AAValueSimplifyImpl::initialize(A);
6373 if (!getAnchorScope() || getAnchorScope()->isDeclaration())
6374 indicatePessimisticFixpoint();
6375 if (hasAttr({Attribute::InAlloca, Attribute::Preallocated,
6376 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6377 /* IgnoreSubsumingPositions */ true))
6378 indicatePessimisticFixpoint();
6379 }
6380
6381 /// See AbstractAttribute::updateImpl(...).
6382 ChangeStatus updateImpl(Attributor &A) override {
6383 // Byval is only replacable if it is readonly otherwise we would write into
6384 // the replaced value and not the copy that byval creates implicitly.
6385 Argument *Arg = getAssociatedArgument();
6386 if (Arg->hasByValAttr()) {
6387 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6388 // there is no race by not copying a constant byval.
6389 bool IsKnown;
6390 if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
6391 return indicatePessimisticFixpoint();
6392 }
6393
6394 auto Before = SimplifiedAssociatedValue;
6395
6396 auto PredForCallSite = [&](AbstractCallSite ACS) {
6397 const IRPosition &ACSArgPos =
6398 IRPosition::callsite_argument(ACS, getCallSiteArgNo());
6399 // Check if a coresponding argument was found or if it is on not
6400 // associated (which can happen for callback calls).
6401 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6402 return false;
6403
6404 // Simplify the argument operand explicitly and check if the result is
6405 // valid in the current scope. This avoids refering to simplified values
6406 // in other functions, e.g., we don't want to say a an argument in a
6407 // static function is actually an argument in a different function.
6408 bool UsedAssumedInformation = false;
6409 std::optional<Constant *> SimpleArgOp =
6410 A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
6411 if (!SimpleArgOp)
6412 return true;
6413 if (!*SimpleArgOp)
6414 return false;
6415 if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
6416 return false;
6417 return unionAssumed(*SimpleArgOp);
6418 };
6419
6420 // Generate a answer specific to a call site context.
6421 bool Success;
6422 bool UsedAssumedInformation = false;
6423 if (hasCallBaseContext() &&
6424 getCallBaseContext()->getCalledFunction() == Arg->getParent())
6425 Success = PredForCallSite(
6426 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6427 else
6428 Success = A.checkForAllCallSites(PredForCallSite, *this, true,
6429 UsedAssumedInformation);
6430
6431 if (!Success)
6432 if (!askSimplifiedValueForOtherAAs(A))
6433 return indicatePessimisticFixpoint();
6434
6435 // If a candidate was found in this update, return CHANGED.
6436 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6437 : ChangeStatus ::CHANGED;
6438 }
6439
6440 /// See AbstractAttribute::trackStatistics()
6441 void trackStatistics() const override {
6442 STATS_DECLTRACK_ARG_ATTR(value_simplify){ static llvm::Statistic NumIRArguments_value_simplify = {"attributor"
, "NumIRArguments_value_simplify", ("Number of " "arguments" " marked '"
"value_simplify" "'")};; ++(NumIRArguments_value_simplify); }
6443 }
6444};
6445
6446struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6447 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6448 : AAValueSimplifyImpl(IRP, A) {}
6449
6450 /// See AAValueSimplify::getAssumedSimplifiedValue()
6451 std::optional<Value *>
6452 getAssumedSimplifiedValue(Attributor &A) const override {
6453 if (!isValidState())
6454 return nullptr;
6455 return SimplifiedAssociatedValue;
6456 }
6457
6458 /// See AbstractAttribute::updateImpl(...).
6459 ChangeStatus updateImpl(Attributor &A) override {
6460 auto Before = SimplifiedAssociatedValue;
6461
6462 auto ReturnInstCB = [&](Instruction &I) {
6463 auto &RI = cast<ReturnInst>(I);
6464 return checkAndUpdate(
6465 A, *this,
6466 IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
6467 };
6468
6469 bool UsedAssumedInformation = false;
6470 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
6471 UsedAssumedInformation))
6472 if (!askSimplifiedValueForOtherAAs(A))
6473 return indicatePessimisticFixpoint();
6474
6475 // If a candidate was found in this update, return CHANGED.
6476 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6477 : ChangeStatus ::CHANGED;
6478 }
6479
6480 ChangeStatus manifest(Attributor &A) override {
6481 // We queried AAValueSimplify for the returned values so they will be
6482 // replaced if a simplified form was found. Nothing to do here.
6483 return ChangeStatus::UNCHANGED;
6484 }
6485
6486 /// See AbstractAttribute::trackStatistics()
6487 void trackStatistics() const override {
6488 STATS_DECLTRACK_FNRET_ATTR(value_simplify){ static llvm::Statistic NumIRFunctionReturn_value_simplify =
{"attributor", "NumIRFunctionReturn_value_simplify", ("Number of "
"function returns" " marked '" "value_simplify" "'")};; ++(NumIRFunctionReturn_value_simplify
); }
6489 }
6490};
6491
6492struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6493 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6494 : AAValueSimplifyImpl(IRP, A) {}
6495
6496 /// See AbstractAttribute::initialize(...).
6497 void initialize(Attributor &A) override {
6498 AAValueSimplifyImpl::initialize(A);
6499 Value &V = getAnchorValue();
6500
6501 // TODO: add other stuffs
6502 if (isa<Constant>(V))
6503 indicatePessimisticFixpoint();
6504 }
6505
6506 /// See AbstractAttribute::updateImpl(...).
6507 ChangeStatus updateImpl(Attributor &A) override {
6508 auto Before = SimplifiedAssociatedValue;
6509 if (!askSimplifiedValueForOtherAAs(A))
6510 return indicatePessimisticFixpoint();
6511
6512 // If a candidate was found in this update, return CHANGED.
6513 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6514 : ChangeStatus ::CHANGED;
6515 }
6516
6517 /// See AbstractAttribute::trackStatistics()
6518 void trackStatistics() const override {
6519 STATS_DECLTRACK_FLOATING_ATTR(value_simplify){ static llvm::Statistic NumIRFloating_value_simplify = {"attributor"
, "NumIRFloating_value_simplify", ("Number of floating values known to be '"
"value_simplify" "'")};; ++(NumIRFloating_value_simplify); }
6520 }
6521};
6522
6523struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6524 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6525 : AAValueSimplifyImpl(IRP, A) {}
6526
6527 /// See AbstractAttribute::initialize(...).
6528 void initialize(Attributor &A) override {
6529 SimplifiedAssociatedValue = nullptr;
6530 indicateOptimisticFixpoint();
6531 }
6532 /// See AbstractAttribute::initialize(...).
6533 ChangeStatus updateImpl(Attributor &A) override {
6534 llvm_unreachable(::llvm::llvm_unreachable_internal("AAValueSimplify(Function|CallSite)::updateImpl will not be called"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6535)
6535 "AAValueSimplify(Function|CallSite)::updateImpl will not be called")::llvm::llvm_unreachable_internal("AAValueSimplify(Function|CallSite)::updateImpl will not be called"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6535)
;
6536 }
6537 /// See AbstractAttribute::trackStatistics()
6538 void trackStatistics() const override {
6539 STATS_DECLTRACK_FN_ATTR(value_simplify){ static llvm::Statistic NumIRFunction_value_simplify = {"attributor"
, "NumIRFunction_value_simplify", ("Number of " "functions" " marked '"
"value_simplify" "'")};; ++(NumIRFunction_value_simplify); }
6540 }
6541};
6542
6543struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6544 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6545 : AAValueSimplifyFunction(IRP, A) {}
6546 /// See AbstractAttribute::trackStatistics()
6547 void trackStatistics() const override {
6548 STATS_DECLTRACK_CS_ATTR(value_simplify){ static llvm::Statistic NumIRCS_value_simplify = {"attributor"
, "NumIRCS_value_simplify", ("Number of " "call site" " marked '"
"value_simplify" "'")};; ++(NumIRCS_value_simplify); }
6549 }
6550};
6551
6552struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6553 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6554 : AAValueSimplifyImpl(IRP, A) {}
6555
6556 void initialize(Attributor &A) override {
6557 AAValueSimplifyImpl::initialize(A);
6558 Function *Fn = getAssociatedFunction();
6559 if (!Fn) {
6560 indicatePessimisticFixpoint();
6561 return;
6562 }
6563 for (Argument &Arg : Fn->args()) {
6564 if (Arg.hasReturnedAttr()) {
6565 auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
6566 Arg.getArgNo());
6567 if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_ARGUMENT &&
6568 checkAndUpdate(A, *this, IRP))
6569 indicateOptimisticFixpoint();
6570 else
6571 indicatePessimisticFixpoint();
6572 return;
6573 }
6574 }
6575 }
6576
6577 /// See AbstractAttribute::updateImpl(...).
6578 ChangeStatus updateImpl(Attributor &A) override {
6579 auto Before = SimplifiedAssociatedValue;
6580 auto &RetAA = A.getAAFor<AAReturnedValues>(
6581 *this, IRPosition::function(*getAssociatedFunction()),
6582 DepClassTy::REQUIRED);
6583 auto PredForReturned =
6584 [&](Value &RetVal, const SmallSetVector<ReturnInst *, 4> &RetInsts) {
6585 bool UsedAssumedInformation = false;
6586 std::optional<Value *> CSRetVal =
6587 A.translateArgumentToCallSiteContent(
6588 &RetVal, *cast<CallBase>(getCtxI()), *this,
6589 UsedAssumedInformation);
6590 SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
6591 SimplifiedAssociatedValue, CSRetVal, getAssociatedType());
6592 return SimplifiedAssociatedValue != std::optional<Value *>(nullptr);
6593 };
6594 if (!RetAA.checkForAllReturnedValuesAndReturnInsts(PredForReturned))
6595 if (!askSimplifiedValueForOtherAAs(A))
6596 return indicatePessimisticFixpoint();
6597 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6598 : ChangeStatus ::CHANGED;
6599 }
6600
6601 void trackStatistics() const override {
6602 STATS_DECLTRACK_CSRET_ATTR(value_simplify){ static llvm::Statistic NumIRCSReturn_value_simplify = {"attributor"
, "NumIRCSReturn_value_simplify", ("Number of " "call site returns"
" marked '" "value_simplify" "'")};; ++(NumIRCSReturn_value_simplify
); }
6603 }
6604};
6605
6606struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6607 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6608 : AAValueSimplifyFloating(IRP, A) {}
6609
6610 /// See AbstractAttribute::manifest(...).
6611 ChangeStatus manifest(Attributor &A) override {
6612 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6613 // TODO: We should avoid simplification duplication to begin with.
6614 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6615 IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
6616 if (FloatAA && FloatAA->getState().isValidState())
6617 return Changed;
6618
6619 if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
6620 Use &U = cast<CallBase>(&getAnchorValue())
6621 ->getArgOperandUse(getCallSiteArgNo());
6622 if (A.changeUseAfterManifest(U, *NewV))
6623 Changed = ChangeStatus::CHANGED;
6624 }
6625
6626 return Changed | AAValueSimplify::manifest(A);
6627 }
6628
6629 void trackStatistics() const override {
6630 STATS_DECLTRACK_CSARG_ATTR(value_simplify){ static llvm::Statistic NumIRCSArguments_value_simplify = {"attributor"
, "NumIRCSArguments_value_simplify", ("Number of " "call site arguments"
" marked '" "value_simplify" "'")};; ++(NumIRCSArguments_value_simplify
); }
6631 }
6632};
6633} // namespace
6634
6635/// ----------------------- Heap-To-Stack Conversion ---------------------------
6636namespace {
6637struct AAHeapToStackFunction final : public AAHeapToStack {
6638
6639 struct AllocationInfo {
6640 /// The call that allocates the memory.
6641 CallBase *const CB;
6642
6643 /// The library function id for the allocation.
6644 LibFunc LibraryFunctionId = NotLibFunc;
6645
6646 /// The status wrt. a rewrite.
6647 enum {
6648 STACK_DUE_TO_USE,
6649 STACK_DUE_TO_FREE,
6650 INVALID,
6651 } Status = STACK_DUE_TO_USE;
6652
6653 /// Flag to indicate if we encountered a use that might free this allocation
6654 /// but which is not in the deallocation infos.
6655 bool HasPotentiallyFreeingUnknownUses = false;
6656
6657 /// Flag to indicate that we should place the new alloca in the function
6658 /// entry block rather than where the call site (CB) is.
6659 bool MoveAllocaIntoEntry = true;
6660
6661 /// The set of free calls that use this allocation.
6662 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6663 };
6664
6665 struct DeallocationInfo {
6666 /// The call that deallocates the memory.
6667 CallBase *const CB;
6668 /// The value freed by the call.
6669 Value *FreedOp;
6670
6671 /// Flag to indicate if we don't know all objects this deallocation might
6672 /// free.
6673 bool MightFreeUnknownObjects = false;
6674
6675 /// The set of allocation calls that are potentially freed.
6676 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6677 };
6678
6679 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6680 : AAHeapToStack(IRP, A) {}
6681
6682 ~AAHeapToStackFunction() {
6683 // Ensure we call the destructor so we release any memory allocated in the
6684 // sets.
6685 for (auto &It : AllocationInfos)
6686 It.second->~AllocationInfo();
6687 for (auto &It : DeallocationInfos)
6688 It.second->~DeallocationInfo();
6689 }
6690
6691 void initialize(Attributor &A) override {
6692 AAHeapToStack::initialize(A);
6693
6694 const Function *F = getAnchorScope();
6695 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6696
6697 auto AllocationIdentifierCB = [&](Instruction &I) {
6698 CallBase *CB = dyn_cast<CallBase>(&I);
6699 if (!CB)
6700 return true;
6701 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6702 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
6703 return true;
6704 }
6705 // To do heap to stack, we need to know that the allocation itself is
6706 // removable once uses are rewritten, and that we can initialize the
6707 // alloca to the same pattern as the original allocation result.
6708 if (isRemovableAlloc(CB, TLI)) {
6709 auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
6710 if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
6711 AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
6712 AllocationInfos[CB] = AI;
6713 if (TLI)
6714 TLI->getLibFunc(*CB, AI->LibraryFunctionId);
6715 }
6716 }
6717 return true;
6718 };
6719
6720 bool UsedAssumedInformation = false;
6721 bool Success = A.checkForAllCallLikeInstructions(
6722 AllocationIdentifierCB, *this, UsedAssumedInformation,
6723 /* CheckBBLivenessOnly */ false,
6724 /* CheckPotentiallyDead */ true);
6725 (void)Success;
6726 assert(Success && "Did not expect the call base visit callback to fail!")(static_cast <bool> (Success && "Did not expect the call base visit callback to fail!"
) ? void (0) : __assert_fail ("Success && \"Did not expect the call base visit callback to fail!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6726, __extension__
__PRETTY_FUNCTION__))
;
6727
6728 Attributor::SimplifictionCallbackTy SCB =
6729 [](const IRPosition &, const AbstractAttribute *,
6730 bool &) -> std::optional<Value *> { return nullptr; };
6731 for (const auto &It : AllocationInfos)
6732 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6733 SCB);
6734 for (const auto &It : DeallocationInfos)
6735 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6736 SCB);
6737 }
6738
6739 const std::string getAsStr() const override {
6740 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6741 for (const auto &It : AllocationInfos) {
6742 if (It.second->Status == AllocationInfo::INVALID)
6743 ++NumInvalidMallocs;
6744 else
6745 ++NumH2SMallocs;
6746 }
6747 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
6748 std::to_string(NumInvalidMallocs);
6749 }
6750
6751 /// See AbstractAttribute::trackStatistics().
6752 void trackStatistics() const override {
6753 STATS_DECL(static llvm::Statistic NumIRFunction_MallocCalls = {"attributor"
, "NumIRFunction_MallocCalls", "Number of malloc/calloc/aligned_alloc calls converted to allocas"
};;
6754 MallocCalls, Function,static llvm::Statistic NumIRFunction_MallocCalls = {"attributor"
, "NumIRFunction_MallocCalls", "Number of malloc/calloc/aligned_alloc calls converted to allocas"
};;
6755 "Number of malloc/calloc/aligned_alloc calls converted to allocas")static llvm::Statistic NumIRFunction_MallocCalls = {"attributor"
, "NumIRFunction_MallocCalls", "Number of malloc/calloc/aligned_alloc calls converted to allocas"
};;
;
6756 for (const auto &It : AllocationInfos)
6757 if (It.second->Status != AllocationInfo::INVALID)
6758 ++BUILD_STAT_NAME(MallocCalls, Function)NumIRFunction_MallocCalls;
6759 }
6760
6761 bool isAssumedHeapToStack(const CallBase &CB) const override {
6762 if (isValidState())
6763 if (AllocationInfo *AI =
6764 AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
6765 return AI->Status != AllocationInfo::INVALID;
6766 return false;
6767 }
6768
6769 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6770 if (!isValidState())
6771 return false;
6772
6773 for (const auto &It : AllocationInfos) {
6774 AllocationInfo &AI = *It.second;
6775 if (AI.Status == AllocationInfo::INVALID)
6776 continue;
6777
6778 if (AI.PotentialFreeCalls.count(&CB))
6779 return true;
6780 }
6781
6782 return false;
6783 }
6784
6785 ChangeStatus manifest(Attributor &A) override {
6786 assert(getState().isValidState() &&(static_cast <bool> (getState().isValidState() &&
"Attempted to manifest an invalid state!") ? void (0) : __assert_fail
("getState().isValidState() && \"Attempted to manifest an invalid state!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6787, __extension__
__PRETTY_FUNCTION__))
6787 "Attempted to manifest an invalid state!")(static_cast <bool> (getState().isValidState() &&
"Attempted to manifest an invalid state!") ? void (0) : __assert_fail
("getState().isValidState() && \"Attempted to manifest an invalid state!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6787, __extension__
__PRETTY_FUNCTION__))
;
6788
6789 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6790 Function *F = getAnchorScope();
6791 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6792
6793 for (auto &It : AllocationInfos) {
6794 AllocationInfo &AI = *It.second;
6795 if (AI.Status == AllocationInfo::INVALID)
6796 continue;
6797
6798 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6799 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "H2S: Removing free call: "
<< *FreeCall << "\n"; } } while (false)
;
6800 A.deleteAfterManifest(*FreeCall);
6801 HasChanged = ChangeStatus::CHANGED;
Value stored to 'HasChanged' is never read
6802 }
6803
6804 LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CBdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "H2S: Removing malloc-like call: "
<< *AI.CB << "\n"; } } while (false)
6805 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "H2S: Removing malloc-like call: "
<< *AI.CB << "\n"; } } while (false)
;
6806
6807 auto Remark = [&](OptimizationRemark OR) {
6808 LibFunc IsAllocShared;
6809 if (TLI->getLibFunc(*AI.CB, IsAllocShared))
6810 if (IsAllocShared == LibFunc___kmpc_alloc_shared)
6811 return OR << "Moving globalized variable to the stack.";
6812 return OR << "Moving memory allocation from the heap to the stack.";
6813 };
6814 if (AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
6815 A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
6816 else
6817 A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);
6818
6819 const DataLayout &DL = A.getInfoCache().getDL();
6820 Value *Size;
6821 std::optional<APInt> SizeAPI = getSize(A, *this, AI);
6822 if (SizeAPI) {
6823 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6824 } else {
6825 LLVMContext &Ctx = AI.CB->getContext();
6826 ObjectSizeOpts Opts;
6827 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts);
6828 SizeOffsetEvalType SizeOffsetPair = Eval.compute(AI.CB);
6829 assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&(static_cast <bool> (SizeOffsetPair != ObjectSizeOffsetEvaluator
::unknown() && cast<ConstantInt>(SizeOffsetPair
.second)->isZero()) ? void (0) : __assert_fail ("SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() && cast<ConstantInt>(SizeOffsetPair.second)->isZero()"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6830, __extension__
__PRETTY_FUNCTION__))
6830 cast<ConstantInt>(SizeOffsetPair.second)->isZero())(static_cast <bool> (SizeOffsetPair != ObjectSizeOffsetEvaluator
::unknown() && cast<ConstantInt>(SizeOffsetPair
.second)->isZero()) ? void (0) : __assert_fail ("SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() && cast<ConstantInt>(SizeOffsetPair.second)->isZero()"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6830, __extension__
__PRETTY_FUNCTION__))
;
6831 Size = SizeOffsetPair.first;
6832 }
6833
6834 Instruction *IP =
6835 AI.MoveAllocaIntoEntry ? &F->getEntryBlock().front() : AI.CB;
6836
6837 Align Alignment(1);
6838 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6839 Alignment = std::max(Alignment, *RetAlign);
6840 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
6841 std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
6842 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&(static_cast <bool> (AlignmentAPI && AlignmentAPI
->getZExtValue() > 0 && "Expected an alignment during manifest!"
) ? void (0) : __assert_fail ("AlignmentAPI && AlignmentAPI->getZExtValue() > 0 && \"Expected an alignment during manifest!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6843, __extension__
__PRETTY_FUNCTION__))
6843 "Expected an alignment during manifest!")(static_cast <bool> (AlignmentAPI && AlignmentAPI
->getZExtValue() > 0 && "Expected an alignment during manifest!"
) ? void (0) : __assert_fail ("AlignmentAPI && AlignmentAPI->getZExtValue() > 0 && \"Expected an alignment during manifest!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6843, __extension__
__PRETTY_FUNCTION__))
;
6844 Alignment =
6845 std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
6846 }
6847
6848 // TODO: Hoist the alloca towards the function entry.
6849 unsigned AS = DL.getAllocaAddrSpace();
6850 Instruction *Alloca =
6851 new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
6852 AI.CB->getName() + ".h2s", IP);
6853
6854 if (Alloca->getType() != AI.CB->getType())
6855 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6856 Alloca, AI.CB->getType(), "malloc_cast", AI.CB);
6857
6858 auto *I8Ty = Type::getInt8Ty(F->getContext());
6859 auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
6860 assert(InitVal &&(static_cast <bool> (InitVal && "Must be able to materialize initial memory state of allocation"
) ? void (0) : __assert_fail ("InitVal && \"Must be able to materialize initial memory state of allocation\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6861, __extension__
__PRETTY_FUNCTION__))
6861 "Must be able to materialize initial memory state of allocation")(static_cast <bool> (InitVal && "Must be able to materialize initial memory state of allocation"
) ? void (0) : __assert_fail ("InitVal && \"Must be able to materialize initial memory state of allocation\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6861, __extension__
__PRETTY_FUNCTION__))
;
6862
6863 A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);
6864
6865 if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
6866 auto *NBB = II->getNormalDest();
6867 BranchInst::Create(NBB, AI.CB->getParent());
6868 A.deleteAfterManifest(*AI.CB);
6869 } else {
6870 A.deleteAfterManifest(*AI.CB);
6871 }
6872
6873 // Initialize the alloca with the same value as used by the allocation
6874 // function. We can skip undef as the initial value of an alloc is
6875 // undef, and the memset would simply end up being DSEd.
6876 if (!isa<UndefValue>(InitVal)) {
6877 IRBuilder<> Builder(Alloca->getNextNode());
6878 // TODO: Use alignment above if align!=1
6879 Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
6880 }
6881 HasChanged = ChangeStatus::CHANGED;
6882 }
6883
6884 return HasChanged;
6885 }
6886
6887 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
6888 Value &V) {
6889 bool UsedAssumedInformation = false;
6890 std::optional<Constant *> SimpleV =
6891 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6892 if (!SimpleV)
6893 return APInt(64, 0);
6894 if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
6895 return CI->getValue();
6896 return std::nullopt;
6897 }
6898
6899 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
6900 AllocationInfo &AI) {
6901 auto Mapper = [&](const Value *V) -> const Value * {
6902 bool UsedAssumedInformation = false;
6903 if (std::optional<Constant *> SimpleV =
6904 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6905 if (*SimpleV)
6906 return *SimpleV;
6907 return V;
6908 };
6909
6910 const Function *F = getAnchorScope();
6911 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6912 return getAllocSize(AI.CB, TLI, Mapper);
6913 }
6914
6915 /// Collection of all malloc-like calls in a function with associated
6916 /// information.
6917 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6918
6919 /// Collection of all free-like calls in a function with associated
6920 /// information.
6921 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6922
6923 ChangeStatus updateImpl(Attributor &A) override;
6924};
6925
6926ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
6927 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6928 const Function *F = getAnchorScope();
6929 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6930
6931 const auto &LivenessAA =
6932 A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);
6933
6934 MustBeExecutedContextExplorer &Explorer =
6935 A.getInfoCache().getMustBeExecutedContextExplorer();
6936
6937 bool StackIsAccessibleByOtherThreads =
6938 A.getInfoCache().stackIsAccessibleByOtherThreads();
6939
6940 LoopInfo *LI =
6941 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6942 std::optional<bool> MayContainIrreducibleControl;
6943 auto IsInLoop = [&](BasicBlock &BB) {
6944 if (&F->getEntryBlock() == &BB)
6945 return false;
6946 if (!MayContainIrreducibleControl.has_value())
6947 MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
6948 if (*MayContainIrreducibleControl)
6949 return true;
6950 if (!LI)
6951 return true;
6952 return LI->getLoopFor(&BB) != nullptr;
6953 };
6954
6955 // Flag to ensure we update our deallocation information at most once per
6956 // updateImpl call and only if we use the free check reasoning.
6957 bool HasUpdatedFrees = false;
6958
6959 auto UpdateFrees = [&]() {
6960 HasUpdatedFrees = true;
6961
6962 for (auto &It : DeallocationInfos) {
6963 DeallocationInfo &DI = *It.second;
6964 // For now we cannot use deallocations that have unknown inputs, skip
6965 // them.
6966 if (DI.MightFreeUnknownObjects)
6967 continue;
6968
6969 // No need to analyze dead calls, ignore them instead.
6970 bool UsedAssumedInformation = false;
6971 if (A.isAssumedDead(*DI.CB, this, &LivenessAA, UsedAssumedInformation,
6972 /* CheckBBLivenessOnly */ true))
6973 continue;
6974
6975 // Use the non-optimistic version to get the freed object.
6976 Value *Obj = getUnderlyingObject(DI.FreedOp);
6977 if (!Obj) {
6978 LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Unknown underlying object for free!\n"
; } } while (false)
;
6979 DI.MightFreeUnknownObjects = true;
6980 continue;
6981 }
6982
6983 // Free of null and undef can be ignored as no-ops (or UB in the latter
6984 // case).
6985 if (isa<ConstantPointerNull>(Obj) || isa<UndefValue>(Obj))
6986 continue;
6987
6988 CallBase *ObjCB = dyn_cast<CallBase>(Obj);
6989 if (!ObjCB) {
6990 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Free of a non-call object: "
<< *Obj << "\n"; } } while (false)
6991 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Free of a non-call object: "
<< *Obj << "\n"; } } while (false)
;
6992 DI.MightFreeUnknownObjects = true;
6993 continue;
6994 }
6995
6996 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
6997 if (!AI) {
6998 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Objdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Free of a non-allocation object: "
<< *Obj << "\n"; } } while (false)
6999 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Free of a non-allocation object: "
<< *Obj << "\n"; } } while (false)
;
7000 DI.MightFreeUnknownObjects = true;
7001 continue;
7002 }
7003
7004 DI.PotentialAllocationCalls.insert(ObjCB);
7005 }
7006 };
7007
7008 auto FreeCheck = [&](AllocationInfo &AI) {
7009 // If the stack is not accessible by other threads, the "must-free" logic
7010 // doesn't apply as the pointer could be shared and needs to be places in
7011 // "shareable" memory.
7012 if (!StackIsAccessibleByOtherThreads) {
7013 auto &NoSyncAA =
7014 A.getAAFor<AANoSync>(*this, getIRPosition(), DepClassTy::OPTIONAL);
7015 if (!NoSyncAA.isAssumedNoSync()) {
7016 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] found an escaping use, stack is not accessible by "
"other threads and function is not nosync:\n"; } } while (false
)
7017 dbgs() << "[H2S] found an escaping use, stack is not accessible by "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] found an escaping use, stack is not accessible by "
"other threads and function is not nosync:\n"; } } while (false
)
7018 "other threads and function is not nosync:\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] found an escaping use, stack is not accessible by "
"other threads and function is not nosync:\n"; } } while (false
)
;
7019 return false;
7020 }
7021 }
7022 if (!HasUpdatedFrees)
7023 UpdateFrees();
7024
7025 // TODO: Allow multi exit functions that have different free calls.
7026 if (AI.PotentialFreeCalls.size() != 1) {
7027 LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] did not find one free call but "
<< AI.PotentialFreeCalls.size() << "\n"; } } while
(false)
7028 << AI.PotentialFreeCalls.size() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] did not find one free call but "
<< AI.PotentialFreeCalls.size() << "\n"; } } while
(false)
;
7029 return false;
7030 }
7031 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7032 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7033 if (!DI) {
7034 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call was not known as deallocation call "
<< *UniqueFree << "\n"; } } while (false)
7035 dbgs() << "[H2S] unique free call was not known as deallocation call "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call was not known as deallocation call "
<< *UniqueFree << "\n"; } } while (false)
7036 << *UniqueFree << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call was not known as deallocation call "
<< *UniqueFree << "\n"; } } while (false)
;
7037 return false;
7038 }
7039 if (DI->MightFreeUnknownObjects) {
7040 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might free unknown allocations\n"
; } } while (false)
7041 dbgs() << "[H2S] unique free call might free unknown allocations\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might free unknown allocations\n"
; } } while (false)
;
7042 return false;
7043 }
7044 if (DI->PotentialAllocationCalls.empty())
7045 return true;
7046 if (DI->PotentialAllocationCalls.size() > 1) {
7047 LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might free "
<< DI->PotentialAllocationCalls.size() << " different allocations\n"
; } } while (false)
7048 << DI->PotentialAllocationCalls.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might free "
<< DI->PotentialAllocationCalls.size() << " different allocations\n"
; } } while (false)
7049 << " different allocations\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might free "
<< DI->PotentialAllocationCalls.size() << " different allocations\n"
; } } while (false)
;
7050 return false;
7051 }
7052 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7053 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call not known to free this allocation but "
<< **DI->PotentialAllocationCalls.begin() << "\n"
; } } while (false)
7054 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call not known to free this allocation but "
<< **DI->PotentialAllocationCalls.begin() << "\n"
; } } while (false)
7055 << "[H2S] unique free call not known to free this allocation but "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call not known to free this allocation but "
<< **DI->PotentialAllocationCalls.begin() << "\n"
; } } while (false)
7056 << **DI->PotentialAllocationCalls.begin() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call not known to free this allocation but "
<< **DI->PotentialAllocationCalls.begin() << "\n"
; } } while (false)
;
7057 return false;
7058 }
7059 Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
7060 if (!Explorer.findInContextOf(UniqueFree, CtxI)) {
7061 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might not be executed with the allocation "
<< *UniqueFree << "\n"; } } while (false)
7062 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might not be executed with the allocation "
<< *UniqueFree << "\n"; } } while (false)
7063 << "[H2S] unique free call might not be executed with the allocation "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might not be executed with the allocation "
<< *UniqueFree << "\n"; } } while (false)
7064 << *UniqueFree << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might not be executed with the allocation "
<< *UniqueFree << "\n"; } } while (false)
;
7065 return false;
7066 }
7067 return true;
7068 };
7069
7070 auto UsesCheck = [&](AllocationInfo &AI) {
7071 bool ValidUsesOnly = true;
7072
7073 auto Pred = [&](const Use &U, bool &Follow) -> bool {
7074 Instruction *UserI = cast<Instruction>(U.getUser());
7075 if (isa<LoadInst>(UserI))
7076 return true;
7077 if (auto *SI = dyn_cast<StoreInst>(UserI)) {
7078 if (SI->getValueOperand() == U.get()) {
7079 LLVM_DEBUG(dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] escaping store to memory: "
<< *UserI << "\n"; } } while (false)
7080 << "[H2S] escaping store to memory: " << *UserI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] escaping store to memory: "
<< *UserI << "\n"; } } while (false)
;
7081 ValidUsesOnly = false;
7082 } else {
7083 // A store into the malloc'ed memory is fine.
7084 }
7085 return true;
7086 }
7087 if (auto *CB = dyn_cast<CallBase>(UserI)) {
7088 if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
7089 return true;
7090 if (DeallocationInfos.count(CB)) {
7091 AI.PotentialFreeCalls.insert(CB);
7092 return true;
7093 }
7094
7095 unsigned ArgNo = CB->getArgOperandNo(&U);
7096
7097 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
7098 *this, IRPosition::callsite_argument(*CB, ArgNo),
7099 DepClassTy::OPTIONAL);
7100
7101 // If a call site argument use is nofree, we are fine.
7102 const auto &ArgNoFreeAA = A.getAAFor<AANoFree>(
7103 *this, IRPosition::callsite_argument(*CB, ArgNo),
7104 DepClassTy::OPTIONAL);
7105
7106 bool MaybeCaptured = !NoCaptureAA.isAssumedNoCapture();
7107 bool MaybeFreed = !ArgNoFreeAA.isAssumedNoFree();
7108 if (MaybeCaptured ||
7109 (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
7110 MaybeFreed)) {
7111 AI.HasPotentiallyFreeingUnknownUses |= MaybeFreed;
7112
7113 // Emit a missed remark if this is missed OpenMP globalization.
7114 auto Remark = [&](OptimizationRemarkMissed ORM) {
7115 return ORM
7116 << "Could not move globalized variable to the stack. "
7117 "Variable is potentially captured in call. Mark "
7118 "parameter as `__attribute__((noescape))` to override.";
7119 };
7120
7121 if (ValidUsesOnly &&
7122 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
7123 A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);
7124
7125 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Bad user: " <<
*UserI << "\n"; } } while (false)
;
7126 ValidUsesOnly = false;
7127 }
7128 return true;
7129 }
7130
7131 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
7132 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
7133 Follow = true;
7134 return true;
7135 }
7136 // Unknown user for which we can not track uses further (in a way that
7137 // makes sense).
7138 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Unknown user: " <<
*UserI << "\n"; } } while (false)
;
7139 ValidUsesOnly = false;
7140 return true;
7141 };
7142 if (!A.checkForAllUses(Pred, *this, *AI.CB, /* CheckBBLivenessOnly */ false,
7143 DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,
7144 [&](const Use &OldU, const Use &NewU) {
7145 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7146 return !SI || StackIsAccessibleByOtherThreads ||
7147 AA::isAssumedThreadLocalObject(
7148 A, *SI->getPointerOperand(), *this);
7149 }))
7150 return false;
7151 return ValidUsesOnly;
7152 };
7153
7154 // The actual update starts here. We look at all allocations and depending on
7155 // their status perform the appropriate check(s).
7156 for (auto &It : AllocationInfos) {
7157 AllocationInfo &AI = *It.second;
7158 if (AI.Status == AllocationInfo::INVALID)
7159 continue;
7160
7161 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
7162 std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
7163 if (!APAlign) {
7164 // Can't generate an alloca which respects the required alignment
7165 // on the allocation.
7166 LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CBdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Unknown allocation alignment: "
<< *AI.CB << "\n"; } } while (false)
7167 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Unknown allocation alignment: "
<< *AI.CB << "\n"; } } while (false)
;
7168 AI.Status = AllocationInfo::INVALID;
7169 Changed = ChangeStatus::CHANGED;
7170 continue;
7171 }
7172 if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
7173 !APAlign->isPowerOf2()) {
7174 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAligndo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Invalid allocation alignment: "
<< APAlign << "\n"; } } while (false)
7175 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Invalid allocation alignment: "
<< APAlign << "\n"; } } while (false)
;
7176 AI.Status = AllocationInfo::INVALID;
7177 Changed = ChangeStatus::CHANGED;
7178 continue;
7179 }
7180 }
7181
7182 std::optional<APInt> Size = getSize(A, *this, AI);
7183 if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
7184 MaxHeapToStackSize != -1) {
7185 if (!Size || Size->ugt(MaxHeapToStackSize)) {
7186 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Size) dbgs() << "[H2S] Unknown allocation size: "
<< *AI.CB << "\n"; else dbgs() << "[H2S] Allocation size too large: "
<< *AI.CB << " vs. " << MaxHeapToStackSize
<< "\n"; }; } } while (false)
7187 if (!Size)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Size) dbgs() << "[H2S] Unknown allocation size: "
<< *AI.CB << "\n"; else dbgs() << "[H2S] Allocation size too large: "
<< *AI.CB << " vs. " << MaxHeapToStackSize
<< "\n"; }; } } while (false)
7188 dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Size) dbgs() << "[H2S] Unknown allocation size: "
<< *AI.CB << "\n"; else dbgs() << "[H2S] Allocation size too large: "
<< *AI.CB << " vs. " << MaxHeapToStackSize
<< "\n"; }; } } while (false)
7189 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Size) dbgs() << "[H2S] Unknown allocation size: "
<< *AI.CB << "\n"; else dbgs() << "[H2S] Allocation size too large: "
<< *AI.CB << " vs. " << MaxHeapToStackSize
<< "\n"; }; } } while (false)
7190 dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Size) dbgs() << "[H2S] Unknown allocation size: "
<< *AI.CB << "\n"; else dbgs() << "[H2S] Allocation size too large: "
<< *AI.CB << " vs. " << MaxHeapToStackSize
<< "\n"; }; } } while (false)
7191 << MaxHeapToStackSize << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Size) dbgs() << "[H2S] Unknown allocation size: "
<< *AI.CB << "\n"; else dbgs() << "[H2S] Allocation size too large: "
<< *AI.CB << " vs. " << MaxHeapToStackSize
<< "\n"; }; } } while (false)
7192 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { if (!Size) dbgs() << "[H2S] Unknown allocation size: "
<< *AI.CB << "\n"; else dbgs() << "[H2S] Allocation size too large: "
<< *AI.CB << " vs. " << MaxHeapToStackSize
<< "\n"; }; } } while (false)
;
7193
7194 AI.Status = AllocationInfo::INVALID;
7195 Changed = ChangeStatus::CHANGED;
7196 continue;
7197 }
7198 }
7199
7200 switch (AI.Status) {
7201 case AllocationInfo::STACK_DUE_TO_USE:
7202 if (UsesCheck(AI))
7203 break;
7204 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7205 [[fallthrough]];
7206 case AllocationInfo::STACK_DUE_TO_FREE:
7207 if (FreeCheck(AI))
7208 break;
7209 AI.Status = AllocationInfo::INVALID;
7210 Changed = ChangeStatus::CHANGED;
7211 break;
7212 case AllocationInfo::INVALID:
7213 llvm_unreachable("Invalid allocations should never reach this point!")::llvm::llvm_unreachable_internal("Invalid allocations should never reach this point!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7213)
;
7214 };
7215
7216 // Check if we still think we can move it into the entry block. If the
7217 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7218 // ignore the potential compilations associated with loops.
7219 bool IsGlobalizedLocal =
7220 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared;
7221 if (AI.MoveAllocaIntoEntry &&
7222 (!Size.has_value() ||
7223 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7224 AI.MoveAllocaIntoEntry = false;
7225 }
7226
7227 return Changed;
7228}
7229} // namespace
7230
7231/// ----------------------- Privatizable Pointers ------------------------------
7232namespace {
7233struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
7234 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7235 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7236
7237 ChangeStatus indicatePessimisticFixpoint() override {
7238 AAPrivatizablePtr::indicatePessimisticFixpoint();
7239 PrivatizableType = nullptr;
7240 return ChangeStatus::CHANGED;
7241 }
7242
7243 /// Identify the type we can chose for a private copy of the underlying
7244 /// argument. std::nullopt means it is not clear yet, nullptr means there is
7245 /// none.
7246 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7247
7248 /// Return a privatizable type that encloses both T0 and T1.
7249 /// TODO: This is merely a stub for now as we should manage a mapping as well.
7250 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7251 std::optional<Type *> T1) {
7252 if (!T0)
7253 return T1;
7254 if (!T1)
7255 return T0;
7256 if (T0 == T1)
7257 return T0;
7258 return nullptr;
7259 }
7260
7261 std::optional<Type *> getPrivatizableType() const override {
7262 return PrivatizableType;
7263 }
7264
7265 const std::string getAsStr() const override {
7266 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7267 }
7268
7269protected:
7270 std::optional<Type *> PrivatizableType;
7271};
7272
7273// TODO: Do this for call site arguments (probably also other values) as well.
7274
7275struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
7276 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7277 : AAPrivatizablePtrImpl(IRP, A) {}
7278
7279 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7280 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7281 // If this is a byval argument and we know all the call sites (so we can
7282 // rewrite them), there is no need to check them explicitly.
7283 bool UsedAssumedInformation = false;
7284 SmallVector<Attribute, 1> Attrs;
7285 getAttrs({Attribute::ByVal}, Attrs, /* IgnoreSubsumingPositions */ true);
7286 if (!Attrs.empty() &&
7287 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
7288 true, UsedAssumedInformation))
7289 return Attrs[0].getValueAsType();
7290
7291 std::optional<Type *> Ty;
7292 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7293
7294 // Make sure the associated call site argument has the same type at all call
7295 // sites and it is an allocation we know is safe to privatize, for now that
7296 // means we only allow alloca instructions.
7297 // TODO: We can additionally analyze the accesses in the callee to create
7298 // the type from that information instead. That is a little more
7299 // involved and will be done in a follow up patch.
7300 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7301 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7302 // Check if a coresponding argument was found or if it is one not
7303 // associated (which can happen for callback calls).
7304 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7305 return false;
7306
7307 // Check that all call sites agree on a type.
7308 auto &PrivCSArgAA =
7309 A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
7310 std::optional<Type *> CSTy = PrivCSArgAA.getPrivatizableType();
7311
7312 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7313 dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7314 if (CSTy && *CSTy)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7315 (*CSTy)->print(dbgs());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7316 else if (CSTy)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7317 dbgs() << "<nullptr>";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7318 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7319 dbgs() << "<none>";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
7320 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] ACSPos: "
<< ACSArgPos << ", CSTy: "; if (CSTy && *
CSTy) (*CSTy)->print(dbgs()); else if (CSTy) dbgs() <<
"<nullptr>"; else dbgs() << "<none>"; }; }
} while (false)
;
7321
7322 Ty = combineTypes(Ty, CSTy);
7323
7324 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7325 dbgs() << " : New Type: ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7326 if (Ty && *Ty)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7327 (*Ty)->print(dbgs());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7328 else if (Ty)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7329 dbgs() << "<nullptr>";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7330 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7331 dbgs() << "<none>";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7332 dbgs() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
7333 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << " : New Type: "; if (Ty &&
*Ty) (*Ty)->print(dbgs()); else if (Ty) dbgs() << "<nullptr>"
; else dbgs() << "<none>"; dbgs() << "\n"; }
; } } while (false)
;
7334
7335 return !Ty || *Ty;
7336 };
7337
7338 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7339 UsedAssumedInformation))
7340 return nullptr;
7341 return Ty;
7342 }
7343
7344 /// See AbstractAttribute::updateImpl(...).
7345 ChangeStatus updateImpl(Attributor &A) override {
7346 PrivatizableType = identifyPrivatizableType(A);
7347 if (!PrivatizableType)
7348 return ChangeStatus::UNCHANGED;
7349 if (!*PrivatizableType)
7350 return indicatePessimisticFixpoint();
7351
7352 // The dependence is optional so we don't give up once we give up on the
7353 // alignment.
7354 A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
7355 DepClassTy::OPTIONAL);
7356
7357 // Avoid arguments with padding for now.
7358 if (!getIRPosition().hasAttr(Attribute::ByVal) &&
7359 !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
7360 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Padding detected\n"
; } } while (false)
;
7361 return indicatePessimisticFixpoint();
7362 }
7363
7364 // Collect the types that will replace the privatizable type in the function
7365 // signature.
7366 SmallVector<Type *, 16> ReplacementTypes;
7367 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7368
7369 // Verify callee and caller agree on how the promoted argument would be
7370 // passed.
7371 Function &Fn = *getIRPosition().getAnchorScope();
7372 const auto *TTI =
7373 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7374 if (!TTI) {
7375 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
<< Fn.getName() << "\n"; } } while (false)
7376 << Fn.getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
<< Fn.getName() << "\n"; } } while (false)
;
7377 return indicatePessimisticFixpoint();
7378 }
7379
7380 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7381 CallBase *CB = ACS.getInstruction();
7382 return TTI->areTypesABICompatible(
7383 CB->getCaller(), CB->getCalledFunction(), ReplacementTypes);
7384 };
7385 bool UsedAssumedInformation = false;
7386 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7387 UsedAssumedInformation)) {
7388 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
<< Fn.getName() << "\n"; } } while (false)
7389 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
<< Fn.getName() << "\n"; } } while (false)
7390 << Fn.getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
<< Fn.getName() << "\n"; } } while (false)
;
7391 return indicatePessimisticFixpoint();
7392 }
7393
7394 // Register a rewrite of the argument.
7395 Argument *Arg = getAssociatedArgument();
7396 if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7397 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n"
; } } while (false)
;
7398 return indicatePessimisticFixpoint();
7399 }
7400
7401 unsigned ArgNo = Arg->getArgNo();
7402
7403 // Helper to check if for the given call site the associated argument is
7404 // passed to a callback where the privatization would be different.
7405 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7406 SmallVector<const Use *, 4> CallbackUses;
7407 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7408 for (const Use *U : CallbackUses) {
7409 AbstractCallSite CBACS(U);
7410 assert(CBACS && CBACS.isCallbackCall())(static_cast <bool> (CBACS && CBACS.isCallbackCall
()) ? void (0) : __assert_fail ("CBACS && CBACS.isCallbackCall()"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7410, __extension__
__PRETTY_FUNCTION__))
;
7411 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7412 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7413
7414 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7415 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7416 << "[AAPrivatizablePtr] Argument " << *Argdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7417 << "check if can be privatized in the context of its parent ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7418 << Arg->getParent()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7419 << ")\n[AAPrivatizablePtr] because it is an argument in a "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7420 "callback ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7421 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7422 << ")\n[AAPrivatizablePtr] " << CBArg << " : "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7423 << CBACS.getCallArgOperand(CBArg) << " vs "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7424 << CB.getArgOperand(ArgNo) << "\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7425 << "[AAPrivatizablePtr] " << CBArg << " : "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7426 << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
7427 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << "check if can be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ")\n[AAPrivatizablePtr] " << CBArg
<< " : " << CBACS.getCallArgOperand(CBArg) <<
" vs " << CB.getArgOperand(ArgNo) << "\n" <<
"[AAPrivatizablePtr] " << CBArg << " : " <<
CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo
<< "\n"; }; } } while (false)
;
7428
7429 if (CBArgNo != int(ArgNo))
7430 continue;
7431 const auto &CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7432 *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
7433 if (CBArgPrivAA.isValidState()) {
7434 auto CBArgPrivTy = CBArgPrivAA.getPrivatizableType();
7435 if (!CBArgPrivTy)
7436 continue;
7437 if (*CBArgPrivTy == PrivatizableType)
7438 continue;
7439 }
7440
7441 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7442 dbgs() << "[AAPrivatizablePtr] Argument " << *Argdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7443 << " cannot be privatized in the context of its parent ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7444 << Arg->getParent()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7445 << ")\n[AAPrivatizablePtr] because it is an argument in a "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7446 "callback ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7447 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7448 << ").\n[AAPrivatizablePtr] for which the argument "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7449 "privatization is not compatible.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7450 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"callback (" << CBArgNo << "@" << CBACS.getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
;
7451 return false;
7452 }
7453 }
7454 return true;
7455 };
7456
7457 // Helper to check if for the given call site the associated argument is
7458 // passed to a direct call where the privatization would be different.
7459 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7460 CallBase *DC = cast<CallBase>(ACS.getInstruction());
7461 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7462 assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&(static_cast <bool> (DCArgNo >= 0 && unsigned
(DCArgNo) < DC->arg_size() && "Expected a direct call operand for callback call operand"
) ? void (0) : __assert_fail ("DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() && \"Expected a direct call operand for callback call operand\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7463, __extension__
__PRETTY_FUNCTION__))
7463 "Expected a direct call operand for callback call operand")(static_cast <bool> (DCArgNo >= 0 && unsigned
(DCArgNo) < DC->arg_size() && "Expected a direct call operand for callback call operand"
) ? void (0) : __assert_fail ("DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() && \"Expected a direct call operand for callback call operand\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7463, __extension__
__PRETTY_FUNCTION__))
;
7464
7465 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7466 dbgs() << "[AAPrivatizablePtr] Argument " << *Argdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7467 << " check if be privatized in the context of its parent ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7468 << Arg->getParent()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7469 << ")\n[AAPrivatizablePtr] because it is an argument in a "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7470 "direct call of ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7471 << DCArgNo << "@" << DC->getCalledFunction()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7472 << ").\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
7473 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " check if be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << DCArgNo << "@" << DC
->getCalledFunction()->getName() << ").\n"; }; } }
while (false)
;
7474
7475 Function *DCCallee = DC->getCalledFunction();
7476 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7477 const auto &DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7478 *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
7479 DepClassTy::REQUIRED);
7480 if (DCArgPrivAA.isValidState()) {
7481 auto DCArgPrivTy = DCArgPrivAA.getPrivatizableType();
7482 if (!DCArgPrivTy)
7483 return true;
7484 if (*DCArgPrivTy == PrivatizableType)
7485 return true;
7486 }
7487 }
7488
7489 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7490 dbgs() << "[AAPrivatizablePtr] Argument " << *Argdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7491 << " cannot be privatized in the context of its parent ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7492 << Arg->getParent()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7493 << ")\n[AAPrivatizablePtr] because it is an argument in a "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7494 "direct call of ("do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7495 << ACS.getInstruction()->getCalledFunction()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7496 << ").\n[AAPrivatizablePtr] for which the argument "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7497 "privatization is not compatible.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
7498 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "[AAPrivatizablePtr] Argument "
<< *Arg << " cannot be privatized in the context of its parent ("
<< Arg->getParent()->getName() << ")\n[AAPrivatizablePtr] because it is an argument in a "
"direct call of (" << ACS.getInstruction()->getCalledFunction
()->getName() << ").\n[AAPrivatizablePtr] for which the argument "
"privatization is not compatible.\n"; }; } } while (false)
;
7499 return false;
7500 };
7501
7502 // Helper to check if the associated argument is used at the given abstract
7503 // call site in a way that is incompatible with the privatization assumed
7504 // here.
7505 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7506 if (ACS.isDirectCall())
7507 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7508 if (ACS.isCallbackCall())
7509 return IsCompatiblePrivArgOfDirectCS(ACS);
7510 return false;
7511 };
7512
7513 if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
7514 UsedAssumedInformation))
7515 return indicatePessimisticFixpoint();
7516
7517 return ChangeStatus::UNCHANGED;
7518 }
7519
7520 /// Given a type to private \p PrivType, collect the constituates (which are
7521 /// used) in \p ReplacementTypes.
7522 static void
7523 identifyReplacementTypes(Type *PrivType,
7524 SmallVectorImpl<Type *> &ReplacementTypes) {
7525 // TODO: For now we expand the privatization type to the fullest which can
7526 // lead to dead arguments that need to be removed later.
7527 assert(PrivType && "Expected privatizable type!")(static_cast <bool> (PrivType && "Expected privatizable type!"
) ? void (0) : __assert_fail ("PrivType && \"Expected privatizable type!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7527, __extension__
__PRETTY_FUNCTION__))
;
7528
7529 // Traverse the type, extract constituate types on the outermost level.
7530 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7531 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7532 ReplacementTypes.push_back(PrivStructType->getElementType(u));
7533 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7534 ReplacementTypes.append(PrivArrayType->getNumElements(),
7535 PrivArrayType->getElementType());
7536 } else {
7537 ReplacementTypes.push_back(PrivType);
7538 }
7539 }
7540
7541 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7542 /// The values needed are taken from the arguments of \p F starting at
7543 /// position \p ArgNo.
7544 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7545 unsigned ArgNo, Instruction &IP) {
7546 assert(PrivType && "Expected privatizable type!")(static_cast <bool> (PrivType && "Expected privatizable type!"
) ? void (0) : __assert_fail ("PrivType && \"Expected privatizable type!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7546, __extension__
__PRETTY_FUNCTION__))
;
7547
7548 IRBuilder<NoFolder> IRB(&IP);
7549 const DataLayout &DL = F.getParent()->getDataLayout();
7550
7551 // Traverse the type, build GEPs and stores.
7552 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7553 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7554 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7555 Type *PointeeTy = PrivStructType->getElementType(u)->getPointerTo();
7556 Value *Ptr =
7557 constructPointer(PointeeTy, PrivType, &Base,
7558 PrivStructLayout->getElementOffset(u), IRB, DL);
7559 new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
7560 }
7561 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7562 Type *PointeeTy = PrivArrayType->getElementType();
7563 Type *PointeePtrTy = PointeeTy->getPointerTo();
7564 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7565 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7566 Value *Ptr = constructPointer(PointeePtrTy, PrivType, &Base,
7567 u * PointeeTySize, IRB, DL);
7568 new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
7569 }
7570 } else {
7571 new StoreInst(F.getArg(ArgNo), &Base, &IP);
7572 }
7573 }
7574
7575 /// Extract values from \p Base according to the type \p PrivType at the
7576 /// call position \p ACS. The values are appended to \p ReplacementValues.
7577 void createReplacementValues(Align Alignment, Type *PrivType,
7578 AbstractCallSite ACS, Value *Base,
7579 SmallVectorImpl<Value *> &ReplacementValues) {
7580 assert(Base && "Expected base value!")(static_cast <bool> (Base && "Expected base value!"
) ? void (0) : __assert_fail ("Base && \"Expected base value!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7580, __extension__
__PRETTY_FUNCTION__))
;
7581 assert(PrivType && "Expected privatizable type!")(static_cast <bool> (PrivType && "Expected privatizable type!"
) ? void (0) : __assert_fail ("PrivType && \"Expected privatizable type!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7581, __extension__
__PRETTY_FUNCTION__))
;
7582 Instruction *IP = ACS.getInstruction();
7583
7584 IRBuilder<NoFolder> IRB(IP);
7585 const DataLayout &DL = IP->getModule()->getDataLayout();
7586
7587 Type *PrivPtrType = PrivType->getPointerTo();
7588 if (Base->getType() != PrivPtrType)
7589 Base = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7590 Base, PrivPtrType, "", ACS.getInstruction());
7591
7592 // Traverse the type, build GEPs and loads.
7593 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7594 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7595 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7596 Type *PointeeTy = PrivStructType->getElementType(u);
7597 Value *Ptr =
7598 constructPointer(PointeeTy->getPointerTo(), PrivType, Base,
7599 PrivStructLayout->getElementOffset(u), IRB, DL);
7600 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
7601 L->setAlignment(Alignment);
7602 ReplacementValues.push_back(L);
7603 }
7604 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7605 Type *PointeeTy = PrivArrayType->getElementType();
7606 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7607 Type *PointeePtrTy = PointeeTy->getPointerTo();
7608 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7609 Value *Ptr = constructPointer(PointeePtrTy, PrivType, Base,
7610 u * PointeeTySize, IRB, DL);
7611 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
7612 L->setAlignment(Alignment);
7613 ReplacementValues.push_back(L);
7614 }
7615 } else {
7616 LoadInst *L = new LoadInst(PrivType, Base, "", IP);
7617 L->setAlignment(Alignment);
7618 ReplacementValues.push_back(L);
7619 }
7620 }
7621
7622 /// See AbstractAttribute::manifest(...)
7623 ChangeStatus manifest(Attributor &A) override {
7624 if (!PrivatizableType)
7625 return ChangeStatus::UNCHANGED;
7626 assert(*PrivatizableType && "Expected privatizable type!")(static_cast <bool> (*PrivatizableType && "Expected privatizable type!"
) ? void (0) : __assert_fail ("*PrivatizableType && \"Expected privatizable type!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7626, __extension__
__PRETTY_FUNCTION__))
;
7627
7628 // Collect all tail calls in the function as we cannot allow new allocas to
7629 // escape into tail recursion.
7630 // TODO: Be smarter about new allocas escaping into tail calls.
7631 SmallVector<CallInst *, 16> TailCalls;
7632 bool UsedAssumedInformation = false;
7633 if (!A.checkForAllInstructions(
7634 [&](Instruction &I) {
7635 CallInst &CI = cast<CallInst>(I);
7636 if (CI.isTailCall())
7637 TailCalls.push_back(&CI);
7638 return true;
7639 },
7640 *this, {Instruction::Call}, UsedAssumedInformation))
7641 return ChangeStatus::UNCHANGED;
7642
7643 Argument *Arg = getAssociatedArgument();
7644 // Query AAAlign attribute for alignment of associated argument to
7645 // determine the best alignment of loads.
7646 const auto &AlignAA =
7647 A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
7648
7649 // Callback to repair the associated function. A new alloca is placed at the
7650 // beginning and initialized with the values passed through arguments. The
7651 // new alloca replaces the use of the old pointer argument.
7652 Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB =
7653 [=](const Attributor::ArgumentReplacementInfo &ARI,
7654 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7655 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7656 Instruction *IP = &*EntryBB.getFirstInsertionPt();
7657 const DataLayout &DL = IP->getModule()->getDataLayout();
7658 unsigned AS = DL.getAllocaAddrSpace();
7659 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7660 Arg->getName() + ".priv", IP);
7661 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7662 ArgIt->getArgNo(), *IP);
7663
7664 if (AI->getType() != Arg->getType())
7665 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7666 AI, Arg->getType(), "", IP);
7667 Arg->replaceAllUsesWith(AI);
7668
7669 for (CallInst *CI : TailCalls)
7670 CI->setTailCall(false);
7671 };
7672
7673 // Callback to repair a call site of the associated function. The elements
7674 // of the privatizable type are loaded prior to the call and passed to the
7675 // new function version.
7676 Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB =
7677 [=, &AlignAA](const Attributor::ArgumentReplacementInfo &ARI,
7678 AbstractCallSite ACS,
7679 SmallVectorImpl<Value *> &NewArgOperands) {
7680 // When no alignment is specified for the load instruction,
7681 // natural alignment is assumed.
7682 createReplacementValues(
7683 AlignAA.getAssumedAlign(), *PrivatizableType, ACS,
7684 ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
7685 NewArgOperands);
7686 };
7687
7688 // Collect the types that will replace the privatizable type in the function
7689 // signature.
7690 SmallVector<Type *, 16> ReplacementTypes;
7691 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7692
7693 // Register a rewrite of the argument.
7694 if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7695 std::move(FnRepairCB),
7696 std::move(ACSRepairCB)))
7697 return ChangeStatus::CHANGED;
7698 return ChangeStatus::UNCHANGED;
7699 }
7700
7701 /// See AbstractAttribute::trackStatistics()
7702 void trackStatistics() const override {
7703 STATS_DECLTRACK_ARG_ATTR(privatizable_ptr){ static llvm::Statistic NumIRArguments_privatizable_ptr = {"attributor"
, "NumIRArguments_privatizable_ptr", ("Number of " "arguments"
" marked '" "privatizable_ptr" "'")};; ++(NumIRArguments_privatizable_ptr
); }
;
7704 }
7705};
7706
7707struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
7708 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7709 : AAPrivatizablePtrImpl(IRP, A) {}
7710
7711 /// See AbstractAttribute::initialize(...).
7712 void initialize(Attributor &A) override {
7713 // TODO: We can privatize more than arguments.
7714 indicatePessimisticFixpoint();
7715 }
7716
7717 ChangeStatus updateImpl(Attributor &A) override {
7718 llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"::llvm::llvm_unreachable_internal("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
"updateImpl will not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7719)
7719 "updateImpl will not be called")::llvm::llvm_unreachable_internal("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
"updateImpl will not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7719)
;
7720 }
7721
7722 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7723 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7724 Value *Obj = getUnderlyingObject(&getAssociatedValue());
7725 if (!Obj) {
7726 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] No underlying object found!\n"
; } } while (false)
;
7727 return nullptr;
7728 }
7729
7730 if (auto *AI = dyn_cast<AllocaInst>(Obj))
7731 if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
7732 if (CI->isOne())
7733 return AI->getAllocatedType();
7734 if (auto *Arg = dyn_cast<Argument>(Obj)) {
7735 auto &PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7736 *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
7737 if (PrivArgAA.isAssumedPrivatizablePtr())
7738 return PrivArgAA.getPrivatizableType();
7739 }
7740
7741 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
"alloca nor privatizable argument: " << *Obj << "!\n"
; } } while (false)
7742 "alloca nor privatizable argument: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
"alloca nor privatizable argument: " << *Obj << "!\n"
; } } while (false)
7743 << *Obj << "!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
"alloca nor privatizable argument: " << *Obj << "!\n"
; } } while (false)
;
7744 return nullptr;
7745 }
7746
7747 /// See AbstractAttribute::trackStatistics()
7748 void trackStatistics() const override {
7749 STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr){ static llvm::Statistic NumIRFloating_privatizable_ptr = {"attributor"
, "NumIRFloating_privatizable_ptr", ("Number of floating values known to be '"
"privatizable_ptr" "'")};; ++(NumIRFloating_privatizable_ptr
); }
;
7750 }
7751};
7752
7753struct AAPrivatizablePtrCallSiteArgument final
7754 : public AAPrivatizablePtrFloating {
7755 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7756 : AAPrivatizablePtrFloating(IRP, A) {}
7757
7758 /// See AbstractAttribute::initialize(...).
7759 void initialize(Attributor &A) override {
7760 if (getIRPosition().hasAttr(Attribute::ByVal))
7761 indicateOptimisticFixpoint();
7762 }
7763
7764 /// See AbstractAttribute::updateImpl(...).
7765 ChangeStatus updateImpl(Attributor &A) override {
7766 PrivatizableType = identifyPrivatizableType(A);
7767 if (!PrivatizableType)
7768 return ChangeStatus::UNCHANGED;
7769 if (!*PrivatizableType)
7770 return indicatePessimisticFixpoint();
7771
7772 const IRPosition &IRP = getIRPosition();
7773 auto &NoCaptureAA =
7774 A.getAAFor<AANoCapture>(*this, IRP, DepClassTy::REQUIRED);
7775 if (!NoCaptureAA.isAssumedNoCapture()) {
7776 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n"
; } } while (false)
;
7777 return indicatePessimisticFixpoint();
7778 }
7779
7780 auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, IRP, DepClassTy::REQUIRED);
7781 if (!NoAliasAA.isAssumedNoAlias()) {
7782 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] pointer might alias!\n"
; } } while (false)
;
7783 return indicatePessimisticFixpoint();
7784 }
7785
7786 bool IsKnown;
7787 if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
7788 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] pointer is written!\n"
; } } while (false)
;
7789 return indicatePessimisticFixpoint();
7790 }
7791
7792 return ChangeStatus::UNCHANGED;
7793 }
7794
7795 /// See AbstractAttribute::trackStatistics()
7796 void trackStatistics() const override {
7797 STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr){ static llvm::Statistic NumIRCSArguments_privatizable_ptr = {
"attributor", "NumIRCSArguments_privatizable_ptr", ("Number of "
"call site arguments" " marked '" "privatizable_ptr" "'")};;
++(NumIRCSArguments_privatizable_ptr); }
;
7798 }
7799};
7800
7801struct AAPrivatizablePtrCallSiteReturned final
7802 : public AAPrivatizablePtrFloating {
7803 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7804 : AAPrivatizablePtrFloating(IRP, A) {}
7805
7806 /// See AbstractAttribute::initialize(...).
7807 void initialize(Attributor &A) override {
7808 // TODO: We can privatize more than arguments.
7809 indicatePessimisticFixpoint();
7810 }
7811
7812 /// See AbstractAttribute::trackStatistics()
7813 void trackStatistics() const override {
7814 STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr){ static llvm::Statistic NumIRCSReturn_privatizable_ptr = {"attributor"
, "NumIRCSReturn_privatizable_ptr", ("Number of " "call site returns"
" marked '" "privatizable_ptr" "'")};; ++(NumIRCSReturn_privatizable_ptr
); }
;
7815 }
7816};
7817
7818struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
7819 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7820 : AAPrivatizablePtrFloating(IRP, A) {}
7821
7822 /// See AbstractAttribute::initialize(...).
7823 void initialize(Attributor &A) override {
7824 // TODO: We can privatize more than arguments.
7825 indicatePessimisticFixpoint();
7826 }
7827
7828 /// See AbstractAttribute::trackStatistics()
7829 void trackStatistics() const override {
7830 STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr){ static llvm::Statistic NumIRFunctionReturn_privatizable_ptr
= {"attributor", "NumIRFunctionReturn_privatizable_ptr", ("Number of "
"function returns" " marked '" "privatizable_ptr" "'")};; ++
(NumIRFunctionReturn_privatizable_ptr); }
;
7831 }
7832};
7833} // namespace
7834
7835/// -------------------- Memory Behavior Attributes ----------------------------
7836/// Includes read-none, read-only, and write-only.
7837/// ----------------------------------------------------------------------------
7838namespace {
7839struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
7840 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7841 : AAMemoryBehavior(IRP, A) {}
7842
7843 /// See AbstractAttribute::initialize(...).
7844 void initialize(Attributor &A) override {
7845 intersectAssumedBits(BEST_STATE);
7846 getKnownStateFromValue(getIRPosition(), getState());
7847 AAMemoryBehavior::initialize(A);
7848 }
7849
7850 /// Return the memory behavior information encoded in the IR for \p IRP.
7851 static void getKnownStateFromValue(const IRPosition &IRP,
7852 BitIntegerState &State,
7853 bool IgnoreSubsumingPositions = false) {
7854 SmallVector<Attribute, 2> Attrs;
7855 IRP.getAttrs(AttrKinds, Attrs, IgnoreSubsumingPositions);
7856 for (const Attribute &Attr : Attrs) {
7857 switch (Attr.getKindAsEnum()) {
7858 case Attribute::ReadNone:
7859 State.addKnownBits(NO_ACCESSES);
7860 break;
7861 case Attribute::ReadOnly:
7862 State.addKnownBits(NO_WRITES);
7863 break;
7864 case Attribute::WriteOnly:
7865 State.addKnownBits(NO_READS);
7866 break;
7867 default:
7868 llvm_unreachable("Unexpected attribute!")::llvm::llvm_unreachable_internal("Unexpected attribute!", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7868)
;
7869 }
7870 }
7871
7872 if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
7873 if (!I->mayReadFromMemory())
7874 State.addKnownBits(NO_READS);
7875 if (!I->mayWriteToMemory())
7876 State.addKnownBits(NO_WRITES);
7877 }
7878 }
7879
7880 /// See AbstractAttribute::getDeducedAttributes(...).
7881 void getDeducedAttributes(LLVMContext &Ctx,
7882 SmallVectorImpl<Attribute> &Attrs) const override {
7883 assert(Attrs.size() == 0)(static_cast <bool> (Attrs.size() == 0) ? void (0) : __assert_fail
("Attrs.size() == 0", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7883, __extension__ __PRETTY_FUNCTION__))
;
7884 if (isAssumedReadNone())
7885 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7886 else if (isAssumedReadOnly())
7887 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7888 else if (isAssumedWriteOnly())
7889 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7890 assert(Attrs.size() <= 1)(static_cast <bool> (Attrs.size() <= 1) ? void (0) :
__assert_fail ("Attrs.size() <= 1", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7890, __extension__ __PRETTY_FUNCTION__))
;
7891 }
7892
7893 /// See AbstractAttribute::manifest(...).
7894 ChangeStatus manifest(Attributor &A) override {
7895 if (hasAttr(Attribute::ReadNone, /* IgnoreSubsumingPositions */ true))
7896 return ChangeStatus::UNCHANGED;
7897
7898 const IRPosition &IRP = getIRPosition();
7899
7900 // Check if we would improve the existing attributes first.
7901 SmallVector<Attribute, 4> DeducedAttrs;
7902 getDeducedAttributes(IRP.getAnchorValue().getContext(), DeducedAttrs);
7903 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
7904 return IRP.hasAttr(Attr.getKindAsEnum(),
7905 /* IgnoreSubsumingPositions */ true);
7906 }))
7907 return ChangeStatus::UNCHANGED;
7908
7909 // Clear existing attributes.
7910 IRP.removeAttrs(AttrKinds);
7911
7912 // Use the generic manifest method.
7913 return IRAttribute::manifest(A);
7914 }
7915
7916 /// See AbstractState::getAsStr().
7917 const std::string getAsStr() const override {
7918 if (isAssumedReadNone())
7919 return "readnone";
7920 if (isAssumedReadOnly())
7921 return "readonly";
7922 if (isAssumedWriteOnly())
7923 return "writeonly";
7924 return "may-read/write";
7925 }
7926
7927 /// The set of IR attributes AAMemoryBehavior deals with.
7928 static const Attribute::AttrKind AttrKinds[3];
7929};
7930
7931const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7932 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7933
7934/// Memory behavior attribute for a floating value.
7935struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7936 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7937 : AAMemoryBehaviorImpl(IRP, A) {}
7938
7939 /// See AbstractAttribute::updateImpl(...).
7940 ChangeStatus updateImpl(Attributor &A) override;
7941
7942 /// See AbstractAttribute::trackStatistics()
7943 void trackStatistics() const override {
7944 if (isAssumedReadNone())
7945 STATS_DECLTRACK_FLOATING_ATTR(readnone){ static llvm::Statistic NumIRFloating_readnone = {"attributor"
, "NumIRFloating_readnone", ("Number of floating values known to be '"
"readnone" "'")};; ++(NumIRFloating_readnone); }
7946 else if (isAssumedReadOnly())
7947 STATS_DECLTRACK_FLOATING_ATTR(readonly){ static llvm::Statistic NumIRFloating_readonly = {"attributor"
, "NumIRFloating_readonly", ("Number of floating values known to be '"
"readonly" "'")};; ++(NumIRFloating_readonly); }
7948 else if (isAssumedWriteOnly())
7949 STATS_DECLTRACK_FLOATING_ATTR(writeonly){ static llvm::Statistic NumIRFloating_writeonly = {"attributor"
, "NumIRFloating_writeonly", ("Number of floating values known to be '"
"writeonly" "'")};; ++(NumIRFloating_writeonly); }
7950 }
7951
7952private:
7953 /// Return true if users of \p UserI might access the underlying
7954 /// variable/location described by \p U and should therefore be analyzed.
7955 bool followUsersOfUseIn(Attributor &A, const Use &U,
7956 const Instruction *UserI);
7957
7958 /// Update the state according to the effect of use \p U in \p UserI.
7959 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
7960};
7961
7962/// Memory behavior attribute for function argument.
7963struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
7964 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
7965 : AAMemoryBehaviorFloating(IRP, A) {}
7966
7967 /// See AbstractAttribute::initialize(...).
7968 void initialize(Attributor &A) override {
7969 intersectAssumedBits(BEST_STATE);
7970 const IRPosition &IRP = getIRPosition();
7971 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
7972 // can query it when we use has/getAttr. That would allow us to reuse the
7973 // initialize of the base class here.
7974 bool HasByVal =
7975 IRP.hasAttr({Attribute::ByVal}, /* IgnoreSubsumingPositions */ true);
7976 getKnownStateFromValue(IRP, getState(),
7977 /* IgnoreSubsumingPositions */ HasByVal);
7978
7979 // Initialize the use vector with all direct uses of the associated value.
7980 Argument *Arg = getAssociatedArgument();
7981 if (!Arg || !A.isFunctionIPOAmendable(*(Arg->getParent())))
7982 indicatePessimisticFixpoint();
7983 }
7984
7985 ChangeStatus manifest(Attributor &A) override {
7986 // TODO: Pointer arguments are not supported on vectors of pointers yet.
7987 if (!getAssociatedValue().getType()->isPointerTy())
7988 return ChangeStatus::UNCHANGED;
7989
7990 // TODO: From readattrs.ll: "inalloca parameters are always
7991 // considered written"
7992 if (hasAttr({Attribute::InAlloca, Attribute::Preallocated})) {
7993 removeKnownBits(NO_WRITES);
7994 removeAssumedBits(NO_WRITES);
7995 }
7996 return AAMemoryBehaviorFloating::manifest(A);
7997 }
7998
7999 /// See AbstractAttribute::trackStatistics()
8000 void trackStatistics() const override {
8001 if (isAssumedReadNone())
8002 STATS_DECLTRACK_ARG_ATTR(readnone){ static llvm::Statistic NumIRArguments_readnone = {"attributor"
, "NumIRArguments_readnone", ("Number of " "arguments" " marked '"
"readnone" "'")};; ++(NumIRArguments_readnone); }
8003 else if (isAssumedReadOnly())
8004 STATS_DECLTRACK_ARG_ATTR(readonly){ static llvm::Statistic NumIRArguments_readonly = {"attributor"
, "NumIRArguments_readonly", ("Number of " "arguments" " marked '"
"readonly" "'")};; ++(NumIRArguments_readonly); }
8005 else if (isAssumedWriteOnly())
8006 STATS_DECLTRACK_ARG_ATTR(writeonly){ static llvm::Statistic NumIRArguments_writeonly = {"attributor"
, "NumIRArguments_writeonly", ("Number of " "arguments" " marked '"
"writeonly" "'")};; ++(NumIRArguments_writeonly); }
8007 }
8008};
8009
8010struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8011 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
8012 : AAMemoryBehaviorArgument(IRP, A) {}
8013
8014 /// See AbstractAttribute::initialize(...).
8015 void initialize(Attributor &A) override {
8016 // If we don't have an associated attribute this is either a variadic call
8017 // or an indirect call, either way, nothing to do here.
8018 Argument *Arg = getAssociatedArgument();
8019 if (!Arg) {
8020 indicatePessimisticFixpoint();
8021 return;
8022 }
8023 if (Arg->hasByValAttr()) {
8024 addKnownBits(NO_WRITES);
8025 removeKnownBits(NO_READS);
8026 removeAssumedBits(NO_READS);
8027 }
8028 AAMemoryBehaviorArgument::initialize(A);
8029 if (getAssociatedFunction()->isDeclaration())
8030 indicatePessimisticFixpoint();
8031 }
8032
8033 /// See AbstractAttribute::updateImpl(...).
8034 ChangeStatus updateImpl(Attributor &A) override {
8035 // TODO: Once we have call site specific value information we can provide
8036 // call site specific liveness liveness information and then it makes
8037 // sense to specialize attributes for call sites arguments instead of
8038 // redirecting requests to the callee argument.
8039 Argument *Arg = getAssociatedArgument();
8040 const IRPosition &ArgPos = IRPosition::argument(*Arg);
8041 auto &ArgAA =
8042 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
8043 return clampStateAndIndicateChange(getState(), ArgAA.getState());
8044 }
8045
8046 /// See AbstractAttribute::trackStatistics()
8047 void trackStatistics() const override {
8048 if (isAssumedReadNone())
8049 STATS_DECLTRACK_CSARG_ATTR(readnone){ static llvm::Statistic NumIRCSArguments_readnone = {"attributor"
, "NumIRCSArguments_readnone", ("Number of " "call site arguments"
" marked '" "readnone" "'")};; ++(NumIRCSArguments_readnone)
; }
8050 else if (isAssumedReadOnly())
8051 STATS_DECLTRACK_CSARG_ATTR(readonly){ static llvm::Statistic NumIRCSArguments_readonly = {"attributor"
, "NumIRCSArguments_readonly", ("Number of " "call site arguments"
" marked '" "readonly" "'")};; ++(NumIRCSArguments_readonly)
; }
8052 else if (isAssumedWriteOnly())
8053 STATS_DECLTRACK_CSARG_ATTR(writeonly){ static llvm::Statistic NumIRCSArguments_writeonly = {"attributor"
, "NumIRCSArguments_writeonly", ("Number of " "call site arguments"
" marked '" "writeonly" "'")};; ++(NumIRCSArguments_writeonly
); }
8054 }
8055};
8056
8057/// Memory behavior attribute for a call site return position.
8058struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8059 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
8060 : AAMemoryBehaviorFloating(IRP, A) {}
8061
8062 /// See AbstractAttribute::initialize(...).
8063 void initialize(Attributor &A) override {
8064 AAMemoryBehaviorImpl::initialize(A);
8065 Function *F = getAssociatedFunction();
8066 if (!F || F->isDeclaration())
8067 indicatePessimisticFixpoint();
8068 }
8069
8070 /// See AbstractAttribute::manifest(...).
8071 ChangeStatus manifest(Attributor &A) override {
8072 // We do not annotate returned values.
8073 return ChangeStatus::UNCHANGED;
8074 }
8075
8076 /// See AbstractAttribute::trackStatistics()
8077 void trackStatistics() const override {}
8078};
8079
8080/// An AA to represent the memory behavior function attributes.
8081struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
8082 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
8083 : AAMemoryBehaviorImpl(IRP, A) {}
8084
8085 /// See AbstractAttribute::updateImpl(Attributor &A).
8086 ChangeStatus updateImpl(Attributor &A) override;
8087
8088 /// See AbstractAttribute::manifest(...).
8089 ChangeStatus manifest(Attributor &A) override {
8090 // TODO: It would be better to merge this with AAMemoryLocation, so that
8091 // we could determine read/write per location. This would also have the
8092 // benefit of only one place trying to manifest the memory attribute.
8093 Function &F = cast<Function>(getAnchorValue());
8094 MemoryEffects ME = MemoryEffects::unknown();
8095 if (isAssumedReadNone())
8096 ME = MemoryEffects::none();
8097 else if (isAssumedReadOnly())
8098 ME = MemoryEffects::readOnly();
8099 else if (isAssumedWriteOnly())
8100 ME = MemoryEffects::writeOnly();
8101
8102 // Intersect with existing memory attribute, as we currently deduce the
8103 // location and modref portion separately.
8104 MemoryEffects ExistingME = F.getMemoryEffects();
8105 ME &= ExistingME;
8106 if (ME == ExistingME)
8107 return ChangeStatus::UNCHANGED;
8108
8109 return IRAttributeManifest::manifestAttrs(
8110 A, getIRPosition(), Attribute::getWithMemoryEffects(F.getContext(), ME),
8111 /*ForceReplace*/ true);
8112 }
8113
8114 /// See AbstractAttribute::trackStatistics()
8115 void trackStatistics() const override {
8116 if (isAssumedReadNone())
8117 STATS_DECLTRACK_FN_ATTR(readnone){ static llvm::Statistic NumIRFunction_readnone = {"attributor"
, "NumIRFunction_readnone", ("Number of " "functions" " marked '"
"readnone" "'")};; ++(NumIRFunction_readnone); }
8118 else if (isAssumedReadOnly())
8119 STATS_DECLTRACK_FN_ATTR(readonly){ static llvm::Statistic NumIRFunction_readonly = {"attributor"
, "NumIRFunction_readonly", ("Number of " "functions" " marked '"
"readonly" "'")};; ++(NumIRFunction_readonly); }
8120 else if (isAssumedWriteOnly())
8121 STATS_DECLTRACK_FN_ATTR(writeonly){ static llvm::Statistic NumIRFunction_writeonly = {"attributor"
, "NumIRFunction_writeonly", ("Number of " "functions" " marked '"
"writeonly" "'")};; ++(NumIRFunction_writeonly); }
8122 }
8123};
8124
8125/// AAMemoryBehavior attribute for call sites.
8126struct AAMemoryBehaviorCallSite final : AAMemoryBehaviorImpl {
8127 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
8128 : AAMemoryBehaviorImpl(IRP, A) {}
8129
8130 /// See AbstractAttribute::initialize(...).
8131 void initialize(Attributor &A) override {
8132 AAMemoryBehaviorImpl::initialize(A);
8133 Function *F = getAssociatedFunction();
8134 if (!F || F->isDeclaration())
8135 indicatePessimisticFixpoint();
8136 }
8137
8138 /// See AbstractAttribute::updateImpl(...).
8139 ChangeStatus updateImpl(Attributor &A) override {
8140 // TODO: Once we have call site specific value information we can provide
8141 // call site specific liveness liveness information and then it makes
8142 // sense to specialize attributes for call sites arguments instead of
8143 // redirecting requests to the callee argument.
8144 Function *F = getAssociatedFunction();
8145 const IRPosition &FnPos = IRPosition::function(*F);
8146 auto &FnAA =
8147 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::REQUIRED);
8148 return clampStateAndIndicateChange(getState(), FnAA.getState());
8149 }
8150
8151 /// See AbstractAttribute::manifest(...).
8152 ChangeStatus manifest(Attributor &A) override {
8153 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8154 CallBase &CB = cast<CallBase>(getAnchorValue());
8155 MemoryEffects ME = MemoryEffects::unknown();
8156 if (isAssumedReadNone())
8157 ME = MemoryEffects::none();
8158 else if (isAssumedReadOnly())
8159 ME = MemoryEffects::readOnly();
8160 else if (isAssumedWriteOnly())
8161 ME = MemoryEffects::writeOnly();
8162
8163 // Intersect with existing memory attribute, as we currently deduce the
8164 // location and modref portion separately.
8165 MemoryEffects ExistingME = CB.getMemoryEffects();
8166 ME &= ExistingME;
8167 if (ME == ExistingME)
8168 return ChangeStatus::UNCHANGED;
8169
8170 return IRAttributeManifest::manifestAttrs(
8171 A, getIRPosition(),
8172 Attribute::getWithMemoryEffects(CB.getContext(), ME),
8173 /*ForceReplace*/ true);
8174 }
8175
8176 /// See AbstractAttribute::trackStatistics()
8177 void trackStatistics() const override {
8178 if (isAssumedReadNone())
8179 STATS_DECLTRACK_CS_ATTR(readnone){ static llvm::Statistic NumIRCS_readnone = {"attributor", "NumIRCS_readnone"
, ("Number of " "call site" " marked '" "readnone" "'")};; ++
(NumIRCS_readnone); }
8180 else if (isAssumedReadOnly())
8181 STATS_DECLTRACK_CS_ATTR(readonly){ static llvm::Statistic NumIRCS_readonly = {"attributor", "NumIRCS_readonly"
, ("Number of " "call site" " marked '" "readonly" "'")};; ++
(NumIRCS_readonly); }
8182 else if (isAssumedWriteOnly())
8183 STATS_DECLTRACK_CS_ATTR(writeonly){ static llvm::Statistic NumIRCS_writeonly = {"attributor", "NumIRCS_writeonly"
, ("Number of " "call site" " marked '" "writeonly" "'")};; ++
(NumIRCS_writeonly); }
8184 }
8185};
8186
8187ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8188
8189 // The current assumed state used to determine a change.
8190 auto AssumedState = getAssumed();
8191
8192 auto CheckRWInst = [&](Instruction &I) {
8193 // If the instruction has an own memory behavior state, use it to restrict
8194 // the local state. No further analysis is required as the other memory
8195 // state is as optimistic as it gets.
8196 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8197 const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8198 *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);
8199 intersectAssumedBits(MemBehaviorAA.getAssumed());
8200 return !isAtFixpoint();
8201 }
8202
8203 // Remove access kind modifiers if necessary.
8204 if (I.mayReadFromMemory())
8205 removeAssumedBits(NO_READS);
8206 if (I.mayWriteToMemory())
8207 removeAssumedBits(NO_WRITES);
8208 return !isAtFixpoint();
8209 };
8210
8211 bool UsedAssumedInformation = false;
8212 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8213 UsedAssumedInformation))
8214 return indicatePessimisticFixpoint();
8215
8216 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8217 : ChangeStatus::UNCHANGED;
8218}
8219
8220ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8221
8222 const IRPosition &IRP = getIRPosition();
8223 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8224 AAMemoryBehavior::StateType &S = getState();
8225
8226 // First, check the function scope. We take the known information and we avoid
8227 // work if the assumed information implies the current assumed information for
8228 // this attribute. This is a valid for all but byval arguments.
8229 Argument *Arg = IRP.getAssociatedArgument();
8230 AAMemoryBehavior::base_t FnMemAssumedState =
8231 AAMemoryBehavior::StateType::getWorstState();
8232 if (!Arg || !Arg->hasByValAttr()) {
8233 const auto &FnMemAA =
8234 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8235 FnMemAssumedState = FnMemAA.getAssumed();
8236 S.addKnownBits(FnMemAA.getKnown());
8237 if ((S.getAssumed() & FnMemAA.getAssumed()) == S.getAssumed())
8238 return ChangeStatus::UNCHANGED;
8239 }
8240
8241 // The current assumed state used to determine a change.
8242 auto AssumedState = S.getAssumed();
8243
8244 // Make sure the value is not captured (except through "return"), if
8245 // it is, any information derived would be irrelevant anyway as we cannot
8246 // check the potential aliases introduced by the capture. However, no need
8247 // to fall back to anythign less optimistic than the function state.
8248 const auto &ArgNoCaptureAA =
8249 A.getAAFor<AANoCapture>(*this, IRP, DepClassTy::OPTIONAL);
8250 if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
8251 S.intersectAssumedBits(FnMemAssumedState);
8252 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8253 : ChangeStatus::UNCHANGED;
8254 }
8255
8256 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8257 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8258 Instruction *UserI = cast<Instruction>(U.getUser());
8259 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryBehavior] Use: " <<
*U << " in " << *UserI << " \n"; } } while
(false)
8260 << " \n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryBehavior] Use: " <<
*U << " in " << *UserI << " \n"; } } while
(false)
;
8261
8262 // Droppable users, e.g., llvm::assume does not actually perform any action.
8263 if (UserI->isDroppable())
8264 return true;
8265
8266 // Check if the users of UserI should also be visited.
8267 Follow = followUsersOfUseIn(A, U, UserI);
8268
8269 // If UserI might touch memory we analyze the use in detail.
8270 if (UserI->mayReadOrWriteMemory())
8271 analyzeUseIn(A, U, UserI);
8272
8273 return !isAtFixpoint();
8274 };
8275
8276 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8277 return indicatePessimisticFixpoint();
8278
8279 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8280 : ChangeStatus::UNCHANGED;
8281}
8282
8283bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8284 const Instruction *UserI) {
8285 // The loaded value is unrelated to the pointer argument, no need to
8286 // follow the users of the load.
8287 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8288 return false;
8289
8290 // By default we follow all uses assuming UserI might leak information on U,
8291 // we have special handling for call sites operands though.
8292 const auto *CB = dyn_cast<CallBase>(UserI);
8293 if (!CB || !CB->isArgOperand(&U))
8294 return true;
8295
8296 // If the use is a call argument known not to be captured, the users of
8297 // the call do not need to be visited because they have to be unrelated to
8298 // the input. Note that this check is not trivial even though we disallow
8299 // general capturing of the underlying argument. The reason is that the
8300 // call might the argument "through return", which we allow and for which we
8301 // need to check call users.
8302 if (U.get()->getType()->isPointerTy()) {
8303 unsigned ArgNo = CB->getArgOperandNo(&U);
8304 const auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(
8305 *this, IRPosition::callsite_argument(*CB, ArgNo), DepClassTy::OPTIONAL);
8306 return !ArgNoCaptureAA.isAssumedNoCapture();
8307 }
8308
8309 return true;
8310}
8311
8312void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8313 const Instruction *UserI) {
8314 assert(UserI->mayReadOrWriteMemory())(static_cast <bool> (UserI->mayReadOrWriteMemory()) ?
void (0) : __assert_fail ("UserI->mayReadOrWriteMemory()"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 8314, __extension__
__PRETTY_FUNCTION__))
;
8315
8316 switch (UserI->getOpcode()) {
8317 default:
8318 // TODO: Handle all atomics and other side-effect operations we know of.
8319 break;
8320 case Instruction::Load:
8321 // Loads cause the NO_READS property to disappear.
8322 removeAssumedBits(NO_READS);
8323 return;
8324
8325 case Instruction::Store:
8326 // Stores cause the NO_WRITES property to disappear if the use is the
8327 // pointer operand. Note that while capturing was taken care of somewhere
8328 // else we need to deal with stores of the value that is not looked through.
8329 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8330 removeAssumedBits(NO_WRITES);
8331 else
8332 indicatePessimisticFixpoint();
8333 return;
8334
8335 case Instruction::Call:
8336 case Instruction::CallBr:
8337 case Instruction::Invoke: {
8338 // For call sites we look at the argument memory behavior attribute (this
8339 // could be recursive!) in order to restrict our own state.
8340 const auto *CB = cast<CallBase>(UserI);
8341
8342 // Give up on operand bundles.
8343 if (CB->isBundleOperand(&U)) {
8344 indicatePessimisticFixpoint();
8345 return;
8346 }
8347
8348 // Calling a function does read the function pointer, maybe write it if the
8349 // function is self-modifying.
8350 if (CB->isCallee(&U)) {
8351 removeAssumedBits(NO_READS);
8352 break;
8353 }
8354
8355 // Adjust the possible access behavior based on the information on the
8356 // argument.
8357 IRPosition Pos;
8358 if (U.get()->getType()->isPointerTy())
8359 Pos = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
8360 else
8361 Pos = IRPosition::callsite_function(*CB);
8362 const auto &MemBehaviorAA =
8363 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8364 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8365 // and at least "known".
8366 intersectAssumedBits(MemBehaviorAA.getAssumed());
8367 return;
8368 }
8369 };
8370
8371 // Generally, look at the "may-properties" and adjust the assumed state if we
8372 // did not trigger special handling before.
8373 if (UserI->mayReadFromMemory())
8374 removeAssumedBits(NO_READS);
8375 if (UserI->mayWriteToMemory())
8376 removeAssumedBits(NO_WRITES);
8377}
8378} // namespace
8379
8380/// -------------------- Memory Locations Attributes ---------------------------
8381/// Includes read-none, argmemonly, inaccessiblememonly,
8382/// inaccessiblememorargmemonly
8383/// ----------------------------------------------------------------------------
8384
8385std::string AAMemoryLocation::getMemoryLocationsAsStr(
8386 AAMemoryLocation::MemoryLocationsKind MLK) {
8387 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8388 return "all memory";
8389 if (MLK == AAMemoryLocation::NO_LOCATIONS)
8390 return "no memory";
8391 std::string S = "memory:";
8392 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8393 S += "stack,";
8394 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8395 S += "constant,";
8396 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_INTERNAL_MEM))
8397 S += "internal global,";
8398 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_EXTERNAL_MEM))
8399 S += "external global,";
8400 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8401 S += "argument,";
8402 if (0 == (MLK & AAMemoryLocation::NO_INACCESSIBLE_MEM))
8403 S += "inaccessible,";
8404 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8405 S += "malloced,";
8406 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8407 S += "unknown,";
8408 S.pop_back();
8409 return S;
8410}
8411
8412namespace {
8413struct AAMemoryLocationImpl : public AAMemoryLocation {
8414
8415 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8416 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8417 AccessKind2Accesses.fill(nullptr);
8418 }
8419
8420 ~AAMemoryLocationImpl() {
8421 // The AccessSets are allocated via a BumpPtrAllocator, we call
8422 // the destructor manually.
8423 for (AccessSet *AS : AccessKind2Accesses)
8424 if (AS)
8425 AS->~AccessSet();
8426 }
8427
8428 /// See AbstractAttribute::initialize(...).
8429 void initialize(Attributor &A) override {
8430 intersectAssumedBits(BEST_STATE);
8431 getKnownStateFromValue(A, getIRPosition(), getState());
8432 AAMemoryLocation::initialize(A);
8433 }
8434
8435 /// Return the memory behavior information encoded in the IR for \p IRP.
8436 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8437 BitIntegerState &State,
8438 bool IgnoreSubsumingPositions = false) {
8439 // For internal functions we ignore `argmemonly` and
8440 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8441 // constant propagation. It is unclear if this is the best way but it is
8442 // unlikely this will cause real performance problems. If we are deriving
8443 // attributes for the anchor function we even remove the attribute in
8444 // addition to ignoring it.
8445 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8446 // MemoryEffects::Other as a possible location.
8447 bool UseArgMemOnly = true;
8448 Function *AnchorFn = IRP.getAnchorScope();
8449 if (AnchorFn && A.isRunOn(*AnchorFn))
8450 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8451
8452 SmallVector<Attribute, 2> Attrs;
8453 IRP.getAttrs({Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8454 for (const Attribute &Attr : Attrs) {
8455 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8456 MemoryEffects ME = Attr.getMemoryEffects();
8457 if (ME.doesNotAccessMemory()) {
8458 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8459 continue;
8460 }
8461 if (ME.onlyAccessesInaccessibleMem()) {
8462 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8463 continue;
8464 }
8465 if (ME.onlyAccessesArgPointees()) {
8466 if (UseArgMemOnly)
8467 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8468 else {
8469 // Remove location information, only keep read/write info.
8470 ME = MemoryEffects(ME.getModRef());
8471 IRAttributeManifest::manifestAttrs(
8472 A, IRP,
8473 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(),
8474 ME),
8475 /*ForceReplace*/ true);
8476 }
8477 continue;
8478 }
8479 if (ME.onlyAccessesInaccessibleOrArgMem()) {
8480 if (UseArgMemOnly)
8481 State.addKnownBits(inverseLocation(
8482 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8483 else {
8484 // Remove location information, only keep read/write info.
8485 ME = MemoryEffects(ME.getModRef());
8486 IRAttributeManifest::manifestAttrs(
8487 A, IRP,
8488 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(),
8489 ME),
8490 /*ForceReplace*/ true);
8491 }
8492 continue;
8493 }
8494 }
8495 }
8496
8497 /// See AbstractAttribute::getDeducedAttributes(...).
8498 void getDeducedAttributes(LLVMContext &Ctx,
8499 SmallVectorImpl<Attribute> &Attrs) const override {
8500 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8501 assert(Attrs.size() == 0)(static_cast <bool> (Attrs.size() == 0) ? void (0) : __assert_fail
("Attrs.size() == 0", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 8501, __extension__ __PRETTY_FUNCTION__))
;
8502 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8503 if (isAssumedReadNone())
8504 Attrs.push_back(
8505 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8506 else if (isAssumedInaccessibleMemOnly())
8507 Attrs.push_back(Attribute::getWithMemoryEffects(
8508 Ctx, MemoryEffects::inaccessibleMemOnly()));
8509 else if (isAssumedArgMemOnly())
8510 Attrs.push_back(
8511 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8512 else if (isAssumedInaccessibleOrArgMemOnly())
8513 Attrs.push_back(Attribute::getWithMemoryEffects(
8514 Ctx, MemoryEffects::inaccessibleOrArgMemOnly()));
8515 }
8516 assert(Attrs.size() <= 1)(static_cast <bool> (Attrs.size() <= 1) ? void (0) :
__assert_fail ("Attrs.size() <= 1", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 8516, __extension__ __PRETTY_FUNCTION__))
;
8517 }
8518
8519 /// See AbstractAttribute::manifest(...).
8520 ChangeStatus manifest(Attributor &A) override {
8521 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8522 // provide per-location modref information here.
8523 const IRPosition &IRP = getIRPosition();
8524
8525 SmallVector<Attribute, 1> DeducedAttrs;
8526 getDeducedAttributes(IRP.getAnchorValue().getContext(), DeducedAttrs);
8527 if (DeducedAttrs.size() != 1)
8528 return ChangeStatus::UNCHANGED;
8529 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8530
8531 // Intersect with existing memory attribute, as we currently deduce the
8532 // location and modref portion separately.
8533 SmallVector<Attribute, 1> ExistingAttrs;
8534 IRP.getAttrs({Attribute::Memory}, ExistingAttrs,
8535 /* IgnoreSubsumingPositions */ true);
8536 if (ExistingAttrs.size() == 1) {
8537 MemoryEffects ExistingME = ExistingAttrs[0].getMemoryEffects();
8538 ME &= ExistingME;
8539 if (ME == ExistingME)
8540 return ChangeStatus::UNCHANGED;
8541 }
8542
8543 return IRAttributeManifest::manifestAttrs(
8544 A, IRP,
8545 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(), ME),
8546 /*ForceReplace*/ true);
8547 }
8548
8549 /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).
8550 bool checkForAllAccessesToMemoryKind(
8551 function_ref<bool(const Instruction *, const Value *, AccessKind,
8552 MemoryLocationsKind)>
8553 Pred,
8554 MemoryLocationsKind RequestedMLK) const override {
8555 if (!isValidState())
8556 return false;
8557
8558 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8559 if (AssumedMLK == NO_LOCATIONS)
8560 return true;
8561
8562 unsigned Idx = 0;
8563 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8564 CurMLK *= 2, ++Idx) {
8565 if (CurMLK & RequestedMLK)
8566 continue;
8567
8568 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8569 for (const AccessInfo &AI : *Accesses)
8570 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8571 return false;
8572 }
8573
8574 return true;
8575 }
8576
8577 ChangeStatus indicatePessimisticFixpoint() override {
8578 // If we give up and indicate a pessimistic fixpoint this instruction will
8579 // become an access for all potential access kinds:
8580 // TODO: Add pointers for argmemonly and globals to improve the results of
8581 // checkForAllAccessesToMemoryKind.
8582 bool Changed = false;
8583 MemoryLocationsKind KnownMLK = getKnown();
8584 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8585 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8586 if (!(CurMLK & KnownMLK))
8587 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8588 getAccessKindFromInst(I));
8589 return AAMemoryLocation::indicatePessimisticFixpoint();
8590 }
8591
8592protected:
8593 /// Helper struct to tie together an instruction that has a read or write
8594 /// effect with the pointer it accesses (if any).
8595 struct AccessInfo {
8596
8597 /// The instruction that caused the access.
8598 const Instruction *I;
8599
8600 /// The base pointer that is accessed, or null if unknown.
8601 const Value *Ptr;
8602
8603 /// The kind of access (read/write/read+write).
8604 AccessKind Kind;
8605
8606 bool operator==(const AccessInfo &RHS) const {
8607 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8608 }
8609 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8610 if (LHS.I != RHS.I)
8611 return LHS.I < RHS.I;
8612 if (LHS.Ptr != RHS.Ptr)
8613 return LHS.Ptr < RHS.Ptr;
8614 if (LHS.Kind != RHS.Kind)
8615 return LHS.Kind < RHS.Kind;
8616 return false;
8617 }
8618 };
8619
8620 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8621 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8622 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8623 std::array<AccessSet *, llvm::CTLog2<VALID_STATE>()> AccessKind2Accesses;
8624
8625 /// Categorize the pointer arguments of CB that might access memory in
8626 /// AccessedLoc and update the state and access map accordingly.
8627 void
8628 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8629 AAMemoryLocation::StateType &AccessedLocs,
8630 bool &Changed);
8631
8632 /// Return the kind(s) of location that may be accessed by \p V.
8633 AAMemoryLocation::MemoryLocationsKind
8634 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8635
8636 /// Return the access kind as determined by \p I.
8637 AccessKind getAccessKindFromInst(const Instruction *I) {
8638 AccessKind AK = READ_WRITE;
8639 if (I) {
8640 AK = I->mayReadFromMemory() ? READ : NONE;
8641 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8642 }
8643 return AK;
8644 }
8645
8646 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8647 /// an access of kind \p AK to a \p MLK memory location with the access
8648 /// pointer \p Ptr.
8649 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8650 MemoryLocationsKind MLK, const Instruction *I,
8651 const Value *Ptr, bool &Changed,
8652 AccessKind AK = READ_WRITE) {
8653
8654 assert(isPowerOf2_32(MLK) && "Expected a single location set!")(static_cast <bool> (isPowerOf2_32(MLK) && "Expected a single location set!"
) ? void (0) : __assert_fail ("isPowerOf2_32(MLK) && \"Expected a single location set!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 8654, __extension__
__PRETTY_FUNCTION__))
;
8655 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8656 if (!Accesses)
8657 Accesses = new (Allocator) AccessSet();
8658 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8659 State.removeAssumedBits(MLK);
8660 }
8661
8662 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8663 /// arguments, and update the state and access map accordingly.
8664 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8665 AAMemoryLocation::StateType &State, bool &Changed);
8666
8667 /// Used to allocate access sets.
8668 BumpPtrAllocator &Allocator;
8669};
8670
8671void AAMemoryLocationImpl::categorizePtrValue(
8672 Attributor &A, const Instruction &I, const Value &Ptr,
8673 AAMemoryLocation::StateType &State, bool &Changed) {
8674 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
<< Ptr << " [" << getMemoryLocationsAsStr(
State.getAssumed()) << "]\n"; } } while (false)
8675 << Ptr << " ["do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
<< Ptr << " [" << getMemoryLocationsAsStr(
State.getAssumed()) << "]\n"; } } while (false)
8676 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
<< Ptr << " [" << getMemoryLocationsAsStr(
State.getAssumed()) << "]\n"; } } while (false)
;
8677
8678 auto Pred = [&](Value &Obj) {
8679 // TODO: recognize the TBAA used for constant accesses.
8680 MemoryLocationsKind MLK = NO_LOCATIONS;
8681 if (isa<UndefValue>(&Obj))
8682 return true;
8683 if (isa<Argument>(&Obj)) {
8684 // TODO: For now we do not treat byval arguments as local copies performed
8685 // on the call edge, though, we should. To make that happen we need to
8686 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8687 // would also allow us to mark functions only accessing byval arguments as
8688 // readnone again, arguably their accesses have no effect outside of the
8689 // function, like accesses to allocas.
8690 MLK = NO_ARGUMENT_MEM;
8691 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8692 // Reading constant memory is not treated as a read "effect" by the
8693 // function attr pass so we won't neither. Constants defined by TBAA are
8694 // similar. (We know we do not write it because it is constant.)
8695 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8696 if (GVar->isConstant())
8697 return true;
8698
8699 if (GV->hasLocalLinkage())
8700 MLK = NO_GLOBAL_INTERNAL_MEM;
8701 else
8702 MLK = NO_GLOBAL_EXTERNAL_MEM;
8703 } else if (isa<ConstantPointerNull>(&Obj) &&
8704 !NullPointerIsDefined(getAssociatedFunction(),
8705 Ptr.getType()->getPointerAddressSpace())) {
8706 return true;
8707 } else if (isa<AllocaInst>(&Obj)) {
8708 MLK = NO_LOCAL_MEM;
8709 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8710 const auto &NoAliasAA = A.getAAFor<AANoAlias>(
8711 *this, IRPosition::callsite_returned(*CB), DepClassTy::OPTIONAL);
8712 if (NoAliasAA.isAssumedNoAlias())
8713 MLK = NO_MALLOCED_MEM;
8714 else
8715 MLK = NO_UNKOWN_MEM;
8716 } else {
8717 MLK = NO_UNKOWN_MEM;
8718 }
8719
8720 assert(MLK != NO_LOCATIONS && "No location specified!")(static_cast <bool> (MLK != NO_LOCATIONS && "No location specified!"
) ? void (0) : __assert_fail ("MLK != NO_LOCATIONS && \"No location specified!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 8720, __extension__
__PRETTY_FUNCTION__))
;
8721 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
<< Obj << " -> " << getMemoryLocationsAsStr
(MLK) << "\n"; } } while (false)
8722 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
<< Obj << " -> " << getMemoryLocationsAsStr
(MLK) << "\n"; } } while (false)
;
8723 updateStateAndAccessesMap(getState(), MLK, &I, &Obj, Changed,
8724 getAccessKindFromInst(&I));
8725
8726 return true;
8727 };
8728
8729 const auto &AA = A.getAAFor<AAUnderlyingObjects>(
8730 *this, IRPosition::value(Ptr), DepClassTy::OPTIONAL);
8731 if (!AA.forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8732 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"
; } } while (false)
8733 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"
; } } while (false)
;
8734 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8735 getAccessKindFromInst(&I));
8736 return;
8737 }
8738
8739 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
<< getMemoryLocationsAsStr(State.getAssumed()) <<
"\n"; } } while (false)
8740 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
<< getMemoryLocationsAsStr(State.getAssumed()) <<
"\n"; } } while (false)
8741 << getMemoryLocationsAsStr(State.getAssumed()) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
<< getMemoryLocationsAsStr(State.getAssumed()) <<
"\n"; } } while (false)
;
8742}
8743
8744void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8745 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8746 bool &Changed) {
8747 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8748
8749 // Skip non-pointer arguments.
8750 const Value *ArgOp = CB.getArgOperand(ArgNo);
8751 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8752 continue;
8753
8754 // Skip readnone arguments.
8755 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8756 const auto &ArgOpMemLocationAA =
8757 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8758
8759 if (ArgOpMemLocationAA.isAssumedReadNone())
8760 continue;
8761
8762 // Categorize potentially accessed pointer arguments as if there was an
8763 // access instruction with them as pointer.
8764 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8765 }
8766}
8767
8768AAMemoryLocation::MemoryLocationsKind
8769AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8770 bool &Changed) {
8771 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
<< I << "\n"; } } while (false)
8772 << I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
<< I << "\n"; } } while (false)
;
8773
8774 AAMemoryLocation::StateType AccessedLocs;
8775 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8776
8777 if (auto *CB = dyn_cast<CallBase>(&I)) {
8778
8779 // First check if we assume any memory is access is visible.
8780 const auto &CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8781 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
8782 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << Ido { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize call site: "
<< I << " [" << CBMemLocationAA << "]\n"
; } } while (false)
8783 << " [" << CBMemLocationAA << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize call site: "
<< I << " [" << CBMemLocationAA << "]\n"
; } } while (false)
;
8784
8785 if (CBMemLocationAA.isAssumedReadNone())
8786 return NO_LOCATIONS;
8787
8788 if (CBMemLocationAA.isAssumedInaccessibleMemOnly()) {
8789 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8790 Changed, getAccessKindFromInst(&I));
8791 return AccessedLocs.getAssumed();
8792 }
8793
8794 uint32_t CBAssumedNotAccessedLocs =
8795 CBMemLocationAA.getAssumedNotAccessedLocation();
8796
8797 // Set the argmemonly and global bit as we handle them separately below.
8798 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8799 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8800
8801 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8802 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8803 continue;
8804 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8805 getAccessKindFromInst(&I));
8806 }
8807
8808 // Now handle global memory if it might be accessed. This is slightly tricky
8809 // as NO_GLOBAL_MEM has multiple bits set.
8810 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8811 if (HasGlobalAccesses) {
8812 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8813 AccessKind Kind, MemoryLocationsKind MLK) {
8814 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8815 getAccessKindFromInst(&I));
8816 return true;
8817 };
8818 if (!CBMemLocationAA.checkForAllAccessesToMemoryKind(
8819 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8820 return AccessedLocs.getWorstState();
8821 }
8822
8823 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
8824 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
8825 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
;
8826
8827 // Now handle argument memory if it might be accessed.
8828 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8829 if (HasArgAccesses)
8830 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8831
8832 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
8833 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
8834 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
;
8835
8836 return AccessedLocs.getAssumed();
8837 }
8838
8839 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8840 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
<< I << " [" << *Ptr << "]\n"; } } while
(false)
8841 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
<< I << " [" << *Ptr << "]\n"; } } while
(false)
8842 << I << " [" << *Ptr << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
<< I << " [" << *Ptr << "]\n"; } } while
(false)
;
8843 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed);
8844 return AccessedLocs.getAssumed();
8845 }
8846
8847 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
<< I << "\n"; } } while (false)
8848 << I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
<< I << "\n"; } } while (false)
;
8849 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8850 getAccessKindFromInst(&I));
8851 return AccessedLocs.getAssumed();
8852}
8853
8854/// An AA to represent the memory behavior function attributes.
8855struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8856 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8857 : AAMemoryLocationImpl(IRP, A) {}
8858
8859 /// See AbstractAttribute::updateImpl(Attributor &A).
8860 ChangeStatus updateImpl(Attributor &A) override {
8861
8862 const auto &MemBehaviorAA =
8863 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8864 if (MemBehaviorAA.isAssumedReadNone()) {
8865 if (MemBehaviorAA.isKnownReadNone())
8866 return indicateOptimisticFixpoint();
8867 assert(isAssumedReadNone() &&(static_cast <bool> (isAssumedReadNone() && "AAMemoryLocation was not read-none but AAMemoryBehavior was!"
) ? void (0) : __assert_fail ("isAssumedReadNone() && \"AAMemoryLocation was not read-none but AAMemoryBehavior was!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 8868, __extension__
__PRETTY_FUNCTION__))
8868 "AAMemoryLocation was not read-none but AAMemoryBehavior was!")(static_cast <bool> (isAssumedReadNone() && "AAMemoryLocation was not read-none but AAMemoryBehavior was!"
) ? void (0) : __assert_fail ("isAssumedReadNone() && \"AAMemoryLocation was not read-none but AAMemoryBehavior was!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 8868, __extension__
__PRETTY_FUNCTION__))
;
8869 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8870 return ChangeStatus::UNCHANGED;
8871 }
8872
8873 // The current assumed state used to determine a change.
8874 auto AssumedState = getAssumed();
8875 bool Changed = false;
8876
8877 auto CheckRWInst = [&](Instruction &I) {
8878 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8879 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << Ido { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations for "
<< I << ": " << getMemoryLocationsAsStr(MLK
) << "\n"; } } while (false)
8880 << ": " << getMemoryLocationsAsStr(MLK) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations for "
<< I << ": " << getMemoryLocationsAsStr(MLK
) << "\n"; } } while (false)
;
8881 removeAssumedBits(inverseLocation(MLK, false, false));
8882 // Stop once only the valid bit set in the *not assumed location*, thus
8883 // once we don't actually exclude any memory locations in the state.
8884 return getAssumedNotAccessedLocation() != VALID_STATE;
8885 };
8886
8887 bool UsedAssumedInformation = false;
8888 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8889 UsedAssumedInformation))
8890 return indicatePessimisticFixpoint();
8891
8892 Changed |= AssumedState != getAssumed();
8893 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8894 }
8895
8896 /// See AbstractAttribute::trackStatistics()
8897 void trackStatistics() const override {
8898 if (isAssumedReadNone())
8899 STATS_DECLTRACK_FN_ATTR(readnone){ static llvm::Statistic NumIRFunction_readnone = {"attributor"
, "NumIRFunction_readnone", ("Number of " "functions" " marked '"
"readnone" "'")};; ++(NumIRFunction_readnone); }
8900 else if (isAssumedArgMemOnly())
8901 STATS_DECLTRACK_FN_ATTR(argmemonly){ static llvm::Statistic NumIRFunction_argmemonly = {"attributor"
, "NumIRFunction_argmemonly", ("Number of " "functions" " marked '"
"argmemonly" "'")};; ++(NumIRFunction_argmemonly); }
8902 else if (isAssumedInaccessibleMemOnly())
8903 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly){ static llvm::Statistic NumIRFunction_inaccessiblememonly = {
"attributor", "NumIRFunction_inaccessiblememonly", ("Number of "
"functions" " marked '" "inaccessiblememonly" "'")};; ++(NumIRFunction_inaccessiblememonly
); }
8904 else if (isAssumedInaccessibleOrArgMemOnly())
8905 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly){ static llvm::Statistic NumIRFunction_inaccessiblememorargmemonly
= {"attributor", "NumIRFunction_inaccessiblememorargmemonly"
, ("Number of " "functions" " marked '" "inaccessiblememorargmemonly"
"'")};; ++(NumIRFunction_inaccessiblememorargmemonly); }
8906 }
8907};
8908
8909/// AAMemoryLocation attribute for call sites.
8910struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8911 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8912 : AAMemoryLocationImpl(IRP, A) {}
8913
8914 /// See AbstractAttribute::initialize(...).
8915 void initialize(Attributor &A) override {
8916 AAMemoryLocationImpl::initialize(A);
8917 Function *F = getAssociatedFunction();
8918 if (!F || F->isDeclaration())
8919 indicatePessimisticFixpoint();
8920 }
8921
8922 /// See AbstractAttribute::updateImpl(...).
8923 ChangeStatus updateImpl(Attributor &A) override {
8924 // TODO: Once we have call site specific value information we can provide
8925 // call site specific liveness liveness information and then it makes
8926 // sense to specialize attributes for call sites arguments instead of
8927 // redirecting requests to the callee argument.
8928 Function *F = getAssociatedFunction();
8929 const IRPosition &FnPos = IRPosition::function(*F);
8930 auto &FnAA =
8931 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
8932 bool Changed = false;
8933 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8934 AccessKind Kind, MemoryLocationsKind MLK) {
8935 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
8936 getAccessKindFromInst(I));
8937 return true;
8938 };
8939 if (!FnAA.checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8940 return indicatePessimisticFixpoint();
8941 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8942 }
8943
8944 /// See AbstractAttribute::trackStatistics()
8945 void trackStatistics() const override {
8946 if (isAssumedReadNone())
8947 STATS_DECLTRACK_CS_ATTR(readnone){ static llvm::Statistic NumIRCS_readnone = {"attributor", "NumIRCS_readnone"
, ("Number of " "call site" " marked '" "readnone" "'")};; ++
(NumIRCS_readnone); }
8948 }
8949};
8950} // namespace
8951
8952/// ------------------ Value Constant Range Attribute -------------------------
8953
8954namespace {
8955struct AAValueConstantRangeImpl : AAValueConstantRange {
8956 using StateType = IntegerRangeState;
8957 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
8958 : AAValueConstantRange(IRP, A) {}
8959
8960 /// See AbstractAttribute::initialize(..).
8961 void initialize(Attributor &A) override {
8962 if (A.hasSimplificationCallback(getIRPosition())) {
8963 indicatePessimisticFixpoint();
8964 return;
8965 }
8966
8967 // Intersect a range given by SCEV.
8968 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
8969
8970 // Intersect a range given by LVI.
8971 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
8972 }
8973
8974 /// See AbstractAttribute::getAsStr().
8975 const std::string getAsStr() const override {
8976 std::string Str;
8977 llvm::raw_string_ostream OS(Str);
8978 OS << "range(" << getBitWidth() << ")<";
8979 getKnown().print(OS);
8980 OS << " / ";
8981 getAssumed().print(OS);
8982 OS << ">";
8983 return OS.str();
8984 }
8985
8986 /// Helper function to get a SCEV expr for the associated value at program
8987 /// point \p I.
8988 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
8989 if (!getAnchorScope())
8990 return nullptr;
8991
8992 ScalarEvolution *SE =
8993 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8994 *getAnchorScope());
8995
8996 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
8997 *getAnchorScope());
8998
8999 if (!SE || !LI)
9000 return nullptr;
9001
9002 const SCEV *S = SE->getSCEV(&getAssociatedValue());
9003 if (!I)
9004 return S;
9005
9006 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
9007 }
9008
9009 /// Helper function to get a range from SCEV for the associated value at
9010 /// program point \p I.
9011 ConstantRange getConstantRangeFromSCEV(Attributor &A,
9012 const Instruction *I = nullptr) const {
9013 if (!getAnchorScope())
9014 return getWorstState(getBitWidth());
9015
9016 ScalarEvolution *SE =
9017 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9018 *getAnchorScope());
9019
9020 const SCEV *S = getSCEV(A, I);
9021 if (!SE || !S)
9022 return getWorstState(getBitWidth());
9023
9024 return SE->getUnsignedRange(S);
9025 }
9026
9027 /// Helper function to get a range from LVI for the associated value at
9028 /// program point \p I.
9029 ConstantRange
9030 getConstantRangeFromLVI(Attributor &A,
9031 const Instruction *CtxI = nullptr) const {
9032 if (!getAnchorScope())
9033 return getWorstState(getBitWidth());
9034
9035 LazyValueInfo *LVI =
9036 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9037 *getAnchorScope());
9038
9039 if (!LVI || !CtxI)
9040 return getWorstState(getBitWidth());
9041 return LVI->getConstantRange(&getAssociatedValue(),
9042 const_cast<Instruction *>(CtxI));
9043 }
9044
9045 /// Return true if \p CtxI is valid for querying outside analyses.
9046 /// This basically makes sure we do not ask intra-procedural analysis
9047 /// about a context in the wrong function or a context that violates
9048 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
9049 /// if the original context of this AA is OK or should be considered invalid.
9050 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
9051 const Instruction *CtxI,
9052 bool AllowAACtxI) const {
9053 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9054 return false;
9055
9056 // Our context might be in a different function, neither intra-procedural
9057 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
9058 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
9059 return false;
9060
9061 // If the context is not dominated by the value there are paths to the
9062 // context that do not define the value. This cannot be handled by
9063 // LazyValueInfo so we need to bail.
9064 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
9065 InformationCache &InfoCache = A.getInfoCache();
9066 const DominatorTree *DT =
9067 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
9068 *I->getFunction());
9069 return DT && DT->dominates(I, CtxI);
9070 }
9071
9072 return true;
9073 }
9074
9075 /// See AAValueConstantRange::getKnownConstantRange(..).
9076 ConstantRange
9077 getKnownConstantRange(Attributor &A,
9078 const Instruction *CtxI = nullptr) const override {
9079 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9080 /* AllowAACtxI */ false))
9081 return getKnown();
9082
9083 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9084 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9085 return getKnown().intersectWith(SCEVR).intersectWith(LVIR);
9086 }
9087
9088 /// See AAValueConstantRange::getAssumedConstantRange(..).
9089 ConstantRange
9090 getAssumedConstantRange(Attributor &A,
9091 const Instruction *CtxI = nullptr) const override {
9092 // TODO: Make SCEV use Attributor assumption.
9093 // We may be able to bound a variable range via assumptions in
9094 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
9095 // evolve to x^2 + x, then we can say that y is in [2, 12].
9096 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9097 /* AllowAACtxI */ false))
9098 return getAssumed();
9099
9100 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9101 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9102 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9103 }
9104
9105 /// Helper function to create MDNode for range metadata.
9106 static MDNode *
9107 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
9108 const ConstantRange &AssumedConstantRange) {
9109 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
9110 Ty, AssumedConstantRange.getLower())),
9111 ConstantAsMetadata::get(ConstantInt::get(
9112 Ty, AssumedConstantRange.getUpper()))};
9113 return MDNode::get(Ctx, LowAndHigh);
9114 }
9115
9116 /// Return true if \p Assumed is included in \p KnownRanges.
9117 static bool isBetterRange(const ConstantRange &Assumed, MDNode *KnownRanges) {
9118
9119 if (Assumed.isFullSet())
9120 return false;
9121
9122 if (!KnownRanges)
9123 return true;
9124
9125 // If multiple ranges are annotated in IR, we give up to annotate assumed
9126 // range for now.
9127
9128 // TODO: If there exists a known range which containts assumed range, we
9129 // can say assumed range is better.
9130 if (KnownRanges->getNumOperands() > 2)
9131 return false;
9132
9133 ConstantInt *Lower =
9134 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
9135 ConstantInt *Upper =
9136 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
9137
9138 ConstantRange Known(Lower->getValue(), Upper->getValue());
9139 return Known.contains(Assumed) && Known != Assumed;
9140 }
9141
9142 /// Helper function to set range metadata.
9143 static bool
9144 setRangeMetadataIfisBetterRange(Instruction *I,
9145 const ConstantRange &AssumedConstantRange) {
9146 auto *OldRangeMD = I->getMetadata(LLVMContext::MD_range);
9147 if (isBetterRange(AssumedConstantRange, OldRangeMD)) {
9148 if (!AssumedConstantRange.isEmptySet()) {
9149 I->setMetadata(LLVMContext::MD_range,
9150 getMDNodeForConstantRange(I->getType(), I->getContext(),
9151 AssumedConstantRange));
9152 return true;
9153 }
9154 }
9155 return false;
9156 }
9157
9158 /// See AbstractAttribute::manifest()
9159 ChangeStatus manifest(Attributor &A) override {
9160 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9161 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9162 assert(!AssumedConstantRange.isFullSet() && "Invalid state")(static_cast <bool> (!AssumedConstantRange.isFullSet() &&
"Invalid state") ? void (0) : __assert_fail ("!AssumedConstantRange.isFullSet() && \"Invalid state\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9162, __extension__
__PRETTY_FUNCTION__))
;
9163
9164 auto &V = getAssociatedValue();
9165 if (!AssumedConstantRange.isEmptySet() &&
9166 !AssumedConstantRange.isSingleElement()) {
9167 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9168 assert(I == getCtxI() && "Should not annotate an instruction which is "(static_cast <bool> (I == getCtxI() && "Should not annotate an instruction which is "
"not the context instruction") ? void (0) : __assert_fail ("I == getCtxI() && \"Should not annotate an instruction which is \" \"not the context instruction\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9169, __extension__
__PRETTY_FUNCTION__))
9169 "not the context instruction")(static_cast <bool> (I == getCtxI() && "Should not annotate an instruction which is "
"not the context instruction") ? void (0) : __assert_fail ("I == getCtxI() && \"Should not annotate an instruction which is \" \"not the context instruction\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9169, __extension__
__PRETTY_FUNCTION__))
;
9170 if (isa<CallInst>(I) || isa<LoadInst>(I))
9171 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9172 Changed = ChangeStatus::CHANGED;
9173 }
9174 }
9175
9176 return Changed;
9177 }
9178};
9179
9180struct AAValueConstantRangeArgument final
9181 : AAArgumentFromCallSiteArguments<
9182 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9183 true /* BridgeCallBaseContext */> {
9184 using Base = AAArgumentFromCallSiteArguments<
9185 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9186 true /* BridgeCallBaseContext */>;
9187 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9188 : Base(IRP, A) {}
9189
9190 /// See AbstractAttribute::initialize(..).
9191 void initialize(Attributor &A) override {
9192 if (!getAnchorScope() || getAnchorScope()->isDeclaration()) {
9193 indicatePessimisticFixpoint();
9194 } else {
9195 Base::initialize(A);
9196 }
9197 }
9198
9199 /// See AbstractAttribute::trackStatistics()
9200 void trackStatistics() const override {
9201 STATS_DECLTRACK_ARG_ATTR(value_range){ static llvm::Statistic NumIRArguments_value_range = {"attributor"
, "NumIRArguments_value_range", ("Number of " "arguments" " marked '"
"value_range" "'")};; ++(NumIRArguments_value_range); }
9202 }
9203};
9204
9205struct AAValueConstantRangeReturned
9206 : AAReturnedFromReturnedValues<AAValueConstantRange,
9207 AAValueConstantRangeImpl,
9208 AAValueConstantRangeImpl::StateType,
9209 /* PropogateCallBaseContext */ true> {
9210 using Base =
9211 AAReturnedFromReturnedValues<AAValueConstantRange,
9212 AAValueConstantRangeImpl,
9213 AAValueConstantRangeImpl::StateType,
9214 /* PropogateCallBaseContext */ true>;
9215 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9216 : Base(IRP, A) {}
9217
9218 /// See AbstractAttribute::initialize(...).
9219 void initialize(Attributor &A) override {}
9220
9221 /// See AbstractAttribute::trackStatistics()
9222 void trackStatistics() const override {
9223 STATS_DECLTRACK_FNRET_ATTR(value_range){ static llvm::Statistic NumIRFunctionReturn_value_range = {"attributor"
, "NumIRFunctionReturn_value_range", ("Number of " "function returns"
" marked '" "value_range" "'")};; ++(NumIRFunctionReturn_value_range
); }
9224 }
9225};
9226
9227struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9228 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9229 : AAValueConstantRangeImpl(IRP, A) {}
9230
9231 /// See AbstractAttribute::initialize(...).
9232 void initialize(Attributor &A) override {
9233 AAValueConstantRangeImpl::initialize(A);
9234 if (isAtFixpoint())
9235 return;
9236
9237 Value &V = getAssociatedValue();
9238
9239 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9240 unionAssumed(ConstantRange(C->getValue()));
9241 indicateOptimisticFixpoint();
9242 return;
9243 }
9244
9245 if (isa<UndefValue>(&V)) {
9246 // Collapse the undef state to 0.
9247 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9248 indicateOptimisticFixpoint();
9249 return;
9250 }
9251
9252 if (isa<CallBase>(&V))
9253 return;
9254
9255 if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))
9256 return;
9257
9258 // If it is a load instruction with range metadata, use it.
9259 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9260 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9261 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9262 return;
9263 }
9264
9265 // We can work with PHI and select instruction as we traverse their operands
9266 // during update.
9267 if (isa<SelectInst>(V) || isa<PHINode>(V))
9268 return;
9269
9270 // Otherwise we give up.
9271 indicatePessimisticFixpoint();
9272
9273 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
9274 << getAssociatedValue() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
;
9275 }
9276
9277 bool calculateBinaryOperator(
9278 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9279 const Instruction *CtxI,
9280 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9281 Value *LHS = BinOp->getOperand(0);
9282 Value *RHS = BinOp->getOperand(1);
9283
9284 // Simplify the operands first.
9285 bool UsedAssumedInformation = false;
9286 const auto &SimplifiedLHS = A.getAssumedSimplified(
9287 IRPosition::value(*LHS, getCallBaseContext()), *this,
9288 UsedAssumedInformation, AA::Interprocedural);
9289 if (!SimplifiedLHS.has_value())
9290 return true;
9291 if (!*SimplifiedLHS)
9292 return false;
9293 LHS = *SimplifiedLHS;
9294
9295 const auto &SimplifiedRHS = A.getAssumedSimplified(
9296 IRPosition::value(*RHS, getCallBaseContext()), *this,
9297 UsedAssumedInformation, AA::Interprocedural);
9298 if (!SimplifiedRHS.has_value())
9299 return true;
9300 if (!*SimplifiedRHS)
9301 return false;
9302 RHS = *SimplifiedRHS;
9303
9304 // TODO: Allow non integers as well.
9305 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9306 return false;
9307
9308 auto &LHSAA = A.getAAFor<AAValueConstantRange>(
9309 *this, IRPosition::value(*LHS, getCallBaseContext()),
9310 DepClassTy::REQUIRED);
9311 QuerriedAAs.push_back(&LHSAA);
9312 auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI);
9313
9314 auto &RHSAA = A.getAAFor<AAValueConstantRange>(
9315 *this, IRPosition::value(*RHS, getCallBaseContext()),
9316 DepClassTy::REQUIRED);
9317 QuerriedAAs.push_back(&RHSAA);
9318 auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI);
9319
9320 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9321
9322 T.unionAssumed(AssumedRange);
9323
9324 // TODO: Track a known state too.
9325
9326 return T.isValidState();
9327 }
9328
9329 bool calculateCastInst(
9330 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9331 const Instruction *CtxI,
9332 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9333 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!")(static_cast <bool> (CastI->getNumOperands() == 1 &&
"Expected cast to be unary!") ? void (0) : __assert_fail ("CastI->getNumOperands() == 1 && \"Expected cast to be unary!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9333, __extension__
__PRETTY_FUNCTION__))
;
9334 // TODO: Allow non integers as well.
9335 Value *OpV = CastI->getOperand(0);
9336
9337 // Simplify the operand first.
9338 bool UsedAssumedInformation = false;
9339 const auto &SimplifiedOpV = A.getAssumedSimplified(
9340 IRPosition::value(*OpV, getCallBaseContext()), *this,
9341 UsedAssumedInformation, AA::Interprocedural);
9342 if (!SimplifiedOpV.has_value())
9343 return true;
9344 if (!*SimplifiedOpV)
9345 return false;
9346 OpV = *SimplifiedOpV;
9347
9348 if (!OpV->getType()->isIntegerTy())
9349 return false;
9350
9351 auto &OpAA = A.getAAFor<AAValueConstantRange>(
9352 *this, IRPosition::value(*OpV, getCallBaseContext()),
9353 DepClassTy::REQUIRED);
9354 QuerriedAAs.push_back(&OpAA);
9355 T.unionAssumed(
9356 OpAA.getAssumed().castOp(CastI->getOpcode(), getState().getBitWidth()));
9357 return T.isValidState();
9358 }
9359
9360 bool
9361 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9362 const Instruction *CtxI,
9363 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9364 Value *LHS = CmpI->getOperand(0);
9365 Value *RHS = CmpI->getOperand(1);
9366
9367 // Simplify the operands first.
9368 bool UsedAssumedInformation = false;
9369 const auto &SimplifiedLHS = A.getAssumedSimplified(
9370 IRPosition::value(*LHS, getCallBaseContext()), *this,
9371 UsedAssumedInformation, AA::Interprocedural);
9372 if (!SimplifiedLHS.has_value())
9373 return true;
9374 if (!*SimplifiedLHS)
9375 return false;
9376 LHS = *SimplifiedLHS;
9377
9378 const auto &SimplifiedRHS = A.getAssumedSimplified(
9379 IRPosition::value(*RHS, getCallBaseContext()), *this,
9380 UsedAssumedInformation, AA::Interprocedural);
9381 if (!SimplifiedRHS.has_value())
9382 return true;
9383 if (!*SimplifiedRHS)
9384 return false;
9385 RHS = *SimplifiedRHS;
9386
9387 // TODO: Allow non integers as well.
9388 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9389 return false;
9390
9391 auto &LHSAA = A.getAAFor<AAValueConstantRange>(
9392 *this, IRPosition::value(*LHS, getCallBaseContext()),
9393 DepClassTy::REQUIRED);
9394 QuerriedAAs.push_back(&LHSAA);
9395 auto &RHSAA = A.getAAFor<AAValueConstantRange>(
9396 *this, IRPosition::value(*RHS, getCallBaseContext()),
9397 DepClassTy::REQUIRED);
9398 QuerriedAAs.push_back(&RHSAA);
9399 auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI);
9400 auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI);
9401
9402 // If one of them is empty set, we can't decide.
9403 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9404 return true;
9405
9406 bool MustTrue = false, MustFalse = false;
9407
9408 auto AllowedRegion =
9409 ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange);
9410
9411 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9412 MustFalse = true;
9413
9414 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9415 MustTrue = true;
9416
9417 assert((!MustTrue || !MustFalse) &&(static_cast <bool> ((!MustTrue || !MustFalse) &&
"Either MustTrue or MustFalse should be false!") ? void (0) :
__assert_fail ("(!MustTrue || !MustFalse) && \"Either MustTrue or MustFalse should be false!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9418, __extension__
__PRETTY_FUNCTION__))
9418 "Either MustTrue or MustFalse should be false!")(static_cast <bool> ((!MustTrue || !MustFalse) &&
"Either MustTrue or MustFalse should be false!") ? void (0) :
__assert_fail ("(!MustTrue || !MustFalse) && \"Either MustTrue or MustFalse should be false!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9418, __extension__
__PRETTY_FUNCTION__))
;
9419
9420 if (MustTrue)
9421 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9422 else if (MustFalse)
9423 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9424 else
9425 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9426
9427 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " " << LHSAAdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] " <<
*CmpI << " " << LHSAA << " " << RHSAA
<< "\n"; } } while (false)
9428 << " " << RHSAA << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] " <<
*CmpI << " " << LHSAA << " " << RHSAA
<< "\n"; } } while (false)
;
9429
9430 // TODO: Track a known state too.
9431 return T.isValidState();
9432 }
9433
9434 /// See AbstractAttribute::updateImpl(...).
9435 ChangeStatus updateImpl(Attributor &A) override {
9436
9437 IntegerRangeState T(getBitWidth());
9438 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9439 Instruction *I = dyn_cast<Instruction>(&V);
9440 if (!I || isa<CallBase>(I)) {
9441
9442 // Simplify the operand first.
9443 bool UsedAssumedInformation = false;
9444 const auto &SimplifiedOpV = A.getAssumedSimplified(
9445 IRPosition::value(V, getCallBaseContext()), *this,
9446 UsedAssumedInformation, AA::Interprocedural);
9447 if (!SimplifiedOpV.has_value())
9448 return true;
9449 if (!*SimplifiedOpV)
9450 return false;
9451 Value *VPtr = *SimplifiedOpV;
9452
9453 // If the value is not instruction, we query AA to Attributor.
9454 const auto &AA = A.getAAFor<AAValueConstantRange>(
9455 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9456 DepClassTy::REQUIRED);
9457
9458 // Clamp operator is not used to utilize a program point CtxI.
9459 T.unionAssumed(AA.getAssumedConstantRange(A, CtxI));
9460
9461 return T.isValidState();
9462 }
9463
9464 SmallVector<const AAValueConstantRange *, 4> QuerriedAAs;
9465 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9466 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9467 return false;
9468 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9469 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9470 return false;
9471 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9472 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9473 return false;
9474 } else {
9475 // Give up with other instructions.
9476 // TODO: Add other instructions
9477
9478 T.indicatePessimisticFixpoint();
9479 return false;
9480 }
9481
9482 // Catch circular reasoning in a pessimistic way for now.
9483 // TODO: Check how the range evolves and if we stripped anything, see also
9484 // AADereferenceable or AAAlign for similar situations.
9485 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9486 if (QueriedAA != this)
9487 continue;
9488 // If we are in a stady state we do not need to worry.
9489 if (T.getAssumed() == getState().getAssumed())
9490 continue;
9491 T.indicatePessimisticFixpoint();
9492 }
9493
9494 return T.isValidState();
9495 };
9496
9497 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9498 return indicatePessimisticFixpoint();
9499
9500 // Ensure that long def-use chains can't cause circular reasoning either by
9501 // introducing a cutoff below.
9502 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9503 return ChangeStatus::UNCHANGED;
9504 if (++NumChanges > MaxNumChanges) {
9505 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChangesdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] performed "
<< NumChanges << " but only " << MaxNumChanges
<< " are allowed to avoid cyclic reasoning."; } } while
(false)
9506 << " but only " << MaxNumChangesdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] performed "
<< NumChanges << " but only " << MaxNumChanges
<< " are allowed to avoid cyclic reasoning."; } } while
(false)
9507 << " are allowed to avoid cyclic reasoning.")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] performed "
<< NumChanges << " but only " << MaxNumChanges
<< " are allowed to avoid cyclic reasoning."; } } while
(false)
;
9508 return indicatePessimisticFixpoint();
9509 }
9510 return ChangeStatus::CHANGED;
9511 }
9512
9513 /// See AbstractAttribute::trackStatistics()
9514 void trackStatistics() const override {
9515 STATS_DECLTRACK_FLOATING_ATTR(value_range){ static llvm::Statistic NumIRFloating_value_range = {"attributor"
, "NumIRFloating_value_range", ("Number of floating values known to be '"
"value_range" "'")};; ++(NumIRFloating_value_range); }
9516 }
9517
9518 /// Tracker to bail after too many widening steps of the constant range.
9519 int NumChanges = 0;
9520
9521 /// Upper bound for the number of allowed changes (=widening steps) for the
9522 /// constant range before we give up.
9523 static constexpr int MaxNumChanges = 5;
9524};
9525
9526struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9527 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9528 : AAValueConstantRangeImpl(IRP, A) {}
9529
9530 /// See AbstractAttribute::initialize(...).
9531 ChangeStatus updateImpl(Attributor &A) override {
9532 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "::llvm::llvm_unreachable_internal("AAValueConstantRange(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 9533)
9533 "not be called")::llvm::llvm_unreachable_internal("AAValueConstantRange(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 9533)
;
9534 }
9535
9536 /// See AbstractAttribute::trackStatistics()
9537 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range){ static llvm::Statistic NumIRFunction_value_range = {"attributor"
, "NumIRFunction_value_range", ("Number of " "functions" " marked '"
"value_range" "'")};; ++(NumIRFunction_value_range); }
}
9538};
9539
9540struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9541 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9542 : AAValueConstantRangeFunction(IRP, A) {}
9543
9544 /// See AbstractAttribute::trackStatistics()
9545 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range){ static llvm::Statistic NumIRCS_value_range = {"attributor",
"NumIRCS_value_range", ("Number of " "call site" " marked '"
"value_range" "'")};; ++(NumIRCS_value_range); }
}
9546};
9547
9548struct AAValueConstantRangeCallSiteReturned
9549 : AACallSiteReturnedFromReturned<AAValueConstantRange,
9550 AAValueConstantRangeImpl,
9551 AAValueConstantRangeImpl::StateType,
9552 /* IntroduceCallBaseContext */ true> {
9553 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9554 : AACallSiteReturnedFromReturned<AAValueConstantRange,
9555 AAValueConstantRangeImpl,
9556 AAValueConstantRangeImpl::StateType,
9557 /* IntroduceCallBaseContext */ true>(IRP,
9558 A) {
9559 }
9560
9561 /// See AbstractAttribute::initialize(...).
9562 void initialize(Attributor &A) override {
9563 // If it is a load instruction with range metadata, use the metadata.
9564 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue()))
9565 if (auto *RangeMD = CI->getMetadata(LLVMContext::MD_range))
9566 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9567
9568 AAValueConstantRangeImpl::initialize(A);
9569 }
9570
9571 /// See AbstractAttribute::trackStatistics()
9572 void trackStatistics() const override {
9573 STATS_DECLTRACK_CSRET_ATTR(value_range){ static llvm::Statistic NumIRCSReturn_value_range = {"attributor"
, "NumIRCSReturn_value_range", ("Number of " "call site returns"
" marked '" "value_range" "'")};; ++(NumIRCSReturn_value_range
); }
9574 }
9575};
9576struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9577 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9578 : AAValueConstantRangeFloating(IRP, A) {}
9579
9580 /// See AbstractAttribute::manifest()
9581 ChangeStatus manifest(Attributor &A) override {
9582 return ChangeStatus::UNCHANGED;
9583 }
9584
9585 /// See AbstractAttribute::trackStatistics()
9586 void trackStatistics() const override {
9587 STATS_DECLTRACK_CSARG_ATTR(value_range){ static llvm::Statistic NumIRCSArguments_value_range = {"attributor"
, "NumIRCSArguments_value_range", ("Number of " "call site arguments"
" marked '" "value_range" "'")};; ++(NumIRCSArguments_value_range
); }
9588 }
9589};
9590} // namespace
9591
9592/// ------------------ Potential Values Attribute -------------------------
9593
9594namespace {
9595struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9596 using StateType = PotentialConstantIntValuesState;
9597
9598 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9599 : AAPotentialConstantValues(IRP, A) {}
9600
9601 /// See AbstractAttribute::initialize(..).
9602 void initialize(Attributor &A) override {
9603 if (A.hasSimplificationCallback(getIRPosition()))
9604 indicatePessimisticFixpoint();
9605 else
9606 AAPotentialConstantValues::initialize(A);
9607 }
9608
9609 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9610 bool &ContainsUndef, bool ForSelf) {
9611 SmallVector<AA::ValueAndContext> Values;
9612 bool UsedAssumedInformation = false;
9613 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9614 UsedAssumedInformation)) {
9615 // Avoid recursion when the caller is computing constant values for this
9616 // IRP itself.
9617 if (ForSelf)
9618 return false;
9619 if (!IRP.getAssociatedType()->isIntegerTy())
9620 return false;
9621 auto &PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9622 *this, IRP, DepClassTy::REQUIRED);
9623 if (!PotentialValuesAA.getState().isValidState())
9624 return false;
9625 ContainsUndef = PotentialValuesAA.getState().undefIsContained();
9626 S = PotentialValuesAA.getState().getAssumedSet();
9627 return true;
9628 }
9629
9630 // Copy all the constant values, except UndefValue. ContainsUndef is true
9631 // iff Values contains only UndefValue instances. If there are other known
9632 // constants, then UndefValue is dropped.
9633 ContainsUndef = false;
9634 for (auto &It : Values) {
9635 if (isa<UndefValue>(It.getValue())) {
9636 ContainsUndef = true;
9637 continue;
9638 }
9639 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9640 if (!CI)
9641 return false;
9642 S.insert(CI->getValue());
9643 }
9644 ContainsUndef &= S.empty();
9645
9646 return true;
9647 }
9648
9649 /// See AbstractAttribute::getAsStr().
9650 const std::string getAsStr() const override {
9651 std::string Str;
9652 llvm::raw_string_ostream OS(Str);
9653 OS << getState();
9654 return OS.str();
9655 }
9656
9657 /// See AbstractAttribute::updateImpl(...).
9658 ChangeStatus updateImpl(Attributor &A) override {
9659 return indicatePessimisticFixpoint();
9660 }
9661};
9662
9663struct AAPotentialConstantValuesArgument final
9664 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9665 AAPotentialConstantValuesImpl,
9666 PotentialConstantIntValuesState> {
9667 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9668 AAPotentialConstantValuesImpl,
9669 PotentialConstantIntValuesState>;
9670 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9671 : Base(IRP, A) {}
9672
9673 /// See AbstractAttribute::initialize(..).
9674 void initialize(Attributor &A) override {
9675 if (!getAnchorScope() || getAnchorScope()->isDeclaration()) {
9676 indicatePessimisticFixpoint();
9677 } else {
9678 Base::initialize(A);
9679 }
9680 }
9681
9682 /// See AbstractAttribute::trackStatistics()
9683 void trackStatistics() const override {
9684 STATS_DECLTRACK_ARG_ATTR(potential_values){ static llvm::Statistic NumIRArguments_potential_values = {"attributor"
, "NumIRArguments_potential_values", ("Number of " "arguments"
" marked '" "potential_values" "'")};; ++(NumIRArguments_potential_values
); }
9685 }
9686};
9687
9688struct AAPotentialConstantValuesReturned
9689 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9690 AAPotentialConstantValuesImpl> {
9691 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9692 AAPotentialConstantValuesImpl>;
9693 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9694 : Base(IRP, A) {}
9695
9696 /// See AbstractAttribute::trackStatistics()
9697 void trackStatistics() const override {
9698 STATS_DECLTRACK_FNRET_ATTR(potential_values){ static llvm::Statistic NumIRFunctionReturn_potential_values
= {"attributor", "NumIRFunctionReturn_potential_values", ("Number of "
"function returns" " marked '" "potential_values" "'")};; ++
(NumIRFunctionReturn_potential_values); }
9699 }
9700};
9701
9702struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9703 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9704 : AAPotentialConstantValuesImpl(IRP, A) {}
9705
9706 /// See AbstractAttribute::initialize(..).
9707 void initialize(Attributor &A) override {
9708 AAPotentialConstantValuesImpl::initialize(A);
9709 if (isAtFixpoint())
9710 return;
9711
9712 Value &V = getAssociatedValue();
9713
9714 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9715 unionAssumed(C->getValue());
9716 indicateOptimisticFixpoint();
9717 return;
9718 }
9719
9720 if (isa<UndefValue>(&V)) {
9721 unionAssumedWithUndef();
9722 indicateOptimisticFixpoint();
9723 return;
9724 }
9725
9726 if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))
9727 return;
9728
9729 if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))
9730 return;
9731
9732 indicatePessimisticFixpoint();
9733
9734 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialConstantValues] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
9735 << getAssociatedValue() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialConstantValues] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
;
9736 }
9737
9738 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9739 const APInt &RHS) {
9740 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9741 }
9742
9743 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9744 uint32_t ResultBitWidth) {
9745 Instruction::CastOps CastOp = CI->getOpcode();
9746 switch (CastOp) {
9747 default:
9748 llvm_unreachable("unsupported or not integer cast")::llvm::llvm_unreachable_internal("unsupported or not integer cast"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9748)
;
9749 case Instruction::Trunc:
9750 return Src.trunc(ResultBitWidth);
9751 case Instruction::SExt:
9752 return Src.sext(ResultBitWidth);
9753 case Instruction::ZExt:
9754 return Src.zext(ResultBitWidth);
9755 case Instruction::BitCast:
9756 return Src;
9757 }
9758 }
9759
9760 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9761 const APInt &LHS, const APInt &RHS,
9762 bool &SkipOperation, bool &Unsupported) {
9763 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9764 // Unsupported is set to true when the binary operator is not supported.
9765 // SkipOperation is set to true when UB occur with the given operand pair
9766 // (LHS, RHS).
9767 // TODO: we should look at nsw and nuw keywords to handle operations
9768 // that create poison or undef value.
9769 switch (BinOpcode) {
9770 default:
9771 Unsupported = true;
9772 return LHS;
9773 case Instruction::Add:
9774 return LHS + RHS;
9775 case Instruction::Sub:
9776 return LHS - RHS;
9777 case Instruction::Mul:
9778 return LHS * RHS;
9779 case Instruction::UDiv:
9780 if (RHS.isZero()) {
9781 SkipOperation = true;
9782 return LHS;
9783 }
9784 return LHS.udiv(RHS);
9785 case Instruction::SDiv:
9786 if (RHS.isZero()) {
9787 SkipOperation = true;
9788 return LHS;
9789 }
9790 return LHS.sdiv(RHS);
9791 case Instruction::URem:
9792 if (RHS.isZero()) {
9793 SkipOperation = true;
9794 return LHS;
9795 }
9796 return LHS.urem(RHS);
9797 case Instruction::SRem:
9798 if (RHS.isZero()) {
9799 SkipOperation = true;
9800 return LHS;
9801 }
9802 return LHS.srem(RHS);
9803 case Instruction::Shl:
9804 return LHS.shl(RHS);
9805 case Instruction::LShr:
9806 return LHS.lshr(RHS);
9807 case Instruction::AShr:
9808 return LHS.ashr(RHS);
9809 case Instruction::And:
9810 return LHS & RHS;
9811 case Instruction::Or:
9812 return LHS | RHS;
9813 case Instruction::Xor:
9814 return LHS ^ RHS;
9815 }
9816 }
9817
9818 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9819 const APInt &LHS, const APInt &RHS) {
9820 bool SkipOperation = false;
9821 bool Unsupported = false;
9822 APInt Result =
9823 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9824 if (Unsupported)
9825 return false;
9826 // If SkipOperation is true, we can ignore this operand pair (L, R).
9827 if (!SkipOperation)
9828 unionAssumed(Result);
9829 return isValidState();
9830 }
9831
9832 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9833 auto AssumedBefore = getAssumed();
9834 Value *LHS = ICI->getOperand(0);
9835 Value *RHS = ICI->getOperand(1);
9836
9837 bool LHSContainsUndef = false, RHSContainsUndef = false;
9838 SetTy LHSAAPVS, RHSAAPVS;
9839 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9840 LHSContainsUndef, /* ForSelf */ false) ||
9841 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9842 RHSContainsUndef, /* ForSelf */ false))
9843 return indicatePessimisticFixpoint();
9844
9845 // TODO: make use of undef flag to limit potential values aggressively.
9846 bool MaybeTrue = false, MaybeFalse = false;
9847 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
9848 if (LHSContainsUndef && RHSContainsUndef) {
9849 // The result of any comparison between undefs can be soundly replaced
9850 // with undef.
9851 unionAssumedWithUndef();
9852 } else if (LHSContainsUndef) {
9853 for (const APInt &R : RHSAAPVS) {
9854 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9855 MaybeTrue |= CmpResult;
9856 MaybeFalse |= !CmpResult;
9857 if (MaybeTrue & MaybeFalse)
9858 return indicatePessimisticFixpoint();
9859 }
9860 } else if (RHSContainsUndef) {
9861 for (const APInt &L : LHSAAPVS) {
9862 bool CmpResult = calculateICmpInst(ICI, L, Zero);
9863 MaybeTrue |= CmpResult;
9864 MaybeFalse |= !CmpResult;
9865 if (MaybeTrue & MaybeFalse)
9866 return indicatePessimisticFixpoint();
9867 }
9868 } else {
9869 for (const APInt &L : LHSAAPVS) {
9870 for (const APInt &R : RHSAAPVS) {
9871 bool CmpResult = calculateICmpInst(ICI, L, R);
9872 MaybeTrue |= CmpResult;
9873 MaybeFalse |= !CmpResult;
9874 if (MaybeTrue & MaybeFalse)
9875 return indicatePessimisticFixpoint();
9876 }
9877 }
9878 }
9879 if (MaybeTrue)
9880 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
9881 if (MaybeFalse)
9882 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
9883 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9884 : ChangeStatus::CHANGED;
9885 }
9886
9887 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
9888 auto AssumedBefore = getAssumed();
9889 Value *LHS = SI->getTrueValue();
9890 Value *RHS = SI->getFalseValue();
9891
9892 bool UsedAssumedInformation = false;
9893 std::optional<Constant *> C = A.getAssumedConstant(
9894 *SI->getCondition(), *this, UsedAssumedInformation);
9895
9896 // Check if we only need one operand.
9897 bool OnlyLeft = false, OnlyRight = false;
9898 if (C && *C && (*C)->isOneValue())
9899 OnlyLeft = true;
9900 else if (C && *C && (*C)->isZeroValue())
9901 OnlyRight = true;
9902
9903 bool LHSContainsUndef = false, RHSContainsUndef = false;
9904 SetTy LHSAAPVS, RHSAAPVS;
9905 if (!OnlyRight &&
9906 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9907 LHSContainsUndef, /* ForSelf */ false))
9908 return indicatePessimisticFixpoint();
9909
9910 if (!OnlyLeft &&
9911 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9912 RHSContainsUndef, /* ForSelf */ false))
9913 return indicatePessimisticFixpoint();
9914
9915 if (OnlyLeft || OnlyRight) {
9916 // select (true/false), lhs, rhs
9917 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9918 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9919
9920 if (Undef)
9921 unionAssumedWithUndef();
9922 else {
9923 for (const auto &It : *OpAA)
9924 unionAssumed(It);
9925 }
9926
9927 } else if (LHSContainsUndef && RHSContainsUndef) {
9928 // select i1 *, undef , undef => undef
9929 unionAssumedWithUndef();
9930 } else {
9931 for (const auto &It : LHSAAPVS)
9932 unionAssumed(It);
9933 for (const auto &It : RHSAAPVS)
9934 unionAssumed(It);
9935 }
9936 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9937 : ChangeStatus::CHANGED;
9938 }
9939
9940 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
9941 auto AssumedBefore = getAssumed();
9942 if (!CI->isIntegerCast())
9943 return indicatePessimisticFixpoint();
9944 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!")(static_cast <bool> (CI->getNumOperands() == 1 &&
"Expected cast to be unary!") ? void (0) : __assert_fail ("CI->getNumOperands() == 1 && \"Expected cast to be unary!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9944, __extension__
__PRETTY_FUNCTION__))
;
9945 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
9946 Value *Src = CI->getOperand(0);
9947
9948 bool SrcContainsUndef = false;
9949 SetTy SrcPVS;
9950 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
9951 SrcContainsUndef, /* ForSelf */ false))
9952 return indicatePessimisticFixpoint();
9953
9954 if (SrcContainsUndef)
9955 unionAssumedWithUndef();
9956 else {
9957 for (const APInt &S : SrcPVS) {
9958 APInt T = calculateCastInst(CI, S, ResultBitWidth);
9959 unionAssumed(T);
9960 }
9961 }
9962 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9963 : ChangeStatus::CHANGED;
9964 }
9965
9966 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
9967 auto AssumedBefore = getAssumed();
9968 Value *LHS = BinOp->getOperand(0);
9969 Value *RHS = BinOp->getOperand(1);
9970
9971 bool LHSContainsUndef = false, RHSContainsUndef = false;
9972 SetTy LHSAAPVS, RHSAAPVS;
9973 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9974 LHSContainsUndef, /* ForSelf */ false) ||
9975 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9976 RHSContainsUndef, /* ForSelf */ false))
9977 return indicatePessimisticFixpoint();
9978
9979 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
9980
9981 // TODO: make use of undef flag to limit potential values aggressively.
9982 if (LHSContainsUndef && RHSContainsUndef) {
9983 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
9984 return indicatePessimisticFixpoint();
9985 } else if (LHSContainsUndef) {
9986 for (const APInt &R : RHSAAPVS) {
9987 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
9988 return indicatePessimisticFixpoint();
9989 }
9990 } else if (RHSContainsUndef) {
9991 for (const APInt &L : LHSAAPVS) {
9992 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
9993 return indicatePessimisticFixpoint();
9994 }
9995 } else {
9996 for (const APInt &L : LHSAAPVS) {
9997 for (const APInt &R : RHSAAPVS) {
9998 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9999 return indicatePessimisticFixpoint();
10000 }
10001 }
10002 }
10003 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10004 : ChangeStatus::CHANGED;
10005 }
10006
10007 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
10008 auto AssumedBefore = getAssumed();
10009 SetTy Incoming;
10010 bool ContainsUndef;
10011 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
10012 ContainsUndef, /* ForSelf */ true))
10013 return indicatePessimisticFixpoint();
10014 if (ContainsUndef) {
10015 unionAssumedWithUndef();
10016 } else {
10017 for (const auto &It : Incoming)
10018 unionAssumed(It);
10019 }
10020 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10021 : ChangeStatus::CHANGED;
10022 }
10023
10024 /// See AbstractAttribute::updateImpl(...).
10025 ChangeStatus updateImpl(Attributor &A) override {
10026 Value &V = getAssociatedValue();
10027 Instruction *I = dyn_cast<Instruction>(&V);
10028
10029 if (auto *ICI = dyn_cast<ICmpInst>(I))
10030 return updateWithICmpInst(A, ICI);
10031
10032 if (auto *SI = dyn_cast<SelectInst>(I))
10033 return updateWithSelectInst(A, SI);
10034
10035 if (auto *CI = dyn_cast<CastInst>(I))
10036 return updateWithCastInst(A, CI);
10037
10038 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
10039 return updateWithBinaryOperator(A, BinOp);
10040
10041 if (isa<PHINode>(I) || isa<LoadInst>(I))
10042 return updateWithInstruction(A, I);
10043
10044 return indicatePessimisticFixpoint();
10045 }
10046
10047 /// See AbstractAttribute::trackStatistics()
10048 void trackStatistics() const override {
10049 STATS_DECLTRACK_FLOATING_ATTR(potential_values){ static llvm::Statistic NumIRFloating_potential_values = {"attributor"
, "NumIRFloating_potential_values", ("Number of floating values known to be '"
"potential_values" "'")};; ++(NumIRFloating_potential_values
); }
10050 }
10051};
10052
10053struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10054 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
10055 : AAPotentialConstantValuesImpl(IRP, A) {}
10056
10057 /// See AbstractAttribute::initialize(...).
10058 ChangeStatus updateImpl(Attributor &A) override {
10059 llvm_unreachable(::llvm::llvm_unreachable_internal("AAPotentialConstantValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 10061)
10060 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "::llvm::llvm_unreachable_internal("AAPotentialConstantValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 10061)
10061 "not be called")::llvm::llvm_unreachable_internal("AAPotentialConstantValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 10061)
;
10062 }
10063
10064 /// See AbstractAttribute::trackStatistics()
10065 void trackStatistics() const override {
10066 STATS_DECLTRACK_FN_ATTR(potential_values){ static llvm::Statistic NumIRFunction_potential_values = {"attributor"
, "NumIRFunction_potential_values", ("Number of " "functions"
" marked '" "potential_values" "'")};; ++(NumIRFunction_potential_values
); }
10067 }
10068};
10069
10070struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10071 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
10072 : AAPotentialConstantValuesFunction(IRP, A) {}
10073
10074 /// See AbstractAttribute::trackStatistics()
10075 void trackStatistics() const override {
10076 STATS_DECLTRACK_CS_ATTR(potential_values){ static llvm::Statistic NumIRCS_potential_values = {"attributor"
, "NumIRCS_potential_values", ("Number of " "call site" " marked '"
"potential_values" "'")};; ++(NumIRCS_potential_values); }
10077 }
10078};
10079
10080struct AAPotentialConstantValuesCallSiteReturned
10081 : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
10082 AAPotentialConstantValuesImpl> {
10083 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
10084 Attributor &A)
10085 : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
10086 AAPotentialConstantValuesImpl>(IRP, A) {}
10087
10088 /// See AbstractAttribute::trackStatistics()
10089 void trackStatistics() const override {
10090 STATS_DECLTRACK_CSRET_ATTR(potential_values){ static llvm::Statistic NumIRCSReturn_potential_values = {"attributor"
, "NumIRCSReturn_potential_values", ("Number of " "call site returns"
" marked '" "potential_values" "'")};; ++(NumIRCSReturn_potential_values
); }
10091 }
10092};
10093
10094struct AAPotentialConstantValuesCallSiteArgument
10095 : AAPotentialConstantValuesFloating {
10096 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
10097 Attributor &A)
10098 : AAPotentialConstantValuesFloating(IRP, A) {}
10099
10100 /// See AbstractAttribute::initialize(..).
10101 void initialize(Attributor &A) override {
10102 AAPotentialConstantValuesImpl::initialize(A);
10103 if (isAtFixpoint())
10104 return;
10105
10106 Value &V = getAssociatedValue();
10107
10108 if (auto *C = dyn_cast<ConstantInt>(&V)) {
10109 unionAssumed(C->getValue());
10110 indicateOptimisticFixpoint();
10111 return;
10112 }
10113
10114 if (isa<UndefValue>(&V)) {
10115 unionAssumedWithUndef();
10116 indicateOptimisticFixpoint();
10117 return;
10118 }
10119 }
10120
10121 /// See AbstractAttribute::updateImpl(...).
10122 ChangeStatus updateImpl(Attributor &A) override {
10123 Value &V = getAssociatedValue();
10124 auto AssumedBefore = getAssumed();
10125 auto &AA = A.getAAFor<AAPotentialConstantValues>(
10126 *this, IRPosition::value(V), DepClassTy::REQUIRED);
10127 const auto &S = AA.getAssumed();
10128 unionAssumed(S);
10129 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10130 : ChangeStatus::CHANGED;
10131 }
10132
10133 /// See AbstractAttribute::trackStatistics()
10134 void trackStatistics() const override {
10135 STATS_DECLTRACK_CSARG_ATTR(potential_values){ static llvm::Statistic NumIRCSArguments_potential_values = {
"attributor", "NumIRCSArguments_potential_values", ("Number of "
"call site arguments" " marked '" "potential_values" "'")};;
++(NumIRCSArguments_potential_values); }
10136 }
10137};
10138
10139/// ------------------------ NoUndef Attribute ---------------------------------
10140struct AANoUndefImpl : AANoUndef {
10141 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
10142
10143 /// See AbstractAttribute::initialize(...).
10144 void initialize(Attributor &A) override {
10145 if (getIRPosition().hasAttr({Attribute::NoUndef})) {
10146 indicateOptimisticFixpoint();
10147 return;
10148 }
10149 Value &V = getAssociatedValue();
10150 if (isa<UndefValue>(V))
10151 indicatePessimisticFixpoint();
10152 else if (isa<FreezeInst>(V))
10153 indicateOptimisticFixpoint();
10154 else if (getPositionKind() != IRPosition::IRP_RETURNED &&
10155 isGuaranteedNotToBeUndefOrPoison(&V))
10156 indicateOptimisticFixpoint();
10157 else
10158 AANoUndef::initialize(A);
10159 }
10160
10161 /// See followUsesInMBEC
10162 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10163 AANoUndef::StateType &State) {
10164 const Value *UseV = U->get();
10165 const DominatorTree *DT = nullptr;
10166 AssumptionCache *AC = nullptr;
10167 InformationCache &InfoCache = A.getInfoCache();
10168 if (Function *F = getAnchorScope()) {
10169 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10170 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10171 }
10172 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10173 bool TrackUse = false;
10174 // Track use for instructions which must produce undef or poison bits when
10175 // at least one operand contains such bits.
10176 if (isa<CastInst>(*I) || isa<GetElementPtrInst>(*I))
10177 TrackUse = true;
10178 return TrackUse;
10179 }
10180
10181 /// See AbstractAttribute::getAsStr().
10182 const std::string getAsStr() const override {
10183 return getAssumed() ? "noundef" : "may-undef-or-poison";
10184 }
10185
10186 ChangeStatus manifest(Attributor &A) override {
10187 // We don't manifest noundef attribute for dead positions because the
10188 // associated values with dead positions would be replaced with undef
10189 // values.
10190 bool UsedAssumedInformation = false;
10191 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10192 UsedAssumedInformation))
10193 return ChangeStatus::UNCHANGED;
10194 // A position whose simplified value does not have any value is
10195 // considered to be dead. We don't manifest noundef in such positions for
10196 // the same reason above.
10197 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10198 AA::Interprocedural)
10199 .has_value())
10200 return ChangeStatus::UNCHANGED;
10201 return AANoUndef::manifest(A);
10202 }
10203};
10204
10205struct AANoUndefFloating : public AANoUndefImpl {
10206 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10207 : AANoUndefImpl(IRP, A) {}
10208
10209 /// See AbstractAttribute::initialize(...).
10210 void initialize(Attributor &A) override {
10211 AANoUndefImpl::initialize(A);
10212 if (!getState().isAtFixpoint())
10213 if (Instruction *CtxI = getCtxI())
10214 followUsesInMBEC(*this, A, getState(), *CtxI);
10215 }
10216
10217 /// See AbstractAttribute::updateImpl(...).
10218 ChangeStatus updateImpl(Attributor &A) override {
10219
10220 SmallVector<AA::ValueAndContext> Values;
10221 bool UsedAssumedInformation = false;
10222 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10223 AA::AnyScope, UsedAssumedInformation)) {
10224 Values.push_back({getAssociatedValue(), getCtxI()});
10225 }
10226
10227 StateType T;
10228 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10229 const auto &AA = A.getAAFor<AANoUndef>(*this, IRPosition::value(V),
10230 DepClassTy::REQUIRED);
10231 if (this == &AA) {
10232 T.indicatePessimisticFixpoint();
10233 } else {
10234 const AANoUndef::StateType &S =
10235 static_cast<const AANoUndef::StateType &>(AA.getState());
10236 T ^= S;
10237 }
10238 return T.isValidState();
10239 };
10240
10241 for (const auto &VAC : Values)
10242 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10243 return indicatePessimisticFixpoint();
10244
10245 return clampStateAndIndicateChange(getState(), T);
10246 }
10247
10248 /// See AbstractAttribute::trackStatistics()
10249 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef){ static llvm::Statistic NumIRFunctionReturn_noundef = {"attributor"
, "NumIRFunctionReturn_noundef", ("Number of " "function returns"
" marked '" "noundef" "'")};; ++(NumIRFunctionReturn_noundef
); }
}
10250};
10251
10252struct AANoUndefReturned final
10253 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10254 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10255 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10256
10257 /// See AbstractAttribute::trackStatistics()
10258 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef){ static llvm::Statistic NumIRFunctionReturn_noundef = {"attributor"
, "NumIRFunctionReturn_noundef", ("Number of " "function returns"
" marked '" "noundef" "'")};; ++(NumIRFunctionReturn_noundef
); }
}
10259};
10260
10261struct AANoUndefArgument final
10262 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10263 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10264 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10265
10266 /// See AbstractAttribute::trackStatistics()
10267 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef){ static llvm::Statistic NumIRArguments_noundef = {"attributor"
, "NumIRArguments_noundef", ("Number of " "arguments" " marked '"
"noundef" "'")};; ++(NumIRArguments_noundef); }
}
10268};
10269
10270struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10271 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10272 : AANoUndefFloating(IRP, A) {}
10273
10274 /// See AbstractAttribute::trackStatistics()
10275 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef){ static llvm::Statistic NumIRCSArguments_noundef = {"attributor"
, "NumIRCSArguments_noundef", ("Number of " "call site arguments"
" marked '" "noundef" "'")};; ++(NumIRCSArguments_noundef); }
}
10276};
10277
10278struct AANoUndefCallSiteReturned final
10279 : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl> {
10280 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10281 : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl>(IRP, A) {}
10282
10283 /// See AbstractAttribute::trackStatistics()
10284 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef){ static llvm::Statistic NumIRCSReturn_noundef = {"attributor"
, "NumIRCSReturn_noundef", ("Number of " "call site returns" " marked '"
"noundef" "'")};; ++(NumIRCSReturn_noundef); }
}
10285};
10286
10287/// ------------------------ NoFPClass Attribute -------------------------------
10288
10289struct AANoFPClassImpl : AANoFPClass {
10290 AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}
10291
10292 void initialize(Attributor &A) override {
10293 const IRPosition &IRP = getIRPosition();
10294
10295 Value &V = IRP.getAssociatedValue();
10296 if (isa<UndefValue>(V)) {
10297 indicateOptimisticFixpoint();
10298 return;
10299 }
10300
10301 SmallVector<Attribute> Attrs;
10302 IRP.getAttrs({Attribute::NoFPClass}, Attrs, false, &A);
10303 if (!Attrs.empty()) {
10304 addKnownBits(Attrs[0].getNoFPClass());
10305 return;
10306 }
10307
10308 const DataLayout &DL = A.getDataLayout();
10309 if (getPositionKind() != IRPosition::IRP_RETURNED) {
10310 KnownFPClass KnownFPClass = computeKnownFPClass(&V, DL);
10311 addKnownBits(~KnownFPClass.KnownFPClasses);
10312 }
10313
10314 if (Instruction *CtxI = getCtxI())
10315 followUsesInMBEC(*this, A, getState(), *CtxI);
10316 }
10317
10318 /// See followUsesInMBEC
10319 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10320 AANoFPClass::StateType &State) {
10321 const Value *UseV = U->get();
10322 const DominatorTree *DT = nullptr;
10323 AssumptionCache *AC = nullptr;
10324 const TargetLibraryInfo *TLI = nullptr;
10325 InformationCache &InfoCache = A.getInfoCache();
10326
10327 if (Function *F = getAnchorScope()) {
10328 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10329 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10330 TLI = InfoCache.getTargetLibraryInfoForFunction(*F);
10331 }
10332
10333 const DataLayout &DL = A.getDataLayout();
10334
10335 KnownFPClass KnownFPClass =
10336 computeKnownFPClass(UseV, DL,
10337 /*InterestedClasses=*/fcAllFlags,
10338 /*Depth=*/0, TLI, AC, I, DT);
10339 State.addKnownBits(~KnownFPClass.KnownFPClasses);
10340
10341 bool TrackUse = false;
10342 return TrackUse;
10343 }
10344
10345 const std::string getAsStr() const override {
10346 std::string Result = "nofpclass";
10347 raw_string_ostream OS(Result);
10348 OS << getAssumedNoFPClass();
10349 return Result;
10350 }
10351
10352 void getDeducedAttributes(LLVMContext &Ctx,
10353 SmallVectorImpl<Attribute> &Attrs) const override {
10354 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10355 }
10356};
10357
10358struct AANoFPClassFloating : public AANoFPClassImpl {
10359 AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
10360 : AANoFPClassImpl(IRP, A) {}
10361
10362 /// See AbstractAttribute::initialize(...).
10363 void initialize(Attributor &A) override {
10364 AANoFPClassImpl::initialize(A);
10365 }
10366
10367 /// See AbstractAttribute::updateImpl(...).
10368 ChangeStatus updateImpl(Attributor &A) override {
10369 SmallVector<AA::ValueAndContext> Values;
10370 bool UsedAssumedInformation = false;
10371 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10372 AA::AnyScope, UsedAssumedInformation)) {
10373 Values.push_back({getAssociatedValue(), getCtxI()});
10374 }
10375
10376 StateType T;
10377 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10378 const auto &AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),
10379 DepClassTy::REQUIRED);
10380 if (this == &AA) {
10381 T.indicatePessimisticFixpoint();
10382 } else {
10383 const AANoFPClass::StateType &S =
10384 static_cast<const AANoFPClass::StateType &>(AA.getState());
10385 T ^= S;
10386 }
10387 return T.isValidState();
10388 };
10389
10390 for (const auto &VAC : Values)
10391 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10392 return indicatePessimisticFixpoint();
10393
10394 return clampStateAndIndicateChange(getState(), T);
10395 }
10396
10397 /// See AbstractAttribute::trackStatistics()
10398 void trackStatistics() const override {
10399 STATS_DECLTRACK_FNRET_ATTR(nofpclass){ static llvm::Statistic NumIRFunctionReturn_nofpclass = {"attributor"
, "NumIRFunctionReturn_nofpclass", ("Number of " "function returns"
" marked '" "nofpclass" "'")};; ++(NumIRFunctionReturn_nofpclass
); }
10400 }
10401};
10402
10403struct AANoFPClassReturned final
10404 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl> {
10405 AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
10406 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10407
10408 /// See AbstractAttribute::trackStatistics()
10409 void trackStatistics() const override {
10410 STATS_DECLTRACK_FNRET_ATTR(nofpclass){ static llvm::Statistic NumIRFunctionReturn_nofpclass = {"attributor"
, "NumIRFunctionReturn_nofpclass", ("Number of " "function returns"
" marked '" "nofpclass" "'")};; ++(NumIRFunctionReturn_nofpclass
); }
10411 }
10412};
10413
10414struct AANoFPClassArgument final
10415 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10416 AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
10417 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10418
10419 /// See AbstractAttribute::trackStatistics()
10420 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass){ static llvm::Statistic NumIRArguments_nofpclass = {"attributor"
, "NumIRArguments_nofpclass", ("Number of " "arguments" " marked '"
"nofpclass" "'")};; ++(NumIRArguments_nofpclass); }
}
10421};
10422
10423struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10424 AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
10425 : AANoFPClassFloating(IRP, A) {}
10426
10427 /// See AbstractAttribute::trackStatistics()
10428 void trackStatistics() const override {
10429 STATS_DECLTRACK_CSARG_ATTR(nofpclass){ static llvm::Statistic NumIRCSArguments_nofpclass = {"attributor"
, "NumIRCSArguments_nofpclass", ("Number of " "call site arguments"
" marked '" "nofpclass" "'")};; ++(NumIRCSArguments_nofpclass
); }
10430 }
10431};
10432
10433struct AANoFPClassCallSiteReturned final
10434 : AACallSiteReturnedFromReturned<AANoFPClass, AANoFPClassImpl> {
10435 AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
10436 : AACallSiteReturnedFromReturned<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10437
10438 /// See AbstractAttribute::trackStatistics()
10439 void trackStatistics() const override {
10440 STATS_DECLTRACK_CSRET_ATTR(nofpclass){ static llvm::Statistic NumIRCSReturn_nofpclass = {"attributor"
, "NumIRCSReturn_nofpclass", ("Number of " "call site returns"
" marked '" "nofpclass" "'")};; ++(NumIRCSReturn_nofpclass);
}
10441 }
10442};
10443
10444struct AACallEdgesImpl : public AACallEdges {
10445 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10446
10447 const SetVector<Function *> &getOptimisticEdges() const override {
10448 return CalledFunctions;
10449 }
10450
10451 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10452
10453 bool hasNonAsmUnknownCallee() const override {
10454 return HasUnknownCalleeNonAsm;
10455 }
10456
10457 const std::string getAsStr() const override {
10458 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10459 std::to_string(CalledFunctions.size()) + "]";
10460 }
10461
10462 void trackStatistics() const override {}
10463
10464protected:
10465 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10466 if (CalledFunctions.insert(Fn)) {
10467 Change = ChangeStatus::CHANGED;
10468 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AACallEdges] New call edge: "
<< Fn->getName() << "\n"; } } while (false)
10469 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AACallEdges] New call edge: "
<< Fn->getName() << "\n"; } } while (false)
;
10470 }
10471 }
10472
10473 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10474 if (!HasUnknownCallee)
10475 Change = ChangeStatus::CHANGED;
10476 if (NonAsm && !HasUnknownCalleeNonAsm)
10477 Change = ChangeStatus::CHANGED;
10478 HasUnknownCalleeNonAsm |= NonAsm;
10479 HasUnknownCallee = true;
10480 }
10481
10482private:
10483 /// Optimistic set of functions that might be called by this position.
10484 SetVector<Function *> CalledFunctions;
10485
10486 /// Is there any call with a unknown callee.
10487 bool HasUnknownCallee = false;
10488
10489 /// Is there any call with a unknown callee, excluding any inline asm.
10490 bool HasUnknownCalleeNonAsm = false;
10491};
10492
10493struct AACallEdgesCallSite : public AACallEdgesImpl {
10494 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10495 : AACallEdgesImpl(IRP, A) {}
10496 /// See AbstractAttribute::updateImpl(...).
10497 ChangeStatus updateImpl(Attributor &A) override {
10498 ChangeStatus Change = ChangeStatus::UNCHANGED;
10499
10500 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10501 if (Function *Fn = dyn_cast<Function>(&V)) {
10502 addCalledFunction(Fn, Change);
10503 } else {
10504 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AACallEdges] Unrecognized value: "
<< V << "\n"; } } while (false)
;
10505 setHasUnknownCallee(true, Change);
10506 }
10507
10508 // Explore all values.
10509 return true;
10510 };
10511
10512 SmallVector<AA::ValueAndContext> Values;
10513 // Process any value that we might call.
10514 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10515 bool UsedAssumedInformation = false;
10516 Values.clear();
10517 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10518 AA::AnyScope, UsedAssumedInformation)) {
10519 Values.push_back({*V, CtxI});
10520 }
10521 for (auto &VAC : Values)
10522 VisitValue(*VAC.getValue(), VAC.getCtxI());
10523 };
10524
10525 CallBase *CB = cast<CallBase>(getCtxI());
10526
10527 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10528 if (IA->hasSideEffects() &&
10529 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10530 !hasAssumption(*CB, "ompx_no_call_asm")) {
10531 setHasUnknownCallee(false, Change);
10532 }
10533 return Change;
10534 }
10535
10536 // Process callee metadata if available.
10537 if (auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees)) {
10538 for (const auto &Op : MD->operands()) {
10539 Function *Callee = mdconst::dyn_extract_or_null<Function>(Op);
10540 if (Callee)
10541 addCalledFunction(Callee, Change);
10542 }
10543 return Change;
10544 }
10545
10546 // The most simple case.
10547 ProcessCalledOperand(CB->getCalledOperand(), CB);
10548
10549 // Process callback functions.
10550 SmallVector<const Use *, 4u> CallbackUses;
10551 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10552 for (const Use *U : CallbackUses)
10553 ProcessCalledOperand(U->get(), CB);
10554
10555 return Change;
10556 }
10557};
10558
10559struct AACallEdgesFunction : public AACallEdgesImpl {
10560 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10561 : AACallEdgesImpl(IRP, A) {}
10562
10563 /// See AbstractAttribute::updateImpl(...).
10564 ChangeStatus updateImpl(Attributor &A) override {
10565 ChangeStatus Change = ChangeStatus::UNCHANGED;
10566
10567 auto ProcessCallInst = [&](Instruction &Inst) {
10568 CallBase &CB = cast<CallBase>(Inst);
10569
10570 auto &CBEdges = A.getAAFor<AACallEdges>(
10571 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10572 if (CBEdges.hasNonAsmUnknownCallee())
10573 setHasUnknownCallee(true, Change);
10574 if (CBEdges.hasUnknownCallee())
10575 setHasUnknownCallee(false, Change);
10576
10577 for (Function *F : CBEdges.getOptimisticEdges())
10578 addCalledFunction(F, Change);
10579
10580 return true;
10581 };
10582
10583 // Visit all callable instructions.
10584 bool UsedAssumedInformation = false;
10585 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10586 UsedAssumedInformation,
10587 /* CheckBBLivenessOnly */ true)) {
10588 // If we haven't looked at all call like instructions, assume that there
10589 // are unknown callees.
10590 setHasUnknownCallee(true, Change);
10591 }
10592
10593 return Change;
10594 }
10595};
10596
10597/// -------------------AAInterFnReachability Attribute--------------------------
10598
10599struct AAInterFnReachabilityFunction
10600 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10601 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10602 : CachedReachabilityAA<AAInterFnReachability, Function>(IRP, A) {}
10603
10604 bool instructionCanReach(
10605 Attributor &A, const Instruction &From, const Function &To,
10606 const AA::InstExclusionSetTy *ExclusionSet,
10607 SmallPtrSet<const Function *, 16> *Visited) const override {
10608 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!")(static_cast <bool> (From.getFunction() == getAnchorScope
() && "Queried the wrong AA!") ? void (0) : __assert_fail
("From.getFunction() == getAnchorScope() && \"Queried the wrong AA!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 10608, __extension__
__PRETTY_FUNCTION__))
;
10609 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10610
10611 RQITy StackRQI(A, From, To, ExclusionSet, false);
10612 typename RQITy::Reachable Result;
10613 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
10614 return NonConstThis->isReachableImpl(A, StackRQI);
10615 return Result == RQITy::Reachable::Yes;
10616 }
10617
10618 bool isReachableImpl(Attributor &A, RQITy &RQI) override {
10619 return isReachableImpl(A, RQI, nullptr);
10620 }
10621
10622 bool isReachableImpl(Attributor &A, RQITy &RQI,
10623 SmallPtrSet<const Function *, 16> *Visited) {
10624
10625 SmallPtrSet<const Function *, 16> LocalVisited;
10626 if (!Visited)
10627 Visited = &LocalVisited;
10628
10629 auto CheckReachableCallBase = [&](CallBase *CB) {
10630 auto &CBEdges = A.getAAFor<AACallEdges>(
10631 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10632 if (!CBEdges.getState().isValidState())
10633 return false;
10634 // TODO Check To backwards in this case.
10635 if (CBEdges.hasUnknownCallee())
10636 return false;
10637
10638 for (Function *Fn : CBEdges.getOptimisticEdges()) {
10639 if (Fn == RQI.To)
10640 return false;
10641 if (!Visited->insert(Fn).second)
10642 continue;
10643 if (Fn->isDeclaration()) {
10644 if (Fn->hasFnAttribute(Attribute::NoCallback))
10645 continue;
10646 // TODO Check To backwards in this case.
10647 return false;
10648 }
10649
10650 const AAInterFnReachability *InterFnReachability = this;
10651 if (Fn != getAnchorScope())
10652 InterFnReachability = &A.getAAFor<AAInterFnReachability>(
10653 *this, IRPosition::function(*Fn), DepClassTy::OPTIONAL);
10654
10655 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10656 if (InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10657 RQI.ExclusionSet, Visited))
10658 return false;
10659 }
10660 return true;
10661 };
10662
10663 const auto &IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10664 *this, IRPosition::function(*RQI.From->getFunction()),
10665 DepClassTy::OPTIONAL);
10666
10667 // Determine call like instructions that we can reach from the inst.
10668 auto CheckCallBase = [&](Instruction &CBInst) {
10669 if (!IntraFnReachability.isAssumedReachable(A, *RQI.From, CBInst,
10670 RQI.ExclusionSet))
10671 return true;
10672 return CheckReachableCallBase(cast<CallBase>(&CBInst));
10673 };
10674
10675 bool UsedExclusionSet = /* conservative */ true;
10676 bool UsedAssumedInformation = false;
10677 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10678 UsedAssumedInformation,
10679 /* CheckBBLivenessOnly */ true))
10680 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet);
10681
10682 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);
10683 }
10684
10685 void trackStatistics() const override {}
10686
10687private:
10688 SmallVector<RQITy *> QueryVector;
10689 DenseSet<RQITy *> QueryCache;
10690};
10691} // namespace
10692
10693template <typename AAType>
10694static std::optional<Constant *>
10695askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA,
10696 const IRPosition &IRP, Type &Ty) {
10697 if (!Ty.isIntegerTy())
10698 return nullptr;
10699
10700 // This will also pass the call base context.
10701 const auto &AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10702
10703 std::optional<Constant *> COpt = AA.getAssumedConstant(A);
10704
10705 if (!COpt.has_value()) {
10706 A.recordDependence(AA, QueryingAA, DepClassTy::OPTIONAL);
10707 return std::nullopt;
10708 }
10709 if (auto *C = *COpt) {
10710 A.recordDependence(AA, QueryingAA, DepClassTy::OPTIONAL);
10711 return C;
10712 }
10713 return nullptr;
10714}
10715
10716Value *AAPotentialValues::getSingleValue(
10717 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10718 SmallVectorImpl<AA::ValueAndContext> &Values) {
10719 Type &Ty = *IRP.getAssociatedType();
10720 std::optional<Value *> V;
10721 for (auto &It : Values) {
10722 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10723 if (V.has_value() && !*V)
10724 break;
10725 }
10726 if (!V.has_value())
10727 return UndefValue::get(&Ty);
10728 return *V;
10729}
10730
10731namespace {
10732struct AAPotentialValuesImpl : AAPotentialValues {
10733 using StateType = PotentialLLVMValuesState;
10734
10735 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10736 : AAPotentialValues(IRP, A) {}
10737
10738 /// See AbstractAttribute::initialize(..).
10739 void initialize(Attributor &A) override {
10740 if (A.hasSimplificationCallback(getIRPosition())) {
10741 indicatePessimisticFixpoint();
10742 return;
10743 }
10744 Value *Stripped = getAssociatedValue().stripPointerCasts();
10745 auto *CE = dyn_cast<ConstantExpr>(Stripped);
10746 if (isa<Constant>(Stripped) &&
10747 (!CE || CE->getOpcode() != Instruction::ICmp)) {
10748 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10749 getAnchorScope());
10750 indicateOptimisticFixpoint();
10751 return;
10752 }
10753 AAPotentialValues::initialize(A);
10754 }
10755
10756 /// See AbstractAttribute::getAsStr().
10757 const std::string getAsStr() const override {
10758 std::string Str;
10759 llvm::raw_string_ostream OS(Str);
10760 OS << getState();
10761 return OS.str();
10762 }
10763
10764 template <typename AAType>
10765 static std::optional<Value *> askOtherAA(Attributor &A,
10766 const AbstractAttribute &AA,
10767 const IRPosition &IRP, Type &Ty) {
10768 if (isa<Constant>(IRP.getAssociatedValue()))
10769 return &IRP.getAssociatedValue();
10770 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10771 if (!C)
10772 return std::nullopt;
10773 if (*C)
10774 if (auto *CC = AA::getWithType(**C, Ty))
10775 return CC;
10776 return nullptr;
10777 }
10778
10779 void addValue(Attributor &A, StateType &State, Value &V,
10780 const Instruction *CtxI, AA::ValueScope S,
10781 Function *AnchorScope) const {
10782
10783 IRPosition ValIRP = IRPosition::value(V);
10784 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
10785 for (const auto &U : CB->args()) {
10786 if (U.get() != &V)
10787 continue;
10788 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
10789 break;
10790 }
10791 }
10792
10793 Value *VPtr = &V;
10794 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10795 Type &Ty = *getAssociatedType();
10796 std::optional<Value *> SimpleV =
10797 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
10798 if (SimpleV.has_value() && !*SimpleV) {
10799 auto &PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10800 *this, ValIRP, DepClassTy::OPTIONAL);
10801 if (PotentialConstantsAA.isValidState()) {
10802 for (const auto &It : PotentialConstantsAA.getAssumedSet())
10803 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
10804 if (PotentialConstantsAA.undefIsContained())
10805 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
10806 return;
10807 }
10808 }
10809 if (!SimpleV.has_value())
10810 return;
10811
10812 if (*SimpleV)
10813 VPtr = *SimpleV;
10814 }
10815
10816 if (isa<ConstantInt>(VPtr))
10817 CtxI = nullptr;
10818 if (!AA::isValidInScope(*VPtr, AnchorScope))
10819 S = AA::ValueScope(S | AA::Interprocedural);
10820
10821 State.unionAssumed({{*VPtr, CtxI}, S});
10822 }
10823
10824 /// Helper struct to tie a value+context pair together with the scope for
10825 /// which this is the simplified version.
10826 struct ItemInfo {
10827 AA::ValueAndContext I;
10828 AA::ValueScope S;
10829
10830 bool operator==(const ItemInfo &II) const {
10831 return II.I == I && II.S == S;
10832 };
10833 bool operator<(const ItemInfo &II) const {
10834 if (I == II.I)
10835 return S < II.S;
10836 return I < II.I;
10837 };
10838 };
10839
10840 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
10841 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10842 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
10843 if (!(CS & S))
10844 continue;
10845
10846 bool UsedAssumedInformation = false;
10847 SmallVector<AA::ValueAndContext> Values;
10848 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
10849 UsedAssumedInformation))
10850 return false;
10851
10852 for (auto &It : Values)
10853 ValueScopeMap[It] += CS;
10854 }
10855 for (auto &It : ValueScopeMap)
10856 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
10857 AA::ValueScope(It.second), getAnchorScope());
10858
10859 return true;
10860 }
10861
10862 void giveUpOnIntraprocedural(Attributor &A) {
10863 auto NewS = StateType::getBestState(getState());
10864 for (const auto &It : getAssumedSet()) {
10865 if (It.second == AA::Intraprocedural)
10866 continue;
10867 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
10868 AA::Interprocedural, getAnchorScope());
10869 }
10870 assert(!undefIsContained() && "Undef should be an explicit value!")(static_cast <bool> (!undefIsContained() && "Undef should be an explicit value!"
) ? void (0) : __assert_fail ("!undefIsContained() && \"Undef should be an explicit value!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 10870, __extension__
__PRETTY_FUNCTION__))
;
10871 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
10872 getAnchorScope());
10873 getState() = NewS;
10874 }
10875
10876 /// See AbstractState::indicatePessimisticFixpoint(...).
10877 ChangeStatus indicatePessimisticFixpoint() override {
10878 getState() = StateType::getBestState(getState());
10879 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
10880 AAPotentialValues::indicateOptimisticFixpoint();
10881 return ChangeStatus::CHANGED;
10882 }
10883
10884 /// See AbstractAttribute::updateImpl(...).
10885 ChangeStatus updateImpl(Attributor &A) override {
10886 return indicatePessimisticFixpoint();
10887 }
10888
10889 /// See AbstractAttribute::manifest(...).
10890 ChangeStatus manifest(Attributor &A) override {
10891 SmallVector<AA::ValueAndContext> Values;
10892 for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {
10893 Values.clear();
10894 if (!getAssumedSimplifiedValues(A, Values, S))
10895 continue;
10896 Value &OldV = getAssociatedValue();
10897 if (isa<UndefValue>(OldV))
10898 continue;
10899 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
10900 if (!NewV || NewV == &OldV)
10901 continue;
10902 if (getCtxI() &&
10903 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
10904 continue;
10905 if (A.changeAfterManifest(getIRPosition(), *NewV))
10906 return ChangeStatus::CHANGED;
10907 }
10908 return ChangeStatus::UNCHANGED;
10909 }
10910
10911 bool getAssumedSimplifiedValues(Attributor &A,
10912 SmallVectorImpl<AA::ValueAndContext> &Values,
10913 AA::ValueScope S) const override {
10914 if (!isValidState())
10915 return false;
10916 for (const auto &It : getAssumedSet())
10917 if (It.second & S)
10918 Values.push_back(It.first);
10919 assert(!undefIsContained() && "Undef should be an explicit value!")(static_cast <bool> (!undefIsContained() && "Undef should be an explicit value!"
) ? void (0) : __assert_fail ("!undefIsContained() && \"Undef should be an explicit value!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 10919, __extension__
__PRETTY_FUNCTION__))
;
10920 return true;
10921 }
10922};
10923
10924struct AAPotentialValuesFloating : AAPotentialValuesImpl {
10925 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
10926 : AAPotentialValuesImpl(IRP, A) {}
10927
10928 /// See AbstractAttribute::updateImpl(...).
10929 ChangeStatus updateImpl(Attributor &A) override {
10930 auto AssumedBefore = getAssumed();
10931
10932 genericValueTraversal(A);
10933
10934 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10935 : ChangeStatus::CHANGED;
10936 }
10937
10938 /// Helper struct to remember which AAIsDead instances we actually used.
10939 struct LivenessInfo {
10940 const AAIsDead *LivenessAA = nullptr;
10941 bool AnyDead = false;
10942 };
10943
10944 /// Check if \p Cmp is a comparison we can simplify.
10945 ///
10946 /// We handle multiple cases, one in which at least one operand is an
10947 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
10948 /// operand. Return true if successful, in that case Worklist will be updated.
10949 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
10950 CmpInst::Predicate Pred, ItemInfo II,
10951 SmallVectorImpl<ItemInfo> &Worklist) {
10952
10953 // Simplify the operands first.
10954 bool UsedAssumedInformation = false;
10955 const auto &SimplifiedLHS = A.getAssumedSimplified(
10956 IRPosition::value(*LHS, getCallBaseContext()), *this,
10957 UsedAssumedInformation, AA::Intraprocedural);
10958 if (!SimplifiedLHS.has_value())
10959 return true;
10960 if (!*SimplifiedLHS)
10961 return false;
10962 LHS = *SimplifiedLHS;
10963
10964 const auto &SimplifiedRHS = A.getAssumedSimplified(
10965 IRPosition::value(*RHS, getCallBaseContext()), *this,
10966 UsedAssumedInformation, AA::Intraprocedural);
10967 if (!SimplifiedRHS.has_value())
10968 return true;
10969 if (!*SimplifiedRHS)
10970 return false;
10971 RHS = *SimplifiedRHS;
10972
10973 LLVMContext &Ctx = LHS->getContext();
10974 // Handle the trivial case first in which we don't even need to think about
10975 // null or non-null.
10976 if (LHS == RHS &&
10977 (CmpInst::isTrueWhenEqual(Pred) || CmpInst::isFalseWhenEqual(Pred))) {
10978 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
10979 CmpInst::isTrueWhenEqual(Pred));
10980 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
10981 getAnchorScope());
10982 return true;
10983 }
10984
10985 // From now on we only handle equalities (==, !=).
10986 if (!CmpInst::isEquality(Pred))
10987 return false;
10988
10989 bool LHSIsNull = isa<ConstantPointerNull>(LHS);
10990 bool RHSIsNull = isa<ConstantPointerNull>(RHS);
10991 if (!LHSIsNull && !RHSIsNull)
10992 return false;
10993
10994 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
10995 // non-nullptr operand and if we assume it's non-null we can conclude the
10996 // result of the comparison.
10997 assert((LHSIsNull || RHSIsNull) &&(static_cast <bool> ((LHSIsNull || RHSIsNull) &&
"Expected nullptr versus non-nullptr comparison at this point"
) ? void (0) : __assert_fail ("(LHSIsNull || RHSIsNull) && \"Expected nullptr versus non-nullptr comparison at this point\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 10998, __extension__
__PRETTY_FUNCTION__))
10998 "Expected nullptr versus non-nullptr comparison at this point")(static_cast <bool> ((LHSIsNull || RHSIsNull) &&
"Expected nullptr versus non-nullptr comparison at this point"
) ? void (0) : __assert_fail ("(LHSIsNull || RHSIsNull) && \"Expected nullptr versus non-nullptr comparison at this point\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 10998, __extension__
__PRETTY_FUNCTION__))
;
10999
11000 // The index is the operand that we assume is not null.
11001 unsigned PtrIdx = LHSIsNull;
11002 auto &PtrNonNullAA = A.getAAFor<AANonNull>(
11003 *this, IRPosition::value(*(PtrIdx ? RHS : LHS)), DepClassTy::REQUIRED);
11004 if (!PtrNonNullAA.isAssumedNonNull())
11005 return false;
11006
11007 // The new value depends on the predicate, true for != and false for ==.
11008 Constant *NewV =
11009 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
11010 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S, getAnchorScope());
11011 return true;
11012 }
11013
11014 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
11015 SmallVectorImpl<ItemInfo> &Worklist) {
11016 const Instruction *CtxI = II.I.getCtxI();
11017 bool UsedAssumedInformation = false;
11018
11019 std::optional<Constant *> C =
11020 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
11021 bool NoValueYet = !C.has_value();
11022 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
11023 return true;
11024 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
11025 if (CI->isZero())
11026 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11027 else
11028 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11029 } else if (&SI == &getAssociatedValue()) {
11030 // We could not simplify the condition, assume both values.
11031 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11032 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11033 } else {
11034 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11035 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
11036 if (!SimpleV.has_value())
11037 return true;
11038 if (*SimpleV) {
11039 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
11040 return true;
11041 }
11042 return false;
11043 }
11044 return true;
11045 }
11046
11047 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
11048 SmallVectorImpl<ItemInfo> &Worklist) {
11049 SmallSetVector<Value *, 4> PotentialCopies;
11050 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11051 bool UsedAssumedInformation = false;
11052 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
11053 PotentialValueOrigins, *this,
11054 UsedAssumedInformation,
11055 /* OnlyExact */ true)) {
11056 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Failed to get potentially "
"loaded values for load instruction " << LI << "\n"
; } } while (false)
11057 "loaded values for load instruction "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Failed to get potentially "
"loaded values for load instruction " << LI << "\n"
; } } while (false)
11058 << LI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Failed to get potentially "
"loaded values for load instruction " << LI << "\n"
; } } while (false)
;
11059 return false;
11060 }
11061
11062 // Do not simplify loads that are only used in llvm.assume if we cannot also
11063 // remove all stores that may feed into the load. The reason is that the
11064 // assume is probably worth something as long as the stores are around.
11065 InformationCache &InfoCache = A.getInfoCache();
11066 if (InfoCache.isOnlyUsedByAssume(LI)) {
11067 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
11068 if (!I || isa<AssumeInst>(I))
11069 return true;
11070 if (auto *SI = dyn_cast<StoreInst>(I))
11071 return A.isAssumedDead(SI->getOperandUse(0), this,
11072 /* LivenessAA */ nullptr,
11073 UsedAssumedInformation,
11074 /* CheckBBLivenessOnly */ false);
11075 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
11076 UsedAssumedInformation,
11077 /* CheckBBLivenessOnly */ false);
11078 })) {
11079 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Load is onl used by assumes "
"and we cannot delete all the stores: " << LI <<
"\n"; } } while (false)
11080 "and we cannot delete all the stores: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Load is onl used by assumes "
"and we cannot delete all the stores: " << LI <<
"\n"; } } while (false)
11081 << LI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Load is onl used by assumes "
"and we cannot delete all the stores: " << LI <<
"\n"; } } while (false)
;
11082 return false;
11083 }
11084 }
11085
11086 // Values have to be dynamically unique or we loose the fact that a
11087 // single llvm::Value might represent two runtime values (e.g.,
11088 // stack locations in different recursive calls).
11089 const Instruction *CtxI = II.I.getCtxI();
11090 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
11091 bool AllLocal = ScopeIsLocal;
11092 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
11093 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
11094 return AA::isDynamicallyUnique(A, *this, *PC);
11095 });
11096 if (!DynamicallyUnique) {
11097 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Not all potentially loaded "
"values are dynamically unique: " << LI << "\n";
} } while (false)
11098 "values are dynamically unique: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Not all potentially loaded "
"values are dynamically unique: " << LI << "\n";
} } while (false)
11099 << LI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Not all potentially loaded "
"values are dynamically unique: " << LI << "\n";
} } while (false)
;
11100 return false;
11101 }
11102
11103 for (auto *PotentialCopy : PotentialCopies) {
11104 if (AllLocal) {
11105 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
11106 } else {
11107 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
11108 }
11109 }
11110 if (!AllLocal && ScopeIsLocal)
11111 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
11112 return true;
11113 }
11114
11115 bool handlePHINode(
11116 Attributor &A, PHINode &PHI, ItemInfo II,
11117 SmallVectorImpl<ItemInfo> &Worklist,
11118 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11119 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
11120 LivenessInfo &LI = LivenessAAs[&F];
11121 if (!LI.LivenessAA)
11122 LI.LivenessAA = &A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
11123 DepClassTy::NONE);
11124 return LI;
11125 };
11126
11127 if (&PHI == &getAssociatedValue()) {
11128 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
11129 const auto *CI =
11130 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11131 *PHI.getFunction());
11132
11133 Cycle *C = nullptr;
11134 bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);
11135 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
11136 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
11137 if (LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
11138 LI.AnyDead = true;
11139 continue;
11140 }
11141 Value *V = PHI.getIncomingValue(u);
11142 if (V == &PHI)
11143 continue;
11144
11145 // If the incoming value is not the PHI but an instruction in the same
11146 // cycle we might have multiple versions of it flying around.
11147 if (CyclePHI && isa<Instruction>(V) &&
11148 (!C || C->contains(cast<Instruction>(V)->getParent())))
11149 return false;
11150
11151 Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});
11152 }
11153 return true;
11154 }
11155
11156 bool UsedAssumedInformation = false;
11157 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11158 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
11159 if (!SimpleV.has_value())
11160 return true;
11161 if (!(*SimpleV))
11162 return false;
11163 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
11164 return true;
11165 }
11166
11167 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
11168 /// simplify any operand of the instruction \p I. Return true if successful,
11169 /// in that case Worklist will be updated.
11170 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
11171 SmallVectorImpl<ItemInfo> &Worklist) {
11172 bool SomeSimplified = false;
11173 bool UsedAssumedInformation = false;
11174
11175 SmallVector<Value *, 8> NewOps(I.getNumOperands());
11176 int Idx = 0;
11177 for (Value *Op : I.operands()) {
11178 const auto &SimplifiedOp = A.getAssumedSimplified(
11179 IRPosition::value(*Op, getCallBaseContext()), *this,
11180 UsedAssumedInformation, AA::Intraprocedural);
11181 // If we are not sure about any operand we are not sure about the entire
11182 // instruction, we'll wait.
11183 if (!SimplifiedOp.has_value())
11184 return true;
11185
11186 if (*SimplifiedOp)
11187 NewOps[Idx] = *SimplifiedOp;
11188 else
11189 NewOps[Idx] = Op;
11190
11191 SomeSimplified |= (NewOps[Idx] != Op);
11192 ++Idx;
11193 }
11194
11195 // We won't bother with the InstSimplify interface if we didn't simplify any
11196 // operand ourselves.
11197 if (!SomeSimplified)
11198 return false;
11199
11200 InformationCache &InfoCache = A.getInfoCache();
11201 Function *F = I.getFunction();
11202 const auto *DT =
11203 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
11204 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
11205 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
11206
11207 const DataLayout &DL = I.getModule()->getDataLayout();
11208 SimplifyQuery Q(DL, TLI, DT, AC, &I);
11209 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);
11210 if (!NewV || NewV == &I)
11211 return false;
11212
11213 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Generic inst " << I <<
" assumed simplified to " << *NewV << "\n"; } } while
(false)
11214 << *NewV << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Generic inst " << I <<
" assumed simplified to " << *NewV << "\n"; } } while
(false)
;
11215 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
11216 return true;
11217 }
11218
11219 bool simplifyInstruction(
11220 Attributor &A, Instruction &I, ItemInfo II,
11221 SmallVectorImpl<ItemInfo> &Worklist,
11222 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11223 if (auto *CI = dyn_cast<CmpInst>(&I))
11224 if (handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
11225 CI->getPredicate(), II, Worklist))
11226 return true;
11227
11228 switch (I.getOpcode()) {
11229 case Instruction::Select:
11230 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
11231 case Instruction::PHI:
11232 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
11233 case Instruction::Load:
11234 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
11235 default:
11236 return handleGenericInst(A, I, II, Worklist);
11237 };
11238 return false;
11239 }
11240
11241 void genericValueTraversal(Attributor &A) {
11242 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11243
11244 Value *InitialV = &getAssociatedValue();
11245 SmallSet<ItemInfo, 16> Visited;
11246 SmallVector<ItemInfo, 16> Worklist;
11247 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
11248
11249 int Iteration = 0;
11250 do {
11251 ItemInfo II = Worklist.pop_back_val();
11252 Value *V = II.I.getValue();
11253 assert(V)(static_cast <bool> (V) ? void (0) : __assert_fail ("V"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11253, __extension__
__PRETTY_FUNCTION__))
;
11254 const Instruction *CtxI = II.I.getCtxI();
11255 AA::ValueScope S = II.S;
11256
11257 // Check if we should process the current value. To prevent endless
11258 // recursion keep a record of the values we followed!
11259 if (!Visited.insert(II).second)
11260 continue;
11261
11262 // Make sure we limit the compile time for complex expressions.
11263 if (Iteration++ >= MaxPotentialValuesIterations) {
11264 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Generic value traversal reached iteration limit: "
<< Iteration << "!\n"; } } while (false)
11265 << Iteration << "!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Generic value traversal reached iteration limit: "
<< Iteration << "!\n"; } } while (false)
;
11266 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11267 continue;
11268 }
11269
11270 // Explicitly look through calls with a "returned" attribute if we do
11271 // not have a pointer as stripPointerCasts only works on them.
11272 Value *NewV = nullptr;
11273 if (V->getType()->isPointerTy()) {
11274 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
11275 } else {
11276 auto *CB = dyn_cast<CallBase>(V);
11277 if (CB && CB->getCalledFunction()) {
11278 for (Argument &Arg : CB->getCalledFunction()->args())
11279 if (Arg.hasReturnedAttr()) {
11280 NewV = CB->getArgOperand(Arg.getArgNo());
11281 break;
11282 }
11283 }
11284 }
11285 if (NewV && NewV != V) {
11286 Worklist.push_back({{*NewV, CtxI}, S});
11287 continue;
11288 }
11289
11290 if (auto *CE = dyn_cast<ConstantExpr>(V)) {
11291 if (CE->getOpcode() == Instruction::ICmp)
11292 if (handleCmp(A, *CE, CE->getOperand(0), CE->getOperand(1),
11293 CmpInst::Predicate(CE->getPredicate()), II, Worklist))
11294 continue;
11295 }
11296
11297 if (auto *I = dyn_cast<Instruction>(V)) {
11298 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
11299 continue;
11300 }
11301
11302 if (V != InitialV || isa<Argument>(V))
11303 if (recurseForValue(A, IRPosition::value(*V), II.S))
11304 continue;
11305
11306 // If we haven't stripped anything we give up.
11307 if (V == InitialV && CtxI == getCtxI()) {
11308 indicatePessimisticFixpoint();
11309 return;
11310 }
11311
11312 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11313 } while (!Worklist.empty());
11314
11315 // If we actually used liveness information so we have to record a
11316 // dependence.
11317 for (auto &It : LivenessAAs)
11318 if (It.second.AnyDead)
11319 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
11320 }
11321
11322 /// See AbstractAttribute::trackStatistics()
11323 void trackStatistics() const override {
11324 STATS_DECLTRACK_FLOATING_ATTR(potential_values){ static llvm::Statistic NumIRFloating_potential_values = {"attributor"
, "NumIRFloating_potential_values", ("Number of floating values known to be '"
"potential_values" "'")};; ++(NumIRFloating_potential_values
); }
11325 }
11326};
11327
11328struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11329 using Base = AAPotentialValuesImpl;
11330 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11331 : Base(IRP, A) {}
11332
11333 /// See AbstractAttribute::initialize(..).
11334 void initialize(Attributor &A) override {
11335 auto &Arg = cast<Argument>(getAssociatedValue());
11336 if (Arg.hasPointeeInMemoryValueAttr())
11337 indicatePessimisticFixpoint();
11338 }
11339
11340 /// See AbstractAttribute::updateImpl(...).
11341 ChangeStatus updateImpl(Attributor &A) override {
11342 auto AssumedBefore = getAssumed();
11343
11344 unsigned CSArgNo = getCallSiteArgNo();
11345
11346 bool UsedAssumedInformation = false;
11347 SmallVector<AA::ValueAndContext> Values;
11348 auto CallSitePred = [&](AbstractCallSite ACS) {
11349 const auto CSArgIRP = IRPosition::callsite_argument(ACS, CSArgNo);
11350 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11351 return false;
11352
11353 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11354 AA::Interprocedural,
11355 UsedAssumedInformation))
11356 return false;
11357
11358 return isValidState();
11359 };
11360
11361 if (!A.checkForAllCallSites(CallSitePred, *this,
11362 /* RequireAllCallSites */ true,
11363 UsedAssumedInformation))
11364 return indicatePessimisticFixpoint();
11365
11366 Function *Fn = getAssociatedFunction();
11367 bool AnyNonLocal = false;
11368 for (auto &It : Values) {
11369 if (isa<Constant>(It.getValue())) {
11370 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11371 getAnchorScope());
11372 continue;
11373 }
11374 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11375 return indicatePessimisticFixpoint();
11376
11377 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11378 if (Arg->getParent() == Fn) {
11379 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11380 getAnchorScope());
11381 continue;
11382 }
11383 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11384 getAnchorScope());
11385 AnyNonLocal = true;
11386 }
11387 assert(!undefIsContained() && "Undef should be an explicit value!")(static_cast <bool> (!undefIsContained() && "Undef should be an explicit value!"
) ? void (0) : __assert_fail ("!undefIsContained() && \"Undef should be an explicit value!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11387, __extension__
__PRETTY_FUNCTION__))
;
11388 if (AnyNonLocal)
11389 giveUpOnIntraprocedural(A);
11390
11391 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11392 : ChangeStatus::CHANGED;
11393 }
11394
11395 /// See AbstractAttribute::trackStatistics()
11396 void trackStatistics() const override {
11397 STATS_DECLTRACK_ARG_ATTR(potential_values){ static llvm::Statistic NumIRArguments_potential_values = {"attributor"
, "NumIRArguments_potential_values", ("Number of " "arguments"
" marked '" "potential_values" "'")};; ++(NumIRArguments_potential_values
); }
11398 }
11399};
11400
11401struct AAPotentialValuesReturned
11402 : AAReturnedFromReturnedValues<AAPotentialValues, AAPotentialValuesImpl> {
11403 using Base =
11404 AAReturnedFromReturnedValues<AAPotentialValues, AAPotentialValuesImpl>;
11405 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11406 : Base(IRP, A) {}
11407
11408 /// See AbstractAttribute::initialize(..).
11409 void initialize(Attributor &A) override {
11410 if (A.hasSimplificationCallback(getIRPosition()))
11411 indicatePessimisticFixpoint();
11412 else
11413 AAPotentialValues::initialize(A);
11414 }
11415
11416 ChangeStatus manifest(Attributor &A) override {
11417 // We queried AAValueSimplify for the returned values so they will be
11418 // replaced if a simplified form was found. Nothing to do here.
11419 return ChangeStatus::UNCHANGED;
11420 }
11421
11422 ChangeStatus indicatePessimisticFixpoint() override {
11423 return AAPotentialValues::indicatePessimisticFixpoint();
11424 }
11425
11426 /// See AbstractAttribute::trackStatistics()
11427 void trackStatistics() const override {
11428 STATS_DECLTRACK_FNRET_ATTR(potential_values){ static llvm::Statistic NumIRFunctionReturn_potential_values
= {"attributor", "NumIRFunctionReturn_potential_values", ("Number of "
"function returns" " marked '" "potential_values" "'")};; ++
(NumIRFunctionReturn_potential_values); }
11429 }
11430};
11431
11432struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11433 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11434 : AAPotentialValuesImpl(IRP, A) {}
11435
11436 /// See AbstractAttribute::updateImpl(...).
11437 ChangeStatus updateImpl(Attributor &A) override {
11438 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "::llvm::llvm_unreachable_internal("AAPotentialValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 11439)
11439 "not be called")::llvm::llvm_unreachable_internal("AAPotentialValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 11439)
;
11440 }
11441
11442 /// See AbstractAttribute::trackStatistics()
11443 void trackStatistics() const override {
11444 STATS_DECLTRACK_FN_ATTR(potential_values){ static llvm::Statistic NumIRFunction_potential_values = {"attributor"
, "NumIRFunction_potential_values", ("Number of " "functions"
" marked '" "potential_values" "'")};; ++(NumIRFunction_potential_values
); }
11445 }
11446};
11447
11448struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11449 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11450 : AAPotentialValuesFunction(IRP, A) {}
11451
11452 /// See AbstractAttribute::trackStatistics()
11453 void trackStatistics() const override {
11454 STATS_DECLTRACK_CS_ATTR(potential_values){ static llvm::Statistic NumIRCS_potential_values = {"attributor"
, "NumIRCS_potential_values", ("Number of " "call site" " marked '"
"potential_values" "'")};; ++(NumIRCS_potential_values); }
11455 }
11456};
11457
11458struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11459 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11460 : AAPotentialValuesImpl(IRP, A) {}
11461
11462 /// See AbstractAttribute::updateImpl(...).
11463 ChangeStatus updateImpl(Attributor &A) override {
11464 auto AssumedBefore = getAssumed();
11465
11466 Function *Callee = getAssociatedFunction();
11467 if (!Callee)
11468 return indicatePessimisticFixpoint();
11469
11470 bool UsedAssumedInformation = false;
11471 auto *CB = cast<CallBase>(getCtxI());
11472 if (CB->isMustTailCall() &&
11473 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11474 UsedAssumedInformation))
11475 return indicatePessimisticFixpoint();
11476
11477 SmallVector<AA::ValueAndContext> Values;
11478 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11479 Values, AA::Intraprocedural,
11480 UsedAssumedInformation))
11481 return indicatePessimisticFixpoint();
11482
11483 Function *Caller = CB->getCaller();
11484
11485 bool AnyNonLocal = false;
11486 for (auto &It : Values) {
11487 Value *V = It.getValue();
11488 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11489 V, *CB, *this, UsedAssumedInformation);
11490 if (!CallerV.has_value()) {
11491 // Nothing to do as long as no value was determined.
11492 continue;
11493 }
11494 V = *CallerV ? *CallerV : V;
11495 if (AA::isDynamicallyUnique(A, *this, *V) &&
11496 AA::isValidInScope(*V, Caller)) {
11497 if (*CallerV) {
11498 SmallVector<AA::ValueAndContext> ArgValues;
11499 IRPosition IRP = IRPosition::value(*V);
11500 if (auto *Arg = dyn_cast<Argument>(V))
11501 if (Arg->getParent() == CB->getCalledFunction())
11502 IRP = IRPosition::callsite_argument(*CB, Arg->getArgNo());
11503 if (recurseForValue(A, IRP, AA::AnyScope))
11504 continue;
11505 }
11506 addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
11507 } else {
11508 AnyNonLocal = true;
11509 break;
11510 }
11511 }
11512 if (AnyNonLocal) {
11513 Values.clear();
11514 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11515 Values, AA::Interprocedural,
11516 UsedAssumedInformation))
11517 return indicatePessimisticFixpoint();
11518 AnyNonLocal = false;
11519 getState() = PotentialLLVMValuesState::getBestState();
11520 for (auto &It : Values) {
11521 Value *V = It.getValue();
11522 if (!AA::isDynamicallyUnique(A, *this, *V))
11523 return indicatePessimisticFixpoint();
11524 if (AA::isValidInScope(*V, Caller)) {
11525 addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
11526 } else {
11527 AnyNonLocal = true;
11528 addValue(A, getState(), *V, CB, AA::Interprocedural,
11529 getAnchorScope());
11530 }
11531 }
11532 if (AnyNonLocal)
11533 giveUpOnIntraprocedural(A);
11534 }
11535 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11536 : ChangeStatus::CHANGED;
11537 }
11538
11539 ChangeStatus indicatePessimisticFixpoint() override {
11540 return AAPotentialValues::indicatePessimisticFixpoint();
11541 }
11542
11543 /// See AbstractAttribute::trackStatistics()
11544 void trackStatistics() const override {
11545 STATS_DECLTRACK_CSRET_ATTR(potential_values){ static llvm::Statistic NumIRCSReturn_potential_values = {"attributor"
, "NumIRCSReturn_potential_values", ("Number of " "call site returns"
" marked '" "potential_values" "'")};; ++(NumIRCSReturn_potential_values
); }
11546 }
11547};
11548
11549struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11550 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11551 : AAPotentialValuesFloating(IRP, A) {}
11552
11553 /// See AbstractAttribute::trackStatistics()
11554 void trackStatistics() const override {
11555 STATS_DECLTRACK_CSARG_ATTR(potential_values){ static llvm::Statistic NumIRCSArguments_potential_values = {
"attributor", "NumIRCSArguments_potential_values", ("Number of "
"call site arguments" " marked '" "potential_values" "'")};;
++(NumIRCSArguments_potential_values); }
11556 }
11557};
11558} // namespace
11559
11560/// ---------------------- Assumption Propagation ------------------------------
11561namespace {
11562struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11563 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11564 const DenseSet<StringRef> &Known)
11565 : AAAssumptionInfo(IRP, A, Known) {}
11566
11567 bool hasAssumption(const StringRef Assumption) const override {
11568 return isValidState() && setContains(Assumption);
11569 }
11570
11571 /// See AbstractAttribute::getAsStr()
11572 const std::string getAsStr() const override {
11573 const SetContents &Known = getKnown();
11574 const SetContents &Assumed = getAssumed();
11575
11576 const std::string KnownStr =
11577 llvm::join(Known.getSet().begin(), Known.getSet().end(), ",");
11578 const std::string AssumedStr =
11579 (Assumed.isUniversal())
11580 ? "Universal"
11581 : llvm::join(Assumed.getSet().begin(), Assumed.getSet().end(), ",");
11582
11583 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11584 }
11585};
11586
11587/// Propagates assumption information from parent functions to all of their
11588/// successors. An assumption can be propagated if the containing function
11589/// dominates the called function.
11590///
11591/// We start with a "known" set of assumptions already valid for the associated
11592/// function and an "assumed" set that initially contains all possible
11593/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11594/// contents as concrete values are known. The concrete values are seeded by the
11595/// first nodes that are either entries into the call graph, or contains no
11596/// assumptions. Each node is updated as the intersection of the assumed state
11597/// with all of its predecessors.
11598struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11599 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11600 : AAAssumptionInfoImpl(IRP, A,
11601 getAssumptions(*IRP.getAssociatedFunction())) {}
11602
11603 /// See AbstractAttribute::manifest(...).
11604 ChangeStatus manifest(Attributor &A) override {
11605 const auto &Assumptions = getKnown();
11606
11607 // Don't manifest a universal set if it somehow made it here.
11608 if (Assumptions.isUniversal())
11609 return ChangeStatus::UNCHANGED;
11610
11611 Function *AssociatedFunction = getAssociatedFunction();
11612
11613 bool Changed = addAssumptions(*AssociatedFunction, Assumptions.getSet());
11614
11615 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11616 }
11617
11618 /// See AbstractAttribute::updateImpl(...).
11619 ChangeStatus updateImpl(Attributor &A) override {
11620 bool Changed = false;
11621
11622 auto CallSitePred = [&](AbstractCallSite ACS) {
11623 const auto &AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11624 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11625 DepClassTy::REQUIRED);
11626 // Get the set of assumptions shared by all of this function's callers.
11627 Changed |= getIntersection(AssumptionAA.getAssumed());
11628 return !getAssumed().empty() || !getKnown().empty();
11629 };
11630
11631 bool UsedAssumedInformation = false;
11632 // Get the intersection of all assumptions held by this node's predecessors.
11633 // If we don't know all the call sites then this is either an entry into the
11634 // call graph or an empty node. This node is known to only contain its own
11635 // assumptions and can be propagated to its successors.
11636 if (!A.checkForAllCallSites(CallSitePred, *this, true,
11637 UsedAssumedInformation))
11638 return indicatePessimisticFixpoint();
11639
11640 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11641 }
11642
11643 void trackStatistics() const override {}
11644};
11645
11646/// Assumption Info defined for call sites.
11647struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11648
11649 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11650 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11651
11652 /// See AbstractAttribute::initialize(...).
11653 void initialize(Attributor &A) override {
11654 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11655 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11656 }
11657
11658 /// See AbstractAttribute::manifest(...).
11659 ChangeStatus manifest(Attributor &A) override {
11660 // Don't manifest a universal set if it somehow made it here.
11661 if (getKnown().isUniversal())
11662 return ChangeStatus::UNCHANGED;
11663
11664 CallBase &AssociatedCall = cast<CallBase>(getAssociatedValue());
11665 bool Changed = addAssumptions(AssociatedCall, getAssumed().getSet());
11666
11667 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11668 }
11669
11670 /// See AbstractAttribute::updateImpl(...).
11671 ChangeStatus updateImpl(Attributor &A) override {
11672 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11673 auto &AssumptionAA =
11674 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11675 bool Changed = getIntersection(AssumptionAA.getAssumed());
11676 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11677 }
11678
11679 /// See AbstractAttribute::trackStatistics()
11680 void trackStatistics() const override {}
11681
11682private:
11683 /// Helper to initialized the known set as all the assumptions this call and
11684 /// the callee contain.
11685 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11686 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
11687 auto Assumptions = getAssumptions(CB);
11688 if (const Function *F = CB.getCaller())
11689 set_union(Assumptions, getAssumptions(*F));
11690 if (Function *F = IRP.getAssociatedFunction())
11691 set_union(Assumptions, getAssumptions(*F));
11692 return Assumptions;
11693 }
11694};
11695} // namespace
11696
11697AACallGraphNode *AACallEdgeIterator::operator*() const {
11698 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11699 &A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
11700}
11701
11702void AttributorCallGraph::print() { llvm::WriteGraph(outs(), this); }
11703
11704/// ------------------------ UnderlyingObjects ---------------------------------
11705
11706namespace {
11707struct AAUnderlyingObjectsImpl
11708 : StateWrapper<BooleanState, AAUnderlyingObjects> {
11709 using BaseTy = StateWrapper<BooleanState, AAUnderlyingObjects>;
11710 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
11711
11712 /// See AbstractAttribute::getAsStr().
11713 const std::string getAsStr() const override {
11714 return std::string("UnderlyingObjects ") +
11715 (isValidState()
11716 ? (std::string("inter #") +
11717 std::to_string(InterAssumedUnderlyingObjects.size()) +
11718 " objs" + std::string(", intra #") +
11719 std::to_string(IntraAssumedUnderlyingObjects.size()) +
11720 " objs")
11721 : "<invalid>");
11722 }
11723
11724 /// See AbstractAttribute::trackStatistics()
11725 void trackStatistics() const override {}
11726
11727 /// See AbstractAttribute::updateImpl(...).
11728 ChangeStatus updateImpl(Attributor &A) override {
11729 auto &Ptr = getAssociatedValue();
11730
11731 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11732 AA::ValueScope Scope) {
11733 bool UsedAssumedInformation = false;
11734 SmallPtrSet<Value *, 8> SeenObjects;
11735 SmallVector<AA::ValueAndContext> Values;
11736
11737 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
11738 Scope, UsedAssumedInformation))
11739 return UnderlyingObjects.insert(&Ptr);
11740
11741 bool Changed = false;
11742
11743 for (unsigned I = 0; I < Values.size(); ++I) {
11744 auto &VAC = Values[I];
11745 auto *Obj = VAC.getValue();
11746 Value *UO = getUnderlyingObject(Obj);
11747 if (UO && UO != VAC.getValue() && SeenObjects.insert(UO).second) {
11748 const auto &OtherAA = A.getAAFor<AAUnderlyingObjects>(
11749 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
11750 auto Pred = [&Values](Value &V) {
11751 Values.emplace_back(V, nullptr);
11752 return true;
11753 };
11754
11755 if (!OtherAA.forallUnderlyingObjects(Pred, Scope))
11756 llvm_unreachable(::llvm::llvm_unreachable_internal("The forall call should not return false at this position"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11757)
11757 "The forall call should not return false at this position")::llvm::llvm_unreachable_internal("The forall call should not return false at this position"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11757)
;
11758
11759 continue;
11760 }
11761
11762 if (isa<SelectInst>(Obj)) {
11763 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope);
11764 continue;
11765 }
11766 if (auto *PHI = dyn_cast<PHINode>(Obj)) {
11767 // Explicitly look through PHIs as we do not care about dynamically
11768 // uniqueness.
11769 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
11770 Changed |= handleIndirect(A, *PHI->getIncomingValue(u),
11771 UnderlyingObjects, Scope);
11772 }
11773 continue;
11774 }
11775
11776 Changed |= UnderlyingObjects.insert(Obj);
11777 }
11778
11779 return Changed;
11780 };
11781
11782 bool Changed = false;
11783 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
11784 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
11785
11786 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11787 }
11788
11789 bool forallUnderlyingObjects(
11790 function_ref<bool(Value &)> Pred,
11791 AA::ValueScope Scope = AA::Interprocedural) const override {
11792 if (!isValidState())
11793 return Pred(getAssociatedValue());
11794
11795 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
11796 ? IntraAssumedUnderlyingObjects
11797 : InterAssumedUnderlyingObjects;
11798 for (Value *Obj : AssumedUnderlyingObjects)
11799 if (!Pred(*Obj))
11800 return false;
11801
11802 return true;
11803 }
11804
11805private:
11806 /// Handle the case where the value is not the actual underlying value, such
11807 /// as a phi node or a select instruction.
11808 bool handleIndirect(Attributor &A, Value &V,
11809 SmallSetVector<Value *, 8> &UnderlyingObjects,
11810 AA::ValueScope Scope) {
11811 bool Changed = false;
11812 const auto &AA = A.getAAFor<AAUnderlyingObjects>(
11813 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
11814 auto Pred = [&](Value &V) {
11815 Changed |= UnderlyingObjects.insert(&V);
11816 return true;
11817 };
11818 if (!AA.forallUnderlyingObjects(Pred, Scope))
11819 llvm_unreachable(::llvm::llvm_unreachable_internal("The forall call should not return false at this position"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11820)
11820 "The forall call should not return false at this position")::llvm::llvm_unreachable_internal("The forall call should not return false at this position"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11820)
;
11821 return Changed;
11822 }
11823
11824 /// All the underlying objects collected so far via intra procedural scope.
11825 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11826 /// All the underlying objects collected so far via inter procedural scope.
11827 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11828};
11829
11830struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
11831 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
11832 : AAUnderlyingObjectsImpl(IRP, A) {}
11833};
11834
11835struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
11836 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
11837 : AAUnderlyingObjectsImpl(IRP, A) {}
11838};
11839
11840struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
11841 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
11842 : AAUnderlyingObjectsImpl(IRP, A) {}
11843};
11844
11845struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
11846 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
11847 : AAUnderlyingObjectsImpl(IRP, A) {}
11848};
11849
11850struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
11851 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
11852 : AAUnderlyingObjectsImpl(IRP, A) {}
11853};
11854
11855struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
11856 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
11857 : AAUnderlyingObjectsImpl(IRP, A) {}
11858};
11859
11860struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
11861 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
11862 : AAUnderlyingObjectsImpl(IRP, A) {}
11863};
11864}
11865
11866const char AAReturnedValues::ID = 0;
11867const char AANoUnwind::ID = 0;
11868const char AANoSync::ID = 0;
11869const char AANoFree::ID = 0;
11870const char AANonNull::ID = 0;
11871const char AANoRecurse::ID = 0;
11872const char AANonConvergent::ID = 0;
11873const char AAWillReturn::ID = 0;
11874const char AAUndefinedBehavior::ID = 0;
11875const char AANoAlias::ID = 0;
11876const char AAIntraFnReachability::ID = 0;
11877const char AANoReturn::ID = 0;
11878const char AAIsDead::ID = 0;
11879const char AADereferenceable::ID = 0;
11880const char AAAlign::ID = 0;
11881const char AAInstanceInfo::ID = 0;
11882const char AANoCapture::ID = 0;
11883const char AAValueSimplify::ID = 0;
11884const char AAHeapToStack::ID = 0;
11885const char AAPrivatizablePtr::ID = 0;
11886const char AAMemoryBehavior::ID = 0;
11887const char AAMemoryLocation::ID = 0;
11888const char AAValueConstantRange::ID = 0;
11889const char AAPotentialConstantValues::ID = 0;
11890const char AAPotentialValues::ID = 0;
11891const char AANoUndef::ID = 0;
11892const char AANoFPClass::ID = 0;
11893const char AACallEdges::ID = 0;
11894const char AAInterFnReachability::ID = 0;
11895const char AAPointerInfo::ID = 0;
11896const char AAAssumptionInfo::ID = 0;
11897const char AAUnderlyingObjects::ID = 0;
11898
11899// Macro magic to create the static generator function for attributes that
11900// follow the naming scheme.
11901
11902#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
11903 case IRPosition::PK: \
11904 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!")::llvm::llvm_unreachable_internal("Cannot create " #CLASS " for a "
POS_NAME " position!", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 11904)
;
11905
11906#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
11907 case IRPosition::PK: \
11908 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
11909 ++NumAAs; \
11910 break;
11911
11912#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11913 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11914 CLASS *AA = nullptr; \
11915 switch (IRP.getPositionKind()) { \
11916 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11917 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
11918 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
11919 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11920 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
11921 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
11922 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11923 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11924 } \
11925 return *AA; \
11926 }
11927
11928#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11929 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11930 CLASS *AA = nullptr; \
11931 switch (IRP.getPositionKind()) { \
11932 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11933 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
11934 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
11935 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11936 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11937 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
11938 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11939 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11940 } \
11941 return *AA; \
11942 }
11943
11944#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11945 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11946 CLASS *AA = nullptr; \
11947 switch (IRP.getPositionKind()) { \
11948 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11949 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11950 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11951 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11952 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11953 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
11954 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11955 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11956 } \
11957 return *AA; \
11958 }
11959
11960#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11961 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11962 CLASS *AA = nullptr; \
11963 switch (IRP.getPositionKind()) { \
11964 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11965 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
11966 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
11967 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11968 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
11969 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
11970 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
11971 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11972 } \
11973 return *AA; \
11974 }
11975
11976#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11977 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11978 CLASS *AA = nullptr; \
11979 switch (IRP.getPositionKind()) { \
11980 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11981 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11982 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11983 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11984 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11985 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11986 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11987 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11988 } \
11989 return *AA; \
11990 }
11991
11992CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
11993CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
11994CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
11995CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
11996CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
11997CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues)
11998CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation)
11999CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges)
12000CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAssumptionInfo)
12001
12002CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
12003CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
12004CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPrivatizablePtr)
12005CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
12006CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
12007CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInstanceInfo)
12008CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
12009CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange)
12010CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialConstantValues)
12011CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues)
12012CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef)
12013CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFPClass)
12014CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo)
12015
12016CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)
12017CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
12018CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
12019CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUnderlyingObjects)
12020
12021CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)
12022CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior)
12023CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonConvergent)
12024CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIntraFnReachability)
12025CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInterFnReachability)
12026
12027CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)
12028
12029#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
12030#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
12031#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
12032#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
12033#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
12034#undef SWITCH_PK_CREATE
12035#undef SWITCH_PK_INV