Bug Summary

File:build/source/llvm/include/llvm/Analysis/ValueTracking.h
Warning:line 274, column 47
Called C++ object pointer is null

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 -resource-dir /usr/lib/llvm-17/lib/clang/17 -I lib/Transforms/IPO -I /build/source/llvm/lib/Transforms/IPO -I include -I /build/source/llvm/include -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -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=build-llvm -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm=build-llvm -fcoverage-prefix-map=/build/source/= -source-date-epoch 1675682001 -O3 -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 -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -fdebug-prefix-map=/build/source/build-llvm=build-llvm -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-02-06-130241-16458-1 -x c++ /build/source/llvm/lib/Transforms/IPO/AttributorAttributes.cpp

/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(AAWillReturn)
160PIPE_OPERATOR(AANoReturn)
161PIPE_OPERATOR(AAReturnedValues)
162PIPE_OPERATOR(AANonNull)
163PIPE_OPERATOR(AANoAlias)
164PIPE_OPERATOR(AADereferenceable)
165PIPE_OPERATOR(AAAlign)
166PIPE_OPERATOR(AAInstanceInfo)
167PIPE_OPERATOR(AANoCapture)
168PIPE_OPERATOR(AAValueSimplify)
169PIPE_OPERATOR(AANoFree)
170PIPE_OPERATOR(AAHeapToStack)
171PIPE_OPERATOR(AAIntraFnReachability)
172PIPE_OPERATOR(AAMemoryBehavior)
173PIPE_OPERATOR(AAMemoryLocation)
174PIPE_OPERATOR(AAValueConstantRange)
175PIPE_OPERATOR(AAPrivatizablePtr)
176PIPE_OPERATOR(AAUndefinedBehavior)
177PIPE_OPERATOR(AAPotentialConstantValues)
178PIPE_OPERATOR(AAPotentialValues)
179PIPE_OPERATOR(AANoUndef)
180PIPE_OPERATOR(AACallEdges)
181PIPE_OPERATOR(AAInterFnReachability)
182PIPE_OPERATOR(AAPointerInfo)
183PIPE_OPERATOR(AAAssumptionInfo)
184PIPE_OPERATOR(AAUnderlyingObjects)
185
186#undef PIPE_OPERATOR
187
188template <>
189ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
190 const DerefState &R) {
191 ChangeStatus CS0 =
192 clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);
193 ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);
194 return CS0 | CS1;
195}
196
197} // namespace llvm
198
199/// Checks if a type could have padding bytes.
200static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
201 // There is no size information, so be conservative.
202 if (!Ty->isSized())
203 return false;
204
205 // If the alloc size is not equal to the storage size, then there are padding
206 // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
207 if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
208 return false;
209
210 // FIXME: This isn't the right way to check for padding in vectors with
211 // non-byte-size elements.
212 if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))
213 return isDenselyPacked(SeqTy->getElementType(), DL);
214
215 // For array types, check for padding within members.
216 if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))
217 return isDenselyPacked(SeqTy->getElementType(), DL);
218
219 if (!isa<StructType>(Ty))
220 return true;
221
222 // Check for padding within and between elements of a struct.
223 StructType *StructTy = cast<StructType>(Ty);
224 const StructLayout *Layout = DL.getStructLayout(StructTy);
225 uint64_t StartPos = 0;
226 for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
227 Type *ElTy = StructTy->getElementType(I);
228 if (!isDenselyPacked(ElTy, DL))
229 return false;
230 if (StartPos != Layout->getElementOffsetInBits(I))
231 return false;
232 StartPos += DL.getTypeAllocSizeInBits(ElTy);
233 }
234
235 return true;
236}
237
238/// Get pointer operand of memory accessing instruction. If \p I is
239/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
240/// is set to false and the instruction is volatile, return nullptr.
241static const Value *getPointerOperand(const Instruction *I,
242 bool AllowVolatile) {
243 if (!AllowVolatile && I->isVolatile())
244 return nullptr;
245
246 if (auto *LI = dyn_cast<LoadInst>(I)) {
247 return LI->getPointerOperand();
248 }
249
250 if (auto *SI = dyn_cast<StoreInst>(I)) {
251 return SI->getPointerOperand();
252 }
253
254 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) {
255 return CXI->getPointerOperand();
256 }
257
258 if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {
259 return RMWI->getPointerOperand();
260 }
261
262 return nullptr;
263}
264
265/// Helper function to create a pointer of type \p ResTy, based on \p Ptr, and
266/// advanced by \p Offset bytes. To aid later analysis the method tries to build
267/// getelement pointer instructions that traverse the natural type of \p Ptr if
268/// possible. If that fails, the remaining offset is adjusted byte-wise, hence
269/// through a cast to i8*.
270///
271/// TODO: This could probably live somewhere more prominantly if it doesn't
272/// already exist.
273static Value *constructPointer(Type *ResTy, Type *PtrElemTy, Value *Ptr,
274 int64_t Offset, IRBuilder<NoFolder> &IRB,
275 const DataLayout &DL) {
276 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", 276, __extension__
__PRETTY_FUNCTION__))
;
277 LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offsetdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Construct pointer: " <<
*Ptr << " + " << Offset << "-bytes as " <<
*ResTy << "\n"; } } while (false)
278 << "-bytes as " << *ResTy << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Construct pointer: " <<
*Ptr << " + " << Offset << "-bytes as " <<
*ResTy << "\n"; } } while (false)
;
279
280 if (Offset) {
281 Type *Ty = PtrElemTy;
282 APInt IntOffset(DL.getIndexTypeSizeInBits(Ptr->getType()), Offset);
283 SmallVector<APInt> IntIndices = DL.getGEPIndicesForOffset(Ty, IntOffset);
284
285 SmallVector<Value *, 4> ValIndices;
286 std::string GEPName = Ptr->getName().str();
287 for (const APInt &Index : IntIndices) {
288 ValIndices.push_back(IRB.getInt(Index));
289 GEPName += "." + std::to_string(Index.getZExtValue());
290 }
291
292 // Create a GEP for the indices collected above.
293 Ptr = IRB.CreateGEP(PtrElemTy, Ptr, ValIndices, GEPName);
294
295 // If an offset is left we use byte-wise adjustment.
296 if (IntOffset != 0) {
297 Ptr = IRB.CreateBitCast(Ptr, IRB.getInt8PtrTy());
298 Ptr = IRB.CreateGEP(IRB.getInt8Ty(), Ptr, IRB.getInt(IntOffset),
299 GEPName + ".b" + Twine(IntOffset.getZExtValue()));
300 }
301 }
302
303 // Ensure the result has the requested type.
304 Ptr = IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr, ResTy,
305 Ptr->getName() + ".cast");
306
307 LLVM_DEBUG(dbgs() << "Constructed pointer: " << *Ptr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Constructed pointer: " <<
*Ptr << "\n"; } } while (false)
;
308 return Ptr;
309}
310
311static const Value *
312stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA,
313 const Value *Val, const DataLayout &DL, APInt &Offset,
314 bool GetMinOffset, bool AllowNonInbounds,
315 bool UseAssumed = false) {
316
317 auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
318 const IRPosition &Pos = IRPosition::value(V);
319 // Only track dependence if we are going to use the assumed info.
320 const AAValueConstantRange &ValueConstantRangeAA =
321 A.getAAFor<AAValueConstantRange>(QueryingAA, Pos,
322 UseAssumed ? DepClassTy::OPTIONAL
323 : DepClassTy::NONE);
324 ConstantRange Range = UseAssumed ? ValueConstantRangeAA.getAssumed()
325 : ValueConstantRangeAA.getKnown();
326 if (Range.isFullSet())
327 return false;
328
329 // We can only use the lower part of the range because the upper part can
330 // be higher than what the value can really be.
331 if (GetMinOffset)
332 ROffset = Range.getSignedMin();
333 else
334 ROffset = Range.getSignedMax();
335 return true;
336 };
337
338 return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
339 /* AllowInvariant */ true,
340 AttributorAnalysis);
341}
342
343static const Value *
344getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA,
345 const Value *Ptr, int64_t &BytesOffset,
346 const DataLayout &DL, bool AllowNonInbounds = false) {
347 APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
348 const Value *Base =
349 stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,
350 /* GetMinOffset */ true, AllowNonInbounds);
351
352 BytesOffset = OffsetAPInt.getSExtValue();
353 return Base;
354}
355
356/// Clamp the information known for all returned values of a function
357/// (identified by \p QueryingAA) into \p S.
358template <typename AAType, typename StateType = typename AAType::StateType>
359static void clampReturnedValueStates(
360 Attributor &A, const AAType &QueryingAA, StateType &S,
361 const IRPosition::CallBaseContext *CBContext = nullptr) {
362 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)
363 << QueryingAA << " into " << S << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Clamp return value states for "
<< QueryingAA << " into " << S << "\n"
; } } while (false)
;
364
365 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", 370, __extension__
__PRETTY_FUNCTION__))
366 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", 370, __extension__
__PRETTY_FUNCTION__))
367 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", 370, __extension__
__PRETTY_FUNCTION__))
368 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", 370, __extension__
__PRETTY_FUNCTION__))
369 "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", 370, __extension__
__PRETTY_FUNCTION__))
370 "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", 370, __extension__
__PRETTY_FUNCTION__))
;
371
372 // Use an optional state as there might not be any return values and we want
373 // to join (IntegerState::operator&) the state of all there are.
374 std::optional<StateType> T;
375
376 // Callback for each possibly returned value.
377 auto CheckReturnValue = [&](Value &RV) -> bool {
378 const IRPosition &RVPos = IRPosition::value(RV, CBContext);
379 const AAType &AA =
380 A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);
381 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)
382 << " @ " << RVPos << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] RV: " <<
RV << " AA: " << AA.getAsStr() << " @ " <<
RVPos << "\n"; } } while (false)
;
383 const StateType &AAS = AA.getState();
384 if (!T)
385 T = StateType::getBestState(AAS);
386 *T &= AAS;
387 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)
388 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] AA State: " <<
AAS << " RV State: " << T << "\n"; } } while
(false)
;
389 return T->isValidState();
390 };
391
392 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA))
393 S.indicatePessimisticFixpoint();
394 else if (T)
395 S ^= *T;
396}
397
398namespace {
399/// Helper class for generic deduction: return value -> returned position.
400template <typename AAType, typename BaseType,
401 typename StateType = typename BaseType::StateType,
402 bool PropagateCallBaseContext = false>
403struct AAReturnedFromReturnedValues : public BaseType {
404 AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
405 : BaseType(IRP, A) {}
406
407 /// See AbstractAttribute::updateImpl(...).
408 ChangeStatus updateImpl(Attributor &A) override {
409 StateType S(StateType::getBestState(this->getState()));
410 clampReturnedValueStates<AAType, StateType>(
411 A, *this, S,
412 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
413 // TODO: If we know we visited all returned values, thus no are assumed
414 // dead, we can take the known information from the state T.
415 return clampStateAndIndicateChange<StateType>(this->getState(), S);
416 }
417};
418
419/// Clamp the information known at all call sites for a given argument
420/// (identified by \p QueryingAA) into \p S.
421template <typename AAType, typename StateType = typename AAType::StateType>
422static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
423 StateType &S) {
424 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)
425 << 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)
;
426
427 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", 429, __extension__
__PRETTY_FUNCTION__))
428 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", 429, __extension__
__PRETTY_FUNCTION__))
429 "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", 429, __extension__
__PRETTY_FUNCTION__))
;
430
431 // Use an optional state as there might not be any return values and we want
432 // to join (IntegerState::operator&) the state of all there are.
433 std::optional<StateType> T;
434
435 // The argument number which is also the call site argument number.
436 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
437
438 auto CallSiteCheck = [&](AbstractCallSite ACS) {
439 const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
440 // Check if a coresponding argument was found or if it is on not associated
441 // (which can happen for callback calls).
442 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
443 return false;
444
445 const AAType &AA =
446 A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);
447 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)
448 << " AA: " << AA.getAsStr() << " @" << ACSArgPos << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] ACS: " <<
*ACS.getInstruction() << " AA: " << AA.getAsStr(
) << " @" << ACSArgPos << "\n"; } } while (
false)
;
449 const StateType &AAS = AA.getState();
450 if (!T)
451 T = StateType::getBestState(AAS);
452 *T &= AAS;
453 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)
454 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] AA State: " <<
AAS << " CSA State: " << T << "\n"; } } while
(false)
;
455 return T->isValidState();
456 };
457
458 bool UsedAssumedInformation = false;
459 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,
460 UsedAssumedInformation))
461 S.indicatePessimisticFixpoint();
462 else if (T)
463 S ^= *T;
464}
465
466/// This function is the bridge between argument position and the call base
467/// context.
468template <typename AAType, typename BaseType,
469 typename StateType = typename AAType::StateType>
470bool getArgumentStateFromCallBaseContext(Attributor &A,
471 BaseType &QueryingAttribute,
472 IRPosition &Pos, StateType &State) {
473 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", 474, __extension__
__PRETTY_FUNCTION__))
474 "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", 474, __extension__
__PRETTY_FUNCTION__))
;
475 const CallBase *CBContext = Pos.getCallBaseContext();
476 if (!CBContext)
477 return false;
478
479 int ArgNo = Pos.getCallSiteArgNo();
480 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", 480, __extension__
__PRETTY_FUNCTION__))
;
481
482 const auto &AA = A.getAAFor<AAType>(
483 QueryingAttribute, IRPosition::callsite_argument(*CBContext, ArgNo),
484 DepClassTy::REQUIRED);
485 const StateType &CBArgumentState =
486 static_cast<const StateType &>(AA.getState());
487
488 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)
489 << "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)
490 << "\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)
;
491
492 // NOTE: If we want to do call site grouping it should happen here.
493 State ^= CBArgumentState;
494 return true;
495}
496
497/// Helper class for generic deduction: call site argument -> argument position.
498template <typename AAType, typename BaseType,
499 typename StateType = typename AAType::StateType,
500 bool BridgeCallBaseContext = false>
501struct AAArgumentFromCallSiteArguments : public BaseType {
502 AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
503 : BaseType(IRP, A) {}
504
505 /// See AbstractAttribute::updateImpl(...).
506 ChangeStatus updateImpl(Attributor &A) override {
507 StateType S = StateType::getBestState(this->getState());
508
509 if (BridgeCallBaseContext) {
510 bool Success =
511 getArgumentStateFromCallBaseContext<AAType, BaseType, StateType>(
512 A, *this, this->getIRPosition(), S);
513 if (Success)
514 return clampStateAndIndicateChange<StateType>(this->getState(), S);
515 }
516 clampCallSiteArgumentStates<AAType, StateType>(A, *this, S);
517
518 // TODO: If we know we visited all incoming values, thus no are assumed
519 // dead, we can take the known information from the state T.
520 return clampStateAndIndicateChange<StateType>(this->getState(), S);
521 }
522};
523
524/// Helper class for generic replication: function returned -> cs returned.
525template <typename AAType, typename BaseType,
526 typename StateType = typename BaseType::StateType,
527 bool IntroduceCallBaseContext = false>
528struct AACallSiteReturnedFromReturned : public BaseType {
529 AACallSiteReturnedFromReturned(const IRPosition &IRP, Attributor &A)
530 : BaseType(IRP, A) {}
531
532 /// See AbstractAttribute::updateImpl(...).
533 ChangeStatus updateImpl(Attributor &A) override {
534 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", 537, __extension__
__PRETTY_FUNCTION__))
535 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", 537, __extension__
__PRETTY_FUNCTION__))
536 "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", 537, __extension__
__PRETTY_FUNCTION__))
537 "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", 537, __extension__
__PRETTY_FUNCTION__))
;
538 auto &S = this->getState();
539
540 const Function *AssociatedFunction =
541 this->getIRPosition().getAssociatedFunction();
542 if (!AssociatedFunction)
543 return S.indicatePessimisticFixpoint();
544
545 CallBase &CBContext = cast<CallBase>(this->getAnchorValue());
546 if (IntroduceCallBaseContext)
547 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)
548 << CBContext << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[Attributor] Introducing call base context:"
<< CBContext << "\n"; } } while (false)
;
549
550 IRPosition FnPos = IRPosition::returned(
551 *AssociatedFunction, IntroduceCallBaseContext ? &CBContext : nullptr);
552 const AAType &AA = A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);
553 return clampStateAndIndicateChange(S, AA.getState());
554 }
555};
556
557/// Helper function to accumulate uses.
558template <class AAType, typename StateType = typename AAType::StateType>
559static void followUsesInContext(AAType &AA, Attributor &A,
560 MustBeExecutedContextExplorer &Explorer,
561 const Instruction *CtxI,
562 SetVector<const Use *> &Uses,
563 StateType &State) {
564 auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);
565 for (unsigned u = 0; u < Uses.size(); ++u) {
566 const Use *U = Uses[u];
567 if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
568 bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
569 if (Found && AA.followUseInMBEC(A, U, UserI, State))
570 for (const Use &Us : UserI->uses())
571 Uses.insert(&Us);
572 }
573 }
574}
575
576/// Use the must-be-executed-context around \p I to add information into \p S.
577/// The AAType class is required to have `followUseInMBEC` method with the
578/// following signature and behaviour:
579///
580/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)
581/// U - Underlying use.
582/// I - The user of the \p U.
583/// Returns true if the value should be tracked transitively.
584///
585template <class AAType, typename StateType = typename AAType::StateType>
586static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,
587 Instruction &CtxI) {
588
589 // Container for (transitive) uses of the associated value.
590 SetVector<const Use *> Uses;
591 for (const Use &U : AA.getIRPosition().getAssociatedValue().uses())
592 Uses.insert(&U);
593
594 MustBeExecutedContextExplorer &Explorer =
595 A.getInfoCache().getMustBeExecutedContextExplorer();
596
597 followUsesInContext<AAType>(AA, A, Explorer, &CtxI, Uses, S);
598
599 if (S.isAtFixpoint())
600 return;
601
602 SmallVector<const BranchInst *, 4> BrInsts;
603 auto Pred = [&](const Instruction *I) {
604 if (const BranchInst *Br = dyn_cast<BranchInst>(I))
605 if (Br->isConditional())
606 BrInsts.push_back(Br);
607 return true;
608 };
609
610 // Here, accumulate conditional branch instructions in the context. We
611 // explore the child paths and collect the known states. The disjunction of
612 // those states can be merged to its own state. Let ParentState_i be a state
613 // to indicate the known information for an i-th branch instruction in the
614 // context. ChildStates are created for its successors respectively.
615 //
616 // ParentS_1 = ChildS_{1, 1} /\ ChildS_{1, 2} /\ ... /\ ChildS_{1, n_1}
617 // ParentS_2 = ChildS_{2, 1} /\ ChildS_{2, 2} /\ ... /\ ChildS_{2, n_2}
618 // ...
619 // ParentS_m = ChildS_{m, 1} /\ ChildS_{m, 2} /\ ... /\ ChildS_{m, n_m}
620 //
621 // Known State |= ParentS_1 \/ ParentS_2 \/... \/ ParentS_m
622 //
623 // FIXME: Currently, recursive branches are not handled. For example, we
624 // can't deduce that ptr must be dereferenced in below function.
625 //
626 // void f(int a, int c, int *ptr) {
627 // if(a)
628 // if (b) {
629 // *ptr = 0;
630 // } else {
631 // *ptr = 1;
632 // }
633 // else {
634 // if (b) {
635 // *ptr = 0;
636 // } else {
637 // *ptr = 1;
638 // }
639 // }
640 // }
641
642 Explorer.checkForAllContext(&CtxI, Pred);
643 for (const BranchInst *Br : BrInsts) {
644 StateType ParentState;
645
646 // The known state of the parent state is a conjunction of children's
647 // known states so it is initialized with a best state.
648 ParentState.indicateOptimisticFixpoint();
649
650 for (const BasicBlock *BB : Br->successors()) {
651 StateType ChildState;
652
653 size_t BeforeSize = Uses.size();
654 followUsesInContext(AA, A, Explorer, &BB->front(), Uses, ChildState);
655
656 // Erase uses which only appear in the child.
657 for (auto It = Uses.begin() + BeforeSize; It != Uses.end();)
658 It = Uses.erase(It);
659
660 ParentState &= ChildState;
661 }
662
663 // Use only known state.
664 S += ParentState;
665 }
666}
667} // namespace
668
669/// ------------------------ PointerInfo ---------------------------------------
670
671namespace llvm {
672namespace AA {
673namespace PointerInfo {
674
675struct State;
676
677} // namespace PointerInfo
678} // namespace AA
679
680/// Helper for AA::PointerInfo::Access DenseMap/Set usage.
681template <>
682struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {
683 using Access = AAPointerInfo::Access;
684 static inline Access getEmptyKey();
685 static inline Access getTombstoneKey();
686 static unsigned getHashValue(const Access &A);
687 static bool isEqual(const Access &LHS, const Access &RHS);
688};
689
690/// Helper that allows RangeTy as a key in a DenseMap.
691template <> struct DenseMapInfo<AA::RangeTy> {
692 static inline AA::RangeTy getEmptyKey() {
693 auto EmptyKey = DenseMapInfo<int64_t>::getEmptyKey();
694 return AA::RangeTy{EmptyKey, EmptyKey};
695 }
696
697 static inline AA::RangeTy getTombstoneKey() {
698 auto TombstoneKey = DenseMapInfo<int64_t>::getTombstoneKey();
699 return AA::RangeTy{TombstoneKey, TombstoneKey};
700 }
701
702 static unsigned getHashValue(const AA::RangeTy &Range) {
703 return detail::combineHashValue(
704 DenseMapInfo<int64_t>::getHashValue(Range.Offset),
705 DenseMapInfo<int64_t>::getHashValue(Range.Size));
706 }
707
708 static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {
709 return A == B;
710 }
711};
712
713/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign
714/// but the instruction
715struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {
716 using Base = DenseMapInfo<Instruction *>;
717 using Access = AAPointerInfo::Access;
718 static inline Access getEmptyKey();
719 static inline Access getTombstoneKey();
720 static unsigned getHashValue(const Access &A);
721 static bool isEqual(const Access &LHS, const Access &RHS);
722};
723
724} // namespace llvm
725
726/// A type to track pointer/struct usage and accesses for AAPointerInfo.
727struct AA::PointerInfo::State : public AbstractState {
728 /// Return the best possible representable state.
729 static State getBestState(const State &SIS) { return State(); }
730
731 /// Return the worst possible representable state.
732 static State getWorstState(const State &SIS) {
733 State R;
734 R.indicatePessimisticFixpoint();
735 return R;
736 }
737
738 State() = default;
739 State(State &&SIS) = default;
740
741 const State &getAssumed() const { return *this; }
742
743 /// See AbstractState::isValidState().
744 bool isValidState() const override { return BS.isValidState(); }
745
746 /// See AbstractState::isAtFixpoint().
747 bool isAtFixpoint() const override { return BS.isAtFixpoint(); }
748
749 /// See AbstractState::indicateOptimisticFixpoint().
750 ChangeStatus indicateOptimisticFixpoint() override {
751 BS.indicateOptimisticFixpoint();
752 return ChangeStatus::UNCHANGED;
753 }
754
755 /// See AbstractState::indicatePessimisticFixpoint().
756 ChangeStatus indicatePessimisticFixpoint() override {
757 BS.indicatePessimisticFixpoint();
758 return ChangeStatus::CHANGED;
759 }
760
761 State &operator=(const State &R) {
762 if (this == &R)
763 return *this;
764 BS = R.BS;
765 AccessList = R.AccessList;
766 OffsetBins = R.OffsetBins;
767 RemoteIMap = R.RemoteIMap;
768 return *this;
769 }
770
771 State &operator=(State &&R) {
772 if (this == &R)
773 return *this;
774 std::swap(BS, R.BS);
775 std::swap(AccessList, R.AccessList);
776 std::swap(OffsetBins, R.OffsetBins);
777 std::swap(RemoteIMap, R.RemoteIMap);
778 return *this;
779 }
780
781 /// Add a new Access to the state at offset \p Offset and with size \p Size.
782 /// The access is associated with \p I, writes \p Content (if anything), and
783 /// is of kind \p Kind. If an Access already exists for the same \p I and same
784 /// \p RemoteI, the two are combined, potentially losing information about
785 /// offset and size. The resulting access must now be moved from its original
786 /// OffsetBin to the bin for its new offset.
787 ///
788 /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
789 ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges,
790 Instruction &I, std::optional<Value *> Content,
791 AAPointerInfo::AccessKind Kind, Type *Ty,
792 Instruction *RemoteI = nullptr);
793
794 using OffsetBinsTy = DenseMap<RangeTy, SmallSet<unsigned, 4>>;
795
796 using const_bin_iterator = OffsetBinsTy::const_iterator;
797 const_bin_iterator begin() const { return OffsetBins.begin(); }
798 const_bin_iterator end() const { return OffsetBins.end(); }
799
800 const AAPointerInfo::Access &getAccess(unsigned Index) const {
801 return AccessList[Index];
802 }
803
804protected:
805 // Every memory instruction results in an Access object. We maintain a list of
806 // all Access objects that we own, along with the following maps:
807 //
808 // - OffsetBins: RangeTy -> { Access }
809 // - RemoteIMap: RemoteI x LocalI -> Access
810 //
811 // A RemoteI is any instruction that accesses memory. RemoteI is different
812 // from LocalI if and only if LocalI is a call; then RemoteI is some
813 // instruction in the callgraph starting from LocalI. Multiple paths in the
814 // callgraph from LocalI to RemoteI may produce multiple accesses, but these
815 // are all combined into a single Access object. This may result in loss of
816 // information in RangeTy in the Access object.
817 SmallVector<AAPointerInfo::Access> AccessList;
818 OffsetBinsTy OffsetBins;
819 DenseMap<const Instruction *, SmallVector<unsigned>> RemoteIMap;
820
821 /// See AAPointerInfo::forallInterferingAccesses.
822 bool forallInterferingAccesses(
823 AA::RangeTy Range,
824 function_ref<bool(const AAPointerInfo::Access &, bool)> CB) const {
825 if (!isValidState())
826 return false;
827
828 for (const auto &It : OffsetBins) {
829 AA::RangeTy ItRange = It.getFirst();
830 if (!Range.mayOverlap(ItRange))
831 continue;
832 bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();
833 for (auto Index : It.getSecond()) {
834 auto &Access = AccessList[Index];
835 if (!CB(Access, IsExact))
836 return false;
837 }
838 }
839 return true;
840 }
841
842 /// See AAPointerInfo::forallInterferingAccesses.
843 bool forallInterferingAccesses(
844 Instruction &I,
845 function_ref<bool(const AAPointerInfo::Access &, bool)> CB,
846 AA::RangeTy &Range) const {
847 if (!isValidState())
848 return false;
849
850 auto LocalList = RemoteIMap.find(&I);
851 if (LocalList == RemoteIMap.end()) {
852 return true;
853 }
854
855 for (unsigned Index : LocalList->getSecond()) {
856 for (auto &R : AccessList[Index]) {
857 Range &= R;
858 if (Range.offsetOrSizeAreUnknown())
859 break;
860 }
861 }
862 return forallInterferingAccesses(Range, CB);
863 }
864
865private:
866 /// State to track fixpoint and validity.
867 BooleanState BS;
868};
869
870ChangeStatus AA::PointerInfo::State::addAccess(
871 Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I,
872 std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,
873 Instruction *RemoteI) {
874 RemoteI = RemoteI ? RemoteI : &I;
875
876 // Check if we have an access for this instruction, if not, simply add it.
877 auto &LocalList = RemoteIMap[RemoteI];
878 bool AccExists = false;
879 unsigned AccIndex = AccessList.size();
880 for (auto Index : LocalList) {
881 auto &A = AccessList[Index];
882 if (A.getLocalInst() == &I) {
883 AccExists = true;
884 AccIndex = Index;
885 break;
886 }
887 }
888
889 auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {
890 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToAdd.size()) dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n"
;; } } while (false)
891 if (ToAdd.size())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToAdd.size()) dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n"
;; } } while (false)
892 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)
893 )do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToAdd.size()) dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n"
;; } } while (false)
;
894
895 for (auto Key : ToAdd) {
896 LLVM_DEBUG(dbgs() << " key " << Key << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " key " << Key <<
"\n"; } } while (false)
;
897 OffsetBins[Key].insert(AccIndex);
898 }
899 };
900
901 if (!AccExists) {
902 AccessList.emplace_back(&I, RemoteI, Ranges, Content, Kind, Ty);
903 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", 904, __extension__
__PRETTY_FUNCTION__))
904 "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", 904, __extension__
__PRETTY_FUNCTION__))
;
905 LocalList.push_back(AccIndex);
906 AddToBins(AccessList[AccIndex].getRanges());
907 return ChangeStatus::CHANGED;
908 }
909
910 // Combine the new Access with the existing Access, and then update the
911 // mapping in the offset bins.
912 AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);
913 auto &Current = AccessList[AccIndex];
914 auto Before = Current;
915 Current &= Acc;
916 if (Current == Before)
917 return ChangeStatus::UNCHANGED;
918
919 auto &ExistingRanges = Before.getRanges();
920 auto &NewRanges = Current.getRanges();
921
922 // Ranges that are in the old access but not the new access need to be removed
923 // from the offset bins.
924 AAPointerInfo::RangeList ToRemove;
925 AAPointerInfo::RangeList::set_difference(ExistingRanges, NewRanges, ToRemove);
926 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToRemove.size()) dbgs() << "[AAPointerInfo] Removing access from old offset bins\n"
;; } } while (false)
927 if (ToRemove.size())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToRemove.size()) dbgs() << "[AAPointerInfo] Removing access from old offset bins\n"
;; } } while (false)
928 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)
929 )do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { if (ToRemove.size()) dbgs() << "[AAPointerInfo] Removing access from old offset bins\n"
;; } } while (false)
;
930
931 for (auto Key : ToRemove) {
932 LLVM_DEBUG(dbgs() << " key " << Key << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " key " << Key <<
"\n"; } } while (false)
;
933 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", 933, __extension__
__PRETTY_FUNCTION__))
;
934 auto &Bin = OffsetBins[Key];
935 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", 936, __extension__
__PRETTY_FUNCTION__))
936 "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", 936, __extension__
__PRETTY_FUNCTION__))
;
937 Bin.erase(AccIndex);
938 }
939
940 // Ranges that are in the new access but not the old access need to be added
941 // to the offset bins.
942 AAPointerInfo::RangeList ToAdd;
943 AAPointerInfo::RangeList::set_difference(NewRanges, ExistingRanges, ToAdd);
944 AddToBins(ToAdd);
945 return ChangeStatus::CHANGED;
946}
947
948namespace {
949
950/// A helper containing a list of offsets computed for a Use. Ideally this
951/// list should be strictly ascending, but we ensure that only when we
952/// actually translate the list of offsets to a RangeList.
953struct OffsetInfo {
954 using VecTy = SmallVector<int64_t>;
955 using const_iterator = VecTy::const_iterator;
956 VecTy Offsets;
957
958 const_iterator begin() const { return Offsets.begin(); }
959 const_iterator end() const { return Offsets.end(); }
960
961 bool operator==(const OffsetInfo &RHS) const {
962 return Offsets == RHS.Offsets;
963 }
964
965 bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }
966
967 void insert(int64_t Offset) { Offsets.push_back(Offset); }
968 bool isUnassigned() const { return Offsets.size() == 0; }
969
970 bool isUnknown() const {
971 if (isUnassigned())
972 return false;
973 if (Offsets.size() == 1)
974 return Offsets.front() == AA::RangeTy::Unknown;
975 return false;
976 }
977
978 void setUnknown() {
979 Offsets.clear();
980 Offsets.push_back(AA::RangeTy::Unknown);
981 }
982
983 void addToAll(int64_t Inc) {
984 for (auto &Offset : Offsets) {
985 Offset += Inc;
986 }
987 }
988
989 /// Copy offsets from \p R into the current list.
990 ///
991 /// Ideally all lists should be strictly ascending, but we defer that to the
992 /// actual use of the list. So we just blindly append here.
993 void merge(const OffsetInfo &R) { Offsets.append(R.Offsets); }
994};
995
996#ifndef NDEBUG
997static raw_ostream &operator<<(raw_ostream &OS, const OffsetInfo &OI) {
998 ListSeparator LS;
999 OS << "[";
1000 for (auto Offset : OI) {
1001 OS << LS << Offset;
1002 }
1003 OS << "]";
1004 return OS;
1005}
1006#endif // NDEBUG
1007
1008struct AAPointerInfoImpl
1009 : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1010 using BaseTy = StateWrapper<AA::PointerInfo::State, AAPointerInfo>;
1011 AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
1012
1013 /// See AbstractAttribute::getAsStr().
1014 const std::string getAsStr() const override {
1015 return std::string("PointerInfo ") +
1016 (isValidState() ? (std::string("#") +
1017 std::to_string(OffsetBins.size()) + " bins")
1018 : "<invalid>");
1019 }
1020
1021 /// See AbstractAttribute::manifest(...).
1022 ChangeStatus manifest(Attributor &A) override {
1023 return AAPointerInfo::manifest(A);
1024 }
1025
1026 bool forallInterferingAccesses(
1027 AA::RangeTy Range,
1028 function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
1029 const override {
1030 return State::forallInterferingAccesses(Range, CB);
1031 }
1032
1033 bool forallInterferingAccesses(
1034 Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
1035 bool FindInterferingWrites, bool FindInterferingReads,
1036 function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
1037 AA::RangeTy &Range) const override {
1038 HasBeenWrittenTo = false;
1039
1040 SmallPtrSet<const Access *, 8> DominatingWrites;
1041 SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;
1042
1043 Function &Scope = *I.getFunction();
1044 const auto &NoSyncAA = A.getAAFor<AANoSync>(
1045 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1046 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
1047 IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);
1048 bool AllInSameNoSyncFn = NoSyncAA.isAssumedNoSync();
1049 bool InstIsExecutedByInitialThreadOnly =
1050 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);
1051 bool InstIsExecutedInAlignedRegion =
1052 ExecDomainAA && ExecDomainAA->isExecutedInAlignedRegion(A, I);
1053 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1054 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1055
1056 InformationCache &InfoCache = A.getInfoCache();
1057 bool IsThreadLocalObj =
1058 AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);
1059
1060 // Helper to determine if we need to consider threading, which we cannot
1061 // right now. However, if the function is (assumed) nosync or the thread
1062 // executing all instructions is the main thread only we can ignore
1063 // threading. Also, thread-local objects do not require threading reasoning.
1064 // Finally, we can ignore threading if either access is executed in an
1065 // aligned region.
1066 auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
1067 if (IsThreadLocalObj || AllInSameNoSyncFn)
1068 return true;
1069 const auto *FnExecDomainAA =
1070 I.getFunction() == &Scope
1071 ? ExecDomainAA
1072 : A.lookupAAFor<AAExecutionDomain>(
1073 IRPosition::function(*I.getFunction()), &QueryingAA,
1074 DepClassTy::NONE);
1075 if (!FnExecDomainAA)
1076 return false;
1077 if (InstIsExecutedInAlignedRegion ||
1078 FnExecDomainAA->isExecutedInAlignedRegion(A, I)) {
1079 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1080 return true;
1081 }
1082 if (InstIsExecutedByInitialThreadOnly &&
1083 FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
1084 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1085 return true;
1086 }
1087 return false;
1088 };
1089
1090 // Helper to determine if the access is executed by the same thread as the
1091 // given instruction, for now it is sufficient to avoid any potential
1092 // threading effects as we cannot deal with them anyway.
1093 auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
1094 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1095 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1096 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1097 };
1098
1099 // TODO: Use inter-procedural reachability and dominance.
1100 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
1101 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1102
1103 const bool UseDominanceReasoning =
1104 FindInterferingWrites && NoRecurseAA.isKnownNoRecurse();
1105 const DominatorTree *DT =
1106 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);
1107
1108 // Helper to check if a value has "kernel lifetime", that is it will not
1109 // outlive a GPU kernel. This is true for shared, constant, and local
1110 // globals on AMD and NVIDIA GPUs.
1111 auto HasKernelLifetime = [&](Value *V, Module &M) {
1112 Triple T(M.getTargetTriple());
1113 if (!(T.isAMDGPU() || T.isNVPTX()))
1114 return false;
1115 switch (AA::GPUAddressSpace(V->getType()->getPointerAddressSpace())) {
1116 case AA::GPUAddressSpace::Shared:
1117 case AA::GPUAddressSpace::Constant:
1118 case AA::GPUAddressSpace::Local:
1119 return true;
1120 default:
1121 return false;
1122 };
1123 };
1124
1125 // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
1126 // to determine if we should look at reachability from the callee. For
1127 // certain pointers we know the lifetime and we do not have to step into the
1128 // callee to determine reachability as the pointer would be dead in the
1129 // callee. See the conditional initialization below.
1130 std::function<bool(const Function &)> IsLiveInCalleeCB;
1131
1132 if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {
1133 // If the alloca containing function is not recursive the alloca
1134 // must be dead in the callee.
1135 const Function *AIFn = AI->getFunction();
1136 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
1137 *this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL);
1138 if (NoRecurseAA.isAssumedNoRecurse()) {
1139 IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
1140 }
1141 } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {
1142 // If the global has kernel lifetime we can stop if we reach a kernel
1143 // as it is "dead" in the (unknown) callees.
1144 if (HasKernelLifetime(GV, *GV->getParent()))
1145 IsLiveInCalleeCB = [](const Function &Fn) {
1146 return !Fn.hasFnAttribute("kernel");
1147 };
1148 }
1149
1150 // Set of accesses/instructions that will overwrite the result and are
1151 // therefore blockers in the reachability traversal.
1152 AA::InstExclusionSetTy ExclusionSet;
1153
1154 auto AccessCB = [&](const Access &Acc, bool Exact) {
1155 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
1156 if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))
1157 ExclusionSet.insert(Acc.getRemoteInst());
1158 }
1159
1160 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1161 (!FindInterferingReads || !Acc.isRead()))
1162 return true;
1163
1164 bool Dominates = FindInterferingWrites && DT && Exact &&
1165 Acc.isMustAccess() &&
1166 (Acc.getRemoteInst()->getFunction() == &Scope) &&
1167 DT->dominates(Acc.getRemoteInst(), &I);
1168 if (Dominates)
1169 DominatingWrites.insert(&Acc);
1170
1171 // Track if all interesting accesses are in the same `nosync` function as
1172 // the given instruction.
1173 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;
1174
1175 InterferingAccesses.push_back({&Acc, Exact});
1176 return true;
1177 };
1178 if (!State::forallInterferingAccesses(I, AccessCB, Range))
1179 return false;
1180
1181 HasBeenWrittenTo = !DominatingWrites.empty();
1182
1183 // Dominating writes form a chain, find the least/lowest member.
1184 Instruction *LeastDominatingWriteInst = nullptr;
1185 for (const Access *Acc : DominatingWrites) {
1186 if (!LeastDominatingWriteInst) {
1187 LeastDominatingWriteInst = Acc->getRemoteInst();
1188 } else if (DT->dominates(LeastDominatingWriteInst,
1189 Acc->getRemoteInst())) {
1190 LeastDominatingWriteInst = Acc->getRemoteInst();
1191 }
1192 }
1193
1194 // Helper to determine if we can skip a specific write access.
1195 auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
1196 if (!CanIgnoreThreading(Acc))
1197 return false;
1198
1199 // Check read (RAW) dependences and write (WAR) dependences as necessary.
1200 // If we successfully excluded all effects we are interested in, the
1201 // access can be skipped.
1202 bool ReadChecked = !FindInterferingReads;
1203 bool WriteChecked = !FindInterferingWrites;
1204
1205 // If the instruction cannot reach the access, the former does not
1206 // interfere with what the access reads.
1207 if (!ReadChecked) {
1208 if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,
1209 &ExclusionSet, IsLiveInCalleeCB))
1210 ReadChecked = true;
1211 }
1212 // If the instruction cannot be reach from the access, the latter does not
1213 // interfere with what the instruction reads.
1214 if (!WriteChecked) {
1215 if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,
1216 &ExclusionSet, IsLiveInCalleeCB))
1217 WriteChecked = true;
1218 }
1219
1220 // If we still might be affected by the write of the access but there are
1221 // dominating writes in the function of the instruction
1222 // (HasBeenWrittenTo), we can try to reason that the access is overwritten
1223 // by them. This would have happend above if they are all in the same
1224 // function, so we only check the inter-procedural case. Effectively, we
1225 // want to show that there is no call after the dominting write that might
1226 // reach the access, and when it returns reach the instruction with the
1227 // updated value. To this end, we iterate all call sites, check if they
1228 // might reach the instruction without going through another access
1229 // (ExclusionSet) and at the same time might reach the access. However,
1230 // that is all part of AAInterFnReachability.
1231 if (!WriteChecked && HasBeenWrittenTo &&
1232 Acc.getRemoteInst()->getFunction() != &Scope) {
1233
1234 const auto &FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
1235 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1236
1237 // Without going backwards in the call tree, can we reach the access
1238 // from the least dominating write. Do not allow to pass the instruction
1239 // itself either.
1240 bool Inserted = ExclusionSet.insert(&I).second;
1241
1242 if (!FnReachabilityAA.instructionCanReach(
1243 A, *LeastDominatingWriteInst,
1244 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1245 WriteChecked = true;
1246
1247 if (Inserted)
1248 ExclusionSet.erase(&I);
1249 }
1250
1251 if (ReadChecked && WriteChecked)
1252 return true;
1253
1254 if (!DT || !UseDominanceReasoning)
1255 return false;
1256 if (!DominatingWrites.count(&Acc))
1257 return false;
1258 return LeastDominatingWriteInst != Acc.getRemoteInst();
1259 };
1260
1261 // Run the user callback on all accesses we cannot skip and return if
1262 // that succeeded for all or not.
1263 for (auto &It : InterferingAccesses) {
1264 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1265 !CanSkipAccess(*It.first, It.second)) {
1266 if (!UserCB(*It.first, It.second))
1267 return false;
1268 }
1269 }
1270 return true;
1271 }
1272
1273 ChangeStatus translateAndAddStateFromCallee(Attributor &A,
1274 const AAPointerInfo &OtherAA,
1275 CallBase &CB) {
1276 using namespace AA::PointerInfo;
1277 if (!OtherAA.getState().isValidState() || !isValidState())
1278 return indicatePessimisticFixpoint();
1279
1280 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1281 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1282
1283 // Combine the accesses bin by bin.
1284 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1285 const auto &State = OtherAAImpl.getState();
1286 for (const auto &It : State) {
1287 for (auto Index : It.getSecond()) {
1288 const auto &RAcc = State.getAccess(Index);
1289 if (IsByval && !RAcc.isRead())
1290 continue;
1291 bool UsedAssumedInformation = false;
1292 AccessKind AK = RAcc.getKind();
1293 auto Content = A.translateArgumentToCallSiteContent(
1294 RAcc.getContent(), CB, *this, UsedAssumedInformation);
1295 AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1296 AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1297
1298 Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,
1299 RAcc.getType(), RAcc.getRemoteInst());
1300 }
1301 }
1302 return Changed;
1303 }
1304
1305 ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
1306 const OffsetInfo &Offsets, CallBase &CB) {
1307 using namespace AA::PointerInfo;
1308 if (!OtherAA.getState().isValidState() || !isValidState())
1309 return indicatePessimisticFixpoint();
1310
1311 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1312
1313 // Combine the accesses bin by bin.
1314 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1315 const auto &State = OtherAAImpl.getState();
1316 for (const auto &It : State) {
1317 for (auto Index : It.getSecond()) {
1318 const auto &RAcc = State.getAccess(Index);
1319 for (auto Offset : Offsets) {
1320 auto NewRanges = Offset == AA::RangeTy::Unknown
1321 ? AA::RangeTy::getUnknown()
1322 : RAcc.getRanges();
1323 if (!NewRanges.isUnknown()) {
1324 NewRanges.addToAllOffsets(Offset);
1325 }
1326 Changed |=
1327 addAccess(A, NewRanges, CB, RAcc.getContent(), RAcc.getKind(),
1328 RAcc.getType(), RAcc.getRemoteInst());
1329 }
1330 }
1331 }
1332 return Changed;
1333 }
1334
1335 /// Statistic tracking for all AAPointerInfo implementations.
1336 /// See AbstractAttribute::trackStatistics().
1337 void trackPointerInfoStatistics(const IRPosition &IRP) const {}
1338
1339 /// Dump the state into \p O.
1340 void dumpState(raw_ostream &O) {
1341 for (auto &It : OffsetBins) {
1342 O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
1343 << "] : " << It.getSecond().size() << "\n";
1344 for (auto AccIndex : It.getSecond()) {
1345 auto &Acc = AccessList[AccIndex];
1346 O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
1347 if (Acc.getLocalInst() != Acc.getRemoteInst())
1348 O << " --> " << *Acc.getRemoteInst()
1349 << "\n";
1350 if (!Acc.isWrittenValueYetUndetermined()) {
1351 if (isa_and_nonnull<Function>(Acc.getWrittenValue()))
1352 O << " - c: func " << Acc.getWrittenValue()->getName()
1353 << "\n";
1354 else if (Acc.getWrittenValue())
1355 O << " - c: " << *Acc.getWrittenValue() << "\n";
1356 else
1357 O << " - c: <unknown>\n";
1358 }
1359 }
1360 }
1361 }
1362};
1363
1364struct AAPointerInfoFloating : public AAPointerInfoImpl {
1365 using AccessKind = AAPointerInfo::AccessKind;
1366 AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
1367 : AAPointerInfoImpl(IRP, A) {}
1368
1369 /// Deal with an access and signal if it was handled successfully.
1370 bool handleAccess(Attributor &A, Instruction &I,
1371 std::optional<Value *> Content, AccessKind Kind,
1372 SmallVectorImpl<int64_t> &Offsets, ChangeStatus &Changed,
1373 Type &Ty) {
1374 using namespace AA::PointerInfo;
1375 auto Size = AA::RangeTy::Unknown;
1376 const DataLayout &DL = A.getDataLayout();
1377 TypeSize AccessSize = DL.getTypeStoreSize(&Ty);
1378 if (!AccessSize.isScalable())
1379 Size = AccessSize.getFixedValue();
1380
1381 // Make a strictly ascending list of offsets as required by addAccess()
1382 llvm::sort(Offsets);
1383 auto *Last = std::unique(Offsets.begin(), Offsets.end());
1384 Offsets.erase(Last, Offsets.end());
1385
1386 VectorType *VT = dyn_cast<VectorType>(&Ty);
1387 if (!VT || VT->getElementCount().isScalable() ||
1388 !Content.value_or(nullptr) || !isa<Constant>(*Content) ||
1389 (*Content)->getType() != VT ||
1390 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1391 Changed = Changed | addAccess(A, {Offsets, Size}, I, Content, Kind, &Ty);
1392 } else {
1393 // Handle vector stores with constant content element-wise.
1394 // TODO: We could look for the elements or create instructions
1395 // representing them.
1396 // TODO: We need to push the Content into the range abstraction
1397 // (AA::RangeTy) to allow different content values for different
1398 // ranges. ranges. Hence, support vectors storing different values.
1399 Type *ElementType = VT->getElementType();
1400 int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();
1401 auto *ConstContent = cast<Constant>(*Content);
1402 Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());
1403 SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());
1404
1405 for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1406 Value *ElementContent = ConstantExpr::getExtractElement(
1407 ConstContent, ConstantInt::get(Int32Ty, i));
1408
1409 // Add the element access.
1410 Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,
1411 ElementContent, Kind, ElementType);
1412
1413 // Advance the offsets for the next element.
1414 for (auto &ElementOffset : ElementOffsets)
1415 ElementOffset += ElementSize;
1416 }
1417 }
1418 return true;
1419 };
1420
1421 /// See AbstractAttribute::updateImpl(...).
1422 ChangeStatus updateImpl(Attributor &A) override;
1423
1424 /// If the indices to \p GEP can be traced to constants, incorporate all
1425 /// of these into \p UsrOI.
1426 ///
1427 /// \return true iff \p UsrOI is updated.
1428 bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
1429 OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
1430 const GEPOperator *GEP);
1431
1432 /// See AbstractAttribute::trackStatistics()
1433 void trackStatistics() const override {
1434 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1435 }
1436};
1437
1438bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
1439 const DataLayout &DL,
1440 OffsetInfo &UsrOI,
1441 const OffsetInfo &PtrOI,
1442 const GEPOperator *GEP) {
1443 unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
1444 MapVector<Value *, APInt> VariableOffsets;
1445 APInt ConstantOffset(BitWidth, 0);
1446
1447 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", 1449, __extension__
__PRETTY_FUNCTION__))
1448 "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", 1449, __extension__
__PRETTY_FUNCTION__))
1449 "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", 1449, __extension__
__PRETTY_FUNCTION__))
;
1450
1451 if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
1452 UsrOI.setUnknown();
1453 return true;
1454 }
1455
1456 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)
1457 << (VariableOffsets.empty() ? "" : "not") << " constant "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] GEP offset is "
<< (VariableOffsets.empty() ? "" : "not") << " constant "
<< *GEP << "\n"; } } while (false)
1458 << *GEP << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] GEP offset is "
<< (VariableOffsets.empty() ? "" : "not") << " constant "
<< *GEP << "\n"; } } while (false)
;
1459
1460 auto Union = PtrOI;
1461 Union.addToAll(ConstantOffset.getSExtValue());
1462
1463 // Each VI in VariableOffsets has a set of potential constant values. Every
1464 // combination of elements, picked one each from these sets, is separately
1465 // added to the original set of offsets, thus resulting in more offsets.
1466 for (const auto &VI : VariableOffsets) {
1467 auto &PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
1468 *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);
1469 if (!PotentialConstantsAA.isValidState()) {
1470 UsrOI.setUnknown();
1471 return true;
1472 }
1473
1474 // UndefValue is treated as a zero, which leaves Union as is.
1475 if (PotentialConstantsAA.undefIsContained())
1476 continue;
1477
1478 // We need at least one constant in every set to compute an actual offset.
1479 // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
1480 // don't actually exist. In other words, the absence of constant values
1481 // implies that the operation can be assumed dead for now.
1482 auto &AssumedSet = PotentialConstantsAA.getAssumedSet();
1483 if (AssumedSet.empty())
1484 return false;
1485
1486 OffsetInfo Product;
1487 for (const auto &ConstOffset : AssumedSet) {
1488 auto CopyPerOffset = Union;
1489 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1490 VI.second.getZExtValue());
1491 Product.merge(CopyPerOffset);
1492 }
1493 Union = Product;
1494 }
1495
1496 UsrOI = std::move(Union);
1497 return true;
1498}
1499
1500ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
1501 using namespace AA::PointerInfo;
1502 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1503 const DataLayout &DL = A.getDataLayout();
1504 Value &AssociatedValue = getAssociatedValue();
1505
1506 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1507 OffsetInfoMap[&AssociatedValue].insert(0);
1508
1509 auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
1510 // One does not simply walk into a map and assign a reference to a possibly
1511 // new location. That can cause an invalidation before the assignment
1512 // happens, like so:
1513 //
1514 // OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
1515 //
1516 // The RHS is a reference that may be invalidated by an insertion caused by
1517 // the LHS. So we ensure that the side-effect of the LHS happens first.
1518 auto &UsrOI = OffsetInfoMap[Usr];
1519 auto &PtrOI = OffsetInfoMap[CurPtr];
1520 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", 1521, __extension__
__PRETTY_FUNCTION__))
1521 "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", 1521, __extension__
__PRETTY_FUNCTION__))
;
1522 UsrOI = PtrOI;
1523 Follow = true;
1524 return true;
1525 };
1526
1527 const auto *F = getAnchorScope();
1528 const auto *CI =
1529 F ? A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(*F)
1530 : nullptr;
1531 const auto *TLI =
1532 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
1533
1534 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1535 Value *CurPtr = U.get();
1536 User *Usr = U.getUser();
1537 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usrdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Analyze " <<
*CurPtr << " in " << *Usr << "\n"; } } while
(false)
1538 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Analyze " <<
*CurPtr << " in " << *Usr << "\n"; } } while
(false)
;
1539 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", 1540, __extension__
__PRETTY_FUNCTION__))
1540 "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", 1540, __extension__
__PRETTY_FUNCTION__))
;
1541
1542 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
1543 if (CE->isCast())
1544 return HandlePassthroughUser(Usr, CurPtr, Follow);
1545 if (CE->isCompare())
1546 return true;
1547 if (!isa<GEPOperator>(CE)) {
1548 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CEdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled constant user "
<< *CE << "\n"; } } while (false)
1549 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled constant user "
<< *CE << "\n"; } } while (false)
;
1550 return false;
1551 }
1552 }
1553 if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {
1554 // Note the order here, the Usr access might change the map, CurPtr is
1555 // already in it though.
1556 auto &UsrOI = OffsetInfoMap[Usr];
1557 auto &PtrOI = OffsetInfoMap[CurPtr];
1558
1559 if (UsrOI.isUnknown())
1560 return true;
1561
1562 if (PtrOI.isUnknown()) {
1563 Follow = true;
1564 UsrOI.setUnknown();
1565 return true;
1566 }
1567
1568 Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
1569 return true;
1570 }
1571 if (isa<PtrToIntInst>(Usr))
1572 return false;
1573 if (isa<CastInst>(Usr) || isa<SelectInst>(Usr) || isa<ReturnInst>(Usr))
1574 return HandlePassthroughUser(Usr, CurPtr, Follow);
1575
1576 // For PHIs we need to take care of the recurrence explicitly as the value
1577 // might change while we iterate through a loop. For now, we give up if
1578 // the PHI is not invariant.
1579 if (isa<PHINode>(Usr)) {
1580 // Note the order here, the Usr access might change the map, CurPtr is
1581 // already in it though.
1582 bool IsFirstPHIUser = !OffsetInfoMap.count(Usr);
1583 auto &UsrOI = OffsetInfoMap[Usr];
1584 auto &PtrOI = OffsetInfoMap[CurPtr];
1585
1586 // Check if the PHI operand has already an unknown offset as we can't
1587 // improve on that anymore.
1588 if (PtrOI.isUnknown()) {
1589 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)
1590 << *CurPtr << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand offset unknown "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1591 Follow = !UsrOI.isUnknown();
1592 UsrOI.setUnknown();
1593 return true;
1594 }
1595
1596 // Check if the PHI is invariant (so far).
1597 if (UsrOI == PtrOI) {
1598 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", 1599, __extension__
__PRETTY_FUNCTION__))
1599 "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", 1599, __extension__
__PRETTY_FUNCTION__))
;
1600 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)
;
1601 return true;
1602 }
1603
1604 // Check if the PHI operand can be traced back to AssociatedValue.
1605 APInt Offset(
1606 DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),
1607 0);
1608 Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
1609 DL, Offset, /* AllowNonInbounds */ true);
1610 auto It = OffsetInfoMap.find(CurPtrBase);
1611 if (It == OffsetInfoMap.end()) {
1612 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)
1613 << *CurPtr << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand is too complex "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1614 UsrOI.setUnknown();
1615 Follow = true;
1616 return true;
1617 }
1618
1619 auto mayBeInCycleHeader = [](const CycleInfo *CI, const Instruction *I) {
1620 if (!CI)
1621 return true;
1622 auto *BB = I->getParent();
1623 auto *C = CI->getCycle(BB);
1624 if (!C)
1625 return false;
1626 return BB == C->getHeader();
1627 };
1628
1629 // Check if the PHI operand is not dependent on the PHI itself. Every
1630 // recurrence is a cyclic net of PHIs in the data flow, and has an
1631 // equivalent Cycle in the control flow. One of those PHIs must be in the
1632 // header of that control flow Cycle. This is independent of the choice of
1633 // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
1634 // every Cycle header; if such a node is marked unknown, this will
1635 // eventually propagate through the whole net of PHIs in the recurrence.
1636 if (mayBeInCycleHeader(CI, cast<Instruction>(Usr))) {
1637 auto BaseOI = It->getSecond();
1638 BaseOI.addToAll(Offset.getZExtValue());
1639 if (IsFirstPHIUser || BaseOI == UsrOI) {
1640 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)
1641 << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI is invariant "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1642 return HandlePassthroughUser(Usr, CurPtr, Follow);
1643 }
1644
1645 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
1646 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)
1647 << *CurPtr << " in " << *Usr << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
<< *CurPtr << " in " << *Usr << "\n"
; } } while (false)
;
1648 UsrOI.setUnknown();
1649 Follow = true;
1650 return true;
1651 }
1652
1653 UsrOI.merge(PtrOI);
1654 Follow = true;
1655 return true;
1656 }
1657
1658 if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {
1659 // If the access is to a pointer that may or may not be the associated
1660 // value, e.g. due to a PHI, we cannot assume it will be read.
1661 AccessKind AK = AccessKind::AK_R;
1662 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1663 AK = AccessKind(AK | AccessKind::AK_MUST);
1664 else
1665 AK = AccessKind(AK | AccessKind::AK_MAY);
1666 if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,
1667 OffsetInfoMap[CurPtr].Offsets, Changed,
1668 *LoadI->getType()))
1669 return false;
1670
1671 auto IsAssumption = [](Instruction &I) {
1672 if (auto *II = dyn_cast<IntrinsicInst>(&I))
1673 return II->isAssumeLikeIntrinsic();
1674 return false;
1675 };
1676
1677 auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
1678 // Check if the assumption and the load are executed together without
1679 // memory modification.
1680 do {
1681 if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
1682 return true;
1683 FromI = FromI->getNextNonDebugInstruction();
1684 } while (FromI && FromI != ToI);
1685 return false;
1686 };
1687
1688 BasicBlock *BB = LoadI->getParent();
1689 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1690 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1691 return false;
1692 BasicBlock *IntrBB = IntrI.getParent();
1693 if (IntrI.getParent() == BB) {
1694 if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(), &IntrI))
1695 return false;
1696 } else {
1697 auto PredIt = pred_begin(IntrBB);
1698 if ((*PredIt) != BB)
1699 return false;
1700 if (++PredIt != pred_end(IntrBB))
1701 return false;
1702 for (auto *SuccBB : successors(BB)) {
1703 if (SuccBB == IntrBB)
1704 continue;
1705 if (isa<UnreachableInst>(SuccBB->getTerminator()))
1706 continue;
1707 return false;
1708 }
1709 if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(),
1710 BB->getTerminator()))
1711 return false;
1712 if (IsImpactedInRange(&IntrBB->front(), &IntrI))
1713 return false;
1714 }
1715 return true;
1716 };
1717
1718 std::pair<Value *, IntrinsicInst *> Assumption;
1719 for (const Use &LoadU : LoadI->uses()) {
1720 if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {
1721 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1722 continue;
1723 for (const Use &CmpU : CmpI->uses()) {
1724 if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {
1725 if (!IsValidAssume(*IntrI))
1726 continue;
1727 int Idx = CmpI->getOperandUse(0) == LoadU;
1728 Assumption = {CmpI->getOperand(Idx), IntrI};
1729 break;
1730 }
1731 }
1732 }
1733 if (Assumption.first)
1734 break;
1735 }
1736
1737 // Check if we found an assumption associated with this load.
1738 if (!Assumption.first || !Assumption.second)
1739 return true;
1740
1741 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)
1742 << *Assumption.second << ": " << *LoadIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Assumption found "
<< *Assumption.second << ": " << *LoadI <<
" == " << *Assumption.first << "\n"; } } while (
false)
1743 << " == " << *Assumption.first << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Assumption found "
<< *Assumption.second << ": " << *LoadI <<
" == " << *Assumption.first << "\n"; } } while (
false)
;
1744
1745 return handleAccess(
1746 A, *Assumption.second, Assumption.first, AccessKind::AK_ASSUMPTION,
1747 OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());
1748 }
1749
1750 auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
1751 ArrayRef<Value *> OtherOps, AccessKind AK) {
1752 for (auto *OtherOp : OtherOps) {
1753 if (OtherOp == CurPtr) {
1754 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Escaping use in store like instruction "
<< I << "\n"; } } while (false)
1755 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Escaping use in store like instruction "
<< I << "\n"; } } while (false)
1756 << "[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)
1757 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Escaping use in store like instruction "
<< I << "\n"; } } while (false)
;
1758 return false;
1759 }
1760 }
1761
1762 // If the access is to a pointer that may or may not be the associated
1763 // value, e.g. due to a PHI, we cannot assume it will be written.
1764 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1765 AK = AccessKind(AK | AccessKind::AK_MUST);
1766 else
1767 AK = AccessKind(AK | AccessKind::AK_MAY);
1768 bool UsedAssumedInformation = false;
1769 std::optional<Value *> Content = nullptr;
1770 if (ValueOp)
1771 Content = A.getAssumedSimplified(
1772 *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
1773 return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1774 Changed, ValueTy);
1775 };
1776
1777 if (auto *StoreI = dyn_cast<StoreInst>(Usr))
1778 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1779 *StoreI->getValueOperand()->getType(),
1780 {StoreI->getValueOperand()}, AccessKind::AK_W);
1781 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
1782 return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
1783 {RMWI->getValOperand()}, AccessKind::AK_RW);
1784 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
1785 return HandleStoreLike(
1786 *CXI, nullptr, *CXI->getNewValOperand()->getType(),
1787 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1788 AccessKind::AK_RW);
1789
1790 if (auto *CB = dyn_cast<CallBase>(Usr)) {
1791 if (CB->isLifetimeStartOrEnd())
1792 return true;
1793 if (getFreedOperand(CB, TLI) == U)
1794 return true;
1795 if (CB->isArgOperand(&U)) {
1796 unsigned ArgNo = CB->getArgOperandNo(&U);
1797 const auto &CSArgPI = A.getAAFor<AAPointerInfo>(
1798 *this, IRPosition::callsite_argument(*CB, ArgNo),
1799 DepClassTy::REQUIRED);
1800 Changed = translateAndAddState(A, CSArgPI, OffsetInfoMap[CurPtr], *CB) |
1801 Changed;
1802 return isValidState();
1803 }
1804 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)
1805 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Call user not handled "
<< *CB << "\n"; } } while (false)
;
1806 // TODO: Allow some call uses
1807 return false;
1808 }
1809
1810 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)
;
1811 return false;
1812 };
1813 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
1814 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", 1814, __extension__
__PRETTY_FUNCTION__))
;
1815 if (OffsetInfoMap.count(NewU)) {
1816 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)
1817 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)
1818 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)
1819 << 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)
1820 << "\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)
1821 }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)
1822 })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)
;
1823 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1824 }
1825 OffsetInfoMap[NewU] = OffsetInfoMap[OldU];
1826 return true;
1827 };
1828 if (!A.checkForAllUses(UsePred, *this, AssociatedValue,
1829 /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,
1830 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
1831 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)
;
1832 return indicatePessimisticFixpoint();
1833 }
1834
1835 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1836 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)
1837 dumpState(dbgs());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1838 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
;
1839
1840 return Changed;
1841}
1842
1843struct AAPointerInfoReturned final : AAPointerInfoImpl {
1844 AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
1845 : AAPointerInfoImpl(IRP, A) {}
1846
1847 /// See AbstractAttribute::updateImpl(...).
1848 ChangeStatus updateImpl(Attributor &A) override {
1849 return indicatePessimisticFixpoint();
1850 }
1851
1852 /// See AbstractAttribute::trackStatistics()
1853 void trackStatistics() const override {
1854 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1855 }
1856};
1857
1858struct AAPointerInfoArgument final : AAPointerInfoFloating {
1859 AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
1860 : AAPointerInfoFloating(IRP, A) {}
1861
1862 /// See AbstractAttribute::initialize(...).
1863 void initialize(Attributor &A) override {
1864 AAPointerInfoFloating::initialize(A);
1865 if (getAnchorScope()->isDeclaration())
1866 indicatePessimisticFixpoint();
1867 }
1868
1869 /// See AbstractAttribute::trackStatistics()
1870 void trackStatistics() const override {
1871 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1872 }
1873};
1874
1875struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1876 AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
1877 : AAPointerInfoFloating(IRP, A) {}
1878
1879 /// See AbstractAttribute::updateImpl(...).
1880 ChangeStatus updateImpl(Attributor &A) override {
1881 using namespace AA::PointerInfo;
1882 // We handle memory intrinsics explicitly, at least the first (=
1883 // destination) and second (=source) arguments as we know how they are
1884 // accessed.
1885 if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
1886 ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
1887 int64_t LengthVal = AA::RangeTy::Unknown;
1888 if (Length)
1889 LengthVal = Length->getSExtValue();
1890 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1891 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1892 if (ArgNo > 1) {
1893 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
<< *MI << "\n"; } } while (false)
1894 << *MI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
<< *MI << "\n"; } } while (false)
;
1895 return indicatePessimisticFixpoint();
1896 } else {
1897 auto Kind =
1898 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1899 Changed =
1900 Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);
1901 }
1902 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1903 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)
1904 dumpState(dbgs());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
1905 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "Accesses by bin after update:\n"
; dumpState(dbgs()); }; } } while (false)
;
1906
1907 return Changed;
1908 }
1909
1910 // TODO: Once we have call site specific value information we can provide
1911 // call site specific liveness information and then it makes
1912 // sense to specialize attributes for call sites arguments instead of
1913 // redirecting requests to the callee argument.
1914 Argument *Arg = getAssociatedArgument();
1915 if (Arg) {
1916 const IRPosition &ArgPos = IRPosition::argument(*Arg);
1917 auto &ArgAA =
1918 A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
1919 if (ArgAA.getState().isValidState())
1920 return translateAndAddStateFromCallee(A, ArgAA,
1921 *cast<CallBase>(getCtxI()));
1922 if (!Arg->getParent()->isDeclaration())
1923 return indicatePessimisticFixpoint();
1924 }
1925
1926 const auto &NoCaptureAA =
1927 A.getAAFor<AANoCapture>(*this, getIRPosition(), DepClassTy::OPTIONAL);
1928
1929 if (!NoCaptureAA.isAssumedNoCapture())
1930 return indicatePessimisticFixpoint();
1931
1932 bool IsKnown = false;
1933 if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
1934 return ChangeStatus::UNCHANGED;
1935 bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);
1936 auto Kind =
1937 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
1938 return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,
1939 nullptr);
1940 }
1941
1942 /// See AbstractAttribute::trackStatistics()
1943 void trackStatistics() const override {
1944 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1945 }
1946};
1947
1948struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
1949 AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
1950 : AAPointerInfoFloating(IRP, A) {}
1951
1952 /// See AbstractAttribute::trackStatistics()
1953 void trackStatistics() const override {
1954 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1955 }
1956};
1957} // namespace
1958
1959/// -----------------------NoUnwind Function Attribute--------------------------
1960
1961namespace {
1962struct AANoUnwindImpl : AANoUnwind {
1963 AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}
1964
1965 const std::string getAsStr() const override {
1966 return getAssumed() ? "nounwind" : "may-unwind";
1967 }
1968
1969 /// See AbstractAttribute::updateImpl(...).
1970 ChangeStatus updateImpl(Attributor &A) override {
1971 auto Opcodes = {
1972 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
1973 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
1974 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
1975
1976 auto CheckForNoUnwind = [&](Instruction &I) {
1977 if (!I.mayThrow())
1978 return true;
1979
1980 if (const auto *CB = dyn_cast<CallBase>(&I)) {
1981 const auto &NoUnwindAA = A.getAAFor<AANoUnwind>(
1982 *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);
1983 return NoUnwindAA.isAssumedNoUnwind();
1984 }
1985 return false;
1986 };
1987
1988 bool UsedAssumedInformation = false;
1989 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
1990 UsedAssumedInformation))
1991 return indicatePessimisticFixpoint();
1992
1993 return ChangeStatus::UNCHANGED;
1994 }
1995};
1996
1997struct AANoUnwindFunction final : public AANoUnwindImpl {
1998 AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
1999 : AANoUnwindImpl(IRP, A) {}
2000
2001 /// See AbstractAttribute::trackStatistics()
2002 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind){ static llvm::Statistic NumIRFunction_nounwind = {"attributor"
, "NumIRFunction_nounwind", ("Number of " "functions" " marked '"
"nounwind" "'")};; ++(NumIRFunction_nounwind); }
}
2003};
2004
2005/// NoUnwind attribute deduction for a call sites.
2006struct AANoUnwindCallSite final : AANoUnwindImpl {
2007 AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
2008 : AANoUnwindImpl(IRP, A) {}
2009
2010 /// See AbstractAttribute::initialize(...).
2011 void initialize(Attributor &A) override {
2012 AANoUnwindImpl::initialize(A);
2013 Function *F = getAssociatedFunction();
2014 if (!F || F->isDeclaration())
2015 indicatePessimisticFixpoint();
2016 }
2017
2018 /// See AbstractAttribute::updateImpl(...).
2019 ChangeStatus updateImpl(Attributor &A) override {
2020 // TODO: Once we have call site specific value information we can provide
2021 // call site specific liveness information and then it makes
2022 // sense to specialize attributes for call sites arguments instead of
2023 // redirecting requests to the callee argument.
2024 Function *F = getAssociatedFunction();
2025 const IRPosition &FnPos = IRPosition::function(*F);
2026 auto &FnAA = A.getAAFor<AANoUnwind>(*this, FnPos, DepClassTy::REQUIRED);
2027 return clampStateAndIndicateChange(getState(), FnAA.getState());
2028 }
2029
2030 /// See AbstractAttribute::trackStatistics()
2031 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); }
; }
2032};
2033} // namespace
2034
2035/// --------------------- Function Return Values -------------------------------
2036
2037namespace {
2038/// "Attribute" that collects all potential returned values and the return
2039/// instructions that they arise from.
2040///
2041/// If there is a unique returned value R, the manifest method will:
2042/// - mark R with the "returned" attribute, if R is an argument.
2043class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
2044
2045 /// Mapping of values potentially returned by the associated function to the
2046 /// return instructions that might return them.
2047 MapVector<Value *, SmallSetVector<ReturnInst *, 4>> ReturnedValues;
2048
2049 /// State flags
2050 ///
2051 ///{
2052 bool IsFixed = false;
2053 bool IsValidState = true;
2054 ///}
2055
2056public:
2057 AAReturnedValuesImpl(const IRPosition &IRP, Attributor &A)
2058 : AAReturnedValues(IRP, A) {}
2059
2060 /// See AbstractAttribute::initialize(...).
2061 void initialize(Attributor &A) override {
2062 // Reset the state.
2063 IsFixed = false;
2064 IsValidState = true;
2065 ReturnedValues.clear();
2066
2067 Function *F = getAssociatedFunction();
2068 if (!F || F->isDeclaration()) {
2069 indicatePessimisticFixpoint();
2070 return;
2071 }
2072 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", 2073, __extension__
__PRETTY_FUNCTION__))
2073 "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", 2073, __extension__
__PRETTY_FUNCTION__))
;
2074
2075 // The map from instruction opcodes to those instructions in the function.
2076 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
2077
2078 // Look through all arguments, if one is marked as returned we are done.
2079 for (Argument &Arg : F->args()) {
2080 if (Arg.hasReturnedAttr()) {
2081 auto &ReturnInstSet = ReturnedValues[&Arg];
2082 if (auto *Insts = OpcodeInstMap.lookup(Instruction::Ret))
2083 for (Instruction *RI : *Insts)
2084 ReturnInstSet.insert(cast<ReturnInst>(RI));
2085
2086 indicateOptimisticFixpoint();
2087 return;
2088 }
2089 }
2090
2091 if (!A.isFunctionIPOAmendable(*F))
2092 indicatePessimisticFixpoint();
2093 }
2094
2095 /// See AbstractAttribute::manifest(...).
2096 ChangeStatus manifest(Attributor &A) override;
2097
2098 /// See AbstractAttribute::getState(...).
2099 AbstractState &getState() override { return *this; }
2100
2101 /// See AbstractAttribute::getState(...).
2102 const AbstractState &getState() const override { return *this; }
2103
2104 /// See AbstractAttribute::updateImpl(Attributor &A).
2105 ChangeStatus updateImpl(Attributor &A) override;
2106
2107 llvm::iterator_range<iterator> returned_values() override {
2108 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
2109 }
2110
2111 llvm::iterator_range<const_iterator> returned_values() const override {
2112 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
2113 }
2114
2115 /// Return the number of potential return values, -1 if unknown.
2116 size_t getNumReturnValues() const override {
2117 return isValidState() ? ReturnedValues.size() : -1;
2118 }
2119
2120 /// Return an assumed unique return value if a single candidate is found. If
2121 /// there cannot be one, return a nullptr. If it is not clear yet, return
2122 /// std::nullopt.
2123 std::optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
2124
2125 /// See AbstractState::checkForAllReturnedValues(...).
2126 bool checkForAllReturnedValuesAndReturnInsts(
2127 function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred)
2128 const override;
2129
2130 /// Pretty print the attribute similar to the IR representation.
2131 const std::string getAsStr() const override;
2132
2133 /// See AbstractState::isAtFixpoint().
2134 bool isAtFixpoint() const override { return IsFixed; }
2135
2136 /// See AbstractState::isValidState().
2137 bool isValidState() const override { return IsValidState; }
2138
2139 /// See AbstractState::indicateOptimisticFixpoint(...).
2140 ChangeStatus indicateOptimisticFixpoint() override {
2141 IsFixed = true;
2142 return ChangeStatus::UNCHANGED;
2143 }
2144
2145 ChangeStatus indicatePessimisticFixpoint() override {
2146 IsFixed = true;
2147 IsValidState = false;
2148 return ChangeStatus::CHANGED;
2149 }
2150};
2151
2152ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
2153 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2154
2155 // Bookkeeping.
2156 assert(isValidState())(static_cast <bool> (isValidState()) ? void (0) : __assert_fail
("isValidState()", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 2156, __extension__ __PRETTY_FUNCTION__))
;
2157 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,{ static llvm::Statistic NumIRFunctionReturn_KnownReturnValues
= {"attributor", "NumIRFunctionReturn_KnownReturnValues", "Number of function with known return values"
};; ++(NumIRFunctionReturn_KnownReturnValues); }
2158 "Number of function with known return values"){ static llvm::Statistic NumIRFunctionReturn_KnownReturnValues
= {"attributor", "NumIRFunctionReturn_KnownReturnValues", "Number of function with known return values"
};; ++(NumIRFunctionReturn_KnownReturnValues); }
;
2159
2160 // Check if we have an assumed unique return value that we could manifest.
2161 std::optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
2162
2163 if (!UniqueRV || !*UniqueRV)
2164 return Changed;
2165
2166 // Bookkeeping.
2167 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,{ static llvm::Statistic NumIRFunctionReturn_UniqueReturnValue
= {"attributor", "NumIRFunctionReturn_UniqueReturnValue", "Number of function with unique return"
};; ++(NumIRFunctionReturn_UniqueReturnValue); }
2168 "Number of function with unique return"){ static llvm::Statistic NumIRFunctionReturn_UniqueReturnValue
= {"attributor", "NumIRFunctionReturn_UniqueReturnValue", "Number of function with unique return"
};; ++(NumIRFunctionReturn_UniqueReturnValue); }
;
2169 // If the assumed unique return value is an argument, annotate it.
2170 if (auto *UniqueRVArg = dyn_cast<Argument>(*UniqueRV)) {
2171 if (UniqueRVArg->getType()->canLosslesslyBitCastTo(
2172 getAssociatedFunction()->getReturnType())) {
2173 getIRPosition() = IRPosition::argument(*UniqueRVArg);
2174 Changed = IRAttribute::manifest(A);
2175 }
2176 }
2177 return Changed;
2178}
2179
2180const std::string AAReturnedValuesImpl::getAsStr() const {
2181 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
2182 (isValidState() ? std::to_string(getNumReturnValues()) : "?") + ")";
2183}
2184
2185std::optional<Value *>
2186AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
2187 // If checkForAllReturnedValues provides a unique value, ignoring potential
2188 // undef values that can also be present, it is assumed to be the actual
2189 // return value and forwarded to the caller of this method. If there are
2190 // multiple, a nullptr is returned indicating there cannot be a unique
2191 // returned value.
2192 std::optional<Value *> UniqueRV;
2193 Type *Ty = getAssociatedFunction()->getReturnType();
2194
2195 auto Pred = [&](Value &RV) -> bool {
2196 UniqueRV = AA::combineOptionalValuesInAAValueLatice(UniqueRV, &RV, Ty);
2197 return UniqueRV != std::optional<Value *>(nullptr);
2198 };
2199
2200 if (!A.checkForAllReturnedValues(Pred, *this))
2201 UniqueRV = nullptr;
2202
2203 return UniqueRV;
2204}
2205
2206bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
2207 function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred)
2208 const {
2209 if (!isValidState())
2210 return false;
2211
2212 // Check all returned values but ignore call sites as long as we have not
2213 // encountered an overdefined one during an update.
2214 for (const auto &It : ReturnedValues) {
2215 Value *RV = It.first;
2216 if (!Pred(*RV, It.second))
2217 return false;
2218 }
2219
2220 return true;
2221}
2222
2223ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
2224 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2225
2226 SmallVector<AA::ValueAndContext> Values;
2227 bool UsedAssumedInformation = false;
2228 auto ReturnInstCB = [&](Instruction &I) {
2229 ReturnInst &Ret = cast<ReturnInst>(I);
2230 Values.clear();
2231 if (!A.getAssumedSimplifiedValues(IRPosition::value(*Ret.getReturnValue()),
2232 *this, Values, AA::Intraprocedural,
2233 UsedAssumedInformation))
2234 Values.push_back({*Ret.getReturnValue(), Ret});
2235
2236 for (auto &VAC : Values) {
2237 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", 2238, __extension__
__PRETTY_FUNCTION__))
2238 "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", 2238, __extension__
__PRETTY_FUNCTION__))
;
2239 if (ReturnedValues[VAC.getValue()].insert(&Ret))
2240 Changed = ChangeStatus::CHANGED;
2241 }
2242 return true;
2243 };
2244
2245 // Discover returned values from all live returned instructions in the
2246 // associated function.
2247 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
2248 UsedAssumedInformation))
2249 return indicatePessimisticFixpoint();
2250 return Changed;
2251}
2252
2253struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
2254 AAReturnedValuesFunction(const IRPosition &IRP, Attributor &A)
2255 : AAReturnedValuesImpl(IRP, A) {}
2256
2257 /// See AbstractAttribute::trackStatistics()
2258 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned){ static llvm::Statistic NumIRArguments_returned = {"attributor"
, "NumIRArguments_returned", ("Number of " "arguments" " marked '"
"returned" "'")};; ++(NumIRArguments_returned); }
}
2259};
2260
2261/// Returned values information for a call sites.
2262struct AAReturnedValuesCallSite final : AAReturnedValuesImpl {
2263 AAReturnedValuesCallSite(const IRPosition &IRP, Attributor &A)
2264 : AAReturnedValuesImpl(IRP, A) {}
2265
2266 /// See AbstractAttribute::initialize(...).
2267 void initialize(Attributor &A) override {
2268 // TODO: Once we have call site specific value information we can provide
2269 // call site specific liveness information and then it makes
2270 // sense to specialize attributes for call sites instead of
2271 // redirecting requests to the callee.
2272 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"
, 2273)
2273 "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"
, 2273)
;
2274 }
2275
2276 /// See AbstractAttribute::updateImpl(...).
2277 ChangeStatus updateImpl(Attributor &A) override {
2278 return indicatePessimisticFixpoint();
2279 }
2280
2281 /// See AbstractAttribute::trackStatistics()
2282 void trackStatistics() const override {}
2283};
2284} // namespace
2285
2286/// ------------------------ NoSync Function Attribute -------------------------
2287
2288bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
2289 switch (CB.getIntrinsicID()) {
2290 case Intrinsic::nvvm_barrier0:
2291 case Intrinsic::nvvm_barrier0_and:
2292 case Intrinsic::nvvm_barrier0_or:
2293 case Intrinsic::nvvm_barrier0_popc:
2294 return true;
2295 case Intrinsic::amdgcn_s_barrier:
2296 if (ExecutedAligned)
2297 return true;
2298 break;
2299 default:
2300 break;
2301 }
2302 return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));
2303}
2304
2305bool AANoSync::isNonRelaxedAtomic(const Instruction *I) {
2306 if (!I->isAtomic())
2307 return false;
2308
2309 if (auto *FI = dyn_cast<FenceInst>(I))
2310 // All legal orderings for fence are stronger than monotonic.
2311 return FI->getSyncScopeID() != SyncScope::SingleThread;
2312 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
2313 // Unordered is not a legal ordering for cmpxchg.
2314 return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
2315 AI->getFailureOrdering() != AtomicOrdering::Monotonic);
2316 }
2317
2318 AtomicOrdering Ordering;
2319 switch (I->getOpcode()) {
2320 case Instruction::AtomicRMW:
2321 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
2322 break;
2323 case Instruction::Store:
2324 Ordering = cast<StoreInst>(I)->getOrdering();
2325 break;
2326 case Instruction::Load:
2327 Ordering = cast<LoadInst>(I)->getOrdering();
2328 break;
2329 default:
2330 llvm_unreachable(::llvm::llvm_unreachable_internal("New atomic operations need to be known in the attributor."
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 2331)
2331 "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", 2331)
;
2332 }
2333
2334 return (Ordering != AtomicOrdering::Unordered &&
2335 Ordering != AtomicOrdering::Monotonic);
2336}
2337
2338/// Return true if this intrinsic is nosync. This is only used for intrinsics
2339/// which would be nosync except that they have a volatile flag. All other
2340/// intrinsics are simply annotated with the nosync attribute in Intrinsics.td.
2341bool AANoSync::isNoSyncIntrinsic(const Instruction *I) {
2342 if (auto *MI = dyn_cast<MemIntrinsic>(I))
2343 return !MI->isVolatile();
2344 return false;
2345}
2346
2347namespace {
2348struct AANoSyncImpl : AANoSync {
2349 AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}
2350
2351 const std::string getAsStr() const override {
2352 return getAssumed() ? "nosync" : "may-sync";
2353 }
2354
2355 /// See AbstractAttribute::updateImpl(...).
2356 ChangeStatus updateImpl(Attributor &A) override;
2357};
2358
2359ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
2360
2361 auto CheckRWInstForNoSync = [&](Instruction &I) {
2362 return AA::isNoSyncInst(A, I, *this);
2363 };
2364
2365 auto CheckForNoSync = [&](Instruction &I) {
2366 // At this point we handled all read/write effects and they are all
2367 // nosync, so they can be skipped.
2368 if (I.mayReadOrWriteMemory())
2369 return true;
2370
2371 // non-convergent and readnone imply nosync.
2372 return !cast<CallBase>(I).isConvergent();
2373 };
2374
2375 bool UsedAssumedInformation = false;
2376 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
2377 UsedAssumedInformation) ||
2378 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
2379 UsedAssumedInformation))
2380 return indicatePessimisticFixpoint();
2381
2382 return ChangeStatus::UNCHANGED;
2383}
2384
2385struct AANoSyncFunction final : public AANoSyncImpl {
2386 AANoSyncFunction(const IRPosition &IRP, Attributor &A)
2387 : AANoSyncImpl(IRP, A) {}
2388
2389 /// See AbstractAttribute::trackStatistics()
2390 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync){ static llvm::Statistic NumIRFunction_nosync = {"attributor"
, "NumIRFunction_nosync", ("Number of " "functions" " marked '"
"nosync" "'")};; ++(NumIRFunction_nosync); }
}
2391};
2392
2393/// NoSync attribute deduction for a call sites.
2394struct AANoSyncCallSite final : AANoSyncImpl {
2395 AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
2396 : AANoSyncImpl(IRP, A) {}
2397
2398 /// See AbstractAttribute::initialize(...).
2399 void initialize(Attributor &A) override {
2400 AANoSyncImpl::initialize(A);
2401 Function *F = getAssociatedFunction();
2402 if (!F || F->isDeclaration())
2403 indicatePessimisticFixpoint();
2404 }
2405
2406 /// See AbstractAttribute::updateImpl(...).
2407 ChangeStatus updateImpl(Attributor &A) override {
2408 // TODO: Once we have call site specific value information we can provide
2409 // call site specific liveness information and then it makes
2410 // sense to specialize attributes for call sites arguments instead of
2411 // redirecting requests to the callee argument.
2412 Function *F = getAssociatedFunction();
2413 const IRPosition &FnPos = IRPosition::function(*F);
2414 auto &FnAA = A.getAAFor<AANoSync>(*this, FnPos, DepClassTy::REQUIRED);
2415 return clampStateAndIndicateChange(getState(), FnAA.getState());
2416 }
2417
2418 /// See AbstractAttribute::trackStatistics()
2419 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
); }
; }
2420};
2421} // namespace
2422
2423/// ------------------------ No-Free Attributes ----------------------------
2424
2425namespace {
2426struct AANoFreeImpl : public AANoFree {
2427 AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}
2428
2429 /// See AbstractAttribute::updateImpl(...).
2430 ChangeStatus updateImpl(Attributor &A) override {
2431 auto CheckForNoFree = [&](Instruction &I) {
2432 const auto &CB = cast<CallBase>(I);
2433 if (CB.hasFnAttr(Attribute::NoFree))
2434 return true;
2435
2436 const auto &NoFreeAA = A.getAAFor<AANoFree>(
2437 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
2438 return NoFreeAA.isAssumedNoFree();
2439 };
2440
2441 bool UsedAssumedInformation = false;
2442 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
2443 UsedAssumedInformation))
2444 return indicatePessimisticFixpoint();
2445 return ChangeStatus::UNCHANGED;
2446 }
2447
2448 /// See AbstractAttribute::getAsStr().
2449 const std::string getAsStr() const override {
2450 return getAssumed() ? "nofree" : "may-free";
2451 }
2452};
2453
2454struct AANoFreeFunction final : public AANoFreeImpl {
2455 AANoFreeFunction(const IRPosition &IRP, Attributor &A)
2456 : AANoFreeImpl(IRP, A) {}
2457
2458 /// See AbstractAttribute::trackStatistics()
2459 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree){ static llvm::Statistic NumIRFunction_nofree = {"attributor"
, "NumIRFunction_nofree", ("Number of " "functions" " marked '"
"nofree" "'")};; ++(NumIRFunction_nofree); }
}
2460};
2461
2462/// NoFree attribute deduction for a call sites.
2463struct AANoFreeCallSite final : AANoFreeImpl {
2464 AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
2465 : AANoFreeImpl(IRP, A) {}
2466
2467 /// See AbstractAttribute::initialize(...).
2468 void initialize(Attributor &A) override {
2469 AANoFreeImpl::initialize(A);
2470 Function *F = getAssociatedFunction();
2471 if (!F || F->isDeclaration())
2472 indicatePessimisticFixpoint();
2473 }
2474
2475 /// See AbstractAttribute::updateImpl(...).
2476 ChangeStatus updateImpl(Attributor &A) override {
2477 // TODO: Once we have call site specific value information we can provide
2478 // call site specific liveness information and then it makes
2479 // sense to specialize attributes for call sites arguments instead of
2480 // redirecting requests to the callee argument.
2481 Function *F = getAssociatedFunction();
2482 const IRPosition &FnPos = IRPosition::function(*F);
2483 auto &FnAA = A.getAAFor<AANoFree>(*this, FnPos, DepClassTy::REQUIRED);
2484 return clampStateAndIndicateChange(getState(), FnAA.getState());
2485 }
2486
2487 /// See AbstractAttribute::trackStatistics()
2488 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
); }
; }
2489};
2490
2491/// NoFree attribute for floating values.
2492struct AANoFreeFloating : AANoFreeImpl {
2493 AANoFreeFloating(const IRPosition &IRP, Attributor &A)
2494 : AANoFreeImpl(IRP, A) {}
2495
2496 /// See AbstractAttribute::trackStatistics()
2497 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); }
}
2498
2499 /// See Abstract Attribute::updateImpl(...).
2500 ChangeStatus updateImpl(Attributor &A) override {
2501 const IRPosition &IRP = getIRPosition();
2502
2503 const auto &NoFreeAA = A.getAAFor<AANoFree>(
2504 *this, IRPosition::function_scope(IRP), DepClassTy::OPTIONAL);
2505 if (NoFreeAA.isAssumedNoFree())
2506 return ChangeStatus::UNCHANGED;
2507
2508 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2509 auto Pred = [&](const Use &U, bool &Follow) -> bool {
2510 Instruction *UserI = cast<Instruction>(U.getUser());
2511 if (auto *CB = dyn_cast<CallBase>(UserI)) {
2512 if (CB->isBundleOperand(&U))
2513 return false;
2514 if (!CB->isArgOperand(&U))
2515 return true;
2516 unsigned ArgNo = CB->getArgOperandNo(&U);
2517
2518 const auto &NoFreeArg = A.getAAFor<AANoFree>(
2519 *this, IRPosition::callsite_argument(*CB, ArgNo),
2520 DepClassTy::REQUIRED);
2521 return NoFreeArg.isAssumedNoFree();
2522 }
2523
2524 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
2525 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
2526 Follow = true;
2527 return true;
2528 }
2529 if (isa<StoreInst>(UserI) || isa<LoadInst>(UserI) ||
2530 isa<ReturnInst>(UserI))
2531 return true;
2532
2533 // Unknown user.
2534 return false;
2535 };
2536 if (!A.checkForAllUses(Pred, *this, AssociatedValue))
2537 return indicatePessimisticFixpoint();
2538
2539 return ChangeStatus::UNCHANGED;
2540 }
2541};
2542
2543/// NoFree attribute for a call site argument.
2544struct AANoFreeArgument final : AANoFreeFloating {
2545 AANoFreeArgument(const IRPosition &IRP, Attributor &A)
2546 : AANoFreeFloating(IRP, A) {}
2547
2548 /// See AbstractAttribute::trackStatistics()
2549 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree){ static llvm::Statistic NumIRArguments_nofree = {"attributor"
, "NumIRArguments_nofree", ("Number of " "arguments" " marked '"
"nofree" "'")};; ++(NumIRArguments_nofree); }
}
2550};
2551
2552/// NoFree attribute for call site arguments.
2553struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2554 AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
2555 : AANoFreeFloating(IRP, A) {}
2556
2557 /// See AbstractAttribute::updateImpl(...).
2558 ChangeStatus updateImpl(Attributor &A) override {
2559 // TODO: Once we have call site specific value information we can provide
2560 // call site specific liveness information and then it makes
2561 // sense to specialize attributes for call sites arguments instead of
2562 // redirecting requests to the callee argument.
2563 Argument *Arg = getAssociatedArgument();
2564 if (!Arg)
2565 return indicatePessimisticFixpoint();
2566 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2567 auto &ArgAA = A.getAAFor<AANoFree>(*this, ArgPos, DepClassTy::REQUIRED);
2568 return clampStateAndIndicateChange(getState(), ArgAA.getState());
2569 }
2570
2571 /// See AbstractAttribute::trackStatistics()
2572 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); }
};
2573};
2574
2575/// NoFree attribute for function return value.
2576struct AANoFreeReturned final : AANoFreeFloating {
2577 AANoFreeReturned(const IRPosition &IRP, Attributor &A)
2578 : AANoFreeFloating(IRP, A) {
2579 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", 2579)
;
2580 }
2581
2582 /// See AbstractAttribute::initialize(...).
2583 void initialize(Attributor &A) override {
2584 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", 2584)
;
2585 }
2586
2587 /// See AbstractAttribute::updateImpl(...).
2588 ChangeStatus updateImpl(Attributor &A) override {
2589 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", 2589)
;
2590 }
2591
2592 /// See AbstractAttribute::trackStatistics()
2593 void trackStatistics() const override {}
2594};
2595
2596/// NoFree attribute deduction for a call site return value.
2597struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2598 AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
2599 : AANoFreeFloating(IRP, A) {}
2600
2601 ChangeStatus manifest(Attributor &A) override {
2602 return ChangeStatus::UNCHANGED;
2603 }
2604 /// See AbstractAttribute::trackStatistics()
2605 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); }
}
2606};
2607} // namespace
2608
2609/// ------------------------ NonNull Argument Attribute ------------------------
2610namespace {
2611static int64_t getKnownNonNullAndDerefBytesForUse(
2612 Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
2613 const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
2614 TrackUse = false;
2615
2616 const Value *UseV = U->get();
2617 if (!UseV->getType()->isPointerTy())
2618 return 0;
2619
2620 // We need to follow common pointer manipulation uses to the accesses they
2621 // feed into. We can try to be smart to avoid looking through things we do not
2622 // like for now, e.g., non-inbounds GEPs.
2623 if (isa<CastInst>(I)) {
2624 TrackUse = true;
2625 return 0;
2626 }
2627
2628 if (isa<GetElementPtrInst>(I)) {
2629 TrackUse = true;
2630 return 0;
2631 }
2632
2633 Type *PtrTy = UseV->getType();
2634 const Function *F = I->getFunction();
2635 bool NullPointerIsDefined =
2636 F ? llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()) : true;
2637 const DataLayout &DL = A.getInfoCache().getDL();
2638 if (const auto *CB = dyn_cast<CallBase>(I)) {
2639 if (CB->isBundleOperand(U)) {
2640 if (RetainedKnowledge RK = getKnowledgeFromUse(
2641 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2642 IsNonNull |=
2643 (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);
2644 return RK.ArgValue;
2645 }
2646 return 0;
2647 }
2648
2649 if (CB->isCallee(U)) {
2650 IsNonNull |= !NullPointerIsDefined;
2651 return 0;
2652 }
2653
2654 unsigned ArgNo = CB->getArgOperandNo(U);
2655 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
2656 // As long as we only use known information there is no need to track
2657 // dependences here.
2658 auto &DerefAA =
2659 A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
2660 IsNonNull |= DerefAA.isKnownNonNull();
2661 return DerefAA.getKnownDereferenceableBytes();
2662 }
2663
2664 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
2665 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
2666 return 0;
2667
2668 int64_t Offset;
2669 const Value *Base =
2670 getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);
2671 if (Base && Base == &AssociatedValue) {
2672 int64_t DerefBytes = Loc->Size.getValue() + Offset;
2673 IsNonNull |= !NullPointerIsDefined;
2674 return std::max(int64_t(0), DerefBytes);
2675 }
2676
2677 /// Corner case when an offset is 0.
2678 Base = GetPointerBaseWithConstantOffset(Loc->Ptr, Offset, DL,
2679 /*AllowNonInbounds*/ true);
2680 if (Base && Base == &AssociatedValue && Offset == 0) {
2681 int64_t DerefBytes = Loc->Size.getValue();
2682 IsNonNull |= !NullPointerIsDefined;
2683 return std::max(int64_t(0), DerefBytes);
2684 }
2685
2686 return 0;
2687}
2688
2689struct AANonNullImpl : AANonNull {
2690 AANonNullImpl(const IRPosition &IRP, Attributor &A)
2691 : AANonNull(IRP, A),
2692 NullIsDefined(NullPointerIsDefined(
2693 getAnchorScope(),
2694 getAssociatedValue().getType()->getPointerAddressSpace())) {}
2695
2696 /// See AbstractAttribute::initialize(...).
2697 void initialize(Attributor &A) override {
2698 Value &V = *getAssociatedValue().stripPointerCasts();
2699 if (!NullIsDefined &&
2700 hasAttr({Attribute::NonNull, Attribute::Dereferenceable},
2701 /* IgnoreSubsumingPositions */ false, &A)) {
2702 indicateOptimisticFixpoint();
2703 return;
2704 }
2705
2706 if (isa<ConstantPointerNull>(V)) {
2707 indicatePessimisticFixpoint();
2708 return;
2709 }
2710
2711 AANonNull::initialize(A);
2712
2713 bool CanBeNull, CanBeFreed;
2714 if (V.getPointerDereferenceableBytes(A.getDataLayout(), CanBeNull,
2715 CanBeFreed)) {
2716 if (!CanBeNull) {
2717 indicateOptimisticFixpoint();
2718 return;
2719 }
2720 }
2721
2722 if (isa<GlobalValue>(V)) {
2723 indicatePessimisticFixpoint();
2724 return;
2725 }
2726
2727 if (Instruction *CtxI = getCtxI())
2728 followUsesInMBEC(*this, A, getState(), *CtxI);
2729 }
2730
2731 /// See followUsesInMBEC
2732 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
2733 AANonNull::StateType &State) {
2734 bool IsNonNull = false;
2735 bool TrackUse = false;
2736 getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,
2737 IsNonNull, TrackUse);
2738 State.setKnown(IsNonNull);
2739 return TrackUse;
2740 }
2741
2742 /// See AbstractAttribute::getAsStr().
2743 const std::string getAsStr() const override {
2744 return getAssumed() ? "nonnull" : "may-null";
2745 }
2746
2747 /// Flag to determine if the underlying value can be null and still allow
2748 /// valid accesses.
2749 const bool NullIsDefined;
2750};
2751
2752/// NonNull attribute for a floating value.
2753struct AANonNullFloating : public AANonNullImpl {
2754 AANonNullFloating(const IRPosition &IRP, Attributor &A)
2755 : AANonNullImpl(IRP, A) {}
2756
2757 /// See AbstractAttribute::updateImpl(...).
2758 ChangeStatus updateImpl(Attributor &A) override {
2759 const DataLayout &DL = A.getDataLayout();
2760
2761 bool Stripped;
2762 bool UsedAssumedInformation = false;
2763 SmallVector<AA::ValueAndContext> Values;
2764 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
2765 AA::AnyScope, UsedAssumedInformation)) {
2766 Values.push_back({getAssociatedValue(), getCtxI()});
2767 Stripped = false;
2768 } else {
2769 Stripped = Values.size() != 1 ||
2770 Values.front().getValue() != &getAssociatedValue();
2771 }
2772
2773 DominatorTree *DT = nullptr;
2774 AssumptionCache *AC = nullptr;
2775 InformationCache &InfoCache = A.getInfoCache();
2776 if (const Function *Fn = getAnchorScope()) {
2777 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*Fn);
2778 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*Fn);
2779 }
2780
2781 AANonNull::StateType T;
2782 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
2783 const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V),
2784 DepClassTy::REQUIRED);
2785 if (!Stripped && this == &AA) {
2786 if (!isKnownNonZero(&V, DL, 0, AC, CtxI, DT))
2787 T.indicatePessimisticFixpoint();
2788 } else {
2789 // Use abstract attribute information.
2790 const AANonNull::StateType &NS = AA.getState();
2791 T ^= NS;
2792 }
2793 return T.isValidState();
2794 };
2795
2796 for (const auto &VAC : Values)
2797 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
2798 return indicatePessimisticFixpoint();
2799
2800 return clampStateAndIndicateChange(getState(), T);
2801 }
2802
2803 /// See AbstractAttribute::trackStatistics()
2804 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
); }
}
2805};
2806
2807/// NonNull attribute for function return value.
2808struct AANonNullReturned final
2809 : AAReturnedFromReturnedValues<AANonNull, AANonNull> {
2810 AANonNullReturned(const IRPosition &IRP, Attributor &A)
2811 : AAReturnedFromReturnedValues<AANonNull, AANonNull>(IRP, A) {}
2812
2813 /// See AbstractAttribute::getAsStr().
2814 const std::string getAsStr() const override {
2815 return getAssumed() ? "nonnull" : "may-null";
2816 }
2817
2818 /// See AbstractAttribute::trackStatistics()
2819 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
); }
}
2820};
2821
2822/// NonNull attribute for function argument.
2823struct AANonNullArgument final
2824 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2825 AANonNullArgument(const IRPosition &IRP, Attributor &A)
2826 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}
2827
2828 /// See AbstractAttribute::trackStatistics()
2829 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull){ static llvm::Statistic NumIRArguments_nonnull = {"attributor"
, "NumIRArguments_nonnull", ("Number of " "arguments" " marked '"
"nonnull" "'")};; ++(NumIRArguments_nonnull); }
}
2830};
2831
2832struct AANonNullCallSiteArgument final : AANonNullFloating {
2833 AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
2834 : AANonNullFloating(IRP, A) {}
2835
2836 /// See AbstractAttribute::trackStatistics()
2837 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); }
}
2838};
2839
2840/// NonNull attribute for a call site return position.
2841struct AANonNullCallSiteReturned final
2842 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl> {
2843 AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
2844 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl>(IRP, A) {}
2845
2846 /// See AbstractAttribute::trackStatistics()
2847 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); }
}
2848};
2849} // namespace
2850
2851/// ------------------------ No-Recurse Attributes ----------------------------
2852
2853namespace {
2854struct AANoRecurseImpl : public AANoRecurse {
2855 AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}
2856
2857 /// See AbstractAttribute::getAsStr()
2858 const std::string getAsStr() const override {
2859 return getAssumed() ? "norecurse" : "may-recurse";
2860 }
2861};
2862
2863struct AANoRecurseFunction final : AANoRecurseImpl {
2864 AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
2865 : AANoRecurseImpl(IRP, A) {}
2866
2867 /// See AbstractAttribute::updateImpl(...).
2868 ChangeStatus updateImpl(Attributor &A) override {
2869
2870 // If all live call sites are known to be no-recurse, we are as well.
2871 auto CallSitePred = [&](AbstractCallSite ACS) {
2872 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
2873 *this, IRPosition::function(*ACS.getInstruction()->getFunction()),
2874 DepClassTy::NONE);
2875 return NoRecurseAA.isKnownNoRecurse();
2876 };
2877 bool UsedAssumedInformation = false;
2878 if (A.checkForAllCallSites(CallSitePred, *this, true,
2879 UsedAssumedInformation)) {
2880 // If we know all call sites and all are known no-recurse, we are done.
2881 // If all known call sites, which might not be all that exist, are known
2882 // to be no-recurse, we are not done but we can continue to assume
2883 // no-recurse. If one of the call sites we have not visited will become
2884 // live, another update is triggered.
2885 if (!UsedAssumedInformation)
2886 indicateOptimisticFixpoint();
2887 return ChangeStatus::UNCHANGED;
2888 }
2889
2890 const AAInterFnReachability &EdgeReachability =
2891 A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),
2892 DepClassTy::REQUIRED);
2893 if (EdgeReachability.canReach(A, *getAnchorScope()))
2894 return indicatePessimisticFixpoint();
2895 return ChangeStatus::UNCHANGED;
2896 }
2897
2898 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse){ static llvm::Statistic NumIRFunction_norecurse = {"attributor"
, "NumIRFunction_norecurse", ("Number of " "functions" " marked '"
"norecurse" "'")};; ++(NumIRFunction_norecurse); }
}
2899};
2900
2901/// NoRecurse attribute deduction for a call sites.
2902struct AANoRecurseCallSite final : AANoRecurseImpl {
2903 AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
2904 : AANoRecurseImpl(IRP, A) {}
2905
2906 /// See AbstractAttribute::initialize(...).
2907 void initialize(Attributor &A) override {
2908 AANoRecurseImpl::initialize(A);
2909 Function *F = getAssociatedFunction();
2910 if (!F || F->isDeclaration())
2911 indicatePessimisticFixpoint();
2912 }
2913
2914 /// See AbstractAttribute::updateImpl(...).
2915 ChangeStatus updateImpl(Attributor &A) override {
2916 // TODO: Once we have call site specific value information we can provide
2917 // call site specific liveness information and then it makes
2918 // sense to specialize attributes for call sites arguments instead of
2919 // redirecting requests to the callee argument.
2920 Function *F = getAssociatedFunction();
2921 const IRPosition &FnPos = IRPosition::function(*F);
2922 auto &FnAA = A.getAAFor<AANoRecurse>(*this, FnPos, DepClassTy::REQUIRED);
2923 return clampStateAndIndicateChange(getState(), FnAA.getState());
2924 }
2925
2926 /// See AbstractAttribute::trackStatistics()
2927 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); }
; }
2928};
2929} // namespace
2930
2931/// -------------------- Undefined-Behavior Attributes ------------------------
2932
2933namespace {
2934struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
2935 AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
2936 : AAUndefinedBehavior(IRP, A) {}
2937
2938 /// See AbstractAttribute::updateImpl(...).
2939 // through a pointer (i.e. also branches etc.)
2940 ChangeStatus updateImpl(Attributor &A) override {
2941 const size_t UBPrevSize = KnownUBInsts.size();
2942 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2943
2944 auto InspectMemAccessInstForUB = [&](Instruction &I) {
2945 // Lang ref now states volatile store is not UB, let's skip them.
2946 if (I.isVolatile() && I.mayWriteToMemory())
2947 return true;
2948
2949 // Skip instructions that are already saved.
2950 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2951 return true;
2952
2953 // If we reach here, we know we have an instruction
2954 // that accesses memory through a pointer operand,
2955 // for which getPointerOperand() should give it to us.
2956 Value *PtrOp =
2957 const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));
2958 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", 2959, __extension__
__PRETTY_FUNCTION__))
2959 "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", 2959, __extension__
__PRETTY_FUNCTION__))
;
2960
2961 // Either we stopped and the appropriate action was taken,
2962 // or we got back a simplified value to continue.
2963 std::optional<Value *> SimplifiedPtrOp =
2964 stopOnUndefOrAssumed(A, PtrOp, &I);
2965 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2966 return true;
2967 const Value *PtrOpVal = *SimplifiedPtrOp;
2968
2969 // A memory access through a pointer is considered UB
2970 // only if the pointer has constant null value.
2971 // TODO: Expand it to not only check constant values.
2972 if (!isa<ConstantPointerNull>(PtrOpVal)) {
2973 AssumedNoUBInsts.insert(&I);
2974 return true;
2975 }
2976 const Type *PtrTy = PtrOpVal->getType();
2977
2978 // Because we only consider instructions inside functions,
2979 // assume that a parent function exists.
2980 const Function *F = I.getFunction();
2981
2982 // A memory access using constant null pointer is only considered UB
2983 // if null pointer is _not_ defined for the target platform.
2984 if (llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()))
2985 AssumedNoUBInsts.insert(&I);
2986 else
2987 KnownUBInsts.insert(&I);
2988 return true;
2989 };
2990
2991 auto InspectBrInstForUB = [&](Instruction &I) {
2992 // A conditional branch instruction is considered UB if it has `undef`
2993 // condition.
2994
2995 // Skip instructions that are already saved.
2996 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2997 return true;
2998
2999 // We know we have a branch instruction.
3000 auto *BrInst = cast<BranchInst>(&I);
3001
3002 // Unconditional branches are never considered UB.
3003 if (BrInst->isUnconditional())
3004 return true;
3005
3006 // Either we stopped and the appropriate action was taken,
3007 // or we got back a simplified value to continue.
3008 std::optional<Value *> SimplifiedCond =
3009 stopOnUndefOrAssumed(A, BrInst->getCondition(), BrInst);
3010 if (!SimplifiedCond || !*SimplifiedCond)
3011 return true;
3012 AssumedNoUBInsts.insert(&I);
3013 return true;
3014 };
3015
3016 auto InspectCallSiteForUB = [&](Instruction &I) {
3017 // Check whether a callsite always cause UB or not
3018
3019 // Skip instructions that are already saved.
3020 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3021 return true;
3022
3023 // Check nonnull and noundef argument attribute violation for each
3024 // callsite.
3025 CallBase &CB = cast<CallBase>(I);
3026 Function *Callee = CB.getCalledFunction();
3027 if (!Callee)
3028 return true;
3029 for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
3030 // If current argument is known to be simplified to null pointer and the
3031 // corresponding argument position is known to have nonnull attribute,
3032 // the argument is poison. Furthermore, if the argument is poison and
3033 // the position is known to have noundef attriubte, this callsite is
3034 // considered UB.
3035 if (idx >= Callee->arg_size())
3036 break;
3037 Value *ArgVal = CB.getArgOperand(idx);
3038 if (!ArgVal)
3039 continue;
3040 // Here, we handle three cases.
3041 // (1) Not having a value means it is dead. (we can replace the value
3042 // with undef)
3043 // (2) Simplified to undef. The argument violate noundef attriubte.
3044 // (3) Simplified to null pointer where known to be nonnull.
3045 // The argument is a poison value and violate noundef attribute.
3046 IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
3047 auto &NoUndefAA =
3048 A.getAAFor<AANoUndef>(*this, CalleeArgumentIRP, DepClassTy::NONE);
3049 if (!NoUndefAA.isKnownNoUndef())
3050 continue;
3051 bool UsedAssumedInformation = false;
3052 std::optional<Value *> SimplifiedVal =
3053 A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,
3054 UsedAssumedInformation, AA::Interprocedural);
3055 if (UsedAssumedInformation)
3056 continue;
3057 if (SimplifiedVal && !*SimplifiedVal)
3058 return true;
3059 if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {
3060 KnownUBInsts.insert(&I);
3061 continue;
3062 }
3063 if (!ArgVal->getType()->isPointerTy() ||
3064 !isa<ConstantPointerNull>(**SimplifiedVal))
3065 continue;
3066 auto &NonNullAA =
3067 A.getAAFor<AANonNull>(*this, CalleeArgumentIRP, DepClassTy::NONE);
3068 if (NonNullAA.isKnownNonNull())
3069 KnownUBInsts.insert(&I);
3070 }
3071 return true;
3072 };
3073
3074 auto InspectReturnInstForUB = [&](Instruction &I) {
3075 auto &RI = cast<ReturnInst>(I);
3076 // Either we stopped and the appropriate action was taken,
3077 // or we got back a simplified return value to continue.
3078 std::optional<Value *> SimplifiedRetValue =
3079 stopOnUndefOrAssumed(A, RI.getReturnValue(), &I);
3080 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3081 return true;
3082
3083 // Check if a return instruction always cause UB or not
3084 // Note: It is guaranteed that the returned position of the anchor
3085 // scope has noundef attribute when this is called.
3086 // We also ensure the return position is not "assumed dead"
3087 // because the returned value was then potentially simplified to
3088 // `undef` in AAReturnedValues without removing the `noundef`
3089 // attribute yet.
3090
3091 // When the returned position has noundef attriubte, UB occurs in the
3092 // following cases.
3093 // (1) Returned value is known to be undef.
3094 // (2) The value is known to be a null pointer and the returned
3095 // position has nonnull attribute (because the returned value is
3096 // poison).
3097 if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {
3098 auto &NonNullAA = A.getAAFor<AANonNull>(
3099 *this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE);
3100 if (NonNullAA.isKnownNonNull())
3101 KnownUBInsts.insert(&I);
3102 }
3103
3104 return true;
3105 };
3106
3107 bool UsedAssumedInformation = false;
3108 A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
3109 {Instruction::Load, Instruction::Store,
3110 Instruction::AtomicCmpXchg,
3111 Instruction::AtomicRMW},
3112 UsedAssumedInformation,
3113 /* CheckBBLivenessOnly */ true);
3114 A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},
3115 UsedAssumedInformation,
3116 /* CheckBBLivenessOnly */ true);
3117 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
3118 UsedAssumedInformation);
3119
3120 // If the returned position of the anchor scope has noundef attriubte, check
3121 // all returned instructions.
3122 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3123 const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
3124 if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
3125 auto &RetPosNoUndefAA =
3126 A.getAAFor<AANoUndef>(*this, ReturnIRP, DepClassTy::NONE);
3127 if (RetPosNoUndefAA.isKnownNoUndef())
3128 A.checkForAllInstructions(InspectReturnInstForUB, *this,
3129 {Instruction::Ret}, UsedAssumedInformation,
3130 /* CheckBBLivenessOnly */ true);
3131 }
3132 }
3133
3134 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3135 UBPrevSize != KnownUBInsts.size())
3136 return ChangeStatus::CHANGED;
3137 return ChangeStatus::UNCHANGED;
3138 }
3139
3140 bool isKnownToCauseUB(Instruction *I) const override {
3141 return KnownUBInsts.count(I);
3142 }
3143
3144 bool isAssumedToCauseUB(Instruction *I) const override {
3145 // In simple words, if an instruction is not in the assumed to _not_
3146 // cause UB, then it is assumed UB (that includes those
3147 // in the KnownUBInsts set). The rest is boilerplate
3148 // is to ensure that it is one of the instructions we test
3149 // for UB.
3150
3151 switch (I->getOpcode()) {
3152 case Instruction::Load:
3153 case Instruction::Store:
3154 case Instruction::AtomicCmpXchg:
3155 case Instruction::AtomicRMW:
3156 return !AssumedNoUBInsts.count(I);
3157 case Instruction::Br: {
3158 auto *BrInst = cast<BranchInst>(I);
3159 if (BrInst->isUnconditional())
3160 return false;
3161 return !AssumedNoUBInsts.count(I);
3162 } break;
3163 default:
3164 return false;
3165 }
3166 return false;
3167 }
3168
3169 ChangeStatus manifest(Attributor &A) override {
3170 if (KnownUBInsts.empty())
3171 return ChangeStatus::UNCHANGED;
3172 for (Instruction *I : KnownUBInsts)
3173 A.changeToUnreachableAfterManifest(I);
3174 return ChangeStatus::CHANGED;
3175 }
3176
3177 /// See AbstractAttribute::getAsStr()
3178 const std::string getAsStr() const override {
3179 return getAssumed() ? "undefined-behavior" : "no-ub";
3180 }
3181
3182 /// Note: The correctness of this analysis depends on the fact that the
3183 /// following 2 sets will stop changing after some point.
3184 /// "Change" here means that their size changes.
3185 /// The size of each set is monotonically increasing
3186 /// (we only add items to them) and it is upper bounded by the number of
3187 /// instructions in the processed function (we can never save more
3188 /// elements in either set than this number). Hence, at some point,
3189 /// they will stop increasing.
3190 /// Consequently, at some point, both sets will have stopped
3191 /// changing, effectively making the analysis reach a fixpoint.
3192
3193 /// Note: These 2 sets are disjoint and an instruction can be considered
3194 /// one of 3 things:
3195 /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
3196 /// the KnownUBInsts set.
3197 /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
3198 /// has a reason to assume it).
3199 /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
3200 /// could not find a reason to assume or prove that it can cause UB,
3201 /// hence it assumes it doesn't. We have a set for these instructions
3202 /// so that we don't reprocess them in every update.
3203 /// Note however that instructions in this set may cause UB.
3204
3205protected:
3206 /// A set of all live instructions _known_ to cause UB.
3207 SmallPtrSet<Instruction *, 8> KnownUBInsts;
3208
3209private:
3210 /// A set of all the (live) instructions that are assumed to _not_ cause UB.
3211 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3212
3213 // Should be called on updates in which if we're processing an instruction
3214 // \p I that depends on a value \p V, one of the following has to happen:
3215 // - If the value is assumed, then stop.
3216 // - If the value is known but undef, then consider it UB.
3217 // - Otherwise, do specific processing with the simplified value.
3218 // We return std::nullopt in the first 2 cases to signify that an appropriate
3219 // action was taken and the caller should stop.
3220 // Otherwise, we return the simplified value that the caller should
3221 // use for specific processing.
3222 std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
3223 Instruction *I) {
3224 bool UsedAssumedInformation = false;
3225 std::optional<Value *> SimplifiedV =
3226 A.getAssumedSimplified(IRPosition::value(*V), *this,
3227 UsedAssumedInformation, AA::Interprocedural);
3228 if (!UsedAssumedInformation) {
3229 // Don't depend on assumed values.
3230 if (!SimplifiedV) {
3231 // If it is known (which we tested above) but it doesn't have a value,
3232 // then we can assume `undef` and hence the instruction is UB.
3233 KnownUBInsts.insert(I);
3234 return std::nullopt;
3235 }
3236 if (!*SimplifiedV)
3237 return nullptr;
3238 V = *SimplifiedV;
3239 }
3240 if (isa<UndefValue>(V)) {
3241 KnownUBInsts.insert(I);
3242 return std::nullopt;
3243 }
3244 return V;
3245 }
3246};
3247
3248struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3249 AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
3250 : AAUndefinedBehaviorImpl(IRP, A) {}
3251
3252 /// See AbstractAttribute::trackStatistics()
3253 void trackStatistics() const override {
3254 STATS_DECL(UndefinedBehaviorInstruction, Instruction,static llvm::Statistic NumIRInstruction_UndefinedBehaviorInstruction
= {"attributor", "NumIRInstruction_UndefinedBehaviorInstruction"
, "Number of instructions known to have UB"};;
3255 "Number of instructions known to have UB")static llvm::Statistic NumIRInstruction_UndefinedBehaviorInstruction
= {"attributor", "NumIRInstruction_UndefinedBehaviorInstruction"
, "Number of instructions known to have UB"};;
;
3256 BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction)NumIRInstruction_UndefinedBehaviorInstruction +=
3257 KnownUBInsts.size();
3258 }
3259};
3260} // namespace
3261
3262/// ------------------------ Will-Return Attributes ----------------------------
3263
3264namespace {
3265// Helper function that checks whether a function has any cycle which we don't
3266// know if it is bounded or not.
3267// Loops with maximum trip count are considered bounded, any other cycle not.
3268static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
3269 ScalarEvolution *SE =
3270 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
3271 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
3272 // If either SCEV or LoopInfo is not available for the function then we assume
3273 // any cycle to be unbounded cycle.
3274 // We use scc_iterator which uses Tarjan algorithm to find all the maximal
3275 // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
3276 if (!SE || !LI) {
3277 for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
3278 if (SCCI.hasCycle())
3279 return true;
3280 return false;
3281 }
3282
3283 // If there's irreducible control, the function may contain non-loop cycles.
3284 if (mayContainIrreducibleControl(F, LI))
3285 return true;
3286
3287 // Any loop that does not have a max trip count is considered unbounded cycle.
3288 for (auto *L : LI->getLoopsInPreorder()) {
3289 if (!SE->getSmallConstantMaxTripCount(L))
3290 return true;
3291 }
3292 return false;
3293}
3294
3295struct AAWillReturnImpl : public AAWillReturn {
3296 AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
3297 : AAWillReturn(IRP, A) {}
3298
3299 /// See AbstractAttribute::initialize(...).
3300 void initialize(Attributor &A) override {
3301 AAWillReturn::initialize(A);
3302
3303 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ true)) {
3304 indicateOptimisticFixpoint();
3305 return;
3306 }
3307 }
3308
3309 /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
3310 bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
3311 // Check for `mustprogress` in the scope and the associated function which
3312 // might be different if this is a call site.
3313 if ((!getAnchorScope() || !getAnchorScope()->mustProgress()) &&
3314 (!getAssociatedFunction() || !getAssociatedFunction()->mustProgress()))
3315 return false;
3316
3317 bool IsKnown;
3318 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3319 return IsKnown || !KnownOnly;
3320 return false;
3321 }
3322
3323 /// See AbstractAttribute::updateImpl(...).
3324 ChangeStatus updateImpl(Attributor &A) override {
3325 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3326 return ChangeStatus::UNCHANGED;
3327
3328 auto CheckForWillReturn = [&](Instruction &I) {
3329 IRPosition IPos = IRPosition::callsite_function(cast<CallBase>(I));
3330 const auto &WillReturnAA =
3331 A.getAAFor<AAWillReturn>(*this, IPos, DepClassTy::REQUIRED);
3332 if (WillReturnAA.isKnownWillReturn())
3333 return true;
3334 if (!WillReturnAA.isAssumedWillReturn())
3335 return false;
3336 const auto &NoRecurseAA =
3337 A.getAAFor<AANoRecurse>(*this, IPos, DepClassTy::REQUIRED);
3338 return NoRecurseAA.isAssumedNoRecurse();
3339 };
3340
3341 bool UsedAssumedInformation = false;
3342 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
3343 UsedAssumedInformation))
3344 return indicatePessimisticFixpoint();
3345
3346 return ChangeStatus::UNCHANGED;
3347 }
3348
3349 /// See AbstractAttribute::getAsStr()
3350 const std::string getAsStr() const override {
3351 return getAssumed() ? "willreturn" : "may-noreturn";
3352 }
3353};
3354
3355struct AAWillReturnFunction final : AAWillReturnImpl {
3356 AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
3357 : AAWillReturnImpl(IRP, A) {}
3358
3359 /// See AbstractAttribute::initialize(...).
3360 void initialize(Attributor &A) override {
3361 AAWillReturnImpl::initialize(A);
3362
3363 Function *F = getAnchorScope();
3364 if (!F || F->isDeclaration() || mayContainUnboundedCycle(*F, A))
3365 indicatePessimisticFixpoint();
3366 }
3367
3368 /// See AbstractAttribute::trackStatistics()
3369 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn){ static llvm::Statistic NumIRFunction_willreturn = {"attributor"
, "NumIRFunction_willreturn", ("Number of " "functions" " marked '"
"willreturn" "'")};; ++(NumIRFunction_willreturn); }
}
3370};
3371
3372/// WillReturn attribute deduction for a call sites.
3373struct AAWillReturnCallSite final : AAWillReturnImpl {
3374 AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)
3375 : AAWillReturnImpl(IRP, A) {}
3376
3377 /// See AbstractAttribute::initialize(...).
3378 void initialize(Attributor &A) override {
3379 AAWillReturnImpl::initialize(A);
3380 Function *F = getAssociatedFunction();
3381 if (!F || !A.isFunctionIPOAmendable(*F))
3382 indicatePessimisticFixpoint();
3383 }
3384
3385 /// See AbstractAttribute::updateImpl(...).
3386 ChangeStatus updateImpl(Attributor &A) override {
3387 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3388 return ChangeStatus::UNCHANGED;
3389
3390 // TODO: Once we have call site specific value information we can provide
3391 // call site specific liveness information and then it makes
3392 // sense to specialize attributes for call sites arguments instead of
3393 // redirecting requests to the callee argument.
3394 Function *F = getAssociatedFunction();
3395 const IRPosition &FnPos = IRPosition::function(*F);
3396 auto &FnAA = A.getAAFor<AAWillReturn>(*this, FnPos, DepClassTy::REQUIRED);
3397 return clampStateAndIndicateChange(getState(), FnAA.getState());
3398 }
3399
3400 /// See AbstractAttribute::trackStatistics()
3401 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); }
; }
3402};
3403} // namespace
3404
3405/// -------------------AAIntraFnReachability Attribute--------------------------
3406
3407/// All information associated with a reachability query. This boilerplate code
3408/// is used by both AAIntraFnReachability and AAInterFnReachability, with
3409/// different \p ToTy values.
3410template <typename ToTy> struct ReachabilityQueryInfo {
3411 enum class Reachable {
3412 No,
3413 Yes,
3414 };
3415
3416 /// Start here,
3417 const Instruction *From = nullptr;
3418 /// reach this place,
3419 const ToTy *To = nullptr;
3420 /// without going through any of these instructions,
3421 const AA::InstExclusionSetTy *ExclusionSet = nullptr;
3422 /// and remember if it worked:
3423 Reachable Result = Reachable::No;
3424
3425 ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
3426 : From(From), To(To) {}
3427
3428 /// Constructor replacement to ensure unique and stable sets are used for the
3429 /// cache.
3430 ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To,
3431 const AA::InstExclusionSetTy *ES)
3432 : From(&From), To(&To), ExclusionSet(ES) {
3433
3434 if (ExclusionSet && !ExclusionSet->empty()) {
3435 ExclusionSet =
3436 A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ExclusionSet);
3437 } else {
3438 ExclusionSet = nullptr;
3439 }
3440 }
3441
3442 ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
3443 : From(RQI.From), To(RQI.To), ExclusionSet(RQI.ExclusionSet) {
3444 assert(RQI.Result == Reachable::No &&(static_cast <bool> (RQI.Result == Reachable::No &&
"Didn't expect to copy an explored RQI!") ? void (0) : __assert_fail
("RQI.Result == Reachable::No && \"Didn't expect to copy an explored RQI!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3445, __extension__
__PRETTY_FUNCTION__))
3445 "Didn't expect to copy an explored RQI!")(static_cast <bool> (RQI.Result == Reachable::No &&
"Didn't expect to copy an explored RQI!") ? void (0) : __assert_fail
("RQI.Result == Reachable::No && \"Didn't expect to copy an explored RQI!\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3445, __extension__
__PRETTY_FUNCTION__))
;
3446 }
3447};
3448
3449namespace llvm {
3450template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
3451 using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;
3452 using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;
3453
3454 static ReachabilityQueryInfo<ToTy> EmptyKey;
3455 static ReachabilityQueryInfo<ToTy> TombstoneKey;
3456
3457 static inline ReachabilityQueryInfo<ToTy> *getEmptyKey() { return &EmptyKey; }
3458 static inline ReachabilityQueryInfo<ToTy> *getTombstoneKey() {
3459 return &TombstoneKey;
3460 }
3461 static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
3462 unsigned H = PairDMI ::getHashValue({RQI->From, RQI->To});
3463 H += InstSetDMI::getHashValue(RQI->ExclusionSet);
3464 return H;
3465 }
3466 static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
3467 const ReachabilityQueryInfo<ToTy> *RHS) {
3468 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3469 return false;
3470 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3471 }
3472};
3473
3474#define DefineKeys(ToTy) \
3475 template <> \
3476 ReachabilityQueryInfo<ToTy> \
3477 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::EmptyKey = \
3478 ReachabilityQueryInfo<ToTy>( \
3479 DenseMapInfo<const Instruction *>::getEmptyKey(), \
3480 DenseMapInfo<const ToTy *>::getEmptyKey()); \
3481 template <> \
3482 ReachabilityQueryInfo<ToTy> \
3483 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::TombstoneKey = \
3484 ReachabilityQueryInfo<ToTy>( \
3485 DenseMapInfo<const Instruction *>::getTombstoneKey(), \
3486 DenseMapInfo<const ToTy *>::getTombstoneKey());
3487
3488DefineKeys(Instruction) DefineKeys(Function)
3489#undef DefineKeys
3490
3491} // namespace llvm
3492
3493namespace {
3494
3495template <typename BaseTy, typename ToTy>
3496struct CachedReachabilityAA : public BaseTy {
3497 using RQITy = ReachabilityQueryInfo<ToTy>;
3498
3499 CachedReachabilityAA<BaseTy, ToTy>(const IRPosition &IRP, Attributor &A)
3500 : BaseTy(IRP, A) {}
3501
3502 /// See AbstractAttribute::isQueryAA.
3503 bool isQueryAA() const override { return true; }
3504
3505 /// See AbstractAttribute::updateImpl(...).
3506 ChangeStatus updateImpl(Attributor &A) override {
3507 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3508 InUpdate = true;
3509 for (RQITy *RQI : QueryVector) {
3510 if (RQI->Result == RQITy::Reachable::No && isReachableImpl(A, *RQI))
3511 Changed = ChangeStatus::CHANGED;
3512 }
3513 InUpdate = false;
3514 return Changed;
3515 }
3516
3517 virtual bool isReachableImpl(Attributor &A, RQITy &RQI) = 0;
3518
3519 bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
3520 RQITy &RQI) {
3521 if (Result == RQITy::Reachable::No) {
3522 if (!InUpdate)
3523 A.registerForUpdate(*this);
3524 return false;
3525 }
3526 assert(RQI.Result == RQITy::Reachable::No && "Already reachable?")(static_cast <bool> (RQI.Result == RQITy::Reachable::No
&& "Already reachable?") ? void (0) : __assert_fail (
"RQI.Result == RQITy::Reachable::No && \"Already reachable?\""
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 3526, __extension__
__PRETTY_FUNCTION__))
;
3527 RQI.Result = Result;
3528 return true;
3529 }
3530
3531 const std::string getAsStr() const override {
3532 // TODO: Return the number of reachable queries.
3533 return "#queries(" + std::to_string(QueryVector.size()) + ")";
3534 }
3535
3536 RQITy *checkQueryCache(Attributor &A, RQITy &StackRQI,
3537 typename RQITy::Reachable &Result) {
3538 if (!this->getState().isValidState()) {
3539 Result = RQITy::Reachable::Yes;
3540 return nullptr;
3541 }
3542
3543 auto It = QueryCache.find(&StackRQI);
3544 if (It != QueryCache.end()) {
3545 Result = (*It)->Result;
3546 return nullptr;
3547 }
3548
3549 RQITy *RQIPtr = new (A.Allocator) RQITy(StackRQI);
3550 QueryVector.push_back(RQIPtr);
3551 QueryCache.insert(RQIPtr);
3552 return RQIPtr;
3553 }
3554
3555private:
3556 bool InUpdate = false;
3557 SmallVector<RQITy *> QueryVector;
3558 DenseSet<RQITy *> QueryCache;
3559};
3560
3561struct AAIntraFnReachabilityFunction final
3562 : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3563 AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
3564 : CachedReachabilityAA<AAIntraFnReachability, Instruction>(IRP, A) {}
3565
3566 bool isAssumedReachable(
3567 Attributor &A, const Instruction &From, const Instruction &To,
3568 const AA::InstExclusionSetTy *ExclusionSet) const override {
3569 auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
3570 if (&From == &To)
3571 return true;
3572
3573 RQITy StackRQI(A, From, To, ExclusionSet);
3574 typename RQITy::Reachable Result;
3575 if (RQITy *RQIPtr = NonConstThis->checkQueryCache(A, StackRQI, Result)) {
3576 return NonConstThis->isReachableImpl(A, *RQIPtr);
3577 }
3578 return Result == RQITy::Reachable::Yes;
3579 }
3580
3581 bool isReachableImpl(Attributor &A, RQITy &RQI) override {
3582 const Instruction *Origin = RQI.From;
3583
3584 auto WillReachInBlock = [=](const Instruction &From, const Instruction &To,
3585 const AA::InstExclusionSetTy *ExclusionSet) {
3586 const Instruction *IP = &From;
3587 while (IP && IP != &To) {
3588 if (ExclusionSet && IP != Origin && ExclusionSet->count(IP))
3589 break;
3590 IP = IP->getNextNode();
3591 }
3592 return IP == &To;
3593 };
3594
3595 const BasicBlock *FromBB = RQI.From->getParent();
3596 const BasicBlock *ToBB = RQI.To->getParent();
3597 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", 3598, __extension__
__PRETTY_FUNCTION__))
3598 "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", 3598, __extension__
__PRETTY_FUNCTION__))
;
3599
3600 // Check intra-block reachability, however, other reaching paths are still
3601 // possible.
3602 if (FromBB == ToBB &&
3603 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3604 return rememberResult(A, RQITy::Reachable::Yes, RQI);
3605
3606 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3607 if (RQI.ExclusionSet)
3608 for (auto *I : *RQI.ExclusionSet)
3609 ExclusionBlocks.insert(I->getParent());
3610
3611 // Check if we make it out of the FromBB block at all.
3612 if (ExclusionBlocks.count(FromBB) &&
3613 !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
3614 RQI.ExclusionSet))
3615 return rememberResult(A, RQITy::Reachable::No, RQI);
3616
3617 SmallPtrSet<const BasicBlock *, 16> Visited;
3618 SmallVector<const BasicBlock *, 16> Worklist;
3619 Worklist.push_back(FromBB);
3620
3621 auto &LivenessAA =
3622 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3623 while (!Worklist.empty()) {
3624 const BasicBlock *BB = Worklist.pop_back_val();
3625 if (!Visited.insert(BB).second)
3626 continue;
3627 for (const BasicBlock *SuccBB : successors(BB)) {
3628 if (LivenessAA.isEdgeDead(BB, SuccBB))
3629 continue;
3630 if (SuccBB == ToBB &&
3631 WillReachInBlock(SuccBB->front(), *RQI.To, RQI.ExclusionSet))
3632 return rememberResult(A, RQITy::Reachable::Yes, RQI);
3633 if (ExclusionBlocks.count(SuccBB))
3634 continue;
3635 Worklist.push_back(SuccBB);
3636 }
3637 }
3638
3639 return rememberResult(A, RQITy::Reachable::No, RQI);
3640 }
3641
3642 /// See AbstractAttribute::trackStatistics()
3643 void trackStatistics() const override {}
3644};
3645} // namespace
3646
3647/// ------------------------ NoAlias Argument Attribute ------------------------
3648
3649namespace {
3650struct AANoAliasImpl : AANoAlias {
3651 AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
3652 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", 3653, __extension__
__PRETTY_FUNCTION__))
3653 "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", 3653, __extension__
__PRETTY_FUNCTION__))
;
3654 }
3655
3656 const std::string getAsStr() const override {
3657 return getAssumed() ? "noalias" : "may-alias";
3658 }
3659};
3660
3661/// NoAlias attribute for a floating value.
3662struct AANoAliasFloating final : AANoAliasImpl {
3663 AANoAliasFloating(const IRPosition &IRP, Attributor &A)
3664 : AANoAliasImpl(IRP, A) {}
3665
3666 /// See AbstractAttribute::initialize(...).
3667 void initialize(Attributor &A) override {
3668 AANoAliasImpl::initialize(A);
3669 Value *Val = &getAssociatedValue();
3670 do {
3671 CastInst *CI = dyn_cast<CastInst>(Val);
3672 if (!CI)
3673 break;
3674 Value *Base = CI->getOperand(0);
3675 if (!Base->hasOneUse())
3676 break;
3677 Val = Base;
3678 } while (true);
3679
3680 if (!Val->getType()->isPointerTy()) {
3681 indicatePessimisticFixpoint();
3682 return;
3683 }
3684
3685 if (isa<AllocaInst>(Val))
3686 indicateOptimisticFixpoint();
3687 else if (isa<ConstantPointerNull>(Val) &&
3688 !NullPointerIsDefined(getAnchorScope(),
3689 Val->getType()->getPointerAddressSpace()))
3690 indicateOptimisticFixpoint();
3691 else if (Val != &getAssociatedValue()) {
3692 const auto &ValNoAliasAA = A.getAAFor<AANoAlias>(
3693 *this, IRPosition::value(*Val), DepClassTy::OPTIONAL);
3694 if (ValNoAliasAA.isKnownNoAlias())
3695 indicateOptimisticFixpoint();
3696 }
3697 }
3698
3699 /// See AbstractAttribute::updateImpl(...).
3700 ChangeStatus updateImpl(Attributor &A) override {
3701 // TODO: Implement this.
3702 return indicatePessimisticFixpoint();
3703 }
3704
3705 /// See AbstractAttribute::trackStatistics()
3706 void trackStatistics() const override {
3707 STATS_DECLTRACK_FLOATING_ATTR(noalias){ static llvm::Statistic NumIRFloating_noalias = {"attributor"
, "NumIRFloating_noalias", ("Number of floating values known to be '"
"noalias" "'")};; ++(NumIRFloating_noalias); }
3708 }
3709};
3710
3711/// NoAlias attribute for an argument.
3712struct AANoAliasArgument final
3713 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3714 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3715 AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
3716
3717 /// See AbstractAttribute::initialize(...).
3718 void initialize(Attributor &A) override {
3719 Base::initialize(A);
3720 // See callsite argument attribute and callee argument attribute.
3721 if (hasAttr({Attribute::ByVal}))
3722 indicateOptimisticFixpoint();
3723 }
3724
3725 /// See AbstractAttribute::update(...).
3726 ChangeStatus updateImpl(Attributor &A) override {
3727 // We have to make sure no-alias on the argument does not break
3728 // synchronization when this is a callback argument, see also [1] below.
3729 // If synchronization cannot be affected, we delegate to the base updateImpl
3730 // function, otherwise we give up for now.
3731
3732 // If the function is no-sync, no-alias cannot break synchronization.
3733 const auto &NoSyncAA =
3734 A.getAAFor<AANoSync>(*this, IRPosition::function_scope(getIRPosition()),
3735 DepClassTy::OPTIONAL);
3736 if (NoSyncAA.isAssumedNoSync())
3737 return Base::updateImpl(A);
3738
3739 // If the argument is read-only, no-alias cannot break synchronization.
3740 bool IsKnown;
3741 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3742 return Base::updateImpl(A);
3743
3744 // If the argument is never passed through callbacks, no-alias cannot break
3745 // synchronization.
3746 bool UsedAssumedInformation = false;
3747 if (A.checkForAllCallSites(
3748 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,
3749 true, UsedAssumedInformation))
3750 return Base::updateImpl(A);
3751
3752 // TODO: add no-alias but make sure it doesn't break synchronization by
3753 // introducing fake uses. See:
3754 // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
3755 // International Workshop on OpenMP 2018,
3756 // http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf
3757
3758 return indicatePessimisticFixpoint();
3759 }
3760
3761 /// See AbstractAttribute::trackStatistics()
3762 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias){ static llvm::Statistic NumIRArguments_noalias = {"attributor"
, "NumIRArguments_noalias", ("Number of " "arguments" " marked '"
"noalias" "'")};; ++(NumIRArguments_noalias); }
}
3763};
3764
3765struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3766 AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
3767 : AANoAliasImpl(IRP, A) {}
3768
3769 /// See AbstractAttribute::initialize(...).
3770 void initialize(Attributor &A) override {
3771 // See callsite argument attribute and callee argument attribute.
3772 const auto &CB = cast<CallBase>(getAnchorValue());
3773 if (CB.paramHasAttr(getCallSiteArgNo(), Attribute::NoAlias))
3774 indicateOptimisticFixpoint();
3775 Value &Val = getAssociatedValue();
3776 if (isa<ConstantPointerNull>(Val) &&
3777 !NullPointerIsDefined(getAnchorScope(),
3778 Val.getType()->getPointerAddressSpace()))
3779 indicateOptimisticFixpoint();
3780 }
3781
3782 /// Determine if the underlying value may alias with the call site argument
3783 /// \p OtherArgNo of \p ICS (= the underlying call site).
3784 bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
3785 const AAMemoryBehavior &MemBehaviorAA,
3786 const CallBase &CB, unsigned OtherArgNo) {
3787 // We do not need to worry about aliasing with the underlying IRP.
3788 if (this->getCalleeArgNo() == (int)OtherArgNo)
3789 return false;
3790
3791 // If it is not a pointer or pointer vector we do not alias.
3792 const Value *ArgOp = CB.getArgOperand(OtherArgNo);
3793 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
3794 return false;
3795
3796 auto &CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
3797 *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);
3798
3799 // If the argument is readnone, there is no read-write aliasing.
3800 if (CBArgMemBehaviorAA.isAssumedReadNone()) {
3801 A.recordDependence(CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3802 return false;
3803 }
3804
3805 // If the argument is readonly and the underlying value is readonly, there
3806 // is no read-write aliasing.
3807 bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
3808 if (CBArgMemBehaviorAA.isAssumedReadOnly() && IsReadOnly) {
3809 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3810 A.recordDependence(CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3811 return false;
3812 }
3813
3814 // We have to utilize actual alias analysis queries so we need the object.
3815 if (!AAR)
3816 AAR = A.getInfoCache().getAAResultsForFunction(*getAnchorScope());
3817
3818 // Try to rule it out at the call site.
3819 bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);
3820 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)
3821 "callsite arguments: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[NoAliasCSArg] Check alias between "
"callsite arguments: " << getAssociatedValue() <<
" " << *ArgOp << " => " << (IsAliasing ?
"" : "no-") << "alias \n"; } } while (false)
3822 << getAssociatedValue() << " " << *ArgOp << " => "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[NoAliasCSArg] Check alias between "
"callsite arguments: " << getAssociatedValue() <<
" " << *ArgOp << " => " << (IsAliasing ?
"" : "no-") << "alias \n"; } } while (false)
3823 << (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)
;
3824
3825 return IsAliasing;
3826 }
3827
3828 bool
3829 isKnownNoAliasDueToNoAliasPreservation(Attributor &A, AAResults *&AAR,
3830 const AAMemoryBehavior &MemBehaviorAA,
3831 const AANoAlias &NoAliasAA) {
3832 // We can deduce "noalias" if the following conditions hold.
3833 // (i) Associated value is assumed to be noalias in the definition.
3834 // (ii) Associated value is assumed to be no-capture in all the uses
3835 // possibly executed before this callsite.
3836 // (iii) There is no other pointer argument which could alias with the
3837 // value.
3838
3839 bool AssociatedValueIsNoAliasAtDef = NoAliasAA.isAssumedNoAlias();
3840 if (!AssociatedValueIsNoAliasAtDef) {
3841 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)
3842 << " 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)
;
3843 return false;
3844 }
3845
3846 auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
3847 const auto &DerefAA = A.getAAFor<AADereferenceable>(
3848 *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
3849 return DerefAA.getAssumedDereferenceableBytes();
3850 };
3851
3852 A.recordDependence(NoAliasAA, *this, DepClassTy::OPTIONAL);
3853
3854 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3855 const Function *ScopeFn = VIRP.getAnchorScope();
3856 auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, VIRP, DepClassTy::NONE);
3857 // Check whether the value is captured in the scope using AANoCapture.
3858 // Look at CFG and check only uses possibly executed before this
3859 // callsite.
3860 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
3861 Instruction *UserI = cast<Instruction>(U.getUser());
3862
3863 // If UserI is the curr instruction and there is a single potential use of
3864 // the value in UserI we allow the use.
3865 // TODO: We should inspect the operands and allow those that cannot alias
3866 // with the value.
3867 if (UserI == getCtxI() && UserI->getNumOperands() == 1)
3868 return true;
3869
3870 if (ScopeFn) {
3871 if (auto *CB = dyn_cast<CallBase>(UserI)) {
3872 if (CB->isArgOperand(&U)) {
3873
3874 unsigned ArgNo = CB->getArgOperandNo(&U);
3875
3876 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
3877 *this, IRPosition::callsite_argument(*CB, ArgNo),
3878 DepClassTy::OPTIONAL);
3879
3880 if (NoCaptureAA.isAssumedNoCapture())
3881 return true;
3882 }
3883 }
3884
3885 if (!AA::isPotentiallyReachable(
3886 A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,
3887 [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
3888 return true;
3889 }
3890
3891 // TODO: We should track the capturing uses in AANoCapture but the problem
3892 // is CGSCC runs. For those we would need to "allow" AANoCapture for
3893 // a value in the module slice.
3894 switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
3895 case UseCaptureKind::NO_CAPTURE:
3896 return true;
3897 case UseCaptureKind::MAY_CAPTURE:
3898 LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] Unknown user: "
<< *UserI << "\n"; } } while (false)
3899 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] Unknown user: "
<< *UserI << "\n"; } } while (false)
;
3900 return false;
3901 case UseCaptureKind::PASSTHROUGH:
3902 Follow = true;
3903 return true;
3904 }
3905 llvm_unreachable("unknown UseCaptureKind")::llvm::llvm_unreachable_internal("unknown UseCaptureKind", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 3905)
;
3906 };
3907
3908 if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
3909 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
3910 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] " <<
getAssociatedValue() << " cannot be noalias as it is potentially captured\n"
; } } while (false)
3911 dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAliasCSArg] " <<
getAssociatedValue() << " cannot be noalias as it is potentially captured\n"
; } } while (false)
3912 << " 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)
;
3913 return false;
3914 }
3915 }
3916 A.recordDependence(NoCaptureAA, *this, DepClassTy::OPTIONAL);
3917
3918 // Check there is no other pointer argument which could alias with the
3919 // value passed at this call site.
3920 // TODO: AbstractCallSite
3921 const auto &CB = cast<CallBase>(getAnchorValue());
3922 for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
3923 if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
3924 return false;
3925
3926 return true;
3927 }
3928
3929 /// See AbstractAttribute::updateImpl(...).
3930 ChangeStatus updateImpl(Attributor &A) override {
3931 // If the argument is readnone we are done as there are no accesses via the
3932 // argument.
3933 auto &MemBehaviorAA =
3934 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
3935 if (MemBehaviorAA.isAssumedReadNone()) {
3936 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3937 return ChangeStatus::UNCHANGED;
3938 }
3939
3940 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3941 const auto &NoAliasAA =
3942 A.getAAFor<AANoAlias>(*this, VIRP, DepClassTy::NONE);
3943
3944 AAResults *AAR = nullptr;
3945 if (isKnownNoAliasDueToNoAliasPreservation(A, AAR, MemBehaviorAA,
3946 NoAliasAA)) {
3947 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n"
; } } while (false)
3948 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)
;
3949 return ChangeStatus::UNCHANGED;
3950 }
3951
3952 return indicatePessimisticFixpoint();
3953 }
3954
3955 /// See AbstractAttribute::trackStatistics()
3956 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); }
}
3957};
3958
3959/// NoAlias attribute for function return value.
3960struct AANoAliasReturned final : AANoAliasImpl {
3961 AANoAliasReturned(const IRPosition &IRP, Attributor &A)
3962 : AANoAliasImpl(IRP, A) {}
3963
3964 /// See AbstractAttribute::initialize(...).
3965 void initialize(Attributor &A) override {
3966 AANoAliasImpl::initialize(A);
3967 Function *F = getAssociatedFunction();
3968 if (!F || F->isDeclaration())
3969 indicatePessimisticFixpoint();
3970 }
3971
3972 /// See AbstractAttribute::updateImpl(...).
3973 ChangeStatus updateImpl(Attributor &A) override {
3974
3975 auto CheckReturnValue = [&](Value &RV) -> bool {
3976 if (Constant *C = dyn_cast<Constant>(&RV))
3977 if (C->isNullValue() || isa<UndefValue>(C))
3978 return true;
3979
3980 /// For now, we can only deduce noalias if we have call sites.
3981 /// FIXME: add more support.
3982 if (!isa<CallBase>(&RV))
3983 return false;
3984
3985 const IRPosition &RVPos = IRPosition::value(RV);
3986 const auto &NoAliasAA =
3987 A.getAAFor<AANoAlias>(*this, RVPos, DepClassTy::REQUIRED);
3988 if (!NoAliasAA.isAssumedNoAlias())
3989 return false;
3990
3991 const auto &NoCaptureAA =
3992 A.getAAFor<AANoCapture>(*this, RVPos, DepClassTy::REQUIRED);
3993 return NoCaptureAA.isAssumedNoCaptureMaybeReturned();
3994 };
3995
3996 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
3997 return indicatePessimisticFixpoint();
3998
3999 return ChangeStatus::UNCHANGED;
4000 }
4001
4002 /// See AbstractAttribute::trackStatistics()
4003 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
); }
}
4004};
4005
4006/// NoAlias attribute deduction for a call site return value.
4007struct AANoAliasCallSiteReturned final : AANoAliasImpl {
4008 AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
4009 : AANoAliasImpl(IRP, A) {}
4010
4011 /// See AbstractAttribute::initialize(...).
4012 void initialize(Attributor &A) override {
4013 AANoAliasImpl::initialize(A);
4014 Function *F = getAssociatedFunction();
4015 if (!F || F->isDeclaration())
4016 indicatePessimisticFixpoint();
4017 }
4018
4019 /// See AbstractAttribute::updateImpl(...).
4020 ChangeStatus updateImpl(Attributor &A) override {
4021 // TODO: Once we have call site specific value information we can provide
4022 // call site specific liveness information and then it makes
4023 // sense to specialize attributes for call sites arguments instead of
4024 // redirecting requests to the callee argument.
4025 Function *F = getAssociatedFunction();
4026 const IRPosition &FnPos = IRPosition::returned(*F);
4027 auto &FnAA = A.getAAFor<AANoAlias>(*this, FnPos, DepClassTy::REQUIRED);
4028 return clampStateAndIndicateChange(getState(), FnAA.getState());
4029 }
4030
4031 /// See AbstractAttribute::trackStatistics()
4032 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); }
; }
4033};
4034} // namespace
4035
4036/// -------------------AAIsDead Function Attribute-----------------------
4037
4038namespace {
4039struct AAIsDeadValueImpl : public AAIsDead {
4040 AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4041
4042 /// See AbstractAttribute::initialize(...).
4043 void initialize(Attributor &A) override {
4044 if (auto *Scope = getAnchorScope())
4045 if (!A.isRunOn(*Scope))
4046 indicatePessimisticFixpoint();
4047 }
4048
4049 /// See AAIsDead::isAssumedDead().
4050 bool isAssumedDead() const override { return isAssumed(IS_DEAD); }
4051
4052 /// See AAIsDead::isKnownDead().
4053 bool isKnownDead() const override { return isKnown(IS_DEAD); }
4054
4055 /// See AAIsDead::isAssumedDead(BasicBlock *).
4056 bool isAssumedDead(const BasicBlock *BB) const override { return false; }
4057
4058 /// See AAIsDead::isKnownDead(BasicBlock *).
4059 bool isKnownDead(const BasicBlock *BB) const override { return false; }
4060
4061 /// See AAIsDead::isAssumedDead(Instruction *I).
4062 bool isAssumedDead(const Instruction *I) const override {
4063 return I == getCtxI() && isAssumedDead();
4064 }
4065
4066 /// See AAIsDead::isKnownDead(Instruction *I).
4067 bool isKnownDead(const Instruction *I) const override {
4068 return isAssumedDead(I) && isKnownDead();
4069 }
4070
4071 /// See AbstractAttribute::getAsStr().
4072 const std::string getAsStr() const override {
4073 return isAssumedDead() ? "assumed-dead" : "assumed-live";
4074 }
4075
4076 /// Check if all uses are assumed dead.
4077 bool areAllUsesAssumedDead(Attributor &A, Value &V) {
4078 // Callers might not check the type, void has no uses.
4079 if (V.getType()->isVoidTy() || V.use_empty())
4080 return true;
4081
4082 // If we replace a value with a constant there are no uses left afterwards.
4083 if (!isa<Constant>(V)) {
4084 if (auto *I = dyn_cast<Instruction>(&V))
4085 if (!A.isRunOn(*I->getFunction()))
4086 return false;
4087 bool UsedAssumedInformation = false;
4088 std::optional<Constant *> C =
4089 A.getAssumedConstant(V, *this, UsedAssumedInformation);
4090 if (!C || *C)
4091 return true;
4092 }
4093
4094 auto UsePred = [&](const Use &U, bool &Follow) { return false; };
4095 // Explicitly set the dependence class to required because we want a long
4096 // chain of N dependent instructions to be considered live as soon as one is
4097 // without going through N update cycles. This is not required for
4098 // correctness.
4099 return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,
4100 DepClassTy::REQUIRED,
4101 /* IgnoreDroppableUses */ false);
4102 }
4103
4104 /// Determine if \p I is assumed to be side-effect free.
4105 bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
4106 if (!I || wouldInstructionBeTriviallyDead(I))
4107 return true;
4108
4109 auto *CB = dyn_cast<CallBase>(I);
4110 if (!CB || isa<IntrinsicInst>(CB))
4111 return false;
4112
4113 const IRPosition &CallIRP = IRPosition::callsite_function(*CB);
4114 const auto &NoUnwindAA =
4115 A.getAndUpdateAAFor<AANoUnwind>(*this, CallIRP, DepClassTy::NONE);
4116 if (!NoUnwindAA.isAssumedNoUnwind())
4117 return false;
4118 if (!NoUnwindAA.isKnownNoUnwind())
4119 A.recordDependence(NoUnwindAA, *this, DepClassTy::OPTIONAL);
4120
4121 bool IsKnown;
4122 return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);
4123 }
4124};
4125
4126struct AAIsDeadFloating : public AAIsDeadValueImpl {
4127 AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
4128 : AAIsDeadValueImpl(IRP, A) {}
4129
4130 /// See AbstractAttribute::initialize(...).
4131 void initialize(Attributor &A) override {
4132 AAIsDeadValueImpl::initialize(A);
4133
4134 if (isa<UndefValue>(getAssociatedValue())) {
4135 indicatePessimisticFixpoint();
4136 return;
4137 }
4138
4139 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4140 if (!isAssumedSideEffectFree(A, I)) {
4141 if (!isa_and_nonnull<StoreInst>(I))
4142 indicatePessimisticFixpoint();
4143 else
4144 removeAssumedBits(HAS_NO_EFFECT);
4145 }
4146 }
4147
4148 bool isDeadStore(Attributor &A, StoreInst &SI,
4149 SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
4150 // Lang ref now states volatile store is not UB/dead, let's skip them.
4151 if (SI.isVolatile())
4152 return false;
4153
4154 // If we are collecting assumes to be deleted we are in the manifest stage.
4155 // It's problematic to collect the potential copies again now so we use the
4156 // cached ones.
4157 bool UsedAssumedInformation = false;
4158 if (!AssumeOnlyInst) {
4159 PotentialCopies.clear();
4160 if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,
4161 UsedAssumedInformation)) {
4162 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Could not determine potential copies of store!\n"
; } } while (false)
4163 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Could not determine potential copies of store!\n"
; } } while (false)
4164 << "[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)
;
4165 return false;
4166 }
4167 }
4168 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)
4169 << " potential copies.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Store has " <<
PotentialCopies.size() << " potential copies.\n"; } } while
(false)
;
4170
4171 InformationCache &InfoCache = A.getInfoCache();
4172 return llvm::all_of(PotentialCopies, [&](Value *V) {
4173 if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,
4174 UsedAssumedInformation))
4175 return true;
4176 if (auto *LI = dyn_cast<LoadInst>(V)) {
4177 if (llvm::all_of(LI->uses(), [&](const Use &U) {
4178 auto &UserI = cast<Instruction>(*U.getUser());
4179 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4180 if (AssumeOnlyInst)
4181 AssumeOnlyInst->insert(&UserI);
4182 return true;
4183 }
4184 return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);
4185 })) {
4186 return true;
4187 }
4188 }
4189 LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *Vdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Potential copy "
<< *V << " is assumed live!\n"; } } while (false
)
4190 << " is assumed live!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Potential copy "
<< *V << " is assumed live!\n"; } } while (false
)
;
4191 return false;
4192 });
4193 }
4194
4195 /// See AbstractAttribute::getAsStr().
4196 const std::string getAsStr() const override {
4197 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4198 if (isa_and_nonnull<StoreInst>(I))
4199 if (isValidState())
4200 return "assumed-dead-store";
4201 return AAIsDeadValueImpl::getAsStr();
4202 }
4203
4204 /// See AbstractAttribute::updateImpl(...).
4205 ChangeStatus updateImpl(Attributor &A) override {
4206 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4207 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
4208 if (!isDeadStore(A, *SI))
4209 return indicatePessimisticFixpoint();
4210 } else {
4211 if (!isAssumedSideEffectFree(A, I))
4212 return indicatePessimisticFixpoint();
4213 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4214 return indicatePessimisticFixpoint();
4215 }
4216 return ChangeStatus::UNCHANGED;
4217 }
4218
4219 bool isRemovableStore() const override {
4220 return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());
4221 }
4222
4223 /// See AbstractAttribute::manifest(...).
4224 ChangeStatus manifest(Attributor &A) override {
4225 Value &V = getAssociatedValue();
4226 if (auto *I = dyn_cast<Instruction>(&V)) {
4227 // If we get here we basically know the users are all dead. We check if
4228 // isAssumedSideEffectFree returns true here again because it might not be
4229 // the case and only the users are dead but the instruction (=call) is
4230 // still needed.
4231 if (auto *SI = dyn_cast<StoreInst>(I)) {
4232 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4233 bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);
4234 (void)IsDead;
4235 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", 4235, __extension__
__PRETTY_FUNCTION__))
;
4236 A.deleteAfterManifest(*I);
4237 for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
4238 Instruction *AOI = AssumeOnlyInst[i];
4239 for (auto *Usr : AOI->users())
4240 AssumeOnlyInst.insert(cast<Instruction>(Usr));
4241 A.deleteAfterManifest(*AOI);
4242 }
4243 return ChangeStatus::CHANGED;
4244 }
4245 if (isAssumedSideEffectFree(A, I) && !isa<InvokeInst>(I)) {
4246 A.deleteAfterManifest(*I);
4247 return ChangeStatus::CHANGED;
4248 }
4249 }
4250 return ChangeStatus::UNCHANGED;
4251 }
4252
4253 /// See AbstractAttribute::trackStatistics()
4254 void trackStatistics() const override {
4255 STATS_DECLTRACK_FLOATING_ATTR(IsDead){ static llvm::Statistic NumIRFloating_IsDead = {"attributor"
, "NumIRFloating_IsDead", ("Number of floating values known to be '"
"IsDead" "'")};; ++(NumIRFloating_IsDead); }
4256 }
4257
4258private:
4259 // The potential copies of a dead store, used for deletion during manifest.
4260 SmallSetVector<Value *, 4> PotentialCopies;
4261};
4262
4263struct AAIsDeadArgument : public AAIsDeadFloating {
4264 AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
4265 : AAIsDeadFloating(IRP, A) {}
4266
4267 /// See AbstractAttribute::initialize(...).
4268 void initialize(Attributor &A) override {
4269 AAIsDeadFloating::initialize(A);
4270 if (!A.isFunctionIPOAmendable(*getAnchorScope()))
4271 indicatePessimisticFixpoint();
4272 }
4273
4274 /// See AbstractAttribute::manifest(...).
4275 ChangeStatus manifest(Attributor &A) override {
4276 Argument &Arg = *getAssociatedArgument();
4277 if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
4278 if (A.registerFunctionSignatureRewrite(
4279 Arg, /* ReplacementTypes */ {},
4280 Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{},
4281 Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) {
4282 return ChangeStatus::CHANGED;
4283 }
4284 return ChangeStatus::UNCHANGED;
4285 }
4286
4287 /// See AbstractAttribute::trackStatistics()
4288 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead){ static llvm::Statistic NumIRArguments_IsDead = {"attributor"
, "NumIRArguments_IsDead", ("Number of " "arguments" " marked '"
"IsDead" "'")};; ++(NumIRArguments_IsDead); }
}
4289};
4290
4291struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
4292 AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
4293 : AAIsDeadValueImpl(IRP, A) {}
4294
4295 /// See AbstractAttribute::initialize(...).
4296 void initialize(Attributor &A) override {
4297 AAIsDeadValueImpl::initialize(A);
4298 if (isa<UndefValue>(getAssociatedValue()))
4299 indicatePessimisticFixpoint();
4300 }
4301
4302 /// See AbstractAttribute::updateImpl(...).
4303 ChangeStatus updateImpl(Attributor &A) override {
4304 // TODO: Once we have call site specific value information we can provide
4305 // call site specific liveness information and then it makes
4306 // sense to specialize attributes for call sites arguments instead of
4307 // redirecting requests to the callee argument.
4308 Argument *Arg = getAssociatedArgument();
4309 if (!Arg)
4310 return indicatePessimisticFixpoint();
4311 const IRPosition &ArgPos = IRPosition::argument(*Arg);
4312 auto &ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);
4313 return clampStateAndIndicateChange(getState(), ArgAA.getState());
4314 }
4315
4316 /// See AbstractAttribute::manifest(...).
4317 ChangeStatus manifest(Attributor &A) override {
4318 CallBase &CB = cast<CallBase>(getAnchorValue());
4319 Use &U = CB.getArgOperandUse(getCallSiteArgNo());
4320 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", 4321, __extension__
__PRETTY_FUNCTION__))
4321 "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", 4321, __extension__
__PRETTY_FUNCTION__))
;
4322 UndefValue &UV = *UndefValue::get(U->getType());
4323 if (A.changeUseAfterManifest(U, UV))
4324 return ChangeStatus::CHANGED;
4325 return ChangeStatus::UNCHANGED;
4326 }
4327
4328 /// See AbstractAttribute::trackStatistics()
4329 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); }
}
4330};
4331
4332struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
4333 AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
4334 : AAIsDeadFloating(IRP, A) {}
4335
4336 /// See AAIsDead::isAssumedDead().
4337 bool isAssumedDead() const override {
4338 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4339 }
4340
4341 /// See AbstractAttribute::initialize(...).
4342 void initialize(Attributor &A) override {
4343 AAIsDeadFloating::initialize(A);
4344 if (isa<UndefValue>(getAssociatedValue())) {
4345 indicatePessimisticFixpoint();
4346 return;
4347 }
4348
4349 // We track this separately as a secondary state.
4350 IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());
4351 }
4352
4353 /// See AbstractAttribute::updateImpl(...).
4354 ChangeStatus updateImpl(Attributor &A) override {
4355 ChangeStatus Changed = ChangeStatus::UNCHANGED;
4356 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {
4357 IsAssumedSideEffectFree = false;
4358 Changed = ChangeStatus::CHANGED;
4359 }
4360 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4361 return indicatePessimisticFixpoint();
4362 return Changed;
4363 }
4364
4365 /// See AbstractAttribute::trackStatistics()
4366 void trackStatistics() const override {
4367 if (IsAssumedSideEffectFree)
4368 STATS_DECLTRACK_CSRET_ATTR(IsDead){ static llvm::Statistic NumIRCSReturn_IsDead = {"attributor"
, "NumIRCSReturn_IsDead", ("Number of " "call site returns" " marked '"
"IsDead" "'")};; ++(NumIRCSReturn_IsDead); }
4369 else
4370 STATS_DECLTRACK_CSRET_ATTR(UnusedResult){ static llvm::Statistic NumIRCSReturn_UnusedResult = {"attributor"
, "NumIRCSReturn_UnusedResult", ("Number of " "call site returns"
" marked '" "UnusedResult" "'")};; ++(NumIRCSReturn_UnusedResult
); }
4371 }
4372
4373 /// See AbstractAttribute::getAsStr().
4374 const std::string getAsStr() const override {
4375 return isAssumedDead()
4376 ? "assumed-dead"
4377 : (getAssumed() ? "assumed-dead-users" : "assumed-live");
4378 }
4379
4380private:
4381 bool IsAssumedSideEffectFree = true;
4382};
4383
4384struct AAIsDeadReturned : public AAIsDeadValueImpl {
4385 AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
4386 : AAIsDeadValueImpl(IRP, A) {}
4387
4388 /// See AbstractAttribute::updateImpl(...).
4389 ChangeStatus updateImpl(Attributor &A) override {
4390
4391 bool UsedAssumedInformation = false;
4392 A.checkForAllInstructions([](Instruction &) { return true; }, *this,
4393 {Instruction::Ret}, UsedAssumedInformation);
4394
4395 auto PredForCallSite = [&](AbstractCallSite ACS) {
4396 if (ACS.isCallbackCall() || !ACS.getInstruction())
4397 return false;
4398 return areAllUsesAssumedDead(A, *ACS.getInstruction());
4399 };
4400
4401 if (!A.checkForAllCallSites(PredForCallSite, *this, true,
4402 UsedAssumedInformation))
4403 return indicatePessimisticFixpoint();
4404
4405 return ChangeStatus::UNCHANGED;
4406 }
4407
4408 /// See AbstractAttribute::manifest(...).
4409 ChangeStatus manifest(Attributor &A) override {
4410 // TODO: Rewrite the signature to return void?
4411 bool AnyChange = false;
4412 UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());
4413 auto RetInstPred = [&](Instruction &I) {
4414 ReturnInst &RI = cast<ReturnInst>(I);
4415 if (!isa<UndefValue>(RI.getReturnValue()))
4416 AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
4417 return true;
4418 };
4419 bool UsedAssumedInformation = false;
4420 A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
4421 UsedAssumedInformation);
4422 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4423 }
4424
4425 /// See AbstractAttribute::trackStatistics()
4426 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);
}
}
4427};
4428
4429struct AAIsDeadFunction : public AAIsDead {
4430 AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4431
4432 /// See AbstractAttribute::initialize(...).
4433 void initialize(Attributor &A) override {
4434 Function *F = getAnchorScope();
4435 if (!F || F->isDeclaration() || !A.isRunOn(*F)) {
4436 indicatePessimisticFixpoint();
4437 return;
4438 }
4439 if (!isAssumedDeadInternalFunction(A)) {
4440 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4441 assumeLive(A, F->getEntryBlock());
4442 }
4443 }
4444
4445 bool isAssumedDeadInternalFunction(Attributor &A) {
4446 if (!getAnchorScope()->hasLocalLinkage())
4447 return false;
4448 bool UsedAssumedInformation = false;
4449 return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,
4450 true, UsedAssumedInformation);
4451 }
4452
4453 /// See AbstractAttribute::getAsStr().
4454 const std::string getAsStr() const override {
4455 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
4456 std::to_string(getAnchorScope()->size()) + "][#TBEP " +
4457 std::to_string(ToBeExploredFrom.size()) + "][#KDE " +
4458 std::to_string(KnownDeadEnds.size()) + "]";
4459 }
4460
4461 /// See AbstractAttribute::manifest(...).
4462 ChangeStatus manifest(Attributor &A) override {
4463 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", 4464, __extension__
__PRETTY_FUNCTION__))
4464 "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", 4464, __extension__
__PRETTY_FUNCTION__))
;
4465
4466 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
4467 Function &F = *getAnchorScope();
4468
4469 if (AssumedLiveBlocks.empty()) {
4470 A.deleteAfterManifest(F);
4471 return ChangeStatus::CHANGED;
4472 }
4473
4474 // Flag to determine if we can change an invoke to a call assuming the
4475 // callee is nounwind. This is not possible if the personality of the
4476 // function allows to catch asynchronous exceptions.
4477 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
4478
4479 KnownDeadEnds.set_union(ToBeExploredFrom);
4480 for (const Instruction *DeadEndI : KnownDeadEnds) {
4481 auto *CB = dyn_cast<CallBase>(DeadEndI);
4482 if (!CB)
4483 continue;
4484 const auto &NoReturnAA = A.getAndUpdateAAFor<AANoReturn>(
4485 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
4486 bool MayReturn = !NoReturnAA.isAssumedNoReturn();
4487 if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))
4488 continue;
4489
4490 if (auto *II = dyn_cast<InvokeInst>(DeadEndI))
4491 A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));
4492 else
4493 A.changeToUnreachableAfterManifest(
4494 const_cast<Instruction *>(DeadEndI->getNextNode()));
4495 HasChanged = ChangeStatus::CHANGED;
4496 }
4497
4498 STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.")static llvm::Statistic NumIRBasicBlock_AAIsDead = {"attributor"
, "NumIRBasicBlock_AAIsDead", "Number of dead basic blocks deleted."
};;
;
4499 for (BasicBlock &BB : F)
4500 if (!AssumedLiveBlocks.count(&BB)) {
4501 A.deleteAfterManifest(BB);
4502 ++BUILD_STAT_NAME(AAIsDead, BasicBlock)NumIRBasicBlock_AAIsDead;
4503 HasChanged = ChangeStatus::CHANGED;
4504 }
4505
4506 return HasChanged;
4507 }
4508
4509 /// See AbstractAttribute::updateImpl(...).
4510 ChangeStatus updateImpl(Attributor &A) override;
4511
4512 bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
4513 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", 4515, __extension__
__PRETTY_FUNCTION__))
4514 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", 4515, __extension__
__PRETTY_FUNCTION__))
4515 "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", 4515, __extension__
__PRETTY_FUNCTION__))
;
4516 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4517 }
4518
4519 /// See AbstractAttribute::trackStatistics()
4520 void trackStatistics() const override {}
4521
4522 /// Returns true if the function is assumed dead.
4523 bool isAssumedDead() const override { return false; }
4524
4525 /// See AAIsDead::isKnownDead().
4526 bool isKnownDead() const override { return false; }
4527
4528 /// See AAIsDead::isAssumedDead(BasicBlock *).
4529 bool isAssumedDead(const BasicBlock *BB) const override {
4530 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", 4531, __extension__
__PRETTY_FUNCTION__))
4531 "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", 4531, __extension__
__PRETTY_FUNCTION__))
;
4532
4533 if (!getAssumed())
4534 return false;
4535 return !AssumedLiveBlocks.count(BB);
4536 }
4537
4538 /// See AAIsDead::isKnownDead(BasicBlock *).
4539 bool isKnownDead(const BasicBlock *BB) const override {
4540 return getKnown() && isAssumedDead(BB);
4541 }
4542
4543 /// See AAIsDead::isAssumed(Instruction *I).
4544 bool isAssumedDead(const Instruction *I) const override {
4545 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", 4546, __extension__
__PRETTY_FUNCTION__))
4546 "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", 4546, __extension__
__PRETTY_FUNCTION__))
;
4547
4548 if (!getAssumed())
4549 return false;
4550
4551 // If it is not in AssumedLiveBlocks then it for sure dead.
4552 // Otherwise, it can still be after noreturn call in a live block.
4553 if (!AssumedLiveBlocks.count(I->getParent()))
4554 return true;
4555
4556 // If it is not after a liveness barrier it is live.
4557 const Instruction *PrevI = I->getPrevNode();
4558 while (PrevI) {
4559 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4560 return true;
4561 PrevI = PrevI->getPrevNode();
4562 }
4563 return false;
4564 }
4565
4566 /// See AAIsDead::isKnownDead(Instruction *I).
4567 bool isKnownDead(const Instruction *I) const override {
4568 return getKnown() && isAssumedDead(I);
4569 }
4570
4571 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
4572 /// that internal function called from \p BB should now be looked at.
4573 bool assumeLive(Attributor &A, const BasicBlock &BB) {
4574 if (!AssumedLiveBlocks.insert(&BB).second)
4575 return false;
4576
4577 // We assume that all of BB is (probably) live now and if there are calls to
4578 // internal functions we will assume that those are now live as well. This
4579 // is a performance optimization for blocks with calls to a lot of internal
4580 // functions. It can however cause dead functions to be treated as live.
4581 for (const Instruction &I : BB)
4582 if (const auto *CB = dyn_cast<CallBase>(&I))
4583 if (const Function *F = CB->getCalledFunction())
4584 if (F->hasLocalLinkage())
4585 A.markLiveInternalFunction(*F);
4586 return true;
4587 }
4588
4589 /// Collection of instructions that need to be explored again, e.g., we
4590 /// did assume they do not transfer control to (one of their) successors.
4591 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4592
4593 /// Collection of instructions that are known to not transfer control.
4594 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4595
4596 /// Collection of all assumed live edges
4597 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4598
4599 /// Collection of all assumed live BasicBlocks.
4600 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4601};
4602
4603static bool
4604identifyAliveSuccessors(Attributor &A, const CallBase &CB,
4605 AbstractAttribute &AA,
4606 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4607 const IRPosition &IPos = IRPosition::callsite_function(CB);
4608
4609 const auto &NoReturnAA =
4610 A.getAndUpdateAAFor<AANoReturn>(AA, IPos, DepClassTy::OPTIONAL);
4611 if (NoReturnAA.isAssumedNoReturn())
4612 return !NoReturnAA.isKnownNoReturn();
4613 if (CB.isTerminator())
4614 AliveSuccessors.push_back(&CB.getSuccessor(0)->front());
4615 else
4616 AliveSuccessors.push_back(CB.getNextNode());
4617 return false;
4618}
4619
4620static bool
4621identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
4622 AbstractAttribute &AA,
4623 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4624 bool UsedAssumedInformation =
4625 identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);
4626
4627 // First, determine if we can change an invoke to a call assuming the
4628 // callee is nounwind. This is not possible if the personality of the
4629 // function allows to catch asynchronous exceptions.
4630 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {
4631 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4632 } else {
4633 const IRPosition &IPos = IRPosition::callsite_function(II);
4634 const auto &AANoUnw =
4635 A.getAndUpdateAAFor<AANoUnwind>(AA, IPos, DepClassTy::OPTIONAL);
4636 if (AANoUnw.isAssumedNoUnwind()) {
4637 UsedAssumedInformation |= !AANoUnw.isKnownNoUnwind();
4638 } else {
4639 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4640 }
4641 }
4642 return UsedAssumedInformation;
4643}
4644
4645static bool
4646identifyAliveSuccessors(Attributor &A, const BranchInst &BI,
4647 AbstractAttribute &AA,
4648 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4649 bool UsedAssumedInformation = false;
4650 if (BI.getNumSuccessors() == 1) {
4651 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4652 } else {
4653 std::optional<Constant *> C =
4654 A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);
4655 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4656 // No value yet, assume both edges are dead.
4657 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4658 const BasicBlock *SuccBB =
4659 BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());
4660 AliveSuccessors.push_back(&SuccBB->front());
4661 } else {
4662 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4663 AliveSuccessors.push_back(&BI.getSuccessor(1)->front());
4664 UsedAssumedInformation = false;
4665 }
4666 }
4667 return UsedAssumedInformation;
4668}
4669
4670static bool
4671identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
4672 AbstractAttribute &AA,
4673 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4674 bool UsedAssumedInformation = false;
4675 std::optional<Constant *> C =
4676 A.getAssumedConstant(*SI.getCondition(), AA, UsedAssumedInformation);
4677 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4678 // No value yet, assume all edges are dead.
4679 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4680 for (const auto &CaseIt : SI.cases()) {
4681 if (CaseIt.getCaseValue() == *C) {
4682 AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());
4683 return UsedAssumedInformation;
4684 }
4685 }
4686 AliveSuccessors.push_back(&SI.getDefaultDest()->front());
4687 return UsedAssumedInformation;
4688 } else {
4689 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4690 AliveSuccessors.push_back(&SuccBB->front());
4691 }
4692 return UsedAssumedInformation;
4693}
4694
4695ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
4696 ChangeStatus Change = ChangeStatus::UNCHANGED;
4697
4698 if (AssumedLiveBlocks.empty()) {
4699 if (isAssumedDeadInternalFunction(A))
4700 return ChangeStatus::UNCHANGED;
4701
4702 Function *F = getAnchorScope();
4703 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4704 assumeLive(A, F->getEntryBlock());
4705 Change = ChangeStatus::CHANGED;
4706 }
4707
4708 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)
4709 << 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)
4710 << 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)
4711 << 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)
;
4712
4713 // Copy and clear the list of instructions we need to explore from. It is
4714 // refilled with instructions the next update has to look at.
4715 SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
4716 ToBeExploredFrom.end());
4717 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4718
4719 SmallVector<const Instruction *, 8> AliveSuccessors;
4720 while (!Worklist.empty()) {
4721 const Instruction *I = Worklist.pop_back_val();
4722 LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] Exploration inst: "
<< *I << "\n"; } } while (false)
;
4723
4724 // Fast forward for uninteresting instructions. We could look for UB here
4725 // though.
4726 while (!I->isTerminator() && !isa<CallBase>(I))
4727 I = I->getNextNode();
4728
4729 AliveSuccessors.clear();
4730
4731 bool UsedAssumedInformation = false;
4732 switch (I->getOpcode()) {
4733 // TODO: look for (assumed) UB to backwards propagate "deadness".
4734 default:
4735 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", 4736, __extension__
__PRETTY_FUNCTION__))
4736 "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", 4736, __extension__
__PRETTY_FUNCTION__))
;
4737 for (const BasicBlock *SuccBB : successors(I->getParent()))
4738 AliveSuccessors.push_back(&SuccBB->front());
4739 break;
4740 case Instruction::Call:
4741 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),
4742 *this, AliveSuccessors);
4743 break;
4744 case Instruction::Invoke:
4745 UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),
4746 *this, AliveSuccessors);
4747 break;
4748 case Instruction::Br:
4749 UsedAssumedInformation = identifyAliveSuccessors(A, cast<BranchInst>(*I),
4750 *this, AliveSuccessors);
4751 break;
4752 case Instruction::Switch:
4753 UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),
4754 *this, AliveSuccessors);
4755 break;
4756 }
4757
4758 if (UsedAssumedInformation) {
4759 NewToBeExploredFrom.insert(I);
4760 } else if (AliveSuccessors.empty() ||
4761 (I->isTerminator() &&
4762 AliveSuccessors.size() < I->getNumSuccessors())) {
4763 if (KnownDeadEnds.insert(I))
4764 Change = ChangeStatus::CHANGED;
4765 }
4766
4767 LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] #AliveSuccessors: "
<< AliveSuccessors.size() << " UsedAssumedInformation: "
<< UsedAssumedInformation << "\n"; } } while (false
)
4768 << AliveSuccessors.size() << " UsedAssumedInformation: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] #AliveSuccessors: "
<< AliveSuccessors.size() << " UsedAssumedInformation: "
<< UsedAssumedInformation << "\n"; } } while (false
)
4769 << UsedAssumedInformation << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAIsDead] #AliveSuccessors: "
<< AliveSuccessors.size() << " UsedAssumedInformation: "
<< UsedAssumedInformation << "\n"; } } while (false
)
;
4770
4771 for (const Instruction *AliveSuccessor : AliveSuccessors) {
4772 if (!I->isTerminator()) {
4773 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", 4774, __extension__
__PRETTY_FUNCTION__))
4774 "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", 4774, __extension__
__PRETTY_FUNCTION__))
;
4775 Worklist.push_back(AliveSuccessor);
4776 } else {
4777 // record the assumed live edge
4778 auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());
4779 if (AssumedLiveEdges.insert(Edge).second)
4780 Change = ChangeStatus::CHANGED;
4781 if (assumeLive(A, *AliveSuccessor->getParent()))
4782 Worklist.push_back(AliveSuccessor);
4783 }
4784 }
4785 }
4786
4787 // Check if the content of ToBeExploredFrom changed, ignore the order.
4788 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4789 llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {
4790 return !ToBeExploredFrom.count(I);
4791 })) {
4792 Change = ChangeStatus::CHANGED;
4793 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4794 }
4795
4796 // If we know everything is live there is no need to query for liveness.
4797 // Instead, indicating a pessimistic fixpoint will cause the state to be
4798 // "invalid" and all queries to be answered conservatively without lookups.
4799 // To be in this state we have to (1) finished the exploration and (3) not
4800 // discovered any non-trivial dead end and (2) not ruled unreachable code
4801 // dead.
4802 if (ToBeExploredFrom.empty() &&
4803 getAnchorScope()->size() == AssumedLiveBlocks.size() &&
4804 llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {
4805 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4806 }))
4807 return indicatePessimisticFixpoint();
4808 return Change;
4809}
4810
4811/// Liveness information for a call sites.
4812struct AAIsDeadCallSite final : AAIsDeadFunction {
4813 AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
4814 : AAIsDeadFunction(IRP, A) {}
4815
4816 /// See AbstractAttribute::initialize(...).
4817 void initialize(Attributor &A) override {
4818 // TODO: Once we have call site specific value information we can provide
4819 // call site specific liveness information and then it makes
4820 // sense to specialize attributes for call sites instead of
4821 // redirecting requests to the callee.
4822 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"
, 4823)
4823 "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"
, 4823)
;
4824 }
4825
4826 /// See AbstractAttribute::updateImpl(...).
4827 ChangeStatus updateImpl(Attributor &A) override {
4828 return indicatePessimisticFixpoint();
4829 }
4830
4831 /// See AbstractAttribute::trackStatistics()
4832 void trackStatistics() const override {}
4833};
4834} // namespace
4835
4836/// -------------------- Dereferenceable Argument Attribute --------------------
4837
4838namespace {
4839struct AADereferenceableImpl : AADereferenceable {
4840 AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
4841 : AADereferenceable(IRP, A) {}
4842 using StateType = DerefState;
4843
4844 /// See AbstractAttribute::initialize(...).
4845 void initialize(Attributor &A) override {
4846 Value &V = *getAssociatedValue().stripPointerCasts();
4847 SmallVector<Attribute, 4> Attrs;
4848 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4849 Attrs, /* IgnoreSubsumingPositions */ false, &A);
4850 for (const Attribute &Attr : Attrs)
4851 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4852
4853 const IRPosition &IRP = this->getIRPosition();
4854 NonNullAA = &A.getAAFor<AANonNull>(*this, IRP, DepClassTy::NONE);
4855
4856 bool CanBeNull, CanBeFreed;
4857 takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(
4858 A.getDataLayout(), CanBeNull, CanBeFreed));
4859
4860 bool IsFnInterface = IRP.isFnInterfaceKind();
4861 Function *FnScope = IRP.getAnchorScope();
4862 if (IsFnInterface && (!FnScope || !A.isFunctionIPOAmendable(*FnScope))) {
4863 indicatePessimisticFixpoint();
4864 return;
4865 }
4866
4867 if (Instruction *CtxI = getCtxI())
4868 followUsesInMBEC(*this, A, getState(), *CtxI);
4869 }
4870
4871 /// See AbstractAttribute::getState()
4872 /// {
4873 StateType &getState() override { return *this; }
4874 const StateType &getState() const override { return *this; }
4875 /// }
4876
4877 /// Helper function for collecting accessed bytes in must-be-executed-context
4878 void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
4879 DerefState &State) {
4880 const Value *UseV = U->get();
4881 if (!UseV->getType()->isPointerTy())
4882 return;
4883
4884 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
4885 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
4886 return;
4887
4888 int64_t Offset;
4889 const Value *Base = GetPointerBaseWithConstantOffset(
4890 Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);
4891 if (Base && Base == &getAssociatedValue())
4892 State.addAccessedBytes(Offset, Loc->Size.getValue());
4893 }
4894
4895 /// See followUsesInMBEC
4896 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
4897 AADereferenceable::StateType &State) {
4898 bool IsNonNull = false;
4899 bool TrackUse = false;
4900 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4901 A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);
4902 LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytesdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AADereferenceable] Deref bytes: "
<< DerefBytes << " for instruction " << *I
<< "\n"; } } while (false)
4903 << " for instruction " << *I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AADereferenceable] Deref bytes: "
<< DerefBytes << " for instruction " << *I
<< "\n"; } } while (false)
;
4904
4905 addAccessedBytesForUse(A, U, I, State);
4906 State.takeKnownDerefBytesMaximum(DerefBytes);
4907 return TrackUse;
4908 }
4909
4910 /// See AbstractAttribute::manifest(...).
4911 ChangeStatus manifest(Attributor &A) override {
4912 ChangeStatus Change = AADereferenceable::manifest(A);
4913 if (isAssumedNonNull() && hasAttr(Attribute::DereferenceableOrNull)) {
4914 removeAttrs({Attribute::DereferenceableOrNull});
4915 return ChangeStatus::CHANGED;
4916 }
4917 return Change;
4918 }
4919
4920 void getDeducedAttributes(LLVMContext &Ctx,
4921 SmallVectorImpl<Attribute> &Attrs) const override {
4922 // TODO: Add *_globally support
4923 if (isAssumedNonNull())
4924 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
4925 Ctx, getAssumedDereferenceableBytes()));
4926 else
4927 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
4928 Ctx, getAssumedDereferenceableBytes()));
4929 }
4930
4931 /// See AbstractAttribute::getAsStr().
4932 const std::string getAsStr() const override {
4933 if (!getAssumedDereferenceableBytes())
4934 return "unknown-dereferenceable";
4935 return std::string("dereferenceable") +
4936 (isAssumedNonNull() ? "" : "_or_null") +
4937 (isAssumedGlobal() ? "_globally" : "") + "<" +
4938 std::to_string(getKnownDereferenceableBytes()) + "-" +
4939 std::to_string(getAssumedDereferenceableBytes()) + ">";
4940 }
4941};
4942
4943/// Dereferenceable attribute for a floating value.
4944struct AADereferenceableFloating : AADereferenceableImpl {
4945 AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
4946 : AADereferenceableImpl(IRP, A) {}
4947
4948 /// See AbstractAttribute::updateImpl(...).
4949 ChangeStatus updateImpl(Attributor &A) override {
4950
4951 bool Stripped;
4952 bool UsedAssumedInformation = false;
4953 SmallVector<AA::ValueAndContext> Values;
4954 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
4955 AA::AnyScope, UsedAssumedInformation)) {
4956 Values.push_back({getAssociatedValue(), getCtxI()});
4957 Stripped = false;
4958 } else {
4959 Stripped = Values.size() != 1 ||
4960 Values.front().getValue() != &getAssociatedValue();
4961 }
4962
4963 const DataLayout &DL = A.getDataLayout();
4964 DerefState T;
4965
4966 auto VisitValueCB = [&](const Value &V) -> bool {
4967 unsigned IdxWidth =
4968 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
4969 APInt Offset(IdxWidth, 0);
4970 const Value *Base = stripAndAccumulateOffsets(
4971 A, *this, &V, DL, Offset, /* GetMinOffset */ false,
4972 /* AllowNonInbounds */ true);
4973
4974 const auto &AA = A.getAAFor<AADereferenceable>(
4975 *this, IRPosition::value(*Base), DepClassTy::REQUIRED);
4976 int64_t DerefBytes = 0;
4977 if (!Stripped && this == &AA) {
4978 // Use IR information if we did not strip anything.
4979 // TODO: track globally.
4980 bool CanBeNull, CanBeFreed;
4981 DerefBytes =
4982 Base->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);
4983 T.GlobalState.indicatePessimisticFixpoint();
4984 } else {
4985 const DerefState &DS = AA.getState();
4986 DerefBytes = DS.DerefBytesState.getAssumed();
4987 T.GlobalState &= DS.GlobalState;
4988 }
4989
4990 // For now we do not try to "increase" dereferenceability due to negative
4991 // indices as we first have to come up with code to deal with loops and
4992 // for overflows of the dereferenceable bytes.
4993 int64_t OffsetSExt = Offset.getSExtValue();
4994 if (OffsetSExt < 0)
4995 OffsetSExt = 0;
4996
4997 T.takeAssumedDerefBytesMinimum(
4998 std::max(int64_t(0), DerefBytes - OffsetSExt));
4999
5000 if (this == &AA) {
5001 if (!Stripped) {
5002 // If nothing was stripped IR information is all we got.
5003 T.takeKnownDerefBytesMaximum(
5004 std::max(int64_t(0), DerefBytes - OffsetSExt));
5005 T.indicatePessimisticFixpoint();
5006 } else if (OffsetSExt > 0) {
5007 // If something was stripped but there is circular reasoning we look
5008 // for the offset. If it is positive we basically decrease the
5009 // dereferenceable bytes in a circular loop now, which will simply
5010 // drive them down to the known value in a very slow way which we
5011 // can accelerate.
5012 T.indicatePessimisticFixpoint();
5013 }
5014 }
5015
5016 return T.isValidState();
5017 };
5018
5019 for (const auto &VAC : Values)
5020 if (!VisitValueCB(*VAC.getValue()))
5021 return indicatePessimisticFixpoint();
5022
5023 return clampStateAndIndicateChange(getState(), T);
5024 }
5025
5026 /// See AbstractAttribute::trackStatistics()
5027 void trackStatistics() const override {
5028 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable){ static llvm::Statistic NumIRFloating_dereferenceable = {"attributor"
, "NumIRFloating_dereferenceable", ("Number of floating values known to be '"
"dereferenceable" "'")};; ++(NumIRFloating_dereferenceable);
}
5029 }
5030};
5031
5032/// Dereferenceable attribute for a return value.
5033struct AADereferenceableReturned final
5034 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5035 AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
5036 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>(
5037 IRP, A) {}
5038
5039 /// See AbstractAttribute::trackStatistics()
5040 void trackStatistics() const override {
5041 STATS_DECLTRACK_FNRET_ATTR(dereferenceable){ static llvm::Statistic NumIRFunctionReturn_dereferenceable =
{"attributor", "NumIRFunctionReturn_dereferenceable", ("Number of "
"function returns" " marked '" "dereferenceable" "'")};; ++(
NumIRFunctionReturn_dereferenceable); }
5042 }
5043};
5044
5045/// Dereferenceable attribute for an argument
5046struct AADereferenceableArgument final
5047 : AAArgumentFromCallSiteArguments<AADereferenceable,
5048 AADereferenceableImpl> {
5049 using Base =
5050 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5051 AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
5052 : Base(IRP, A) {}
5053
5054 /// See AbstractAttribute::trackStatistics()
5055 void trackStatistics() const override {
5056 STATS_DECLTRACK_ARG_ATTR(dereferenceable){ static llvm::Statistic NumIRArguments_dereferenceable = {"attributor"
, "NumIRArguments_dereferenceable", ("Number of " "arguments"
" marked '" "dereferenceable" "'")};; ++(NumIRArguments_dereferenceable
); }
5057 }
5058};
5059
5060/// Dereferenceable attribute for a call site argument.
5061struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5062 AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
5063 : AADereferenceableFloating(IRP, A) {}
5064
5065 /// See AbstractAttribute::trackStatistics()
5066 void trackStatistics() const override {
5067 STATS_DECLTRACK_CSARG_ATTR(dereferenceable){ static llvm::Statistic NumIRCSArguments_dereferenceable = {
"attributor", "NumIRCSArguments_dereferenceable", ("Number of "
"call site arguments" " marked '" "dereferenceable" "'")};; ++
(NumIRCSArguments_dereferenceable); }
5068 }
5069};
5070
5071/// Dereferenceable attribute deduction for a call site return value.
5072struct AADereferenceableCallSiteReturned final
5073 : AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl> {
5074 using Base =
5075 AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl>;
5076 AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
5077 : Base(IRP, A) {}
5078
5079 /// See AbstractAttribute::trackStatistics()
5080 void trackStatistics() const override {
5081 STATS_DECLTRACK_CS_ATTR(dereferenceable){ static llvm::Statistic NumIRCS_dereferenceable = {"attributor"
, "NumIRCS_dereferenceable", ("Number of " "call site" " marked '"
"dereferenceable" "'")};; ++(NumIRCS_dereferenceable); }
;
5082 }
5083};
5084} // namespace
5085
5086// ------------------------ Align Argument Attribute ------------------------
5087
5088namespace {
5089static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
5090 Value &AssociatedValue, const Use *U,
5091 const Instruction *I, bool &TrackUse) {
5092 // We need to follow common pointer manipulation uses to the accesses they
5093 // feed into.
5094 if (isa<CastInst>(I)) {
1
Assuming 'I' is not a 'CastInst'
2
Taking false branch
5095 // Follow all but ptr2int casts.
5096 TrackUse = !isa<PtrToIntInst>(I);
5097 return 0;
5098 }
5099 if (auto *GEP
3.1
'GEP' is null
3.1
'GEP' is null
= dyn_cast<GetElementPtrInst>(I)) {
3
Assuming 'I' is not a 'CastReturnType'
4
Taking false branch
5100 if (GEP->hasAllConstantIndices())
5101 TrackUse = true;
5102 return 0;
5103 }
5104
5105 MaybeAlign MA;
5106 if (const auto *CB
5.1
'CB' is null
5.1
'CB' is null
= dyn_cast<CallBase>(I)) {
5
Assuming 'I' is not a 'CastReturnType'
6
Taking false branch
5107 if (CB->isBundleOperand(U) || CB->isCallee(U))
5108 return 0;
5109
5110 unsigned ArgNo = CB->getArgOperandNo(U);
5111 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
5112 // As long as we only use known information there is no need to track
5113 // dependences here.
5114 auto &AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);
5115 MA = MaybeAlign(AlignAA.getKnownAlign());
5116 }
5117
5118 const DataLayout &DL = A.getDataLayout();
5119 const Value *UseV = U->get();
7
'UseV' initialized here
5120 if (auto *SI
8.1
'SI' is non-null
8.1
'SI' is non-null
= dyn_cast<StoreInst>(I)) {
8
Assuming 'I' is a 'CastReturnType'
9
Taking true branch
5121 if (SI->getPointerOperand() == UseV)
10
Assuming pointer value is null
11
Taking true branch
5122 MA = SI->getAlign();
5123 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
5124 if (LI->getPointerOperand() == UseV)
5125 MA = LI->getAlign();
5126 }
5127
5128 if (!MA || *MA <= QueryingAA.getKnownAlign())
12
Taking false branch
5129 return 0;
5130
5131 unsigned Alignment = MA->value();
5132 int64_t Offset;
5133
5134 if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
13
Passing null pointer value via 1st parameter 'Ptr'
14
Calling 'GetPointerBaseWithConstantOffset'
5135 if (Base == &AssociatedValue) {
5136 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5137 // So we can say that the maximum power of two which is a divisor of
5138 // gcd(Offset, Alignment) is an alignment.
5139
5140 uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);
5141 Alignment = llvm::bit_floor(gcd);
5142 }
5143 }
5144
5145 return Alignment;
5146}
5147
5148struct AAAlignImpl : AAAlign {
5149 AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}
5150
5151 /// See AbstractAttribute::initialize(...).
5152 void initialize(Attributor &A) override {
5153 SmallVector<Attribute, 4> Attrs;
5154 getAttrs({Attribute::Alignment}, Attrs);
5155 for (const Attribute &Attr : Attrs)
5156 takeKnownMaximum(Attr.getValueAsInt());
5157
5158 Value &V = *getAssociatedValue().stripPointerCasts();
5159 takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());
5160
5161 if (getIRPosition().isFnInterfaceKind() &&
5162 (!getAnchorScope() ||
5163 !A.isFunctionIPOAmendable(*getAssociatedFunction()))) {
5164 indicatePessimisticFixpoint();
5165 return;
5166 }
5167
5168 if (Instruction *CtxI = getCtxI())
5169 followUsesInMBEC(*this, A, getState(), *CtxI);
5170 }
5171
5172 /// See AbstractAttribute::manifest(...).
5173 ChangeStatus manifest(Attributor &A) override {
5174 ChangeStatus LoadStoreChanged = ChangeStatus::UNCHANGED;
5175
5176 // Check for users that allow alignment annotations.
5177 Value &AssociatedValue = getAssociatedValue();
5178 for (const Use &U : AssociatedValue.uses()) {
5179 if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
5180 if (SI->getPointerOperand() == &AssociatedValue)
5181 if (SI->getAlign() < getAssumedAlign()) {
5182 STATS_DECLTRACK(AAAlign, Store,{ static llvm::Statistic NumIRStore_AAAlign = {"attributor", "NumIRStore_AAAlign"
, "Number of times alignment added to a store"};; ++(NumIRStore_AAAlign
); }
5183 "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
); }
;
5184 SI->setAlignment(getAssumedAlign());
5185 LoadStoreChanged = ChangeStatus::CHANGED;
5186 }
5187 } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
5188 if (LI->getPointerOperand() == &AssociatedValue)
5189 if (LI->getAlign() < getAssumedAlign()) {
5190 LI->setAlignment(getAssumedAlign());
5191 STATS_DECLTRACK(AAAlign, Load,{ static llvm::Statistic NumIRLoad_AAAlign = {"attributor", "NumIRLoad_AAAlign"
, "Number of times alignment added to a load"};; ++(NumIRLoad_AAAlign
); }
5192 "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
); }
;
5193 LoadStoreChanged = ChangeStatus::CHANGED;
5194 }
5195 }
5196 }
5197
5198 ChangeStatus Changed = AAAlign::manifest(A);
5199
5200 Align InheritAlign =
5201 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5202 if (InheritAlign >= getAssumedAlign())
5203 return LoadStoreChanged;
5204 return Changed | LoadStoreChanged;
5205 }
5206
5207 // TODO: Provide a helper to determine the implied ABI alignment and check in
5208 // the existing manifest method and a new one for AAAlignImpl that value
5209 // to avoid making the alignment explicit if it did not improve.
5210
5211 /// See AbstractAttribute::getDeducedAttributes
5212 void getDeducedAttributes(LLVMContext &Ctx,
5213 SmallVectorImpl<Attribute> &Attrs) const override {
5214 if (getAssumedAlign() > 1)
5215 Attrs.emplace_back(
5216 Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
5217 }
5218
5219 /// See followUsesInMBEC
5220 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5221 AAAlign::StateType &State) {
5222 bool TrackUse = false;
5223
5224 unsigned int KnownAlign =
5225 getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
5226 State.takeKnownMaximum(KnownAlign);
5227
5228 return TrackUse;
5229 }
5230
5231 /// See AbstractAttribute::getAsStr().
5232 const std::string getAsStr() const override {
5233 return "align<" + std::to_string(getKnownAlign().value()) + "-" +
5234 std::to_string(getAssumedAlign().value()) + ">";
5235 }
5236};
5237
5238/// Align attribute for a floating value.
5239struct AAAlignFloating : AAAlignImpl {
5240 AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}
5241
5242 /// See AbstractAttribute::updateImpl(...).
5243 ChangeStatus updateImpl(Attributor &A) override {
5244 const DataLayout &DL = A.getDataLayout();
5245
5246 bool Stripped;
5247 bool UsedAssumedInformation = false;
5248 SmallVector<AA::ValueAndContext> Values;
5249 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5250 AA::AnyScope, UsedAssumedInformation)) {
5251 Values.push_back({getAssociatedValue(), getCtxI()});
5252 Stripped = false;
5253 } else {
5254 Stripped = Values.size() != 1 ||
5255 Values.front().getValue() != &getAssociatedValue();
5256 }
5257
5258 StateType T;
5259 auto VisitValueCB = [&](Value &V) -> bool {
5260 if (isa<UndefValue>(V) || isa<ConstantPointerNull>(V))
5261 return true;
5262 const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),
5263 DepClassTy::REQUIRED);
5264 if (!Stripped && this == &AA) {
5265 int64_t Offset;
5266 unsigned Alignment = 1;
5267 if (const Value *Base =
5268 GetPointerBaseWithConstantOffset(&V, Offset, DL)) {
5269 // TODO: Use AAAlign for the base too.
5270 Align PA = Base->getPointerAlignment(DL);
5271 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5272 // So we can say that the maximum power of two which is a divisor of
5273 // gcd(Offset, Alignment) is an alignment.
5274
5275 uint32_t gcd =
5276 std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));
5277 Alignment = llvm::bit_floor(gcd);
5278 } else {
5279 Alignment = V.getPointerAlignment(DL).value();
5280 }
5281 // Use only IR information if we did not strip anything.
5282 T.takeKnownMaximum(Alignment);
5283 T.indicatePessimisticFixpoint();
5284 } else {
5285 // Use abstract attribute information.
5286 const AAAlign::StateType &DS = AA.getState();
5287 T ^= DS;
5288 }
5289 return T.isValidState();
5290 };
5291
5292 for (const auto &VAC : Values) {
5293 if (!VisitValueCB(*VAC.getValue()))
5294 return indicatePessimisticFixpoint();
5295 }
5296
5297 // TODO: If we know we visited all incoming values, thus no are assumed
5298 // dead, we can take the known information from the state T.
5299 return clampStateAndIndicateChange(getState(), T);
5300 }
5301
5302 /// See AbstractAttribute::trackStatistics()
5303 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); }
}
5304};
5305
5306/// Align attribute for function return value.
5307struct AAAlignReturned final
5308 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5309 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5310 AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5311
5312 /// See AbstractAttribute::initialize(...).
5313 void initialize(Attributor &A) override {
5314 Base::initialize(A);
5315 Function *F = getAssociatedFunction();
5316 if (!F || F->isDeclaration())
5317 indicatePessimisticFixpoint();
5318 }
5319
5320 /// See AbstractAttribute::trackStatistics()
5321 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
); }
}
5322};
5323
5324/// Align attribute for function argument.
5325struct AAAlignArgument final
5326 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5327 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5328 AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5329
5330 /// See AbstractAttribute::manifest(...).
5331 ChangeStatus manifest(Attributor &A) override {
5332 // If the associated argument is involved in a must-tail call we give up
5333 // because we would need to keep the argument alignments of caller and
5334 // callee in-sync. Just does not seem worth the trouble right now.
5335 if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5336 return ChangeStatus::UNCHANGED;
5337 return Base::manifest(A);
5338 }
5339
5340 /// See AbstractAttribute::trackStatistics()
5341 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned){ static llvm::Statistic NumIRArguments_aligned = {"attributor"
, "NumIRArguments_aligned", ("Number of " "arguments" " marked '"
"aligned" "'")};; ++(NumIRArguments_aligned); }
}
5342};
5343
5344struct AAAlignCallSiteArgument final : AAAlignFloating {
5345 AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
5346 : AAAlignFloating(IRP, A) {}
5347
5348 /// See AbstractAttribute::manifest(...).
5349 ChangeStatus manifest(Attributor &A) override {
5350 // If the associated argument is involved in a must-tail call we give up
5351 // because we would need to keep the argument alignments of caller and
5352 // callee in-sync. Just does not seem worth the trouble right now.
5353 if (Argument *Arg = getAssociatedArgument())
5354 if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5355 return ChangeStatus::UNCHANGED;
5356 ChangeStatus Changed = AAAlignImpl::manifest(A);
5357 Align InheritAlign =
5358 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5359 if (InheritAlign >= getAssumedAlign())
5360 Changed = ChangeStatus::UNCHANGED;
5361 return Changed;
5362 }
5363
5364 /// See AbstractAttribute::updateImpl(Attributor &A).
5365 ChangeStatus updateImpl(Attributor &A) override {
5366 ChangeStatus Changed = AAAlignFloating::updateImpl(A);
5367 if (Argument *Arg = getAssociatedArgument()) {
5368 // We only take known information from the argument
5369 // so we do not need to track a dependence.
5370 const auto &ArgAlignAA = A.getAAFor<AAAlign>(
5371 *this, IRPosition::argument(*Arg), DepClassTy::NONE);
5372 takeKnownMaximum(ArgAlignAA.getKnownAlign().value());
5373 }
5374 return Changed;
5375 }
5376
5377 /// See AbstractAttribute::trackStatistics()
5378 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); }
}
5379};
5380
5381/// Align attribute deduction for a call site return value.
5382struct AAAlignCallSiteReturned final
5383 : AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl> {
5384 using Base = AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl>;
5385 AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
5386 : Base(IRP, A) {}
5387
5388 /// See AbstractAttribute::initialize(...).
5389 void initialize(Attributor &A) override {
5390 Base::initialize(A);
5391 Function *F = getAssociatedFunction();
5392 if (!F || F->isDeclaration())
5393 indicatePessimisticFixpoint();
5394 }
5395
5396 /// See AbstractAttribute::trackStatistics()
5397 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
); }
; }
5398};
5399} // namespace
5400
5401/// ------------------ Function No-Return Attribute ----------------------------
5402namespace {
5403struct AANoReturnImpl : public AANoReturn {
5404 AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}
5405
5406 /// See AbstractAttribute::initialize(...).
5407 void initialize(Attributor &A) override {
5408 AANoReturn::initialize(A);
5409 Function *F = getAssociatedFunction();
5410 if (!F || F->isDeclaration())
5411 indicatePessimisticFixpoint();
5412 }
5413
5414 /// See AbstractAttribute::getAsStr().
5415 const std::string getAsStr() const override {
5416 return getAssumed() ? "noreturn" : "may-return";
5417 }
5418
5419 /// See AbstractAttribute::updateImpl(Attributor &A).
5420 ChangeStatus updateImpl(Attributor &A) override {
5421 auto CheckForNoReturn = [](Instruction &) { return false; };
5422 bool UsedAssumedInformation = false;
5423 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
5424 {(unsigned)Instruction::Ret},
5425 UsedAssumedInformation))
5426 return indicatePessimisticFixpoint();
5427 return ChangeStatus::UNCHANGED;
5428 }
5429};
5430
5431struct AANoReturnFunction final : AANoReturnImpl {
5432 AANoReturnFunction(const IRPosition &IRP, Attributor &A)
5433 : AANoReturnImpl(IRP, A) {}
5434
5435 /// See AbstractAttribute::trackStatistics()
5436 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn){ static llvm::Statistic NumIRFunction_noreturn = {"attributor"
, "NumIRFunction_noreturn", ("Number of " "functions" " marked '"
"noreturn" "'")};; ++(NumIRFunction_noreturn); }
}
5437};
5438
5439/// NoReturn attribute deduction for a call sites.
5440struct AANoReturnCallSite final : AANoReturnImpl {
5441 AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
5442 : AANoReturnImpl(IRP, A) {}
5443
5444 /// See AbstractAttribute::initialize(...).
5445 void initialize(Attributor &A) override {
5446 AANoReturnImpl::initialize(A);
5447 if (Function *F = getAssociatedFunction()) {
5448 const IRPosition &FnPos = IRPosition::function(*F);
5449 auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos, DepClassTy::REQUIRED);
5450 if (!FnAA.isAssumedNoReturn())
5451 indicatePessimisticFixpoint();
5452 }
5453 }
5454
5455 /// See AbstractAttribute::updateImpl(...).
5456 ChangeStatus updateImpl(Attributor &A) override {
5457 // TODO: Once we have call site specific value information we can provide
5458 // call site specific liveness information and then it makes
5459 // sense to specialize attributes for call sites arguments instead of
5460 // redirecting requests to the callee argument.
5461 Function *F = getAssociatedFunction();
5462 const IRPosition &FnPos = IRPosition::function(*F);
5463 auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos, DepClassTy::REQUIRED);
5464 return clampStateAndIndicateChange(getState(), FnAA.getState());
5465 }
5466
5467 /// See AbstractAttribute::trackStatistics()
5468 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); }
; }
5469};
5470} // namespace
5471
5472/// ----------------------- Instance Info ---------------------------------
5473
5474namespace {
5475/// A class to hold the state of for no-capture attributes.
5476struct AAInstanceInfoImpl : public AAInstanceInfo {
5477 AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
5478 : AAInstanceInfo(IRP, A) {}
5479
5480 /// See AbstractAttribute::initialize(...).
5481 void initialize(Attributor &A) override {
5482 Value &V = getAssociatedValue();
5483 if (auto *C = dyn_cast<Constant>(&V)) {
5484 if (C->isThreadDependent())
5485 indicatePessimisticFixpoint();
5486 else
5487 indicateOptimisticFixpoint();
5488 return;
5489 }
5490 if (auto *CB = dyn_cast<CallBase>(&V))
5491 if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
5492 !CB->mayReadFromMemory()) {
5493 indicateOptimisticFixpoint();
5494 return;
5495 }
5496 }
5497
5498 /// See AbstractAttribute::updateImpl(...).
5499 ChangeStatus updateImpl(Attributor &A) override {
5500 ChangeStatus Changed = ChangeStatus::UNCHANGED;
5501
5502 Value &V = getAssociatedValue();
5503 const Function *Scope = nullptr;
5504 if (auto *I = dyn_cast<Instruction>(&V))
5505 Scope = I->getFunction();
5506 if (auto *A = dyn_cast<Argument>(&V)) {
5507 Scope = A->getParent();
5508 if (!Scope->hasLocalLinkage())
5509 return Changed;
5510 }
5511 if (!Scope)
5512 return indicateOptimisticFixpoint();
5513
5514 auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
5515 *this, IRPosition::function(*Scope), DepClassTy::OPTIONAL);
5516 if (NoRecurseAA.isAssumedNoRecurse())
5517 return Changed;
5518
5519 auto UsePred = [&](const Use &U, bool &Follow) {
5520 const Instruction *UserI = dyn_cast<Instruction>(U.getUser());
5521 if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||
5522 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
5523 Follow = true;
5524 return true;
5525 }
5526 if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||
5527 (isa<StoreInst>(UserI) &&
5528 cast<StoreInst>(UserI)->getValueOperand() != U.get()))
5529 return true;
5530 if (auto *CB = dyn_cast<CallBase>(UserI)) {
5531 // This check is not guaranteeing uniqueness but for now that we cannot
5532 // end up with two versions of \p U thinking it was one.
5533 if (!CB->getCalledFunction() ||
5534 !CB->getCalledFunction()->hasLocalLinkage())
5535 return true;
5536 if (!CB->isArgOperand(&U))
5537 return false;
5538 const auto &ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
5539 *this, IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U)),
5540 DepClassTy::OPTIONAL);
5541 if (!ArgInstanceInfoAA.isAssumedUniqueForAnalysis())
5542 return false;
5543 // If this call base might reach the scope again we might forward the
5544 // argument back here. This is very conservative.
5545 if (AA::isPotentiallyReachable(
5546 A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,
5547 [Scope](const Function &Fn) { return &Fn != Scope; }))
5548 return false;
5549 return true;
5550 }
5551 return false;
5552 };
5553
5554 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
5555 if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {
5556 auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
5557 if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&
5558 AA::isDynamicallyUnique(A, *this, *Ptr))
5559 return true;
5560 }
5561 return false;
5562 };
5563
5564 if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,
5565 DepClassTy::OPTIONAL,
5566 /* IgnoreDroppableUses */ true, EquivalentUseCB))
5567 return indicatePessimisticFixpoint();
5568
5569 return Changed;
5570 }
5571
5572 /// See AbstractState::getAsStr().
5573 const std::string getAsStr() const override {
5574 return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
5575 }
5576
5577 /// See AbstractAttribute::trackStatistics()
5578 void trackStatistics() const override {}
5579};
5580
5581/// InstanceInfo attribute for floating values.
5582struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5583 AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
5584 : AAInstanceInfoImpl(IRP, A) {}
5585};
5586
5587/// NoCapture attribute for function arguments.
5588struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5589 AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
5590 : AAInstanceInfoFloating(IRP, A) {}
5591};
5592
5593/// InstanceInfo attribute for call site arguments.
5594struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5595 AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
5596 : AAInstanceInfoImpl(IRP, A) {}
5597
5598 /// See AbstractAttribute::updateImpl(...).
5599 ChangeStatus updateImpl(Attributor &A) override {
5600 // TODO: Once we have call site specific value information we can provide
5601 // call site specific liveness information and then it makes
5602 // sense to specialize attributes for call sites arguments instead of
5603 // redirecting requests to the callee argument.
5604 Argument *Arg = getAssociatedArgument();
5605 if (!Arg)
5606 return indicatePessimisticFixpoint();
5607 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5608 auto &ArgAA =
5609 A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);
5610 return clampStateAndIndicateChange(getState(), ArgAA.getState());
5611 }
5612};
5613
5614/// InstanceInfo attribute for function return value.
5615struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5616 AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
5617 : AAInstanceInfoImpl(IRP, A) {
5618 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", 5618)
;
5619 }
5620
5621 /// See AbstractAttribute::initialize(...).
5622 void initialize(Attributor &A) override {
5623 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", 5623)
;
5624 }
5625
5626 /// See AbstractAttribute::updateImpl(...).
5627 ChangeStatus updateImpl(Attributor &A) override {
5628 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", 5628)
;
5629 }
5630};
5631
5632/// InstanceInfo attribute deduction for a call site return value.
5633struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5634 AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
5635 : AAInstanceInfoFloating(IRP, A) {}
5636};
5637} // namespace
5638
5639/// ----------------------- Variable Capturing ---------------------------------
5640
5641namespace {
5642/// A class to hold the state of for no-capture attributes.
5643struct AANoCaptureImpl : public AANoCapture {
5644 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5645
5646 /// See AbstractAttribute::initialize(...).
5647 void initialize(Attributor &A) override {
5648 if (hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ true)) {
5649 indicateOptimisticFixpoint();
5650 return;
5651 }
5652 Function *AnchorScope = getAnchorScope();
5653 if (isFnInterfaceKind() &&
5654 (!AnchorScope || !A.isFunctionIPOAmendable(*AnchorScope))) {
5655 indicatePessimisticFixpoint();
5656 return;
5657 }
5658
5659 // You cannot "capture" null in the default address space.
5660 if (isa<ConstantPointerNull>(getAssociatedValue()) &&
5661 getAssociatedValue().getType()->getPointerAddressSpace() == 0) {
5662 indicateOptimisticFixpoint();
5663 return;
5664 }
5665
5666 const Function *F =
5667 isArgumentPosition() ? getAssociatedFunction() : AnchorScope;
5668
5669 // Check what state the associated function can actually capture.
5670 if (F)
5671 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
5672 else
5673 indicatePessimisticFixpoint();
5674 }
5675
5676 /// See AbstractAttribute::updateImpl(...).
5677 ChangeStatus updateImpl(Attributor &A) override;
5678
5679 /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
5680 void getDeducedAttributes(LLVMContext &Ctx,
5681 SmallVectorImpl<Attribute> &Attrs) const override {
5682 if (!isAssumedNoCaptureMaybeReturned())
5683 return;
5684
5685 if (isArgumentPosition()) {
5686 if (isAssumedNoCapture())
5687 Attrs.emplace_back(Attribute::get(Ctx, Attribute::NoCapture));
5688 else if (ManifestInternal)
5689 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
5690 }
5691 }
5692
5693 /// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
5694 /// depending on the ability of the function associated with \p IRP to capture
5695 /// state in memory and through "returning/throwing", respectively.
5696 static void determineFunctionCaptureCapabilities(const IRPosition &IRP,
5697 const Function &F,
5698 BitIntegerState &State) {
5699 // TODO: Once we have memory behavior attributes we should use them here.
5700
5701 // If we know we cannot communicate or write to memory, we do not care about
5702 // ptr2int anymore.
5703 if (F.onlyReadsMemory() && F.doesNotThrow() &&
5704 F.getReturnType()->isVoidTy()) {
5705 State.addKnownBits(NO_CAPTURE);
5706 return;
5707 }
5708
5709 // A function cannot capture state in memory if it only reads memory, it can
5710 // however return/throw state and the state might be influenced by the
5711 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5712 if (F.onlyReadsMemory())
5713 State.addKnownBits(NOT_CAPTURED_IN_MEM);
5714
5715 // A function cannot communicate state back if it does not through
5716 // exceptions and doesn not return values.
5717 if (F.doesNotThrow() && F.getReturnType()->isVoidTy())
5718 State.addKnownBits(NOT_CAPTURED_IN_RET);
5719
5720 // Check existing "returned" attributes.
5721 int ArgNo = IRP.getCalleeArgNo();
5722 if (F.doesNotThrow() && ArgNo >= 0) {
5723 for (unsigned u = 0, e = F.arg_size(); u < e; ++u)
5724 if (F.hasParamAttribute(u, Attribute::Returned)) {
5725 if (u == unsigned(ArgNo))
5726 State.removeAssumedBits(NOT_CAPTURED_IN_RET);
5727 else if (F.onlyReadsMemory())
5728 State.addKnownBits(NO_CAPTURE);
5729 else
5730 State.addKnownBits(NOT_CAPTURED_IN_RET);
5731 break;
5732 }
5733 }
5734 }
5735
5736 /// See AbstractState::getAsStr().
5737 const std::string getAsStr() const override {
5738 if (isKnownNoCapture())
5739 return "known not-captured";
5740 if (isAssumedNoCapture())
5741 return "assumed not-captured";
5742 if (isKnownNoCaptureMaybeReturned())
5743 return "known not-captured-maybe-returned";
5744 if (isAssumedNoCaptureMaybeReturned())
5745 return "assumed not-captured-maybe-returned";
5746 return "assumed-captured";
5747 }
5748
5749 /// Check the use \p U and update \p State accordingly. Return true if we
5750 /// should continue to update the state.
5751 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
5752 bool &Follow) {
5753 Instruction *UInst = cast<Instruction>(U.getUser());
5754 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)
5755 << *UInst << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AANoCapture] Check use: "
<< *U.get() << " in " << *UInst << "\n"
; } } while (false)
;
5756
5757 // Deal with ptr2int by following uses.
5758 if (isa<PtrToIntInst>(UInst)) {
5759 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " - ptr2int assume the worst!\n"
; } } while (false)
;
5760 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5761 /* Return */ true);
5762 }
5763
5764 // For stores we already checked if we can follow them, if they make it
5765 // here we give up.
5766 if (isa<StoreInst>(UInst))
5767 return isCapturedIn(State, /* Memory */ true, /* Integer */ false,
5768 /* Return */ false);
5769
5770 // Explicitly catch return instructions.
5771 if (isa<ReturnInst>(UInst)) {
5772 if (UInst->getFunction() == getAnchorScope())
5773 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5774 /* Return */ true);
5775 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5776 /* Return */ true);
5777 }
5778
5779 // For now we only use special logic for call sites. However, the tracker
5780 // itself knows about a lot of other non-capturing cases already.
5781 auto *CB = dyn_cast<CallBase>(UInst);
5782 if (!CB || !CB->isArgOperand(&U))
5783 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5784 /* Return */ true);
5785
5786 unsigned ArgNo = CB->getArgOperandNo(&U);
5787 const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
5788 // If we have a abstract no-capture attribute for the argument we can use
5789 // it to justify a non-capture attribute here. This allows recursion!
5790 auto &ArgNoCaptureAA =
5791 A.getAAFor<AANoCapture>(*this, CSArgPos, DepClassTy::REQUIRED);
5792 if (ArgNoCaptureAA.isAssumedNoCapture())
5793 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5794 /* Return */ false);
5795 if (ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
5796 Follow = true;
5797 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5798 /* Return */ false);
5799 }
5800
5801 // Lastly, we could not find a reason no-capture can be assumed so we don't.
5802 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5803 /* Return */ true);
5804 }
5805
5806 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
5807 /// \p CapturedInRet, then return true if we should continue updating the
5808 /// state.
5809 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
5810 bool CapturedInInt, bool CapturedInRet) {
5811 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
)
5812 << CapturedInInt << "|Ret " << CapturedInRet << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << " - captures [Mem " <<
CapturedInMem << "|Int " << CapturedInInt <<
"|Ret " << CapturedInRet << "]\n"; } } while (false
)
;
5813 if (CapturedInMem)
5814 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
5815 if (CapturedInInt)
5816 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
5817 if (CapturedInRet)
5818 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
5819 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
5820 }
5821};
5822
5823ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
5824 const IRPosition &IRP = getIRPosition();
5825 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
5826 : &IRP.getAssociatedValue();
5827 if (!V)
5828 return indicatePessimisticFixpoint();
5829
5830 const Function *F =
5831 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
5832 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", 5832, __extension__
__PRETTY_FUNCTION__))
;
5833 const IRPosition &FnPos = IRPosition::function(*F);
5834
5835 AANoCapture::StateType T;
5836
5837 // Readonly means we cannot capture through memory.
5838 bool IsKnown;
5839 if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
5840 T.addKnownBits(NOT_CAPTURED_IN_MEM);
5841 if (IsKnown)
5842 addKnownBits(NOT_CAPTURED_IN_MEM);
5843 }
5844
5845 // Make sure all returned values are different than the underlying value.
5846 // TODO: we could do this in a more sophisticated way inside
5847 // AAReturnedValues, e.g., track all values that escape through returns
5848 // directly somehow.
5849 auto CheckReturnedArgs = [&](const AAReturnedValues &RVAA) {
5850 if (!RVAA.getState().isValidState())
5851 return false;
5852 bool SeenConstant = false;
5853 for (const auto &It : RVAA.returned_values()) {
5854 if (isa<Constant>(It.first)) {
5855 if (SeenConstant)
5856 return false;
5857 SeenConstant = true;
5858 } else if (!isa<Argument>(It.first) ||
5859 It.first == getAssociatedArgument())
5860 return false;
5861 }
5862 return true;
5863 };
5864
5865 const auto &NoUnwindAA =
5866 A.getAAFor<AANoUnwind>(*this, FnPos, DepClassTy::OPTIONAL);
5867 if (NoUnwindAA.isAssumedNoUnwind()) {
5868 bool IsVoidTy = F->getReturnType()->isVoidTy();
5869 const AAReturnedValues *RVAA =
5870 IsVoidTy ? nullptr
5871 : &A.getAAFor<AAReturnedValues>(*this, FnPos,
5872
5873 DepClassTy::OPTIONAL);
5874 if (IsVoidTy || CheckReturnedArgs(*RVAA)) {
5875 T.addKnownBits(NOT_CAPTURED_IN_RET);
5876 if (T.isKnown(NOT_CAPTURED_IN_MEM))
5877 return ChangeStatus::UNCHANGED;
5878 if (NoUnwindAA.isKnownNoUnwind() &&
5879 (IsVoidTy || RVAA->getState().isAtFixpoint())) {
5880 addKnownBits(NOT_CAPTURED_IN_RET);
5881 if (isKnown(NOT_CAPTURED_IN_MEM))
5882 return indicateOptimisticFixpoint();
5883 }
5884 }
5885 }
5886
5887 auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
5888 const auto &DerefAA = A.getAAFor<AADereferenceable>(
5889 *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
5890 return DerefAA.getAssumedDereferenceableBytes();
5891 };
5892
5893 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
5894 switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
5895 case UseCaptureKind::NO_CAPTURE:
5896 return true;
5897 case UseCaptureKind::MAY_CAPTURE:
5898 return checkUse(A, T, U, Follow);
5899 case UseCaptureKind::PASSTHROUGH:
5900 Follow = true;
5901 return true;
5902 }
5903 llvm_unreachable("Unexpected use capture kind!")::llvm::llvm_unreachable_internal("Unexpected use capture kind!"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 5903)
;
5904 };
5905
5906 if (!A.checkForAllUses(UseCheck, *this, *V))
5907 return indicatePessimisticFixpoint();
5908
5909 AANoCapture::StateType &S = getState();
5910 auto Assumed = S.getAssumed();
5911 S.intersectAssumedBits(T.getAssumed());
5912 if (!isAssumedNoCaptureMaybeReturned())
5913 return indicatePessimisticFixpoint();
5914 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
5915 : ChangeStatus::CHANGED;
5916}
5917
5918/// NoCapture attribute for function arguments.
5919struct AANoCaptureArgument final : AANoCaptureImpl {
5920 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
5921 : AANoCaptureImpl(IRP, A) {}
5922
5923 /// See AbstractAttribute::trackStatistics()
5924 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture){ static llvm::Statistic NumIRArguments_nocapture = {"attributor"
, "NumIRArguments_nocapture", ("Number of " "arguments" " marked '"
"nocapture" "'")};; ++(NumIRArguments_nocapture); }
}
5925};
5926
5927/// NoCapture attribute for call site arguments.
5928struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
5929 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
5930 : AANoCaptureImpl(IRP, A) {}
5931
5932 /// See AbstractAttribute::initialize(...).
5933 void initialize(Attributor &A) override {
5934 if (Argument *Arg = getAssociatedArgument())
5935 if (Arg->hasByValAttr())
5936 indicateOptimisticFixpoint();
5937 AANoCaptureImpl::initialize(A);
5938 }
5939
5940 /// See AbstractAttribute::updateImpl(...).
5941 ChangeStatus updateImpl(Attributor &A) override {
5942 // TODO: Once we have call site specific value information we can provide
5943 // call site specific liveness information and then it makes
5944 // sense to specialize attributes for call sites arguments instead of
5945 // redirecting requests to the callee argument.
5946 Argument *Arg = getAssociatedArgument();
5947 if (!Arg)
5948 return indicatePessimisticFixpoint();
5949 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5950 auto &ArgAA = A.getAAFor<AANoCapture>(*this, ArgPos, DepClassTy::REQUIRED);
5951 return clampStateAndIndicateChange(getState(), ArgAA.getState());
5952 }
5953
5954 /// See AbstractAttribute::trackStatistics()
5955 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
); }
};
5956};
5957
5958/// NoCapture attribute for floating values.
5959struct AANoCaptureFloating final : AANoCaptureImpl {
5960 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
5961 : AANoCaptureImpl(IRP, A) {}
5962
5963 /// See AbstractAttribute::trackStatistics()
5964 void trackStatistics() const override {
5965 STATS_DECLTRACK_FLOATING_ATTR(nocapture){ static llvm::Statistic NumIRFloating_nocapture = {"attributor"
, "NumIRFloating_nocapture", ("Number of floating values known to be '"
"nocapture" "'")};; ++(NumIRFloating_nocapture); }
5966 }
5967};
5968
5969/// NoCapture attribute for function return value.
5970struct AANoCaptureReturned final : AANoCaptureImpl {
5971 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
5972 : AANoCaptureImpl(IRP, A) {
5973 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", 5973)
;
5974 }
5975
5976 /// See AbstractAttribute::initialize(...).
5977 void initialize(Attributor &A) override {
5978 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", 5978)
;
5979 }
5980
5981 /// See AbstractAttribute::updateImpl(...).
5982 ChangeStatus updateImpl(Attributor &A) override {
5983 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", 5983)
;
5984 }
5985
5986 /// See AbstractAttribute::trackStatistics()
5987 void trackStatistics() const override {}
5988};
5989
5990/// NoCapture attribute deduction for a call site return value.
5991struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
5992 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
5993 : AANoCaptureImpl(IRP, A) {}
5994
5995 /// See AbstractAttribute::initialize(...).
5996 void initialize(Attributor &A) override {
5997 const Function *F = getAnchorScope();
5998 // Check what state the associated function can actually capture.
5999 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
6000 }
6001
6002 /// See AbstractAttribute::trackStatistics()
6003 void trackStatistics() const override {
6004 STATS_DECLTRACK_CSRET_ATTR(nocapture){ static llvm::Statistic NumIRCSReturn_nocapture = {"attributor"
, "NumIRCSReturn_nocapture", ("Number of " "call site returns"
" marked '" "nocapture" "'")};; ++(NumIRCSReturn_nocapture);
}
6005 }
6006};
6007} // namespace
6008
6009/// ------------------ Value Simplify Attribute ----------------------------
6010
6011bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6012 // FIXME: Add a typecast support.
6013 SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
6014 SimplifiedAssociatedValue, Other, Ty);
6015 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6016 return false;
6017
6018 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)
6019 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)
6020 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)
6021 << **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)
6022 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)
6023 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)
6024 })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)
;
6025 return true;
6026}
6027
6028namespace {
6029struct AAValueSimplifyImpl : AAValueSimplify {
6030 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6031 : AAValueSimplify(IRP, A) {}
6032
6033 /// See AbstractAttribute::initialize(...).
6034 void initialize(Attributor &A) override {
6035 if (getAssociatedValue().getType()->isVoidTy())
6036 indicatePessimisticFixpoint();
6037 if (A.hasSimplificationCallback(getIRPosition()))
6038 indicatePessimisticFixpoint();
6039 }
6040
6041 /// See AbstractAttribute::getAsStr().
6042 const std::string getAsStr() const override {
6043 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6044 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6045 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6046 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
6047 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { { dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue
<< " "; if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue
) dbgs() << "SAV: " << **SimplifiedAssociatedValue
<< " "; }; } } while (false)
;
6048 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6049 : "not-simple";
6050 }
6051
6052 /// See AbstractAttribute::trackStatistics()
6053 void trackStatistics() const override {}
6054
6055 /// See AAValueSimplify::getAssumedSimplifiedValue()
6056 std::optional<Value *>
6057 getAssumedSimplifiedValue(Attributor &A) const override {
6058 return SimplifiedAssociatedValue;
6059 }
6060
6061 /// Ensure the return value is \p V with type \p Ty, if not possible return
6062 /// nullptr. If \p Check is true we will only verify such an operation would
6063 /// suceed and return a non-nullptr value if that is the case. No IR is
6064 /// generated or modified.
6065 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6066 bool Check) {
6067 if (auto *TypedV = AA::getWithType(V, Ty))
6068 return TypedV;
6069 if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
6070 return Check ? &V
6071 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(&V, &Ty,
6072 "", CtxI);
6073 return nullptr;
6074 }
6075
6076 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6077 /// If \p Check is true we will only verify such an operation would suceed and
6078 /// return a non-nullptr value if that is the case. No IR is generated or
6079 /// modified.
6080 static Value *reproduceInst(Attributor &A,
6081 const AbstractAttribute &QueryingAA,
6082 Instruction &I, Type &Ty, Instruction *CtxI,
6083 bool Check, ValueToValueMapTy &VMap) {
6084 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", 6084, __extension__
__PRETTY_FUNCTION__))
;
6085 if (Check && (I.mayReadFromMemory() ||
6086 !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
6087 /* TLI */ nullptr)))
6088 return nullptr;
6089 for (Value *Op : I.operands()) {
6090 Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
6091 if (!NewOp) {
6092 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", 6092, __extension__
__PRETTY_FUNCTION__))
;
6093 return nullptr;
6094 }
6095 if (!Check)
6096 VMap[Op] = NewOp;
6097 }
6098 if (Check)
6099 return &I;
6100
6101 Instruction *CloneI = I.clone();
6102 // TODO: Try to salvage debug information here.
6103 CloneI->setDebugLoc(DebugLoc());
6104 VMap[&I] = CloneI;
6105 CloneI->insertBefore(CtxI);
6106 RemapInstruction(CloneI, VMap);
6107 return CloneI;
6108 }
6109
6110 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6111 /// If \p Check is true we will only verify such an operation would suceed and
6112 /// return a non-nullptr value if that is the case. No IR is generated or
6113 /// modified.
6114 static Value *reproduceValue(Attributor &A,
6115 const AbstractAttribute &QueryingAA, Value &V,
6116 Type &Ty, Instruction *CtxI, bool Check,
6117 ValueToValueMapTy &VMap) {
6118 if (const auto &NewV = VMap.lookup(&V))
6119 return NewV;
6120 bool UsedAssumedInformation = false;
6121 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6122 V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6123 if (!SimpleV.has_value())
6124 return PoisonValue::get(&Ty);
6125 Value *EffectiveV = &V;
6126 if (*SimpleV)
6127 EffectiveV = *SimpleV;
6128 if (auto *C = dyn_cast<Constant>(EffectiveV))
6129 return C;
6130 if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
6131 A.getInfoCache()))
6132 return ensureType(A, *EffectiveV, Ty, CtxI, Check);
6133 if (auto *I = dyn_cast<Instruction>(EffectiveV))
6134 if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
6135 return ensureType(A, *NewV, Ty, CtxI, Check);
6136 return nullptr;
6137 }
6138
6139 /// Return a value we can use as replacement for the associated one, or
6140 /// nullptr if we don't have one that makes sense.
6141 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6142 Value *NewV = SimplifiedAssociatedValue
6143 ? *SimplifiedAssociatedValue
6144 : UndefValue::get(getAssociatedType());
6145 if (NewV && NewV != &getAssociatedValue()) {
6146 ValueToValueMapTy VMap;
6147 // First verify we can reprduce the value with the required type at the
6148 // context location before we actually start modifying the IR.
6149 if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6150 /* CheckOnly */ true, VMap))
6151 return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6152 /* CheckOnly */ false, VMap);
6153 }
6154 return nullptr;
6155 }
6156
6157 /// Helper function for querying AAValueSimplify and updating candidate.
6158 /// \param IRP The value position we are trying to unify with SimplifiedValue
6159 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6160 const IRPosition &IRP, bool Simplify = true) {
6161 bool UsedAssumedInformation = false;
6162 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6163 if (Simplify)
6164 QueryingValueSimplified = A.getAssumedSimplified(
6165 IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6166 return unionAssumed(QueryingValueSimplified);
6167 }
6168
6169 /// Returns a candidate is found or not
6170 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6171 if (!getAssociatedValue().getType()->isIntegerTy())
6172 return false;
6173
6174 // This will also pass the call base context.
6175 const auto &AA =
6176 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6177
6178 std::optional<Constant *> COpt = AA.getAssumedConstant(A);
6179
6180 if (!COpt) {
6181 SimplifiedAssociatedValue = std::nullopt;
6182 A.recordDependence(AA, *this, DepClassTy::OPTIONAL);
6183 return true;
6184 }
6185 if (auto *C = *COpt) {
6186 SimplifiedAssociatedValue = C;
6187 A.recordDependence(AA, *this, DepClassTy::OPTIONAL);
6188 return true;
6189 }
6190 return false;
6191 }
6192
6193 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6194 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6195 return true;
6196 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6197 return true;
6198 return false;
6199 }
6200
6201 /// See AbstractAttribute::manifest(...).
6202 ChangeStatus manifest(Attributor &A) override {
6203 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6204 for (auto &U : getAssociatedValue().uses()) {
6205 // Check if we need to adjust the insertion point to make sure the IR is
6206 // valid.
6207 Instruction *IP = dyn_cast<Instruction>(U.getUser());
6208 if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
6209 IP = PHI->getIncomingBlock(U)->getTerminator();
6210 if (auto *NewV = manifestReplacementValue(A, IP)) {
6211 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[ValueSimplify] " <<
getAssociatedValue() << " -> " << *NewV <<
" :: " << *this << "\n"; } } while (false)
6212 << " -> " << *NewV << " :: " << *this << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[ValueSimplify] " <<
getAssociatedValue() << " -> " << *NewV <<
" :: " << *this << "\n"; } } while (false)
;
6213 if (A.changeUseAfterManifest(U, *NewV))
6214 Changed = ChangeStatus::CHANGED;
6215 }
6216 }
6217
6218 return Changed | AAValueSimplify::manifest(A);
6219 }
6220
6221 /// See AbstractState::indicatePessimisticFixpoint(...).
6222 ChangeStatus indicatePessimisticFixpoint() override {
6223 SimplifiedAssociatedValue = &getAssociatedValue();
6224 return AAValueSimplify::indicatePessimisticFixpoint();
6225 }
6226};
6227
6228struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6229 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6230 : AAValueSimplifyImpl(IRP, A) {}
6231
6232 void initialize(Attributor &A) override {
6233 AAValueSimplifyImpl::initialize(A);
6234 if (!getAnchorScope() || getAnchorScope()->isDeclaration())
6235 indicatePessimisticFixpoint();
6236 if (hasAttr({Attribute::InAlloca, Attribute::Preallocated,
6237 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6238 /* IgnoreSubsumingPositions */ true))
6239 indicatePessimisticFixpoint();
6240 }
6241
6242 /// See AbstractAttribute::updateImpl(...).
6243 ChangeStatus updateImpl(Attributor &A) override {
6244 // Byval is only replacable if it is readonly otherwise we would write into
6245 // the replaced value and not the copy that byval creates implicitly.
6246 Argument *Arg = getAssociatedArgument();
6247 if (Arg->hasByValAttr()) {
6248 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6249 // there is no race by not copying a constant byval.
6250 bool IsKnown;
6251 if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
6252 return indicatePessimisticFixpoint();
6253 }
6254
6255 auto Before = SimplifiedAssociatedValue;
6256
6257 auto PredForCallSite = [&](AbstractCallSite ACS) {
6258 const IRPosition &ACSArgPos =
6259 IRPosition::callsite_argument(ACS, getCallSiteArgNo());
6260 // Check if a coresponding argument was found or if it is on not
6261 // associated (which can happen for callback calls).
6262 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6263 return false;
6264
6265 // Simplify the argument operand explicitly and check if the result is
6266 // valid in the current scope. This avoids refering to simplified values
6267 // in other functions, e.g., we don't want to say a an argument in a
6268 // static function is actually an argument in a different function.
6269 bool UsedAssumedInformation = false;
6270 std::optional<Constant *> SimpleArgOp =
6271 A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
6272 if (!SimpleArgOp)
6273 return true;
6274 if (!*SimpleArgOp)
6275 return false;
6276 if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
6277 return false;
6278 return unionAssumed(*SimpleArgOp);
6279 };
6280
6281 // Generate a answer specific to a call site context.
6282 bool Success;
6283 bool UsedAssumedInformation = false;
6284 if (hasCallBaseContext() &&
6285 getCallBaseContext()->getCalledFunction() == Arg->getParent())
6286 Success = PredForCallSite(
6287 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6288 else
6289 Success = A.checkForAllCallSites(PredForCallSite, *this, true,
6290 UsedAssumedInformation);
6291
6292 if (!Success)
6293 if (!askSimplifiedValueForOtherAAs(A))
6294 return indicatePessimisticFixpoint();
6295
6296 // If a candidate was found in this update, return CHANGED.
6297 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6298 : ChangeStatus ::CHANGED;
6299 }
6300
6301 /// See AbstractAttribute::trackStatistics()
6302 void trackStatistics() const override {
6303 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); }
6304 }
6305};
6306
6307struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6308 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6309 : AAValueSimplifyImpl(IRP, A) {}
6310
6311 /// See AAValueSimplify::getAssumedSimplifiedValue()
6312 std::optional<Value *>
6313 getAssumedSimplifiedValue(Attributor &A) const override {
6314 if (!isValidState())
6315 return nullptr;
6316 return SimplifiedAssociatedValue;
6317 }
6318
6319 /// See AbstractAttribute::updateImpl(...).
6320 ChangeStatus updateImpl(Attributor &A) override {
6321 auto Before = SimplifiedAssociatedValue;
6322
6323 auto ReturnInstCB = [&](Instruction &I) {
6324 auto &RI = cast<ReturnInst>(I);
6325 return checkAndUpdate(
6326 A, *this,
6327 IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
6328 };
6329
6330 bool UsedAssumedInformation = false;
6331 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
6332 UsedAssumedInformation))
6333 if (!askSimplifiedValueForOtherAAs(A))
6334 return indicatePessimisticFixpoint();
6335
6336 // If a candidate was found in this update, return CHANGED.
6337 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6338 : ChangeStatus ::CHANGED;
6339 }
6340
6341 ChangeStatus manifest(Attributor &A) override {
6342 // We queried AAValueSimplify for the returned values so they will be
6343 // replaced if a simplified form was found. Nothing to do here.
6344 return ChangeStatus::UNCHANGED;
6345 }
6346
6347 /// See AbstractAttribute::trackStatistics()
6348 void trackStatistics() const override {
6349 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
); }
6350 }
6351};
6352
6353struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6354 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6355 : AAValueSimplifyImpl(IRP, A) {}
6356
6357 /// See AbstractAttribute::initialize(...).
6358 void initialize(Attributor &A) override {
6359 AAValueSimplifyImpl::initialize(A);
6360 Value &V = getAnchorValue();
6361
6362 // TODO: add other stuffs
6363 if (isa<Constant>(V))
6364 indicatePessimisticFixpoint();
6365 }
6366
6367 /// See AbstractAttribute::updateImpl(...).
6368 ChangeStatus updateImpl(Attributor &A) override {
6369 auto Before = SimplifiedAssociatedValue;
6370 if (!askSimplifiedValueForOtherAAs(A))
6371 return indicatePessimisticFixpoint();
6372
6373 // If a candidate was found in this update, return CHANGED.
6374 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6375 : ChangeStatus ::CHANGED;
6376 }
6377
6378 /// See AbstractAttribute::trackStatistics()
6379 void trackStatistics() const override {
6380 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); }
6381 }
6382};
6383
6384struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6385 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6386 : AAValueSimplifyImpl(IRP, A) {}
6387
6388 /// See AbstractAttribute::initialize(...).
6389 void initialize(Attributor &A) override {
6390 SimplifiedAssociatedValue = nullptr;
6391 indicateOptimisticFixpoint();
6392 }
6393 /// See AbstractAttribute::initialize(...).
6394 ChangeStatus updateImpl(Attributor &A) override {
6395 llvm_unreachable(::llvm::llvm_unreachable_internal("AAValueSimplify(Function|CallSite)::updateImpl will not be called"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 6396)
6396 "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", 6396)
;
6397 }
6398 /// See AbstractAttribute::trackStatistics()
6399 void trackStatistics() const override {
6400 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); }
6401 }
6402};
6403
6404struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6405 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6406 : AAValueSimplifyFunction(IRP, A) {}
6407 /// See AbstractAttribute::trackStatistics()
6408 void trackStatistics() const override {
6409 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); }
6410 }
6411};
6412
6413struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6414 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6415 : AAValueSimplifyImpl(IRP, A) {}
6416
6417 void initialize(Attributor &A) override {
6418 AAValueSimplifyImpl::initialize(A);
6419 Function *Fn = getAssociatedFunction();
6420 if (!Fn) {
6421 indicatePessimisticFixpoint();
6422 return;
6423 }
6424 for (Argument &Arg : Fn->args()) {
6425 if (Arg.hasReturnedAttr()) {
6426 auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
6427 Arg.getArgNo());
6428 if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_ARGUMENT &&
6429 checkAndUpdate(A, *this, IRP))
6430 indicateOptimisticFixpoint();
6431 else
6432 indicatePessimisticFixpoint();
6433 return;
6434 }
6435 }
6436 }
6437
6438 /// See AbstractAttribute::updateImpl(...).
6439 ChangeStatus updateImpl(Attributor &A) override {
6440 auto Before = SimplifiedAssociatedValue;
6441 auto &RetAA = A.getAAFor<AAReturnedValues>(
6442 *this, IRPosition::function(*getAssociatedFunction()),
6443 DepClassTy::REQUIRED);
6444 auto PredForReturned =
6445 [&](Value &RetVal, const SmallSetVector<ReturnInst *, 4> &RetInsts) {
6446 bool UsedAssumedInformation = false;
6447 std::optional<Value *> CSRetVal =
6448 A.translateArgumentToCallSiteContent(
6449 &RetVal, *cast<CallBase>(getCtxI()), *this,
6450 UsedAssumedInformation);
6451 SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
6452 SimplifiedAssociatedValue, CSRetVal, getAssociatedType());
6453 return SimplifiedAssociatedValue != std::optional<Value *>(nullptr);
6454 };
6455 if (!RetAA.checkForAllReturnedValuesAndReturnInsts(PredForReturned))
6456 if (!askSimplifiedValueForOtherAAs(A))
6457 return indicatePessimisticFixpoint();
6458 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6459 : ChangeStatus ::CHANGED;
6460 }
6461
6462 void trackStatistics() const override {
6463 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
); }
6464 }
6465};
6466
6467struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6468 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6469 : AAValueSimplifyFloating(IRP, A) {}
6470
6471 /// See AbstractAttribute::manifest(...).
6472 ChangeStatus manifest(Attributor &A) override {
6473 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6474 // TODO: We should avoid simplification duplication to begin with.
6475 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6476 IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
6477 if (FloatAA && FloatAA->getState().isValidState())
6478 return Changed;
6479
6480 if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
6481 Use &U = cast<CallBase>(&getAnchorValue())
6482 ->getArgOperandUse(getCallSiteArgNo());
6483 if (A.changeUseAfterManifest(U, *NewV))
6484 Changed = ChangeStatus::CHANGED;
6485 }
6486
6487 return Changed | AAValueSimplify::manifest(A);
6488 }
6489
6490 void trackStatistics() const override {
6491 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
); }
6492 }
6493};
6494} // namespace
6495
6496/// ----------------------- Heap-To-Stack Conversion ---------------------------
6497namespace {
6498struct AAHeapToStackFunction final : public AAHeapToStack {
6499
6500 struct AllocationInfo {
6501 /// The call that allocates the memory.
6502 CallBase *const CB;
6503
6504 /// The library function id for the allocation.
6505 LibFunc LibraryFunctionId = NotLibFunc;
6506
6507 /// The status wrt. a rewrite.
6508 enum {
6509 STACK_DUE_TO_USE,
6510 STACK_DUE_TO_FREE,
6511 INVALID,
6512 } Status = STACK_DUE_TO_USE;
6513
6514 /// Flag to indicate if we encountered a use that might free this allocation
6515 /// but which is not in the deallocation infos.
6516 bool HasPotentiallyFreeingUnknownUses = false;
6517
6518 /// Flag to indicate that we should place the new alloca in the function
6519 /// entry block rather than where the call site (CB) is.
6520 bool MoveAllocaIntoEntry = true;
6521
6522 /// The set of free calls that use this allocation.
6523 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6524 };
6525
6526 struct DeallocationInfo {
6527 /// The call that deallocates the memory.
6528 CallBase *const CB;
6529 /// The value freed by the call.
6530 Value *FreedOp;
6531
6532 /// Flag to indicate if we don't know all objects this deallocation might
6533 /// free.
6534 bool MightFreeUnknownObjects = false;
6535
6536 /// The set of allocation calls that are potentially freed.
6537 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6538 };
6539
6540 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6541 : AAHeapToStack(IRP, A) {}
6542
6543 ~AAHeapToStackFunction() {
6544 // Ensure we call the destructor so we release any memory allocated in the
6545 // sets.
6546 for (auto &It : AllocationInfos)
6547 It.second->~AllocationInfo();
6548 for (auto &It : DeallocationInfos)
6549 It.second->~DeallocationInfo();
6550 }
6551
6552 void initialize(Attributor &A) override {
6553 AAHeapToStack::initialize(A);
6554
6555 const Function *F = getAnchorScope();
6556 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6557
6558 auto AllocationIdentifierCB = [&](Instruction &I) {
6559 CallBase *CB = dyn_cast<CallBase>(&I);
6560 if (!CB)
6561 return true;
6562 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6563 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
6564 return true;
6565 }
6566 // To do heap to stack, we need to know that the allocation itself is
6567 // removable once uses are rewritten, and that we can initialize the
6568 // alloca to the same pattern as the original allocation result.
6569 if (isRemovableAlloc(CB, TLI)) {
6570 auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
6571 if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
6572 AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
6573 AllocationInfos[CB] = AI;
6574 if (TLI)
6575 TLI->getLibFunc(*CB, AI->LibraryFunctionId);
6576 }
6577 }
6578 return true;
6579 };
6580
6581 bool UsedAssumedInformation = false;
6582 bool Success = A.checkForAllCallLikeInstructions(
6583 AllocationIdentifierCB, *this, UsedAssumedInformation,
6584 /* CheckBBLivenessOnly */ false,
6585 /* CheckPotentiallyDead */ true);
6586 (void)Success;
6587 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", 6587, __extension__
__PRETTY_FUNCTION__))
;
6588
6589 Attributor::SimplifictionCallbackTy SCB =
6590 [](const IRPosition &, const AbstractAttribute *,
6591 bool &) -> std::optional<Value *> { return nullptr; };
6592 for (const auto &It : AllocationInfos)
6593 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6594 SCB);
6595 for (const auto &It : DeallocationInfos)
6596 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6597 SCB);
6598 }
6599
6600 const std::string getAsStr() const override {
6601 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6602 for (const auto &It : AllocationInfos) {
6603 if (It.second->Status == AllocationInfo::INVALID)
6604 ++NumInvalidMallocs;
6605 else
6606 ++NumH2SMallocs;
6607 }
6608 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
6609 std::to_string(NumInvalidMallocs);
6610 }
6611
6612 /// See AbstractAttribute::trackStatistics().
6613 void trackStatistics() const override {
6614 STATS_DECL(static llvm::Statistic NumIRFunction_MallocCalls = {"attributor"
, "NumIRFunction_MallocCalls", "Number of malloc/calloc/aligned_alloc calls converted to allocas"
};;
6615 MallocCalls, Function,static llvm::Statistic NumIRFunction_MallocCalls = {"attributor"
, "NumIRFunction_MallocCalls", "Number of malloc/calloc/aligned_alloc calls converted to allocas"
};;
6616 "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"
};;
;
6617 for (const auto &It : AllocationInfos)
6618 if (It.second->Status != AllocationInfo::INVALID)
6619 ++BUILD_STAT_NAME(MallocCalls, Function)NumIRFunction_MallocCalls;
6620 }
6621
6622 bool isAssumedHeapToStack(const CallBase &CB) const override {
6623 if (isValidState())
6624 if (AllocationInfo *AI =
6625 AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
6626 return AI->Status != AllocationInfo::INVALID;
6627 return false;
6628 }
6629
6630 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6631 if (!isValidState())
6632 return false;
6633
6634 for (const auto &It : AllocationInfos) {
6635 AllocationInfo &AI = *It.second;
6636 if (AI.Status == AllocationInfo::INVALID)
6637 continue;
6638
6639 if (AI.PotentialFreeCalls.count(&CB))
6640 return true;
6641 }
6642
6643 return false;
6644 }
6645
6646 ChangeStatus manifest(Attributor &A) override {
6647 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", 6648, __extension__
__PRETTY_FUNCTION__))
6648 "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", 6648, __extension__
__PRETTY_FUNCTION__))
;
6649
6650 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6651 Function *F = getAnchorScope();
6652 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6653
6654 for (auto &It : AllocationInfos) {
6655 AllocationInfo &AI = *It.second;
6656 if (AI.Status == AllocationInfo::INVALID)
6657 continue;
6658
6659 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6660 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)
;
6661 A.deleteAfterManifest(*FreeCall);
6662 HasChanged = ChangeStatus::CHANGED;
6663 }
6664
6665 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)
6666 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "H2S: Removing malloc-like call: "
<< *AI.CB << "\n"; } } while (false)
;
6667
6668 auto Remark = [&](OptimizationRemark OR) {
6669 LibFunc IsAllocShared;
6670 if (TLI->getLibFunc(*AI.CB, IsAllocShared))
6671 if (IsAllocShared == LibFunc___kmpc_alloc_shared)
6672 return OR << "Moving globalized variable to the stack.";
6673 return OR << "Moving memory allocation from the heap to the stack.";
6674 };
6675 if (AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
6676 A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
6677 else
6678 A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);
6679
6680 const DataLayout &DL = A.getInfoCache().getDL();
6681 Value *Size;
6682 std::optional<APInt> SizeAPI = getSize(A, *this, AI);
6683 if (SizeAPI) {
6684 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6685 } else {
6686 LLVMContext &Ctx = AI.CB->getContext();
6687 ObjectSizeOpts Opts;
6688 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts);
6689 SizeOffsetEvalType SizeOffsetPair = Eval.compute(AI.CB);
6690 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", 6691, __extension__
__PRETTY_FUNCTION__))
6691 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", 6691, __extension__
__PRETTY_FUNCTION__))
;
6692 Size = SizeOffsetPair.first;
6693 }
6694
6695 Instruction *IP =
6696 AI.MoveAllocaIntoEntry ? &F->getEntryBlock().front() : AI.CB;
6697
6698 Align Alignment(1);
6699 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6700 Alignment = std::max(Alignment, *RetAlign);
6701 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
6702 std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
6703 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", 6704, __extension__
__PRETTY_FUNCTION__))
6704 "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", 6704, __extension__
__PRETTY_FUNCTION__))
;
6705 Alignment =
6706 std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
6707 }
6708
6709 // TODO: Hoist the alloca towards the function entry.
6710 unsigned AS = DL.getAllocaAddrSpace();
6711 Instruction *Alloca =
6712 new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
6713 AI.CB->getName() + ".h2s", IP);
6714
6715 if (Alloca->getType() != AI.CB->getType())
6716 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6717 Alloca, AI.CB->getType(), "malloc_cast", AI.CB);
6718
6719 auto *I8Ty = Type::getInt8Ty(F->getContext());
6720 auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
6721 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", 6722, __extension__
__PRETTY_FUNCTION__))
6722 "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", 6722, __extension__
__PRETTY_FUNCTION__))
;
6723
6724 A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);
6725
6726 if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
6727 auto *NBB = II->getNormalDest();
6728 BranchInst::Create(NBB, AI.CB->getParent());
6729 A.deleteAfterManifest(*AI.CB);
6730 } else {
6731 A.deleteAfterManifest(*AI.CB);
6732 }
6733
6734 // Initialize the alloca with the same value as used by the allocation
6735 // function. We can skip undef as the initial value of an alloc is
6736 // undef, and the memset would simply end up being DSEd.
6737 if (!isa<UndefValue>(InitVal)) {
6738 IRBuilder<> Builder(Alloca->getNextNode());
6739 // TODO: Use alignment above if align!=1
6740 Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
6741 }
6742 HasChanged = ChangeStatus::CHANGED;
6743 }
6744
6745 return HasChanged;
6746 }
6747
6748 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
6749 Value &V) {
6750 bool UsedAssumedInformation = false;
6751 std::optional<Constant *> SimpleV =
6752 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6753 if (!SimpleV)
6754 return APInt(64, 0);
6755 if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
6756 return CI->getValue();
6757 return std::nullopt;
6758 }
6759
6760 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
6761 AllocationInfo &AI) {
6762 auto Mapper = [&](const Value *V) -> const Value * {
6763 bool UsedAssumedInformation = false;
6764 if (std::optional<Constant *> SimpleV =
6765 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6766 if (*SimpleV)
6767 return *SimpleV;
6768 return V;
6769 };
6770
6771 const Function *F = getAnchorScope();
6772 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6773 return getAllocSize(AI.CB, TLI, Mapper);
6774 }
6775
6776 /// Collection of all malloc-like calls in a function with associated
6777 /// information.
6778 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6779
6780 /// Collection of all free-like calls in a function with associated
6781 /// information.
6782 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6783
6784 ChangeStatus updateImpl(Attributor &A) override;
6785};
6786
6787ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
6788 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6789 const Function *F = getAnchorScope();
6790 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6791
6792 const auto &LivenessAA =
6793 A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);
6794
6795 MustBeExecutedContextExplorer &Explorer =
6796 A.getInfoCache().getMustBeExecutedContextExplorer();
6797
6798 bool StackIsAccessibleByOtherThreads =
6799 A.getInfoCache().stackIsAccessibleByOtherThreads();
6800
6801 LoopInfo *LI =
6802 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6803 std::optional<bool> MayContainIrreducibleControl;
6804 auto IsInLoop = [&](BasicBlock &BB) {
6805 if (&F->getEntryBlock() == &BB)
6806 return false;
6807 if (!MayContainIrreducibleControl.has_value())
6808 MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
6809 if (*MayContainIrreducibleControl)
6810 return true;
6811 if (!LI)
6812 return true;
6813 return LI->getLoopFor(&BB) != nullptr;
6814 };
6815
6816 // Flag to ensure we update our deallocation information at most once per
6817 // updateImpl call and only if we use the free check reasoning.
6818 bool HasUpdatedFrees = false;
6819
6820 auto UpdateFrees = [&]() {
6821 HasUpdatedFrees = true;
6822
6823 for (auto &It : DeallocationInfos) {
6824 DeallocationInfo &DI = *It.second;
6825 // For now we cannot use deallocations that have unknown inputs, skip
6826 // them.
6827 if (DI.MightFreeUnknownObjects)
6828 continue;
6829
6830 // No need to analyze dead calls, ignore them instead.
6831 bool UsedAssumedInformation = false;
6832 if (A.isAssumedDead(*DI.CB, this, &LivenessAA, UsedAssumedInformation,
6833 /* CheckBBLivenessOnly */ true))
6834 continue;
6835
6836 // Use the non-optimistic version to get the freed object.
6837 Value *Obj = getUnderlyingObject(DI.FreedOp);
6838 if (!Obj) {
6839 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)
;
6840 DI.MightFreeUnknownObjects = true;
6841 continue;
6842 }
6843
6844 // Free of null and undef can be ignored as no-ops (or UB in the latter
6845 // case).
6846 if (isa<ConstantPointerNull>(Obj) || isa<UndefValue>(Obj))
6847 continue;
6848
6849 CallBase *ObjCB = dyn_cast<CallBase>(Obj);
6850 if (!ObjCB) {
6851 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)
6852 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Free of a non-call object: "
<< *Obj << "\n"; } } while (false)
;
6853 DI.MightFreeUnknownObjects = true;
6854 continue;
6855 }
6856
6857 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
6858 if (!AI) {
6859 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)
6860 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Free of a non-allocation object: "
<< *Obj << "\n"; } } while (false)
;
6861 DI.MightFreeUnknownObjects = true;
6862 continue;
6863 }
6864
6865 DI.PotentialAllocationCalls.insert(ObjCB);
6866 }
6867 };
6868
6869 auto FreeCheck = [&](AllocationInfo &AI) {
6870 // If the stack is not accessible by other threads, the "must-free" logic
6871 // doesn't apply as the pointer could be shared and needs to be places in
6872 // "shareable" memory.
6873 if (!StackIsAccessibleByOtherThreads) {
6874 auto &NoSyncAA =
6875 A.getAAFor<AANoSync>(*this, getIRPosition(), DepClassTy::OPTIONAL);
6876 if (!NoSyncAA.isAssumedNoSync()) {
6877 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
)
6878 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
)
6879 "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
)
;
6880 return false;
6881 }
6882 }
6883 if (!HasUpdatedFrees)
6884 UpdateFrees();
6885
6886 // TODO: Allow multi exit functions that have different free calls.
6887 if (AI.PotentialFreeCalls.size() != 1) {
6888 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)
6889 << 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)
;
6890 return false;
6891 }
6892 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
6893 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
6894 if (!DI) {
6895 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call was not known as deallocation call "
<< *UniqueFree << "\n"; } } while (false)
6896 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)
6897 << *UniqueFree << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call was not known as deallocation call "
<< *UniqueFree << "\n"; } } while (false)
;
6898 return false;
6899 }
6900 if (DI->MightFreeUnknownObjects) {
6901 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might free unknown allocations\n"
; } } while (false)
6902 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)
;
6903 return false;
6904 }
6905 if (DI->PotentialAllocationCalls.empty())
6906 return true;
6907 if (DI->PotentialAllocationCalls.size() > 1) {
6908 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)
6909 << 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)
6910 << " 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)
;
6911 return false;
6912 }
6913 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
6914 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)
6915 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)
6916 << "[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)
6917 << **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)
;
6918 return false;
6919 }
6920 Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
6921 if (!Explorer.findInContextOf(UniqueFree, CtxI)) {
6922 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)
6923 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] unique free call might not be executed with the allocation "
<< *UniqueFree << "\n"; } } while (false)
6924 << "[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)
6925 << *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)
;
6926 return false;
6927 }
6928 return true;
6929 };
6930
6931 auto UsesCheck = [&](AllocationInfo &AI) {
6932 bool ValidUsesOnly = true;
6933
6934 auto Pred = [&](const Use &U, bool &Follow) -> bool {
6935 Instruction *UserI = cast<Instruction>(U.getUser());
6936 if (isa<LoadInst>(UserI))
6937 return true;
6938 if (auto *SI = dyn_cast<StoreInst>(UserI)) {
6939 if (SI->getValueOperand() == U.get()) {
6940 LLVM_DEBUG(dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] escaping store to memory: "
<< *UserI << "\n"; } } while (false)
6941 << "[H2S] escaping store to memory: " << *UserI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] escaping store to memory: "
<< *UserI << "\n"; } } while (false)
;
6942 ValidUsesOnly = false;
6943 } else {
6944 // A store into the malloc'ed memory is fine.
6945 }
6946 return true;
6947 }
6948 if (auto *CB = dyn_cast<CallBase>(UserI)) {
6949 if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
6950 return true;
6951 if (DeallocationInfos.count(CB)) {
6952 AI.PotentialFreeCalls.insert(CB);
6953 return true;
6954 }
6955
6956 unsigned ArgNo = CB->getArgOperandNo(&U);
6957
6958 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
6959 *this, IRPosition::callsite_argument(*CB, ArgNo),
6960 DepClassTy::OPTIONAL);
6961
6962 // If a call site argument use is nofree, we are fine.
6963 const auto &ArgNoFreeAA = A.getAAFor<AANoFree>(
6964 *this, IRPosition::callsite_argument(*CB, ArgNo),
6965 DepClassTy::OPTIONAL);
6966
6967 bool MaybeCaptured = !NoCaptureAA.isAssumedNoCapture();
6968 bool MaybeFreed = !ArgNoFreeAA.isAssumedNoFree();
6969 if (MaybeCaptured ||
6970 (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
6971 MaybeFreed)) {
6972 AI.HasPotentiallyFreeingUnknownUses |= MaybeFreed;
6973
6974 // Emit a missed remark if this is missed OpenMP globalization.
6975 auto Remark = [&](OptimizationRemarkMissed ORM) {
6976 return ORM
6977 << "Could not move globalized variable to the stack. "
6978 "Variable is potentially captured in call. Mark "
6979 "parameter as `__attribute__((noescape))` to override.";
6980 };
6981
6982 if (ValidUsesOnly &&
6983 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
6984 A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);
6985
6986 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Bad user: " <<
*UserI << "\n"; } } while (false)
;
6987 ValidUsesOnly = false;
6988 }
6989 return true;
6990 }
6991
6992 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
6993 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
6994 Follow = true;
6995 return true;
6996 }
6997 // Unknown user for which we can not track uses further (in a way that
6998 // makes sense).
6999 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Unknown user: " <<
*UserI << "\n"; } } while (false)
;
7000 ValidUsesOnly = false;
7001 return true;
7002 };
7003 if (!A.checkForAllUses(Pred, *this, *AI.CB))
7004 return false;
7005 return ValidUsesOnly;
7006 };
7007
7008 // The actual update starts here. We look at all allocations and depending on
7009 // their status perform the appropriate check(s).
7010 for (auto &It : AllocationInfos) {
7011 AllocationInfo &AI = *It.second;
7012 if (AI.Status == AllocationInfo::INVALID)
7013 continue;
7014
7015 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
7016 std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
7017 if (!APAlign) {
7018 // Can't generate an alloca which respects the required alignment
7019 // on the allocation.
7020 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)
7021 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Unknown allocation alignment: "
<< *AI.CB << "\n"; } } while (false)
;
7022 AI.Status = AllocationInfo::INVALID;
7023 Changed = ChangeStatus::CHANGED;
7024 continue;
7025 }
7026 if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
7027 !APAlign->isPowerOf2()) {
7028 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAligndo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Invalid allocation alignment: "
<< APAlign << "\n"; } } while (false)
7029 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[H2S] Invalid allocation alignment: "
<< APAlign << "\n"; } } while (false)
;
7030 AI.Status = AllocationInfo::INVALID;
7031 Changed = ChangeStatus::CHANGED;
7032 continue;
7033 }
7034 }
7035
7036 std::optional<APInt> Size = getSize(A, *this, AI);
7037 if (MaxHeapToStackSize != -1) {
7038 if (!Size || Size->ugt(MaxHeapToStackSize)) {
7039 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)
7040 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)
7041 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)
7042 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)
7043 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)
7044 << 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)
7045 })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)
;
7046
7047 AI.Status = AllocationInfo::INVALID;
7048 Changed = ChangeStatus::CHANGED;
7049 continue;
7050 }
7051 }
7052
7053 switch (AI.Status) {
7054 case AllocationInfo::STACK_DUE_TO_USE:
7055 if (UsesCheck(AI))
7056 break;
7057 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7058 [[fallthrough]];
7059 case AllocationInfo::STACK_DUE_TO_FREE:
7060 if (FreeCheck(AI))
7061 break;
7062 AI.Status = AllocationInfo::INVALID;
7063 Changed = ChangeStatus::CHANGED;
7064 break;
7065 case AllocationInfo::INVALID:
7066 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", 7066)
;
7067 };
7068
7069 // Check if we still think we can move it into the entry block. If the
7070 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7071 // ignore the potential compilations associated with loops.
7072 bool IsGlobalizedLocal =
7073 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared;
7074 if (AI.MoveAllocaIntoEntry &&
7075 (!Size.has_value() ||
7076 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7077 AI.MoveAllocaIntoEntry = false;
7078 }
7079
7080 return Changed;
7081}
7082} // namespace
7083
7084/// ----------------------- Privatizable Pointers ------------------------------
7085namespace {
7086struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
7087 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7088 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7089
7090 ChangeStatus indicatePessimisticFixpoint() override {
7091 AAPrivatizablePtr::indicatePessimisticFixpoint();
7092 PrivatizableType = nullptr;
7093 return ChangeStatus::CHANGED;
7094 }
7095
7096 /// Identify the type we can chose for a private copy of the underlying
7097 /// argument. None means it is not clear yet, nullptr means there is none.
7098 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7099
7100 /// Return a privatizable type that encloses both T0 and T1.
7101 /// TODO: This is merely a stub for now as we should manage a mapping as well.
7102 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7103 std::optional<Type *> T1) {
7104 if (!T0)
7105 return T1;
7106 if (!T1)
7107 return T0;
7108 if (T0 == T1)
7109 return T0;
7110 return nullptr;
7111 }
7112
7113 std::optional<Type *> getPrivatizableType() const override {
7114 return PrivatizableType;
7115 }
7116
7117 const std::string getAsStr() const override {
7118 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7119 }
7120
7121protected:
7122 std::optional<Type *> PrivatizableType;
7123};
7124
7125// TODO: Do this for call site arguments (probably also other values) as well.
7126
7127struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
7128 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7129 : AAPrivatizablePtrImpl(IRP, A) {}
7130
7131 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7132 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7133 // If this is a byval argument and we know all the call sites (so we can
7134 // rewrite them), there is no need to check them explicitly.
7135 bool UsedAssumedInformation = false;
7136 SmallVector<Attribute, 1> Attrs;
7137 getAttrs({Attribute::ByVal}, Attrs, /* IgnoreSubsumingPositions */ true);
7138 if (!Attrs.empty() &&
7139 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
7140 true, UsedAssumedInformation))
7141 return Attrs[0].getValueAsType();
7142
7143 std::optional<Type *> Ty;
7144 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7145
7146 // Make sure the associated call site argument has the same type at all call
7147 // sites and it is an allocation we know is safe to privatize, for now that
7148 // means we only allow alloca instructions.
7149 // TODO: We can additionally analyze the accesses in the callee to create
7150 // the type from that information instead. That is a little more
7151 // involved and will be done in a follow up patch.
7152 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7153 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7154 // Check if a coresponding argument was found or if it is one not
7155 // associated (which can happen for callback calls).
7156 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7157 return false;
7158
7159 // Check that all call sites agree on a type.
7160 auto &PrivCSArgAA =
7161 A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
7162 std::optional<Type *> CSTy = PrivCSArgAA.getPrivatizableType();
7163
7164 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)
7165 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)
7166 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)
7167 (*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)
7168 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)
7169 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)
7170 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)
7171 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)
7172 })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)
;
7173
7174 Ty = combineTypes(Ty, CSTy);
7175
7176 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)
7177 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)
7178 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)
7179 (*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)
7180 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)
7181 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)
7182 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)
7183 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)
7184 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)
7185 })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)
;
7186
7187 return !Ty || *Ty;
7188 };
7189
7190 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7191 UsedAssumedInformation))
7192 return nullptr;
7193 return Ty;
7194 }
7195
7196 /// See AbstractAttribute::updateImpl(...).
7197 ChangeStatus updateImpl(Attributor &A) override {
7198 PrivatizableType = identifyPrivatizableType(A);
7199 if (!PrivatizableType)
7200 return ChangeStatus::UNCHANGED;
7201 if (!*PrivatizableType)
7202 return indicatePessimisticFixpoint();
7203
7204 // The dependence is optional so we don't give up once we give up on the
7205 // alignment.
7206 A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
7207 DepClassTy::OPTIONAL);
7208
7209 // Avoid arguments with padding for now.
7210 if (!getIRPosition().hasAttr(Attribute::ByVal) &&
7211 !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
7212 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Padding detected\n"
; } } while (false)
;
7213 return indicatePessimisticFixpoint();
7214 }
7215
7216 // Collect the types that will replace the privatizable type in the function
7217 // signature.
7218 SmallVector<Type *, 16> ReplacementTypes;
7219 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7220
7221 // Verify callee and caller agree on how the promoted argument would be
7222 // passed.
7223 Function &Fn = *getIRPosition().getAnchorScope();
7224 const auto *TTI =
7225 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7226 if (!TTI) {
7227 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)
7228 << Fn.getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
<< Fn.getName() << "\n"; } } while (false)
;
7229 return indicatePessimisticFixpoint();
7230 }
7231
7232 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7233 CallBase *CB = ACS.getInstruction();
7234 return TTI->areTypesABICompatible(
7235 CB->getCaller(), CB->getCalledFunction(), ReplacementTypes);
7236 };
7237 bool UsedAssumedInformation = false;
7238 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7239 UsedAssumedInformation)) {
7240 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
<< Fn.getName() << "\n"; } } while (false)
7241 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
<< Fn.getName() << "\n"; } } while (false)
7242 << Fn.getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
<< Fn.getName() << "\n"; } } while (false)
;
7243 return indicatePessimisticFixpoint();
7244 }
7245
7246 // Register a rewrite of the argument.
7247 Argument *Arg = getAssociatedArgument();
7248 if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7249 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n"
; } } while (false)
;
7250 return indicatePessimisticFixpoint();
7251 }
7252
7253 unsigned ArgNo = Arg->getArgNo();
7254
7255 // Helper to check if for the given call site the associated argument is
7256 // passed to a callback where the privatization would be different.
7257 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7258 SmallVector<const Use *, 4> CallbackUses;
7259 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7260 for (const Use *U : CallbackUses) {
7261 AbstractCallSite CBACS(U);
7262 assert(CBACS && CBACS.isCallbackCall())(static_cast <bool> (CBACS && CBACS.isCallbackCall
()) ? void (0) : __assert_fail ("CBACS && CBACS.isCallbackCall()"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 7262, __extension__
__PRETTY_FUNCTION__))
;
7263 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7264 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7265
7266 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)
7267 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)
7268 << "[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)
7269 << "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)
7270 << 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)
7271 << ")\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)
7272 "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)
7273 << 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)
7274 << ")\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)
7275 << 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)
7276 << 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)
7277 << "[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)
7278 << 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)
7279 })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)
;
7280
7281 if (CBArgNo != int(ArgNo))
7282 continue;
7283 const auto &CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7284 *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
7285 if (CBArgPrivAA.isValidState()) {
7286 auto CBArgPrivTy = CBArgPrivAA.getPrivatizableType();
7287 if (!CBArgPrivTy)
7288 continue;
7289 if (*CBArgPrivTy == PrivatizableType)
7290 continue;
7291 }
7292
7293 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)
7294 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)
7295 << " 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)
7296 << 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)
7297 << ")\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)
7298 "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)
7299 << 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)
7300 << ").\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)
7301 "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)
7302 })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)
;
7303 return false;
7304 }
7305 }
7306 return true;
7307 };
7308
7309 // Helper to check if for the given call site the associated argument is
7310 // passed to a direct call where the privatization would be different.
7311 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7312 CallBase *DC = cast<CallBase>(ACS.getInstruction());
7313 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7314 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", 7315, __extension__
__PRETTY_FUNCTION__))
7315 "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", 7315, __extension__
__PRETTY_FUNCTION__))
;
7316
7317 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)
7318 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)
7319 << " 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)
7320 << 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)
7321 << ")\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)
7322 "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)
7323 << 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)
7324 << ").\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)
7325 })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)
;
7326
7327 Function *DCCallee = DC->getCalledFunction();
7328 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7329 const auto &DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7330 *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
7331 DepClassTy::REQUIRED);
7332 if (DCArgPrivAA.isValidState()) {
7333 auto DCArgPrivTy = DCArgPrivAA.getPrivatizableType();
7334 if (!DCArgPrivTy)
7335 return true;
7336 if (*DCArgPrivTy == PrivatizableType)
7337 return true;
7338 }
7339 }
7340
7341 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)
7342 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)
7343 << " 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)
7344 << 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)
7345 << ")\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)
7346 "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)
7347 << 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)
7348 << ").\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)
7349 "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)
7350 })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)
;
7351 return false;
7352 };
7353
7354 // Helper to check if the associated argument is used at the given abstract
7355 // call site in a way that is incompatible with the privatization assumed
7356 // here.
7357 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7358 if (ACS.isDirectCall())
7359 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7360 if (ACS.isCallbackCall())
7361 return IsCompatiblePrivArgOfDirectCS(ACS);
7362 return false;
7363 };
7364
7365 if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
7366 UsedAssumedInformation))
7367 return indicatePessimisticFixpoint();
7368
7369 return ChangeStatus::UNCHANGED;
7370 }
7371
7372 /// Given a type to private \p PrivType, collect the constituates (which are
7373 /// used) in \p ReplacementTypes.
7374 static void
7375 identifyReplacementTypes(Type *PrivType,
7376 SmallVectorImpl<Type *> &ReplacementTypes) {
7377 // TODO: For now we expand the privatization type to the fullest which can
7378 // lead to dead arguments that need to be removed later.
7379 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", 7379, __extension__
__PRETTY_FUNCTION__))
;
7380
7381 // Traverse the type, extract constituate types on the outermost level.
7382 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7383 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7384 ReplacementTypes.push_back(PrivStructType->getElementType(u));
7385 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7386 ReplacementTypes.append(PrivArrayType->getNumElements(),
7387 PrivArrayType->getElementType());
7388 } else {
7389 ReplacementTypes.push_back(PrivType);
7390 }
7391 }
7392
7393 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7394 /// The values needed are taken from the arguments of \p F starting at
7395 /// position \p ArgNo.
7396 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7397 unsigned ArgNo, Instruction &IP) {
7398 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", 7398, __extension__
__PRETTY_FUNCTION__))
;
7399
7400 IRBuilder<NoFolder> IRB(&IP);
7401 const DataLayout &DL = F.getParent()->getDataLayout();
7402
7403 // Traverse the type, build GEPs and stores.
7404 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7405 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7406 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7407 Type *PointeeTy = PrivStructType->getElementType(u)->getPointerTo();
7408 Value *Ptr =
7409 constructPointer(PointeeTy, PrivType, &Base,
7410 PrivStructLayout->getElementOffset(u), IRB, DL);
7411 new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
7412 }
7413 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7414 Type *PointeeTy = PrivArrayType->getElementType();
7415 Type *PointeePtrTy = PointeeTy->getPointerTo();
7416 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7417 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7418 Value *Ptr = constructPointer(PointeePtrTy, PrivType, &Base,
7419 u * PointeeTySize, IRB, DL);
7420 new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
7421 }
7422 } else {
7423 new StoreInst(F.getArg(ArgNo), &Base, &IP);
7424 }
7425 }
7426
7427 /// Extract values from \p Base according to the type \p PrivType at the
7428 /// call position \p ACS. The values are appended to \p ReplacementValues.
7429 void createReplacementValues(Align Alignment, Type *PrivType,
7430 AbstractCallSite ACS, Value *Base,
7431 SmallVectorImpl<Value *> &ReplacementValues) {
7432 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", 7432, __extension__
__PRETTY_FUNCTION__))
;
7433 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", 7433, __extension__
__PRETTY_FUNCTION__))
;
7434 Instruction *IP = ACS.getInstruction();
7435
7436 IRBuilder<NoFolder> IRB(IP);
7437 const DataLayout &DL = IP->getModule()->getDataLayout();
7438
7439 Type *PrivPtrType = PrivType->getPointerTo();
7440 if (Base->getType() != PrivPtrType)
7441 Base = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7442 Base, PrivPtrType, "", ACS.getInstruction());
7443
7444 // Traverse the type, build GEPs and loads.
7445 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7446 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7447 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7448 Type *PointeeTy = PrivStructType->getElementType(u);
7449 Value *Ptr =
7450 constructPointer(PointeeTy->getPointerTo(), PrivType, Base,
7451 PrivStructLayout->getElementOffset(u), IRB, DL);
7452 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
7453 L->setAlignment(Alignment);
7454 ReplacementValues.push_back(L);
7455 }
7456 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7457 Type *PointeeTy = PrivArrayType->getElementType();
7458 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7459 Type *PointeePtrTy = PointeeTy->getPointerTo();
7460 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7461 Value *Ptr = constructPointer(PointeePtrTy, PrivType, Base,
7462 u * PointeeTySize, IRB, DL);
7463 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
7464 L->setAlignment(Alignment);
7465 ReplacementValues.push_back(L);
7466 }
7467 } else {
7468 LoadInst *L = new LoadInst(PrivType, Base, "", IP);
7469 L->setAlignment(Alignment);
7470 ReplacementValues.push_back(L);
7471 }
7472 }
7473
7474 /// See AbstractAttribute::manifest(...)
7475 ChangeStatus manifest(Attributor &A) override {
7476 if (!PrivatizableType)
7477 return ChangeStatus::UNCHANGED;
7478 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", 7478, __extension__
__PRETTY_FUNCTION__))
;
7479
7480 // Collect all tail calls in the function as we cannot allow new allocas to
7481 // escape into tail recursion.
7482 // TODO: Be smarter about new allocas escaping into tail calls.
7483 SmallVector<CallInst *, 16> TailCalls;
7484 bool UsedAssumedInformation = false;
7485 if (!A.checkForAllInstructions(
7486 [&](Instruction &I) {
7487 CallInst &CI = cast<CallInst>(I);
7488 if (CI.isTailCall())
7489 TailCalls.push_back(&CI);
7490 return true;
7491 },
7492 *this, {Instruction::Call}, UsedAssumedInformation))
7493 return ChangeStatus::UNCHANGED;
7494
7495 Argument *Arg = getAssociatedArgument();
7496 // Query AAAlign attribute for alignment of associated argument to
7497 // determine the best alignment of loads.
7498 const auto &AlignAA =
7499 A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
7500
7501 // Callback to repair the associated function. A new alloca is placed at the
7502 // beginning and initialized with the values passed through arguments. The
7503 // new alloca replaces the use of the old pointer argument.
7504 Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB =
7505 [=](const Attributor::ArgumentReplacementInfo &ARI,
7506 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7507 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7508 Instruction *IP = &*EntryBB.getFirstInsertionPt();
7509 const DataLayout &DL = IP->getModule()->getDataLayout();
7510 unsigned AS = DL.getAllocaAddrSpace();
7511 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7512 Arg->getName() + ".priv", IP);
7513 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7514 ArgIt->getArgNo(), *IP);
7515
7516 if (AI->getType() != Arg->getType())
7517 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7518 AI, Arg->getType(), "", IP);
7519 Arg->replaceAllUsesWith(AI);
7520
7521 for (CallInst *CI : TailCalls)
7522 CI->setTailCall(false);
7523 };
7524
7525 // Callback to repair a call site of the associated function. The elements
7526 // of the privatizable type are loaded prior to the call and passed to the
7527 // new function version.
7528 Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB =
7529 [=, &AlignAA](const Attributor::ArgumentReplacementInfo &ARI,
7530 AbstractCallSite ACS,
7531 SmallVectorImpl<Value *> &NewArgOperands) {
7532 // When no alignment is specified for the load instruction,
7533 // natural alignment is assumed.
7534 createReplacementValues(
7535 AlignAA.getAssumedAlign(), *PrivatizableType, ACS,
7536 ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
7537 NewArgOperands);
7538 };
7539
7540 // Collect the types that will replace the privatizable type in the function
7541 // signature.
7542 SmallVector<Type *, 16> ReplacementTypes;
7543 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7544
7545 // Register a rewrite of the argument.
7546 if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7547 std::move(FnRepairCB),
7548 std::move(ACSRepairCB)))
7549 return ChangeStatus::CHANGED;
7550 return ChangeStatus::UNCHANGED;
7551 }
7552
7553 /// See AbstractAttribute::trackStatistics()
7554 void trackStatistics() const override {
7555 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
); }
;
7556 }
7557};
7558
7559struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
7560 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7561 : AAPrivatizablePtrImpl(IRP, A) {}
7562
7563 /// See AbstractAttribute::initialize(...).
7564 void initialize(Attributor &A) override {
7565 // TODO: We can privatize more than arguments.
7566 indicatePessimisticFixpoint();
7567 }
7568
7569 ChangeStatus updateImpl(Attributor &A) override {
7570 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"
, 7571)
7571 "updateImpl will not be called")::llvm::llvm_unreachable_internal("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
"updateImpl will not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7571)
;
7572 }
7573
7574 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7575 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7576 Value *Obj = getUnderlyingObject(&getAssociatedValue());
7577 if (!Obj) {
7578 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)
;
7579 return nullptr;
7580 }
7581
7582 if (auto *AI = dyn_cast<AllocaInst>(Obj))
7583 if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
7584 if (CI->isOne())
7585 return AI->getAllocatedType();
7586 if (auto *Arg = dyn_cast<Argument>(Obj)) {
7587 auto &PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7588 *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
7589 if (PrivArgAA.isAssumedPrivatizablePtr())
7590 return PrivArgAA.getPrivatizableType();
7591 }
7592
7593 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)
7594 "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)
7595 << *Obj << "!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
"alloca nor privatizable argument: " << *Obj << "!\n"
; } } while (false)
;
7596 return nullptr;
7597 }
7598
7599 /// See AbstractAttribute::trackStatistics()
7600 void trackStatistics() const override {
7601 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
); }
;
7602 }
7603};
7604
7605struct AAPrivatizablePtrCallSiteArgument final
7606 : public AAPrivatizablePtrFloating {
7607 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7608 : AAPrivatizablePtrFloating(IRP, A) {}
7609
7610 /// See AbstractAttribute::initialize(...).
7611 void initialize(Attributor &A) override {
7612 if (getIRPosition().hasAttr(Attribute::ByVal))
7613 indicateOptimisticFixpoint();
7614 }
7615
7616 /// See AbstractAttribute::updateImpl(...).
7617 ChangeStatus updateImpl(Attributor &A) override {
7618 PrivatizableType = identifyPrivatizableType(A);
7619 if (!PrivatizableType)
7620 return ChangeStatus::UNCHANGED;
7621 if (!*PrivatizableType)
7622 return indicatePessimisticFixpoint();
7623
7624 const IRPosition &IRP = getIRPosition();
7625 auto &NoCaptureAA =
7626 A.getAAFor<AANoCapture>(*this, IRP, DepClassTy::REQUIRED);
7627 if (!NoCaptureAA.isAssumedNoCapture()) {
7628 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)
;
7629 return indicatePessimisticFixpoint();
7630 }
7631
7632 auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, IRP, DepClassTy::REQUIRED);
7633 if (!NoAliasAA.isAssumedNoAlias()) {
7634 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] pointer might alias!\n"
; } } while (false)
;
7635 return indicatePessimisticFixpoint();
7636 }
7637
7638 bool IsKnown;
7639 if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
7640 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPrivatizablePtr] pointer is written!\n"
; } } while (false)
;
7641 return indicatePessimisticFixpoint();
7642 }
7643
7644 return ChangeStatus::UNCHANGED;
7645 }
7646
7647 /// See AbstractAttribute::trackStatistics()
7648 void trackStatistics() const override {
7649 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); }
;
7650 }
7651};
7652
7653struct AAPrivatizablePtrCallSiteReturned final
7654 : public AAPrivatizablePtrFloating {
7655 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7656 : AAPrivatizablePtrFloating(IRP, A) {}
7657
7658 /// See AbstractAttribute::initialize(...).
7659 void initialize(Attributor &A) override {
7660 // TODO: We can privatize more than arguments.
7661 indicatePessimisticFixpoint();
7662 }
7663
7664 /// See AbstractAttribute::trackStatistics()
7665 void trackStatistics() const override {
7666 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
); }
;
7667 }
7668};
7669
7670struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
7671 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7672 : AAPrivatizablePtrFloating(IRP, A) {}
7673
7674 /// See AbstractAttribute::initialize(...).
7675 void initialize(Attributor &A) override {
7676 // TODO: We can privatize more than arguments.
7677 indicatePessimisticFixpoint();
7678 }
7679
7680 /// See AbstractAttribute::trackStatistics()
7681 void trackStatistics() const override {
7682 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); }
;
7683 }
7684};
7685} // namespace
7686
7687/// -------------------- Memory Behavior Attributes ----------------------------
7688/// Includes read-none, read-only, and write-only.
7689/// ----------------------------------------------------------------------------
7690namespace {
7691struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
7692 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7693 : AAMemoryBehavior(IRP, A) {}
7694
7695 /// See AbstractAttribute::initialize(...).
7696 void initialize(Attributor &A) override {
7697 intersectAssumedBits(BEST_STATE);
7698 getKnownStateFromValue(getIRPosition(), getState());
7699 AAMemoryBehavior::initialize(A);
7700 }
7701
7702 /// Return the memory behavior information encoded in the IR for \p IRP.
7703 static void getKnownStateFromValue(const IRPosition &IRP,
7704 BitIntegerState &State,
7705 bool IgnoreSubsumingPositions = false) {
7706 SmallVector<Attribute, 2> Attrs;
7707 IRP.getAttrs(AttrKinds, Attrs, IgnoreSubsumingPositions);
7708 for (const Attribute &Attr : Attrs) {
7709 switch (Attr.getKindAsEnum()) {
7710 case Attribute::ReadNone:
7711 State.addKnownBits(NO_ACCESSES);
7712 break;
7713 case Attribute::ReadOnly:
7714 State.addKnownBits(NO_WRITES);
7715 break;
7716 case Attribute::WriteOnly:
7717 State.addKnownBits(NO_READS);
7718 break;
7719 default:
7720 llvm_unreachable("Unexpected attribute!")::llvm::llvm_unreachable_internal("Unexpected attribute!", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7720)
;
7721 }
7722 }
7723
7724 if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
7725 if (!I->mayReadFromMemory())
7726 State.addKnownBits(NO_READS);
7727 if (!I->mayWriteToMemory())
7728 State.addKnownBits(NO_WRITES);
7729 }
7730 }
7731
7732 /// See AbstractAttribute::getDeducedAttributes(...).
7733 void getDeducedAttributes(LLVMContext &Ctx,
7734 SmallVectorImpl<Attribute> &Attrs) const override {
7735 assert(Attrs.size() == 0)(static_cast <bool> (Attrs.size() == 0) ? void (0) : __assert_fail
("Attrs.size() == 0", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7735, __extension__ __PRETTY_FUNCTION__))
;
7736 if (isAssumedReadNone())
7737 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7738 else if (isAssumedReadOnly())
7739 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7740 else if (isAssumedWriteOnly())
7741 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7742 assert(Attrs.size() <= 1)(static_cast <bool> (Attrs.size() <= 1) ? void (0) :
__assert_fail ("Attrs.size() <= 1", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 7742, __extension__ __PRETTY_FUNCTION__))
;
7743 }
7744
7745 /// See AbstractAttribute::manifest(...).
7746 ChangeStatus manifest(Attributor &A) override {
7747 if (hasAttr(Attribute::ReadNone, /* IgnoreSubsumingPositions */ true))
7748 return ChangeStatus::UNCHANGED;
7749
7750 const IRPosition &IRP = getIRPosition();
7751
7752 // Check if we would improve the existing attributes first.
7753 SmallVector<Attribute, 4> DeducedAttrs;
7754 getDeducedAttributes(IRP.getAnchorValue().getContext(), DeducedAttrs);
7755 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
7756 return IRP.hasAttr(Attr.getKindAsEnum(),
7757 /* IgnoreSubsumingPositions */ true);
7758 }))
7759 return ChangeStatus::UNCHANGED;
7760
7761 // Clear existing attributes.
7762 IRP.removeAttrs(AttrKinds);
7763
7764 // Use the generic manifest method.
7765 return IRAttribute::manifest(A);
7766 }
7767
7768 /// See AbstractState::getAsStr().
7769 const std::string getAsStr() const override {
7770 if (isAssumedReadNone())
7771 return "readnone";
7772 if (isAssumedReadOnly())
7773 return "readonly";
7774 if (isAssumedWriteOnly())
7775 return "writeonly";
7776 return "may-read/write";
7777 }
7778
7779 /// The set of IR attributes AAMemoryBehavior deals with.
7780 static const Attribute::AttrKind AttrKinds[3];
7781};
7782
7783const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7784 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7785
7786/// Memory behavior attribute for a floating value.
7787struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7788 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7789 : AAMemoryBehaviorImpl(IRP, A) {}
7790
7791 /// See AbstractAttribute::updateImpl(...).
7792 ChangeStatus updateImpl(Attributor &A) override;
7793
7794 /// See AbstractAttribute::trackStatistics()
7795 void trackStatistics() const override {
7796 if (isAssumedReadNone())
7797 STATS_DECLTRACK_FLOATING_ATTR(readnone){ static llvm::Statistic NumIRFloating_readnone = {"attributor"
, "NumIRFloating_readnone", ("Number of floating values known to be '"
"readnone" "'")};; ++(NumIRFloating_readnone); }
7798 else if (isAssumedReadOnly())
7799 STATS_DECLTRACK_FLOATING_ATTR(readonly){ static llvm::Statistic NumIRFloating_readonly = {"attributor"
, "NumIRFloating_readonly", ("Number of floating values known to be '"
"readonly" "'")};; ++(NumIRFloating_readonly); }
7800 else if (isAssumedWriteOnly())
7801 STATS_DECLTRACK_FLOATING_ATTR(writeonly){ static llvm::Statistic NumIRFloating_writeonly = {"attributor"
, "NumIRFloating_writeonly", ("Number of floating values known to be '"
"writeonly" "'")};; ++(NumIRFloating_writeonly); }
7802 }
7803
7804private:
7805 /// Return true if users of \p UserI might access the underlying
7806 /// variable/location described by \p U and should therefore be analyzed.
7807 bool followUsersOfUseIn(Attributor &A, const Use &U,
7808 const Instruction *UserI);
7809
7810 /// Update the state according to the effect of use \p U in \p UserI.
7811 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
7812};
7813
7814/// Memory behavior attribute for function argument.
7815struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
7816 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
7817 : AAMemoryBehaviorFloating(IRP, A) {}
7818
7819 /// See AbstractAttribute::initialize(...).
7820 void initialize(Attributor &A) override {
7821 intersectAssumedBits(BEST_STATE);
7822 const IRPosition &IRP = getIRPosition();
7823 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
7824 // can query it when we use has/getAttr. That would allow us to reuse the
7825 // initialize of the base class here.
7826 bool HasByVal =
7827 IRP.hasAttr({Attribute::ByVal}, /* IgnoreSubsumingPositions */ true);
7828 getKnownStateFromValue(IRP, getState(),
7829 /* IgnoreSubsumingPositions */ HasByVal);
7830
7831 // Initialize the use vector with all direct uses of the associated value.
7832 Argument *Arg = getAssociatedArgument();
7833 if (!Arg || !A.isFunctionIPOAmendable(*(Arg->getParent())))
7834 indicatePessimisticFixpoint();
7835 }
7836
7837 ChangeStatus manifest(Attributor &A) override {
7838 // TODO: Pointer arguments are not supported on vectors of pointers yet.
7839 if (!getAssociatedValue().getType()->isPointerTy())
7840 return ChangeStatus::UNCHANGED;
7841
7842 // TODO: From readattrs.ll: "inalloca parameters are always
7843 // considered written"
7844 if (hasAttr({Attribute::InAlloca, Attribute::Preallocated})) {
7845 removeKnownBits(NO_WRITES);
7846 removeAssumedBits(NO_WRITES);
7847 }
7848 return AAMemoryBehaviorFloating::manifest(A);
7849 }
7850
7851 /// See AbstractAttribute::trackStatistics()
7852 void trackStatistics() const override {
7853 if (isAssumedReadNone())
7854 STATS_DECLTRACK_ARG_ATTR(readnone){ static llvm::Statistic NumIRArguments_readnone = {"attributor"
, "NumIRArguments_readnone", ("Number of " "arguments" " marked '"
"readnone" "'")};; ++(NumIRArguments_readnone); }
7855 else if (isAssumedReadOnly())
7856 STATS_DECLTRACK_ARG_ATTR(readonly){ static llvm::Statistic NumIRArguments_readonly = {"attributor"
, "NumIRArguments_readonly", ("Number of " "arguments" " marked '"
"readonly" "'")};; ++(NumIRArguments_readonly); }
7857 else if (isAssumedWriteOnly())
7858 STATS_DECLTRACK_ARG_ATTR(writeonly){ static llvm::Statistic NumIRArguments_writeonly = {"attributor"
, "NumIRArguments_writeonly", ("Number of " "arguments" " marked '"
"writeonly" "'")};; ++(NumIRArguments_writeonly); }
7859 }
7860};
7861
7862struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
7863 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
7864 : AAMemoryBehaviorArgument(IRP, A) {}
7865
7866 /// See AbstractAttribute::initialize(...).
7867 void initialize(Attributor &A) override {
7868 // If we don't have an associated attribute this is either a variadic call
7869 // or an indirect call, either way, nothing to do here.
7870 Argument *Arg = getAssociatedArgument();
7871 if (!Arg) {
7872 indicatePessimisticFixpoint();
7873 return;
7874 }
7875 if (Arg->hasByValAttr()) {
7876 addKnownBits(NO_WRITES);
7877 removeKnownBits(NO_READS);
7878 removeAssumedBits(NO_READS);
7879 }
7880 AAMemoryBehaviorArgument::initialize(A);
7881 if (getAssociatedFunction()->isDeclaration())
7882 indicatePessimisticFixpoint();
7883 }
7884
7885 /// See AbstractAttribute::updateImpl(...).
7886 ChangeStatus updateImpl(Attributor &A) override {
7887 // TODO: Once we have call site specific value information we can provide
7888 // call site specific liveness liveness information and then it makes
7889 // sense to specialize attributes for call sites arguments instead of
7890 // redirecting requests to the callee argument.
7891 Argument *Arg = getAssociatedArgument();
7892 const IRPosition &ArgPos = IRPosition::argument(*Arg);
7893 auto &ArgAA =
7894 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
7895 return clampStateAndIndicateChange(getState(), ArgAA.getState());
7896 }
7897
7898 /// See AbstractAttribute::trackStatistics()
7899 void trackStatistics() const override {
7900 if (isAssumedReadNone())
7901 STATS_DECLTRACK_CSARG_ATTR(readnone){ static llvm::Statistic NumIRCSArguments_readnone = {"attributor"
, "NumIRCSArguments_readnone", ("Number of " "call site arguments"
" marked '" "readnone" "'")};; ++(NumIRCSArguments_readnone)
; }
7902 else if (isAssumedReadOnly())
7903 STATS_DECLTRACK_CSARG_ATTR(readonly){ static llvm::Statistic NumIRCSArguments_readonly = {"attributor"
, "NumIRCSArguments_readonly", ("Number of " "call site arguments"
" marked '" "readonly" "'")};; ++(NumIRCSArguments_readonly)
; }
7904 else if (isAssumedWriteOnly())
7905 STATS_DECLTRACK_CSARG_ATTR(writeonly){ static llvm::Statistic NumIRCSArguments_writeonly = {"attributor"
, "NumIRCSArguments_writeonly", ("Number of " "call site arguments"
" marked '" "writeonly" "'")};; ++(NumIRCSArguments_writeonly
); }
7906 }
7907};
7908
7909/// Memory behavior attribute for a call site return position.
7910struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
7911 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
7912 : AAMemoryBehaviorFloating(IRP, A) {}
7913
7914 /// See AbstractAttribute::initialize(...).
7915 void initialize(Attributor &A) override {
7916 AAMemoryBehaviorImpl::initialize(A);
7917 Function *F = getAssociatedFunction();
7918 if (!F || F->isDeclaration())
7919 indicatePessimisticFixpoint();
7920 }
7921
7922 /// See AbstractAttribute::manifest(...).
7923 ChangeStatus manifest(Attributor &A) override {
7924 // We do not annotate returned values.
7925 return ChangeStatus::UNCHANGED;
7926 }
7927
7928 /// See AbstractAttribute::trackStatistics()
7929 void trackStatistics() const override {}
7930};
7931
7932/// An AA to represent the memory behavior function attributes.
7933struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
7934 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
7935 : AAMemoryBehaviorImpl(IRP, A) {}
7936
7937 /// See AbstractAttribute::updateImpl(Attributor &A).
7938 ChangeStatus updateImpl(Attributor &A) override;
7939
7940 /// See AbstractAttribute::manifest(...).
7941 ChangeStatus manifest(Attributor &A) override {
7942 // TODO: It would be better to merge this with AAMemoryLocation, so that
7943 // we could determine read/write per location. This would also have the
7944 // benefit of only one place trying to manifest the memory attribute.
7945 Function &F = cast<Function>(getAnchorValue());
7946 MemoryEffects ME = MemoryEffects::unknown();
7947 if (isAssumedReadNone())
7948 ME = MemoryEffects::none();
7949 else if (isAssumedReadOnly())
7950 ME = MemoryEffects::readOnly();
7951 else if (isAssumedWriteOnly())
7952 ME = MemoryEffects::writeOnly();
7953
7954 // Intersect with existing memory attribute, as we currently deduce the
7955 // location and modref portion separately.
7956 MemoryEffects ExistingME = F.getMemoryEffects();
7957 ME &= ExistingME;
7958 if (ME == ExistingME)
7959 return ChangeStatus::UNCHANGED;
7960
7961 return IRAttributeManifest::manifestAttrs(
7962 A, getIRPosition(), Attribute::getWithMemoryEffects(F.getContext(), ME),
7963 /*ForceReplace*/ true);
7964 }
7965
7966 /// See AbstractAttribute::trackStatistics()
7967 void trackStatistics() const override {
7968 if (isAssumedReadNone())
7969 STATS_DECLTRACK_FN_ATTR(readnone){ static llvm::Statistic NumIRFunction_readnone = {"attributor"
, "NumIRFunction_readnone", ("Number of " "functions" " marked '"
"readnone" "'")};; ++(NumIRFunction_readnone); }
7970 else if (isAssumedReadOnly())
7971 STATS_DECLTRACK_FN_ATTR(readonly){ static llvm::Statistic NumIRFunction_readonly = {"attributor"
, "NumIRFunction_readonly", ("Number of " "functions" " marked '"
"readonly" "'")};; ++(NumIRFunction_readonly); }
7972 else if (isAssumedWriteOnly())
7973 STATS_DECLTRACK_FN_ATTR(writeonly){ static llvm::Statistic NumIRFunction_writeonly = {"attributor"
, "NumIRFunction_writeonly", ("Number of " "functions" " marked '"
"writeonly" "'")};; ++(NumIRFunction_writeonly); }
7974 }
7975};
7976
7977/// AAMemoryBehavior attribute for call sites.
7978struct AAMemoryBehaviorCallSite final : AAMemoryBehaviorImpl {
7979 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
7980 : AAMemoryBehaviorImpl(IRP, A) {}
7981
7982 /// See AbstractAttribute::initialize(...).
7983 void initialize(Attributor &A) override {
7984 AAMemoryBehaviorImpl::initialize(A);
7985 Function *F = getAssociatedFunction();
7986 if (!F || F->isDeclaration())
7987 indicatePessimisticFixpoint();
7988 }
7989
7990 /// See AbstractAttribute::updateImpl(...).
7991 ChangeStatus updateImpl(Attributor &A) override {
7992 // TODO: Once we have call site specific value information we can provide
7993 // call site specific liveness liveness information and then it makes
7994 // sense to specialize attributes for call sites arguments instead of
7995 // redirecting requests to the callee argument.
7996 Function *F = getAssociatedFunction();
7997 const IRPosition &FnPos = IRPosition::function(*F);
7998 auto &FnAA =
7999 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::REQUIRED);
8000 return clampStateAndIndicateChange(getState(), FnAA.getState());
8001 }
8002
8003 /// See AbstractAttribute::manifest(...).
8004 ChangeStatus manifest(Attributor &A) override {
8005 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8006 CallBase &CB = cast<CallBase>(getAnchorValue());
8007 MemoryEffects ME = MemoryEffects::unknown();
8008 if (isAssumedReadNone())
8009 ME = MemoryEffects::none();
8010 else if (isAssumedReadOnly())
8011 ME = MemoryEffects::readOnly();
8012 else if (isAssumedWriteOnly())
8013 ME = MemoryEffects::writeOnly();
8014
8015 // Intersect with existing memory attribute, as we currently deduce the
8016 // location and modref portion separately.
8017 MemoryEffects ExistingME = CB.getMemoryEffects();
8018 ME &= ExistingME;
8019 if (ME == ExistingME)
8020 return ChangeStatus::UNCHANGED;
8021
8022 return IRAttributeManifest::manifestAttrs(
8023 A, getIRPosition(),
8024 Attribute::getWithMemoryEffects(CB.getContext(), ME),
8025 /*ForceReplace*/ true);
8026 }
8027
8028 /// See AbstractAttribute::trackStatistics()
8029 void trackStatistics() const override {
8030 if (isAssumedReadNone())
8031 STATS_DECLTRACK_CS_ATTR(readnone){ static llvm::Statistic NumIRCS_readnone = {"attributor", "NumIRCS_readnone"
, ("Number of " "call site" " marked '" "readnone" "'")};; ++
(NumIRCS_readnone); }
8032 else if (isAssumedReadOnly())
8033 STATS_DECLTRACK_CS_ATTR(readonly){ static llvm::Statistic NumIRCS_readonly = {"attributor", "NumIRCS_readonly"
, ("Number of " "call site" " marked '" "readonly" "'")};; ++
(NumIRCS_readonly); }
8034 else if (isAssumedWriteOnly())
8035 STATS_DECLTRACK_CS_ATTR(writeonly){ static llvm::Statistic NumIRCS_writeonly = {"attributor", "NumIRCS_writeonly"
, ("Number of " "call site" " marked '" "writeonly" "'")};; ++
(NumIRCS_writeonly); }
8036 }
8037};
8038
8039ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8040
8041 // The current assumed state used to determine a change.
8042 auto AssumedState = getAssumed();
8043
8044 auto CheckRWInst = [&](Instruction &I) {
8045 // If the instruction has an own memory behavior state, use it to restrict
8046 // the local state. No further analysis is required as the other memory
8047 // state is as optimistic as it gets.
8048 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8049 const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8050 *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);
8051 intersectAssumedBits(MemBehaviorAA.getAssumed());
8052 return !isAtFixpoint();
8053 }
8054
8055 // Remove access kind modifiers if necessary.
8056 if (I.mayReadFromMemory())
8057 removeAssumedBits(NO_READS);
8058 if (I.mayWriteToMemory())
8059 removeAssumedBits(NO_WRITES);
8060 return !isAtFixpoint();
8061 };
8062
8063 bool UsedAssumedInformation = false;
8064 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8065 UsedAssumedInformation))
8066 return indicatePessimisticFixpoint();
8067
8068 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8069 : ChangeStatus::UNCHANGED;
8070}
8071
8072ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8073
8074 const IRPosition &IRP = getIRPosition();
8075 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8076 AAMemoryBehavior::StateType &S = getState();
8077
8078 // First, check the function scope. We take the known information and we avoid
8079 // work if the assumed information implies the current assumed information for
8080 // this attribute. This is a valid for all but byval arguments.
8081 Argument *Arg = IRP.getAssociatedArgument();
8082 AAMemoryBehavior::base_t FnMemAssumedState =
8083 AAMemoryBehavior::StateType::getWorstState();
8084 if (!Arg || !Arg->hasByValAttr()) {
8085 const auto &FnMemAA =
8086 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8087 FnMemAssumedState = FnMemAA.getAssumed();
8088 S.addKnownBits(FnMemAA.getKnown());
8089 if ((S.getAssumed() & FnMemAA.getAssumed()) == S.getAssumed())
8090 return ChangeStatus::UNCHANGED;
8091 }
8092
8093 // The current assumed state used to determine a change.
8094 auto AssumedState = S.getAssumed();
8095
8096 // Make sure the value is not captured (except through "return"), if
8097 // it is, any information derived would be irrelevant anyway as we cannot
8098 // check the potential aliases introduced by the capture. However, no need
8099 // to fall back to anythign less optimistic than the function state.
8100 const auto &ArgNoCaptureAA =
8101 A.getAAFor<AANoCapture>(*this, IRP, DepClassTy::OPTIONAL);
8102 if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
8103 S.intersectAssumedBits(FnMemAssumedState);
8104 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8105 : ChangeStatus::UNCHANGED;
8106 }
8107
8108 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8109 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8110 Instruction *UserI = cast<Instruction>(U.getUser());
8111 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryBehavior] Use: " <<
*U << " in " << *UserI << " \n"; } } while
(false)
8112 << " \n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryBehavior] Use: " <<
*U << " in " << *UserI << " \n"; } } while
(false)
;
8113
8114 // Droppable users, e.g., llvm::assume does not actually perform any action.
8115 if (UserI->isDroppable())
8116 return true;
8117
8118 // Check if the users of UserI should also be visited.
8119 Follow = followUsersOfUseIn(A, U, UserI);
8120
8121 // If UserI might touch memory we analyze the use in detail.
8122 if (UserI->mayReadOrWriteMemory())
8123 analyzeUseIn(A, U, UserI);
8124
8125 return !isAtFixpoint();
8126 };
8127
8128 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8129 return indicatePessimisticFixpoint();
8130
8131 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8132 : ChangeStatus::UNCHANGED;
8133}
8134
8135bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8136 const Instruction *UserI) {
8137 // The loaded value is unrelated to the pointer argument, no need to
8138 // follow the users of the load.
8139 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8140 return false;
8141
8142 // By default we follow all uses assuming UserI might leak information on U,
8143 // we have special handling for call sites operands though.
8144 const auto *CB = dyn_cast<CallBase>(UserI);
8145 if (!CB || !CB->isArgOperand(&U))
8146 return true;
8147
8148 // If the use is a call argument known not to be captured, the users of
8149 // the call do not need to be visited because they have to be unrelated to
8150 // the input. Note that this check is not trivial even though we disallow
8151 // general capturing of the underlying argument. The reason is that the
8152 // call might the argument "through return", which we allow and for which we
8153 // need to check call users.
8154 if (U.get()->getType()->isPointerTy()) {
8155 unsigned ArgNo = CB->getArgOperandNo(&U);
8156 const auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(
8157 *this, IRPosition::callsite_argument(*CB, ArgNo), DepClassTy::OPTIONAL);
8158 return !ArgNoCaptureAA.isAssumedNoCapture();
8159 }
8160
8161 return true;
8162}
8163
8164void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8165 const Instruction *UserI) {
8166 assert(UserI->mayReadOrWriteMemory())(static_cast <bool> (UserI->mayReadOrWriteMemory()) ?
void (0) : __assert_fail ("UserI->mayReadOrWriteMemory()"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 8166, __extension__
__PRETTY_FUNCTION__))
;
8167
8168 switch (UserI->getOpcode()) {
8169 default:
8170 // TODO: Handle all atomics and other side-effect operations we know of.
8171 break;
8172 case Instruction::Load:
8173 // Loads cause the NO_READS property to disappear.
8174 removeAssumedBits(NO_READS);
8175 return;
8176
8177 case Instruction::Store:
8178 // Stores cause the NO_WRITES property to disappear if the use is the
8179 // pointer operand. Note that while capturing was taken care of somewhere
8180 // else we need to deal with stores of the value that is not looked through.
8181 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8182 removeAssumedBits(NO_WRITES);
8183 else
8184 indicatePessimisticFixpoint();
8185 return;
8186
8187 case Instruction::Call:
8188 case Instruction::CallBr:
8189 case Instruction::Invoke: {
8190 // For call sites we look at the argument memory behavior attribute (this
8191 // could be recursive!) in order to restrict our own state.
8192 const auto *CB = cast<CallBase>(UserI);
8193
8194 // Give up on operand bundles.
8195 if (CB->isBundleOperand(&U)) {
8196 indicatePessimisticFixpoint();
8197 return;
8198 }
8199
8200 // Calling a function does read the function pointer, maybe write it if the
8201 // function is self-modifying.
8202 if (CB->isCallee(&U)) {
8203 removeAssumedBits(NO_READS);
8204 break;
8205 }
8206
8207 // Adjust the possible access behavior based on the information on the
8208 // argument.
8209 IRPosition Pos;
8210 if (U.get()->getType()->isPointerTy())
8211 Pos = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
8212 else
8213 Pos = IRPosition::callsite_function(*CB);
8214 const auto &MemBehaviorAA =
8215 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8216 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8217 // and at least "known".
8218 intersectAssumedBits(MemBehaviorAA.getAssumed());
8219 return;
8220 }
8221 };
8222
8223 // Generally, look at the "may-properties" and adjust the assumed state if we
8224 // did not trigger special handling before.
8225 if (UserI->mayReadFromMemory())
8226 removeAssumedBits(NO_READS);
8227 if (UserI->mayWriteToMemory())
8228 removeAssumedBits(NO_WRITES);
8229}
8230} // namespace
8231
8232/// -------------------- Memory Locations Attributes ---------------------------
8233/// Includes read-none, argmemonly, inaccessiblememonly,
8234/// inaccessiblememorargmemonly
8235/// ----------------------------------------------------------------------------
8236
8237std::string AAMemoryLocation::getMemoryLocationsAsStr(
8238 AAMemoryLocation::MemoryLocationsKind MLK) {
8239 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8240 return "all memory";
8241 if (MLK == AAMemoryLocation::NO_LOCATIONS)
8242 return "no memory";
8243 std::string S = "memory:";
8244 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8245 S += "stack,";
8246 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8247 S += "constant,";
8248 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_INTERNAL_MEM))
8249 S += "internal global,";
8250 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_EXTERNAL_MEM))
8251 S += "external global,";
8252 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8253 S += "argument,";
8254 if (0 == (MLK & AAMemoryLocation::NO_INACCESSIBLE_MEM))
8255 S += "inaccessible,";
8256 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8257 S += "malloced,";
8258 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8259 S += "unknown,";
8260 S.pop_back();
8261 return S;
8262}
8263
8264namespace {
8265struct AAMemoryLocationImpl : public AAMemoryLocation {
8266
8267 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8268 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8269 AccessKind2Accesses.fill(nullptr);
8270 }
8271
8272 ~AAMemoryLocationImpl() {
8273 // The AccessSets are allocated via a BumpPtrAllocator, we call
8274 // the destructor manually.
8275 for (AccessSet *AS : AccessKind2Accesses)
8276 if (AS)
8277 AS->~AccessSet();
8278 }
8279
8280 /// See AbstractAttribute::initialize(...).
8281 void initialize(Attributor &A) override {
8282 intersectAssumedBits(BEST_STATE);
8283 getKnownStateFromValue(A, getIRPosition(), getState());
8284 AAMemoryLocation::initialize(A);
8285 }
8286
8287 /// Return the memory behavior information encoded in the IR for \p IRP.
8288 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8289 BitIntegerState &State,
8290 bool IgnoreSubsumingPositions = false) {
8291 // For internal functions we ignore `argmemonly` and
8292 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8293 // constant propagation. It is unclear if this is the best way but it is
8294 // unlikely this will cause real performance problems. If we are deriving
8295 // attributes for the anchor function we even remove the attribute in
8296 // addition to ignoring it.
8297 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8298 // MemoryEffects::Other as a possible location.
8299 bool UseArgMemOnly = true;
8300 Function *AnchorFn = IRP.getAnchorScope();
8301 if (AnchorFn && A.isRunOn(*AnchorFn))
8302 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8303
8304 SmallVector<Attribute, 2> Attrs;
8305 IRP.getAttrs({Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8306 for (const Attribute &Attr : Attrs) {
8307 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8308 MemoryEffects ME = Attr.getMemoryEffects();
8309 if (ME.doesNotAccessMemory()) {
8310 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8311 continue;
8312 }
8313 if (ME.onlyAccessesInaccessibleMem()) {
8314 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8315 continue;
8316 }
8317 if (ME.onlyAccessesArgPointees()) {
8318 if (UseArgMemOnly)
8319 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8320 else {
8321 // Remove location information, only keep read/write info.
8322 ME = MemoryEffects(ME.getModRef());
8323 IRAttributeManifest::manifestAttrs(
8324 A, IRP,
8325 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(),
8326 ME),
8327 /*ForceReplace*/ true);
8328 }
8329 continue;
8330 }
8331 if (ME.onlyAccessesInaccessibleOrArgMem()) {
8332 if (UseArgMemOnly)
8333 State.addKnownBits(inverseLocation(
8334 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8335 else {
8336 // Remove location information, only keep read/write info.
8337 ME = MemoryEffects(ME.getModRef());
8338 IRAttributeManifest::manifestAttrs(
8339 A, IRP,
8340 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(),
8341 ME),
8342 /*ForceReplace*/ true);
8343 }
8344 continue;
8345 }
8346 }
8347 }
8348
8349 /// See AbstractAttribute::getDeducedAttributes(...).
8350 void getDeducedAttributes(LLVMContext &Ctx,
8351 SmallVectorImpl<Attribute> &Attrs) const override {
8352 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8353 assert(Attrs.size() == 0)(static_cast <bool> (Attrs.size() == 0) ? void (0) : __assert_fail
("Attrs.size() == 0", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 8353, __extension__ __PRETTY_FUNCTION__))
;
8354 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8355 if (isAssumedReadNone())
8356 Attrs.push_back(
8357 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8358 else if (isAssumedInaccessibleMemOnly())
8359 Attrs.push_back(Attribute::getWithMemoryEffects(
8360 Ctx, MemoryEffects::inaccessibleMemOnly()));
8361 else if (isAssumedArgMemOnly())
8362 Attrs.push_back(
8363 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8364 else if (isAssumedInaccessibleOrArgMemOnly())
8365 Attrs.push_back(Attribute::getWithMemoryEffects(
8366 Ctx, MemoryEffects::inaccessibleOrArgMemOnly()));
8367 }
8368 assert(Attrs.size() <= 1)(static_cast <bool> (Attrs.size() <= 1) ? void (0) :
__assert_fail ("Attrs.size() <= 1", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 8368, __extension__ __PRETTY_FUNCTION__))
;
8369 }
8370
8371 /// See AbstractAttribute::manifest(...).
8372 ChangeStatus manifest(Attributor &A) override {
8373 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8374 // provide per-location modref information here.
8375 const IRPosition &IRP = getIRPosition();
8376
8377 SmallVector<Attribute, 1> DeducedAttrs;
8378 getDeducedAttributes(IRP.getAnchorValue().getContext(), DeducedAttrs);
8379 if (DeducedAttrs.size() != 1)
8380 return ChangeStatus::UNCHANGED;
8381 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8382
8383 // Intersect with existing memory attribute, as we currently deduce the
8384 // location and modref portion separately.
8385 SmallVector<Attribute, 1> ExistingAttrs;
8386 IRP.getAttrs({Attribute::Memory}, ExistingAttrs,
8387 /* IgnoreSubsumingPositions */ true);
8388 if (ExistingAttrs.size() == 1) {
8389 MemoryEffects ExistingME = ExistingAttrs[0].getMemoryEffects();
8390 ME &= ExistingME;
8391 if (ME == ExistingME)
8392 return ChangeStatus::UNCHANGED;
8393 }
8394
8395 return IRAttributeManifest::manifestAttrs(
8396 A, IRP,
8397 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(), ME),
8398 /*ForceReplace*/ true);
8399 }
8400
8401 /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).
8402 bool checkForAllAccessesToMemoryKind(
8403 function_ref<bool(const Instruction *, const Value *, AccessKind,
8404 MemoryLocationsKind)>
8405 Pred,
8406 MemoryLocationsKind RequestedMLK) const override {
8407 if (!isValidState())
8408 return false;
8409
8410 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8411 if (AssumedMLK == NO_LOCATIONS)
8412 return true;
8413
8414 unsigned Idx = 0;
8415 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8416 CurMLK *= 2, ++Idx) {
8417 if (CurMLK & RequestedMLK)
8418 continue;
8419
8420 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8421 for (const AccessInfo &AI : *Accesses)
8422 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8423 return false;
8424 }
8425
8426 return true;
8427 }
8428
8429 ChangeStatus indicatePessimisticFixpoint() override {
8430 // If we give up and indicate a pessimistic fixpoint this instruction will
8431 // become an access for all potential access kinds:
8432 // TODO: Add pointers for argmemonly and globals to improve the results of
8433 // checkForAllAccessesToMemoryKind.
8434 bool Changed = false;
8435 MemoryLocationsKind KnownMLK = getKnown();
8436 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8437 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8438 if (!(CurMLK & KnownMLK))
8439 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8440 getAccessKindFromInst(I));
8441 return AAMemoryLocation::indicatePessimisticFixpoint();
8442 }
8443
8444protected:
8445 /// Helper struct to tie together an instruction that has a read or write
8446 /// effect with the pointer it accesses (if any).
8447 struct AccessInfo {
8448
8449 /// The instruction that caused the access.
8450 const Instruction *I;
8451
8452 /// The base pointer that is accessed, or null if unknown.
8453 const Value *Ptr;
8454
8455 /// The kind of access (read/write/read+write).
8456 AccessKind Kind;
8457
8458 bool operator==(const AccessInfo &RHS) const {
8459 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8460 }
8461 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8462 if (LHS.I != RHS.I)
8463 return LHS.I < RHS.I;
8464 if (LHS.Ptr != RHS.Ptr)
8465 return LHS.Ptr < RHS.Ptr;
8466 if (LHS.Kind != RHS.Kind)
8467 return LHS.Kind < RHS.Kind;
8468 return false;
8469 }
8470 };
8471
8472 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8473 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8474 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8475 std::array<AccessSet *, llvm::CTLog2<VALID_STATE>()> AccessKind2Accesses;
8476
8477 /// Categorize the pointer arguments of CB that might access memory in
8478 /// AccessedLoc and update the state and access map accordingly.
8479 void
8480 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8481 AAMemoryLocation::StateType &AccessedLocs,
8482 bool &Changed);
8483
8484 /// Return the kind(s) of location that may be accessed by \p V.
8485 AAMemoryLocation::MemoryLocationsKind
8486 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8487
8488 /// Return the access kind as determined by \p I.
8489 AccessKind getAccessKindFromInst(const Instruction *I) {
8490 AccessKind AK = READ_WRITE;
8491 if (I) {
8492 AK = I->mayReadFromMemory() ? READ : NONE;
8493 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8494 }
8495 return AK;
8496 }
8497
8498 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8499 /// an access of kind \p AK to a \p MLK memory location with the access
8500 /// pointer \p Ptr.
8501 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8502 MemoryLocationsKind MLK, const Instruction *I,
8503 const Value *Ptr, bool &Changed,
8504 AccessKind AK = READ_WRITE) {
8505
8506 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", 8506, __extension__
__PRETTY_FUNCTION__))
;
8507 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8508 if (!Accesses)
8509 Accesses = new (Allocator) AccessSet();
8510 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8511 State.removeAssumedBits(MLK);
8512 }
8513
8514 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8515 /// arguments, and update the state and access map accordingly.
8516 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8517 AAMemoryLocation::StateType &State, bool &Changed);
8518
8519 /// Used to allocate access sets.
8520 BumpPtrAllocator &Allocator;
8521};
8522
8523void AAMemoryLocationImpl::categorizePtrValue(
8524 Attributor &A, const Instruction &I, const Value &Ptr,
8525 AAMemoryLocation::StateType &State, bool &Changed) {
8526 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)
8527 << Ptr << " ["do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
<< Ptr << " [" << getMemoryLocationsAsStr(
State.getAssumed()) << "]\n"; } } while (false)
8528 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
<< Ptr << " [" << getMemoryLocationsAsStr(
State.getAssumed()) << "]\n"; } } while (false)
;
8529
8530 auto Pred = [&](Value &Obj) {
8531 // TODO: recognize the TBAA used for constant accesses.
8532 MemoryLocationsKind MLK = NO_LOCATIONS;
8533 if (isa<UndefValue>(&Obj))
8534 return true;
8535 if (isa<Argument>(&Obj)) {
8536 // TODO: For now we do not treat byval arguments as local copies performed
8537 // on the call edge, though, we should. To make that happen we need to
8538 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8539 // would also allow us to mark functions only accessing byval arguments as
8540 // readnone again, arguably their accesses have no effect outside of the
8541 // function, like accesses to allocas.
8542 MLK = NO_ARGUMENT_MEM;
8543 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8544 // Reading constant memory is not treated as a read "effect" by the
8545 // function attr pass so we won't neither. Constants defined by TBAA are
8546 // similar. (We know we do not write it because it is constant.)
8547 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8548 if (GVar->isConstant())
8549 return true;
8550
8551 if (GV->hasLocalLinkage())
8552 MLK = NO_GLOBAL_INTERNAL_MEM;
8553 else
8554 MLK = NO_GLOBAL_EXTERNAL_MEM;
8555 } else if (isa<ConstantPointerNull>(&Obj) &&
8556 !NullPointerIsDefined(getAssociatedFunction(),
8557 Ptr.getType()->getPointerAddressSpace())) {
8558 return true;
8559 } else if (isa<AllocaInst>(&Obj)) {
8560 MLK = NO_LOCAL_MEM;
8561 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8562 const auto &NoAliasAA = A.getAAFor<AANoAlias>(
8563 *this, IRPosition::callsite_returned(*CB), DepClassTy::OPTIONAL);
8564 if (NoAliasAA.isAssumedNoAlias())
8565 MLK = NO_MALLOCED_MEM;
8566 else
8567 MLK = NO_UNKOWN_MEM;
8568 } else {
8569 MLK = NO_UNKOWN_MEM;
8570 }
8571
8572 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", 8572, __extension__
__PRETTY_FUNCTION__))
;
8573 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)
8574 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
<< Obj << " -> " << getMemoryLocationsAsStr
(MLK) << "\n"; } } while (false)
;
8575 updateStateAndAccessesMap(getState(), MLK, &I, &Obj, Changed,
8576 getAccessKindFromInst(&I));
8577
8578 return true;
8579 };
8580
8581 const auto &AA = A.getAAFor<AAUnderlyingObjects>(
8582 *this, IRPosition::value(Ptr), DepClassTy::OPTIONAL);
8583 if (!AA.forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8584 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"
; } } while (false)
8585 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"
; } } while (false)
;
8586 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8587 getAccessKindFromInst(&I));
8588 return;
8589 }
8590
8591 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
<< getMemoryLocationsAsStr(State.getAssumed()) <<
"\n"; } } while (false)
8592 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)
8593 << getMemoryLocationsAsStr(State.getAssumed()) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
<< getMemoryLocationsAsStr(State.getAssumed()) <<
"\n"; } } while (false)
;
8594}
8595
8596void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8597 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8598 bool &Changed) {
8599 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8600
8601 // Skip non-pointer arguments.
8602 const Value *ArgOp = CB.getArgOperand(ArgNo);
8603 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8604 continue;
8605
8606 // Skip readnone arguments.
8607 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8608 const auto &ArgOpMemLocationAA =
8609 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8610
8611 if (ArgOpMemLocationAA.isAssumedReadNone())
8612 continue;
8613
8614 // Categorize potentially accessed pointer arguments as if there was an
8615 // access instruction with them as pointer.
8616 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8617 }
8618}
8619
8620AAMemoryLocation::MemoryLocationsKind
8621AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8622 bool &Changed) {
8623 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)
8624 << I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
<< I << "\n"; } } while (false)
;
8625
8626 AAMemoryLocation::StateType AccessedLocs;
8627 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8628
8629 if (auto *CB = dyn_cast<CallBase>(&I)) {
8630
8631 // First check if we assume any memory is access is visible.
8632 const auto &CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8633 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
8634 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << Ido { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize call site: "
<< I << " [" << CBMemLocationAA << "]\n"
; } } while (false)
8635 << " [" << CBMemLocationAA << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize call site: "
<< I << " [" << CBMemLocationAA << "]\n"
; } } while (false)
;
8636
8637 if (CBMemLocationAA.isAssumedReadNone())
8638 return NO_LOCATIONS;
8639
8640 if (CBMemLocationAA.isAssumedInaccessibleMemOnly()) {
8641 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8642 Changed, getAccessKindFromInst(&I));
8643 return AccessedLocs.getAssumed();
8644 }
8645
8646 uint32_t CBAssumedNotAccessedLocs =
8647 CBMemLocationAA.getAssumedNotAccessedLocation();
8648
8649 // Set the argmemonly and global bit as we handle them separately below.
8650 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8651 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8652
8653 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8654 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8655 continue;
8656 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8657 getAccessKindFromInst(&I));
8658 }
8659
8660 // Now handle global memory if it might be accessed. This is slightly tricky
8661 // as NO_GLOBAL_MEM has multiple bits set.
8662 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8663 if (HasGlobalAccesses) {
8664 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8665 AccessKind Kind, MemoryLocationsKind MLK) {
8666 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8667 getAccessKindFromInst(&I));
8668 return true;
8669 };
8670 if (!CBMemLocationAA.checkForAllAccessesToMemoryKind(
8671 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8672 return AccessedLocs.getWorstState();
8673 }
8674
8675 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
8676 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)
8677 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
;
8678
8679 // Now handle argument memory if it might be accessed.
8680 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8681 if (HasArgAccesses)
8682 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8683
8684 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
8685 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)
8686 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
<< getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n"; } } while (false)
;
8687
8688 return AccessedLocs.getAssumed();
8689 }
8690
8691 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8692 LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
<< I << " [" << *Ptr << "]\n"; } } while
(false)
8693 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)
8694 << I << " [" << *Ptr << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
<< I << " [" << *Ptr << "]\n"; } } while
(false)
;
8695 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed);
8696 return AccessedLocs.getAssumed();
8697 }
8698
8699 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)
8700 << I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
<< I << "\n"; } } while (false)
;
8701 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8702 getAccessKindFromInst(&I));
8703 return AccessedLocs.getAssumed();
8704}
8705
8706/// An AA to represent the memory behavior function attributes.
8707struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8708 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8709 : AAMemoryLocationImpl(IRP, A) {}
8710
8711 /// See AbstractAttribute::updateImpl(Attributor &A).
8712 ChangeStatus updateImpl(Attributor &A) override {
8713
8714 const auto &MemBehaviorAA =
8715 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8716 if (MemBehaviorAA.isAssumedReadNone()) {
8717 if (MemBehaviorAA.isKnownReadNone())
8718 return indicateOptimisticFixpoint();
8719 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", 8720, __extension__
__PRETTY_FUNCTION__))
8720 "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", 8720, __extension__
__PRETTY_FUNCTION__))
;
8721 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8722 return ChangeStatus::UNCHANGED;
8723 }
8724
8725 // The current assumed state used to determine a change.
8726 auto AssumedState = getAssumed();
8727 bool Changed = false;
8728
8729 auto CheckRWInst = [&](Instruction &I) {
8730 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8731 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)
8732 << ": " << getMemoryLocationsAsStr(MLK) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAMemoryLocation] Accessed locations for "
<< I << ": " << getMemoryLocationsAsStr(MLK
) << "\n"; } } while (false)
;
8733 removeAssumedBits(inverseLocation(MLK, false, false));
8734 // Stop once only the valid bit set in the *not assumed location*, thus
8735 // once we don't actually exclude any memory locations in the state.
8736 return getAssumedNotAccessedLocation() != VALID_STATE;
8737 };
8738
8739 bool UsedAssumedInformation = false;
8740 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8741 UsedAssumedInformation))
8742 return indicatePessimisticFixpoint();
8743
8744 Changed |= AssumedState != getAssumed();
8745 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8746 }
8747
8748 /// See AbstractAttribute::trackStatistics()
8749 void trackStatistics() const override {
8750 if (isAssumedReadNone())
8751 STATS_DECLTRACK_FN_ATTR(readnone){ static llvm::Statistic NumIRFunction_readnone = {"attributor"
, "NumIRFunction_readnone", ("Number of " "functions" " marked '"
"readnone" "'")};; ++(NumIRFunction_readnone); }
8752 else if (isAssumedArgMemOnly())
8753 STATS_DECLTRACK_FN_ATTR(argmemonly){ static llvm::Statistic NumIRFunction_argmemonly = {"attributor"
, "NumIRFunction_argmemonly", ("Number of " "functions" " marked '"
"argmemonly" "'")};; ++(NumIRFunction_argmemonly); }
8754 else if (isAssumedInaccessibleMemOnly())
8755 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly){ static llvm::Statistic NumIRFunction_inaccessiblememonly = {
"attributor", "NumIRFunction_inaccessiblememonly", ("Number of "
"functions" " marked '" "inaccessiblememonly" "'")};; ++(NumIRFunction_inaccessiblememonly
); }
8756 else if (isAssumedInaccessibleOrArgMemOnly())
8757 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly){ static llvm::Statistic NumIRFunction_inaccessiblememorargmemonly
= {"attributor", "NumIRFunction_inaccessiblememorargmemonly"
, ("Number of " "functions" " marked '" "inaccessiblememorargmemonly"
"'")};; ++(NumIRFunction_inaccessiblememorargmemonly); }
8758 }
8759};
8760
8761/// AAMemoryLocation attribute for call sites.
8762struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8763 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8764 : AAMemoryLocationImpl(IRP, A) {}
8765
8766 /// See AbstractAttribute::initialize(...).
8767 void initialize(Attributor &A) override {
8768 AAMemoryLocationImpl::initialize(A);
8769 Function *F = getAssociatedFunction();
8770 if (!F || F->isDeclaration())
8771 indicatePessimisticFixpoint();
8772 }
8773
8774 /// See AbstractAttribute::updateImpl(...).
8775 ChangeStatus updateImpl(Attributor &A) override {
8776 // TODO: Once we have call site specific value information we can provide
8777 // call site specific liveness liveness information and then it makes
8778 // sense to specialize attributes for call sites arguments instead of
8779 // redirecting requests to the callee argument.
8780 Function *F = getAssociatedFunction();
8781 const IRPosition &FnPos = IRPosition::function(*F);
8782 auto &FnAA =
8783 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
8784 bool Changed = false;
8785 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8786 AccessKind Kind, MemoryLocationsKind MLK) {
8787 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
8788 getAccessKindFromInst(I));
8789 return true;
8790 };
8791 if (!FnAA.checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8792 return indicatePessimisticFixpoint();
8793 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8794 }
8795
8796 /// See AbstractAttribute::trackStatistics()
8797 void trackStatistics() const override {
8798 if (isAssumedReadNone())
8799 STATS_DECLTRACK_CS_ATTR(readnone){ static llvm::Statistic NumIRCS_readnone = {"attributor", "NumIRCS_readnone"
, ("Number of " "call site" " marked '" "readnone" "'")};; ++
(NumIRCS_readnone); }
8800 }
8801};
8802} // namespace
8803
8804/// ------------------ Value Constant Range Attribute -------------------------
8805
8806namespace {
8807struct AAValueConstantRangeImpl : AAValueConstantRange {
8808 using StateType = IntegerRangeState;
8809 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
8810 : AAValueConstantRange(IRP, A) {}
8811
8812 /// See AbstractAttribute::initialize(..).
8813 void initialize(Attributor &A) override {
8814 if (A.hasSimplificationCallback(getIRPosition())) {
8815 indicatePessimisticFixpoint();
8816 return;
8817 }
8818
8819 // Intersect a range given by SCEV.
8820 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
8821
8822 // Intersect a range given by LVI.
8823 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
8824 }
8825
8826 /// See AbstractAttribute::getAsStr().
8827 const std::string getAsStr() const override {
8828 std::string Str;
8829 llvm::raw_string_ostream OS(Str);
8830 OS << "range(" << getBitWidth() << ")<";
8831 getKnown().print(OS);
8832 OS << " / ";
8833 getAssumed().print(OS);
8834 OS << ">";
8835 return OS.str();
8836 }
8837
8838 /// Helper function to get a SCEV expr for the associated value at program
8839 /// point \p I.
8840 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
8841 if (!getAnchorScope())
8842 return nullptr;
8843
8844 ScalarEvolution *SE =
8845 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8846 *getAnchorScope());
8847
8848 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
8849 *getAnchorScope());
8850
8851 if (!SE || !LI)
8852 return nullptr;
8853
8854 const SCEV *S = SE->getSCEV(&getAssociatedValue());
8855 if (!I)
8856 return S;
8857
8858 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
8859 }
8860
8861 /// Helper function to get a range from SCEV for the associated value at
8862 /// program point \p I.
8863 ConstantRange getConstantRangeFromSCEV(Attributor &A,
8864 const Instruction *I = nullptr) const {
8865 if (!getAnchorScope())
8866 return getWorstState(getBitWidth());
8867
8868 ScalarEvolution *SE =
8869 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8870 *getAnchorScope());
8871
8872 const SCEV *S = getSCEV(A, I);
8873 if (!SE || !S)
8874 return getWorstState(getBitWidth());
8875
8876 return SE->getUnsignedRange(S);
8877 }
8878
8879 /// Helper function to get a range from LVI for the associated value at
8880 /// program point \p I.
8881 ConstantRange
8882 getConstantRangeFromLVI(Attributor &A,
8883 const Instruction *CtxI = nullptr) const {
8884 if (!getAnchorScope())
8885 return getWorstState(getBitWidth());
8886
8887 LazyValueInfo *LVI =
8888 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
8889 *getAnchorScope());
8890
8891 if (!LVI || !CtxI)
8892 return getWorstState(getBitWidth());
8893 return LVI->getConstantRange(&getAssociatedValue(),
8894 const_cast<Instruction *>(CtxI));
8895 }
8896
8897 /// Return true if \p CtxI is valid for querying outside analyses.
8898 /// This basically makes sure we do not ask intra-procedural analysis
8899 /// about a context in the wrong function or a context that violates
8900 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
8901 /// if the original context of this AA is OK or should be considered invalid.
8902 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
8903 const Instruction *CtxI,
8904 bool AllowAACtxI) const {
8905 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
8906 return false;
8907
8908 // Our context might be in a different function, neither intra-procedural
8909 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
8910 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
8911 return false;
8912
8913 // If the context is not dominated by the value there are paths to the
8914 // context that do not define the value. This cannot be handled by
8915 // LazyValueInfo so we need to bail.
8916 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
8917 InformationCache &InfoCache = A.getInfoCache();
8918 const DominatorTree *DT =
8919 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
8920 *I->getFunction());
8921 return DT && DT->dominates(I, CtxI);
8922 }
8923
8924 return true;
8925 }
8926
8927 /// See AAValueConstantRange::getKnownConstantRange(..).
8928 ConstantRange
8929 getKnownConstantRange(Attributor &A,
8930 const Instruction *CtxI = nullptr) const override {
8931 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
8932 /* AllowAACtxI */ false))
8933 return getKnown();
8934
8935 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
8936 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
8937 return getKnown().intersectWith(SCEVR).intersectWith(LVIR);
8938 }
8939
8940 /// See AAValueConstantRange::getAssumedConstantRange(..).
8941 ConstantRange
8942 getAssumedConstantRange(Attributor &A,
8943 const Instruction *CtxI = nullptr) const override {
8944 // TODO: Make SCEV use Attributor assumption.
8945 // We may be able to bound a variable range via assumptions in
8946 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
8947 // evolve to x^2 + x, then we can say that y is in [2, 12].
8948 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
8949 /* AllowAACtxI */ false))
8950 return getAssumed();
8951
8952 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
8953 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
8954 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
8955 }
8956
8957 /// Helper function to create MDNode for range metadata.
8958 static MDNode *
8959 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
8960 const ConstantRange &AssumedConstantRange) {
8961 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
8962 Ty, AssumedConstantRange.getLower())),
8963 ConstantAsMetadata::get(ConstantInt::get(
8964 Ty, AssumedConstantRange.getUpper()))};
8965 return MDNode::get(Ctx, LowAndHigh);
8966 }
8967
8968 /// Return true if \p Assumed is included in \p KnownRanges.
8969 static bool isBetterRange(const ConstantRange &Assumed, MDNode *KnownRanges) {
8970
8971 if (Assumed.isFullSet())
8972 return false;
8973
8974 if (!KnownRanges)
8975 return true;
8976
8977 // If multiple ranges are annotated in IR, we give up to annotate assumed
8978 // range for now.
8979
8980 // TODO: If there exists a known range which containts assumed range, we
8981 // can say assumed range is better.
8982 if (KnownRanges->getNumOperands() > 2)
8983 return false;
8984
8985 ConstantInt *Lower =
8986 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
8987 ConstantInt *Upper =
8988 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
8989
8990 ConstantRange Known(Lower->getValue(), Upper->getValue());
8991 return Known.contains(Assumed) && Known != Assumed;
8992 }
8993
8994 /// Helper function to set range metadata.
8995 static bool
8996 setRangeMetadataIfisBetterRange(Instruction *I,
8997 const ConstantRange &AssumedConstantRange) {
8998 auto *OldRangeMD = I->getMetadata(LLVMContext::MD_range);
8999 if (isBetterRange(AssumedConstantRange, OldRangeMD)) {
9000 if (!AssumedConstantRange.isEmptySet()) {
9001 I->setMetadata(LLVMContext::MD_range,
9002 getMDNodeForConstantRange(I->getType(), I->getContext(),
9003 AssumedConstantRange));
9004 return true;
9005 }
9006 }
9007 return false;
9008 }
9009
9010 /// See AbstractAttribute::manifest()
9011 ChangeStatus manifest(Attributor &A) override {
9012 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9013 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9014 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", 9014, __extension__
__PRETTY_FUNCTION__))
;
9015
9016 auto &V = getAssociatedValue();
9017 if (!AssumedConstantRange.isEmptySet() &&
9018 !AssumedConstantRange.isSingleElement()) {
9019 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9020 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", 9021, __extension__
__PRETTY_FUNCTION__))
9021 "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", 9021, __extension__
__PRETTY_FUNCTION__))
;
9022 if (isa<CallInst>(I) || isa<LoadInst>(I))
9023 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9024 Changed = ChangeStatus::CHANGED;
9025 }
9026 }
9027
9028 return Changed;
9029 }
9030};
9031
9032struct AAValueConstantRangeArgument final
9033 : AAArgumentFromCallSiteArguments<
9034 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9035 true /* BridgeCallBaseContext */> {
9036 using Base = AAArgumentFromCallSiteArguments<
9037 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9038 true /* BridgeCallBaseContext */>;
9039 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9040 : Base(IRP, A) {}
9041
9042 /// See AbstractAttribute::initialize(..).
9043 void initialize(Attributor &A) override {
9044 if (!getAnchorScope() || getAnchorScope()->isDeclaration()) {
9045 indicatePessimisticFixpoint();
9046 } else {
9047 Base::initialize(A);
9048 }
9049 }
9050
9051 /// See AbstractAttribute::trackStatistics()
9052 void trackStatistics() const override {
9053 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); }
9054 }
9055};
9056
9057struct AAValueConstantRangeReturned
9058 : AAReturnedFromReturnedValues<AAValueConstantRange,
9059 AAValueConstantRangeImpl,
9060 AAValueConstantRangeImpl::StateType,
9061 /* PropogateCallBaseContext */ true> {
9062 using Base =
9063 AAReturnedFromReturnedValues<AAValueConstantRange,
9064 AAValueConstantRangeImpl,
9065 AAValueConstantRangeImpl::StateType,
9066 /* PropogateCallBaseContext */ true>;
9067 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9068 : Base(IRP, A) {}
9069
9070 /// See AbstractAttribute::initialize(...).
9071 void initialize(Attributor &A) override {}
9072
9073 /// See AbstractAttribute::trackStatistics()
9074 void trackStatistics() const override {
9075 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
); }
9076 }
9077};
9078
9079struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9080 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9081 : AAValueConstantRangeImpl(IRP, A) {}
9082
9083 /// See AbstractAttribute::initialize(...).
9084 void initialize(Attributor &A) override {
9085 AAValueConstantRangeImpl::initialize(A);
9086 if (isAtFixpoint())
9087 return;
9088
9089 Value &V = getAssociatedValue();
9090
9091 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9092 unionAssumed(ConstantRange(C->getValue()));
9093 indicateOptimisticFixpoint();
9094 return;
9095 }
9096
9097 if (isa<UndefValue>(&V)) {
9098 // Collapse the undef state to 0.
9099 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9100 indicateOptimisticFixpoint();
9101 return;
9102 }
9103
9104 if (isa<CallBase>(&V))
9105 return;
9106
9107 if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))
9108 return;
9109
9110 // If it is a load instruction with range metadata, use it.
9111 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9112 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9113 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9114 return;
9115 }
9116
9117 // We can work with PHI and select instruction as we traverse their operands
9118 // during update.
9119 if (isa<SelectInst>(V) || isa<PHINode>(V))
9120 return;
9121
9122 // Otherwise we give up.
9123 indicatePessimisticFixpoint();
9124
9125 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
9126 << getAssociatedValue() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
;
9127 }
9128
9129 bool calculateBinaryOperator(
9130 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9131 const Instruction *CtxI,
9132 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9133 Value *LHS = BinOp->getOperand(0);
9134 Value *RHS = BinOp->getOperand(1);
9135
9136 // Simplify the operands first.
9137 bool UsedAssumedInformation = false;
9138 const auto &SimplifiedLHS = A.getAssumedSimplified(
9139 IRPosition::value(*LHS, getCallBaseContext()), *this,
9140 UsedAssumedInformation, AA::Interprocedural);
9141 if (!SimplifiedLHS.has_value())
9142 return true;
9143 if (!*SimplifiedLHS)
9144 return false;
9145 LHS = *SimplifiedLHS;
9146
9147 const auto &SimplifiedRHS = A.getAssumedSimplified(
9148 IRPosition::value(*RHS, getCallBaseContext()), *this,
9149 UsedAssumedInformation, AA::Interprocedural);
9150 if (!SimplifiedRHS.has_value())
9151 return true;
9152 if (!*SimplifiedRHS)
9153 return false;
9154 RHS = *SimplifiedRHS;
9155
9156 // TODO: Allow non integers as well.
9157 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9158 return false;
9159
9160 auto &LHSAA = A.getAAFor<AAValueConstantRange>(
9161 *this, IRPosition::value(*LHS, getCallBaseContext()),
9162 DepClassTy::REQUIRED);
9163 QuerriedAAs.push_back(&LHSAA);
9164 auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI);
9165
9166 auto &RHSAA = A.getAAFor<AAValueConstantRange>(
9167 *this, IRPosition::value(*RHS, getCallBaseContext()),
9168 DepClassTy::REQUIRED);
9169 QuerriedAAs.push_back(&RHSAA);
9170 auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI);
9171
9172 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9173
9174 T.unionAssumed(AssumedRange);
9175
9176 // TODO: Track a known state too.
9177
9178 return T.isValidState();
9179 }
9180
9181 bool calculateCastInst(
9182 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9183 const Instruction *CtxI,
9184 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9185 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", 9185, __extension__
__PRETTY_FUNCTION__))
;
9186 // TODO: Allow non integers as well.
9187 Value *OpV = CastI->getOperand(0);
9188
9189 // Simplify the operand first.
9190 bool UsedAssumedInformation = false;
9191 const auto &SimplifiedOpV = A.getAssumedSimplified(
9192 IRPosition::value(*OpV, getCallBaseContext()), *this,
9193 UsedAssumedInformation, AA::Interprocedural);
9194 if (!SimplifiedOpV.has_value())
9195 return true;
9196 if (!*SimplifiedOpV)
9197 return false;
9198 OpV = *SimplifiedOpV;
9199
9200 if (!OpV->getType()->isIntegerTy())
9201 return false;
9202
9203 auto &OpAA = A.getAAFor<AAValueConstantRange>(
9204 *this, IRPosition::value(*OpV, getCallBaseContext()),
9205 DepClassTy::REQUIRED);
9206 QuerriedAAs.push_back(&OpAA);
9207 T.unionAssumed(
9208 OpAA.getAssumed().castOp(CastI->getOpcode(), getState().getBitWidth()));
9209 return T.isValidState();
9210 }
9211
9212 bool
9213 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9214 const Instruction *CtxI,
9215 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9216 Value *LHS = CmpI->getOperand(0);
9217 Value *RHS = CmpI->getOperand(1);
9218
9219 // Simplify the operands first.
9220 bool UsedAssumedInformation = false;
9221 const auto &SimplifiedLHS = A.getAssumedSimplified(
9222 IRPosition::value(*LHS, getCallBaseContext()), *this,
9223 UsedAssumedInformation, AA::Interprocedural);
9224 if (!SimplifiedLHS.has_value())
9225 return true;
9226 if (!*SimplifiedLHS)
9227 return false;
9228 LHS = *SimplifiedLHS;
9229
9230 const auto &SimplifiedRHS = A.getAssumedSimplified(
9231 IRPosition::value(*RHS, getCallBaseContext()), *this,
9232 UsedAssumedInformation, AA::Interprocedural);
9233 if (!SimplifiedRHS.has_value())
9234 return true;
9235 if (!*SimplifiedRHS)
9236 return false;
9237 RHS = *SimplifiedRHS;
9238
9239 // TODO: Allow non integers as well.
9240 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9241 return false;
9242
9243 auto &LHSAA = A.getAAFor<AAValueConstantRange>(
9244 *this, IRPosition::value(*LHS, getCallBaseContext()),
9245 DepClassTy::REQUIRED);
9246 QuerriedAAs.push_back(&LHSAA);
9247 auto &RHSAA = A.getAAFor<AAValueConstantRange>(
9248 *this, IRPosition::value(*RHS, getCallBaseContext()),
9249 DepClassTy::REQUIRED);
9250 QuerriedAAs.push_back(&RHSAA);
9251 auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI);
9252 auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI);
9253
9254 // If one of them is empty set, we can't decide.
9255 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9256 return true;
9257
9258 bool MustTrue = false, MustFalse = false;
9259
9260 auto AllowedRegion =
9261 ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange);
9262
9263 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9264 MustFalse = true;
9265
9266 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9267 MustTrue = true;
9268
9269 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", 9270, __extension__
__PRETTY_FUNCTION__))
9270 "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", 9270, __extension__
__PRETTY_FUNCTION__))
;
9271
9272 if (MustTrue)
9273 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9274 else if (MustFalse)
9275 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9276 else
9277 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9278
9279 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " " << LHSAAdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] " <<
*CmpI << " " << LHSAA << " " << RHSAA
<< "\n"; } } while (false)
9280 << " " << RHSAA << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] " <<
*CmpI << " " << LHSAA << " " << RHSAA
<< "\n"; } } while (false)
;
9281
9282 // TODO: Track a known state too.
9283 return T.isValidState();
9284 }
9285
9286 /// See AbstractAttribute::updateImpl(...).
9287 ChangeStatus updateImpl(Attributor &A) override {
9288
9289 IntegerRangeState T(getBitWidth());
9290 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9291 Instruction *I = dyn_cast<Instruction>(&V);
9292 if (!I || isa<CallBase>(I)) {
9293
9294 // Simplify the operand first.
9295 bool UsedAssumedInformation = false;
9296 const auto &SimplifiedOpV = A.getAssumedSimplified(
9297 IRPosition::value(V, getCallBaseContext()), *this,
9298 UsedAssumedInformation, AA::Interprocedural);
9299 if (!SimplifiedOpV.has_value())
9300 return true;
9301 if (!*SimplifiedOpV)
9302 return false;
9303 Value *VPtr = *SimplifiedOpV;
9304
9305 // If the value is not instruction, we query AA to Attributor.
9306 const auto &AA = A.getAAFor<AAValueConstantRange>(
9307 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9308 DepClassTy::REQUIRED);
9309
9310 // Clamp operator is not used to utilize a program point CtxI.
9311 T.unionAssumed(AA.getAssumedConstantRange(A, CtxI));
9312
9313 return T.isValidState();
9314 }
9315
9316 SmallVector<const AAValueConstantRange *, 4> QuerriedAAs;
9317 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9318 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9319 return false;
9320 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9321 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9322 return false;
9323 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9324 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9325 return false;
9326 } else {
9327 // Give up with other instructions.
9328 // TODO: Add other instructions
9329
9330 T.indicatePessimisticFixpoint();
9331 return false;
9332 }
9333
9334 // Catch circular reasoning in a pessimistic way for now.
9335 // TODO: Check how the range evolves and if we stripped anything, see also
9336 // AADereferenceable or AAAlign for similar situations.
9337 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9338 if (QueriedAA != this)
9339 continue;
9340 // If we are in a stady state we do not need to worry.
9341 if (T.getAssumed() == getState().getAssumed())
9342 continue;
9343 T.indicatePessimisticFixpoint();
9344 }
9345
9346 return T.isValidState();
9347 };
9348
9349 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9350 return indicatePessimisticFixpoint();
9351
9352 // Ensure that long def-use chains can't cause circular reasoning either by
9353 // introducing a cutoff below.
9354 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9355 return ChangeStatus::UNCHANGED;
9356 if (++NumChanges > MaxNumChanges) {
9357 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)
9358 << " but only " << MaxNumChangesdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAValueConstantRange] performed "
<< NumChanges << " but only " << MaxNumChanges
<< " are allowed to avoid cyclic reasoning."; } } while
(false)
9359 << " 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)
;
9360 return indicatePessimisticFixpoint();
9361 }
9362 return ChangeStatus::CHANGED;
9363 }
9364
9365 /// See AbstractAttribute::trackStatistics()
9366 void trackStatistics() const override {
9367 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); }
9368 }
9369
9370 /// Tracker to bail after too many widening steps of the constant range.
9371 int NumChanges = 0;
9372
9373 /// Upper bound for the number of allowed changes (=widening steps) for the
9374 /// constant range before we give up.
9375 static constexpr int MaxNumChanges = 5;
9376};
9377
9378struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9379 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9380 : AAValueConstantRangeImpl(IRP, A) {}
9381
9382 /// See AbstractAttribute::initialize(...).
9383 ChangeStatus updateImpl(Attributor &A) override {
9384 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"
, 9385)
9385 "not be called")::llvm::llvm_unreachable_internal("AAValueConstantRange(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 9385)
;
9386 }
9387
9388 /// See AbstractAttribute::trackStatistics()
9389 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); }
}
9390};
9391
9392struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9393 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9394 : AAValueConstantRangeFunction(IRP, A) {}
9395
9396 /// See AbstractAttribute::trackStatistics()
9397 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); }
}
9398};
9399
9400struct AAValueConstantRangeCallSiteReturned
9401 : AACallSiteReturnedFromReturned<AAValueConstantRange,
9402 AAValueConstantRangeImpl,
9403 AAValueConstantRangeImpl::StateType,
9404 /* IntroduceCallBaseContext */ true> {
9405 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9406 : AACallSiteReturnedFromReturned<AAValueConstantRange,
9407 AAValueConstantRangeImpl,
9408 AAValueConstantRangeImpl::StateType,
9409 /* IntroduceCallBaseContext */ true>(IRP,
9410 A) {
9411 }
9412
9413 /// See AbstractAttribute::initialize(...).
9414 void initialize(Attributor &A) override {
9415 // If it is a load instruction with range metadata, use the metadata.
9416 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue()))
9417 if (auto *RangeMD = CI->getMetadata(LLVMContext::MD_range))
9418 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9419
9420 AAValueConstantRangeImpl::initialize(A);
9421 }
9422
9423 /// See AbstractAttribute::trackStatistics()
9424 void trackStatistics() const override {
9425 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
); }
9426 }
9427};
9428struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9429 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9430 : AAValueConstantRangeFloating(IRP, A) {}
9431
9432 /// See AbstractAttribute::manifest()
9433 ChangeStatus manifest(Attributor &A) override {
9434 return ChangeStatus::UNCHANGED;
9435 }
9436
9437 /// See AbstractAttribute::trackStatistics()
9438 void trackStatistics() const override {
9439 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
); }
9440 }
9441};
9442} // namespace
9443
9444/// ------------------ Potential Values Attribute -------------------------
9445
9446namespace {
9447struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9448 using StateType = PotentialConstantIntValuesState;
9449
9450 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9451 : AAPotentialConstantValues(IRP, A) {}
9452
9453 /// See AbstractAttribute::initialize(..).
9454 void initialize(Attributor &A) override {
9455 if (A.hasSimplificationCallback(getIRPosition()))
9456 indicatePessimisticFixpoint();
9457 else
9458 AAPotentialConstantValues::initialize(A);
9459 }
9460
9461 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9462 bool &ContainsUndef, bool ForSelf) {
9463 SmallVector<AA::ValueAndContext> Values;
9464 bool UsedAssumedInformation = false;
9465 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9466 UsedAssumedInformation)) {
9467 // Avoid recursion when the caller is computing constant values for this
9468 // IRP itself.
9469 if (ForSelf)
9470 return false;
9471 if (!IRP.getAssociatedType()->isIntegerTy())
9472 return false;
9473 auto &PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9474 *this, IRP, DepClassTy::REQUIRED);
9475 if (!PotentialValuesAA.getState().isValidState())
9476 return false;
9477 ContainsUndef = PotentialValuesAA.getState().undefIsContained();
9478 S = PotentialValuesAA.getState().getAssumedSet();
9479 return true;
9480 }
9481
9482 // Copy all the constant values, except UndefValue. ContainsUndef is true
9483 // iff Values contains only UndefValue instances. If there are other known
9484 // constants, then UndefValue is dropped.
9485 ContainsUndef = false;
9486 for (auto &It : Values) {
9487 if (isa<UndefValue>(It.getValue())) {
9488 ContainsUndef = true;
9489 continue;
9490 }
9491 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9492 if (!CI)
9493 return false;
9494 S.insert(CI->getValue());
9495 }
9496 ContainsUndef &= S.empty();
9497
9498 return true;
9499 }
9500
9501 /// See AbstractAttribute::getAsStr().
9502 const std::string getAsStr() const override {
9503 std::string Str;
9504 llvm::raw_string_ostream OS(Str);
9505 OS << getState();
9506 return OS.str();
9507 }
9508
9509 /// See AbstractAttribute::updateImpl(...).
9510 ChangeStatus updateImpl(Attributor &A) override {
9511 return indicatePessimisticFixpoint();
9512 }
9513};
9514
9515struct AAPotentialConstantValuesArgument final
9516 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9517 AAPotentialConstantValuesImpl,
9518 PotentialConstantIntValuesState> {
9519 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9520 AAPotentialConstantValuesImpl,
9521 PotentialConstantIntValuesState>;
9522 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9523 : Base(IRP, A) {}
9524
9525 /// See AbstractAttribute::initialize(..).
9526 void initialize(Attributor &A) override {
9527 if (!getAnchorScope() || getAnchorScope()->isDeclaration()) {
9528 indicatePessimisticFixpoint();
9529 } else {
9530 Base::initialize(A);
9531 }
9532 }
9533
9534 /// See AbstractAttribute::trackStatistics()
9535 void trackStatistics() const override {
9536 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
); }
9537 }
9538};
9539
9540struct AAPotentialConstantValuesReturned
9541 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9542 AAPotentialConstantValuesImpl> {
9543 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9544 AAPotentialConstantValuesImpl>;
9545 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9546 : Base(IRP, A) {}
9547
9548 /// See AbstractAttribute::trackStatistics()
9549 void trackStatistics() const override {
9550 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); }
9551 }
9552};
9553
9554struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9555 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9556 : AAPotentialConstantValuesImpl(IRP, A) {}
9557
9558 /// See AbstractAttribute::initialize(..).
9559 void initialize(Attributor &A) override {
9560 AAPotentialConstantValuesImpl::initialize(A);
9561 if (isAtFixpoint())
9562 return;
9563
9564 Value &V = getAssociatedValue();
9565
9566 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9567 unionAssumed(C->getValue());
9568 indicateOptimisticFixpoint();
9569 return;
9570 }
9571
9572 if (isa<UndefValue>(&V)) {
9573 unionAssumedWithUndef();
9574 indicateOptimisticFixpoint();
9575 return;
9576 }
9577
9578 if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))
9579 return;
9580
9581 if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))
9582 return;
9583
9584 indicatePessimisticFixpoint();
9585
9586 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialConstantValues] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
9587 << getAssociatedValue() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialConstantValues] We give up: "
<< getAssociatedValue() << "\n"; } } while (false
)
;
9588 }
9589
9590 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9591 const APInt &RHS) {
9592 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9593 }
9594
9595 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9596 uint32_t ResultBitWidth) {
9597 Instruction::CastOps CastOp = CI->getOpcode();
9598 switch (CastOp) {
9599 default:
9600 llvm_unreachable("unsupported or not integer cast")::llvm::llvm_unreachable_internal("unsupported or not integer cast"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 9600)
;
9601 case Instruction::Trunc:
9602 return Src.trunc(ResultBitWidth);
9603 case Instruction::SExt:
9604 return Src.sext(ResultBitWidth);
9605 case Instruction::ZExt:
9606 return Src.zext(ResultBitWidth);
9607 case Instruction::BitCast:
9608 return Src;
9609 }
9610 }
9611
9612 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9613 const APInt &LHS, const APInt &RHS,
9614 bool &SkipOperation, bool &Unsupported) {
9615 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9616 // Unsupported is set to true when the binary operator is not supported.
9617 // SkipOperation is set to true when UB occur with the given operand pair
9618 // (LHS, RHS).
9619 // TODO: we should look at nsw and nuw keywords to handle operations
9620 // that create poison or undef value.
9621 switch (BinOpcode) {
9622 default:
9623 Unsupported = true;
9624 return LHS;
9625 case Instruction::Add:
9626 return LHS + RHS;
9627 case Instruction::Sub:
9628 return LHS - RHS;
9629 case Instruction::Mul:
9630 return LHS * RHS;
9631 case Instruction::UDiv:
9632 if (RHS.isZero()) {
9633 SkipOperation = true;
9634 return LHS;
9635 }
9636 return LHS.udiv(RHS);
9637 case Instruction::SDiv:
9638 if (RHS.isZero()) {
9639 SkipOperation = true;
9640 return LHS;
9641 }
9642 return LHS.sdiv(RHS);
9643 case Instruction::URem:
9644 if (RHS.isZero()) {
9645 SkipOperation = true;
9646 return LHS;
9647 }
9648 return LHS.urem(RHS);
9649 case Instruction::SRem:
9650 if (RHS.isZero()) {
9651 SkipOperation = true;
9652 return LHS;
9653 }
9654 return LHS.srem(RHS);
9655 case Instruction::Shl:
9656 return LHS.shl(RHS);
9657 case Instruction::LShr:
9658 return LHS.lshr(RHS);
9659 case Instruction::AShr:
9660 return LHS.ashr(RHS);
9661 case Instruction::And:
9662 return LHS & RHS;
9663 case Instruction::Or:
9664 return LHS | RHS;
9665 case Instruction::Xor:
9666 return LHS ^ RHS;
9667 }
9668 }
9669
9670 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9671 const APInt &LHS, const APInt &RHS) {
9672 bool SkipOperation = false;
9673 bool Unsupported = false;
9674 APInt Result =
9675 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9676 if (Unsupported)
9677 return false;
9678 // If SkipOperation is true, we can ignore this operand pair (L, R).
9679 if (!SkipOperation)
9680 unionAssumed(Result);
9681 return isValidState();
9682 }
9683
9684 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9685 auto AssumedBefore = getAssumed();
9686 Value *LHS = ICI->getOperand(0);
9687 Value *RHS = ICI->getOperand(1);
9688
9689 bool LHSContainsUndef = false, RHSContainsUndef = false;
9690 SetTy LHSAAPVS, RHSAAPVS;
9691 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9692 LHSContainsUndef, /* ForSelf */ false) ||
9693 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9694 RHSContainsUndef, /* ForSelf */ false))
9695 return indicatePessimisticFixpoint();
9696
9697 // TODO: make use of undef flag to limit potential values aggressively.
9698 bool MaybeTrue = false, MaybeFalse = false;
9699 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
9700 if (LHSContainsUndef && RHSContainsUndef) {
9701 // The result of any comparison between undefs can be soundly replaced
9702 // with undef.
9703 unionAssumedWithUndef();
9704 } else if (LHSContainsUndef) {
9705 for (const APInt &R : RHSAAPVS) {
9706 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9707 MaybeTrue |= CmpResult;
9708 MaybeFalse |= !CmpResult;
9709 if (MaybeTrue & MaybeFalse)
9710 return indicatePessimisticFixpoint();
9711 }
9712 } else if (RHSContainsUndef) {
9713 for (const APInt &L : LHSAAPVS) {
9714 bool CmpResult = calculateICmpInst(ICI, L, Zero);
9715 MaybeTrue |= CmpResult;
9716 MaybeFalse |= !CmpResult;
9717 if (MaybeTrue & MaybeFalse)
9718 return indicatePessimisticFixpoint();
9719 }
9720 } else {
9721 for (const APInt &L : LHSAAPVS) {
9722 for (const APInt &R : RHSAAPVS) {
9723 bool CmpResult = calculateICmpInst(ICI, L, R);
9724 MaybeTrue |= CmpResult;
9725 MaybeFalse |= !CmpResult;
9726 if (MaybeTrue & MaybeFalse)
9727 return indicatePessimisticFixpoint();
9728 }
9729 }
9730 }
9731 if (MaybeTrue)
9732 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
9733 if (MaybeFalse)
9734 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
9735 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9736 : ChangeStatus::CHANGED;
9737 }
9738
9739 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
9740 auto AssumedBefore = getAssumed();
9741 Value *LHS = SI->getTrueValue();
9742 Value *RHS = SI->getFalseValue();
9743
9744 bool UsedAssumedInformation = false;
9745 std::optional<Constant *> C = A.getAssumedConstant(
9746 *SI->getCondition(), *this, UsedAssumedInformation);
9747
9748 // Check if we only need one operand.
9749 bool OnlyLeft = false, OnlyRight = false;
9750 if (C && *C && (*C)->isOneValue())
9751 OnlyLeft = true;
9752 else if (C && *C && (*C)->isZeroValue())
9753 OnlyRight = true;
9754
9755 bool LHSContainsUndef = false, RHSContainsUndef = false;
9756 SetTy LHSAAPVS, RHSAAPVS;
9757 if (!OnlyRight &&
9758 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9759 LHSContainsUndef, /* ForSelf */ false))
9760 return indicatePessimisticFixpoint();
9761
9762 if (!OnlyLeft &&
9763 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9764 RHSContainsUndef, /* ForSelf */ false))
9765 return indicatePessimisticFixpoint();
9766
9767 if (OnlyLeft || OnlyRight) {
9768 // select (true/false), lhs, rhs
9769 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9770 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9771
9772 if (Undef)
9773 unionAssumedWithUndef();
9774 else {
9775 for (const auto &It : *OpAA)
9776 unionAssumed(It);
9777 }
9778
9779 } else if (LHSContainsUndef && RHSContainsUndef) {
9780 // select i1 *, undef , undef => undef
9781 unionAssumedWithUndef();
9782 } else {
9783 for (const auto &It : LHSAAPVS)
9784 unionAssumed(It);
9785 for (const auto &It : RHSAAPVS)
9786 unionAssumed(It);
9787 }
9788 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9789 : ChangeStatus::CHANGED;
9790 }
9791
9792 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
9793 auto AssumedBefore = getAssumed();
9794 if (!CI->isIntegerCast())
9795 return indicatePessimisticFixpoint();
9796 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", 9796, __extension__
__PRETTY_FUNCTION__))
;
9797 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
9798 Value *Src = CI->getOperand(0);
9799
9800 bool SrcContainsUndef = false;
9801 SetTy SrcPVS;
9802 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
9803 SrcContainsUndef, /* ForSelf */ false))
9804 return indicatePessimisticFixpoint();
9805
9806 if (SrcContainsUndef)
9807 unionAssumedWithUndef();
9808 else {
9809 for (const APInt &S : SrcPVS) {
9810 APInt T = calculateCastInst(CI, S, ResultBitWidth);
9811 unionAssumed(T);
9812 }
9813 }
9814 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9815 : ChangeStatus::CHANGED;
9816 }
9817
9818 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
9819 auto AssumedBefore = getAssumed();
9820 Value *LHS = BinOp->getOperand(0);
9821 Value *RHS = BinOp->getOperand(1);
9822
9823 bool LHSContainsUndef = false, RHSContainsUndef = false;
9824 SetTy LHSAAPVS, RHSAAPVS;
9825 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9826 LHSContainsUndef, /* ForSelf */ false) ||
9827 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9828 RHSContainsUndef, /* ForSelf */ false))
9829 return indicatePessimisticFixpoint();
9830
9831 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
9832
9833 // TODO: make use of undef flag to limit potential values aggressively.
9834 if (LHSContainsUndef && RHSContainsUndef) {
9835 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
9836 return indicatePessimisticFixpoint();
9837 } else if (LHSContainsUndef) {
9838 for (const APInt &R : RHSAAPVS) {
9839 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
9840 return indicatePessimisticFixpoint();
9841 }
9842 } else if (RHSContainsUndef) {
9843 for (const APInt &L : LHSAAPVS) {
9844 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
9845 return indicatePessimisticFixpoint();
9846 }
9847 } else {
9848 for (const APInt &L : LHSAAPVS) {
9849 for (const APInt &R : RHSAAPVS) {
9850 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9851 return indicatePessimisticFixpoint();
9852 }
9853 }
9854 }
9855 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9856 : ChangeStatus::CHANGED;
9857 }
9858
9859 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
9860 auto AssumedBefore = getAssumed();
9861 SetTy Incoming;
9862 bool ContainsUndef;
9863 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
9864 ContainsUndef, /* ForSelf */ true))
9865 return indicatePessimisticFixpoint();
9866 if (ContainsUndef) {
9867 unionAssumedWithUndef();
9868 } else {
9869 for (const auto &It : Incoming)
9870 unionAssumed(It);
9871 }
9872 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9873 : ChangeStatus::CHANGED;
9874 }
9875
9876 /// See AbstractAttribute::updateImpl(...).
9877 ChangeStatus updateImpl(Attributor &A) override {
9878 Value &V = getAssociatedValue();
9879 Instruction *I = dyn_cast<Instruction>(&V);
9880
9881 if (auto *ICI = dyn_cast<ICmpInst>(I))
9882 return updateWithICmpInst(A, ICI);
9883
9884 if (auto *SI = dyn_cast<SelectInst>(I))
9885 return updateWithSelectInst(A, SI);
9886
9887 if (auto *CI = dyn_cast<CastInst>(I))
9888 return updateWithCastInst(A, CI);
9889
9890 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
9891 return updateWithBinaryOperator(A, BinOp);
9892
9893 if (isa<PHINode>(I) || isa<LoadInst>(I))
9894 return updateWithInstruction(A, I);
9895
9896 return indicatePessimisticFixpoint();
9897 }
9898
9899 /// See AbstractAttribute::trackStatistics()
9900 void trackStatistics() const override {
9901 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
); }
9902 }
9903};
9904
9905struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
9906 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
9907 : AAPotentialConstantValuesImpl(IRP, A) {}
9908
9909 /// See AbstractAttribute::initialize(...).
9910 ChangeStatus updateImpl(Attributor &A) override {
9911 llvm_unreachable(::llvm::llvm_unreachable_internal("AAPotentialConstantValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 9913)
9912 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "::llvm::llvm_unreachable_internal("AAPotentialConstantValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 9913)
9913 "not be called")::llvm::llvm_unreachable_internal("AAPotentialConstantValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 9913)
;
9914 }
9915
9916 /// See AbstractAttribute::trackStatistics()
9917 void trackStatistics() const override {
9918 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
); }
9919 }
9920};
9921
9922struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
9923 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
9924 : AAPotentialConstantValuesFunction(IRP, A) {}
9925
9926 /// See AbstractAttribute::trackStatistics()
9927 void trackStatistics() const override {
9928 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); }
9929 }
9930};
9931
9932struct AAPotentialConstantValuesCallSiteReturned
9933 : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
9934 AAPotentialConstantValuesImpl> {
9935 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
9936 Attributor &A)
9937 : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
9938 AAPotentialConstantValuesImpl>(IRP, A) {}
9939
9940 /// See AbstractAttribute::trackStatistics()
9941 void trackStatistics() const override {
9942 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
); }
9943 }
9944};
9945
9946struct AAPotentialConstantValuesCallSiteArgument
9947 : AAPotentialConstantValuesFloating {
9948 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
9949 Attributor &A)
9950 : AAPotentialConstantValuesFloating(IRP, A) {}
9951
9952 /// See AbstractAttribute::initialize(..).
9953 void initialize(Attributor &A) override {
9954 AAPotentialConstantValuesImpl::initialize(A);
9955 if (isAtFixpoint())
9956 return;
9957
9958 Value &V = getAssociatedValue();
9959
9960 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9961 unionAssumed(C->getValue());
9962 indicateOptimisticFixpoint();
9963 return;
9964 }
9965
9966 if (isa<UndefValue>(&V)) {
9967 unionAssumedWithUndef();
9968 indicateOptimisticFixpoint();
9969 return;
9970 }
9971 }
9972
9973 /// See AbstractAttribute::updateImpl(...).
9974 ChangeStatus updateImpl(Attributor &A) override {
9975 Value &V = getAssociatedValue();
9976 auto AssumedBefore = getAssumed();
9977 auto &AA = A.getAAFor<AAPotentialConstantValues>(
9978 *this, IRPosition::value(V), DepClassTy::REQUIRED);
9979 const auto &S = AA.getAssumed();
9980 unionAssumed(S);
9981 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9982 : ChangeStatus::CHANGED;
9983 }
9984
9985 /// See AbstractAttribute::trackStatistics()
9986 void trackStatistics() const override {
9987 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); }
9988 }
9989};
9990
9991/// ------------------------ NoUndef Attribute ---------------------------------
9992struct AANoUndefImpl : AANoUndef {
9993 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
9994
9995 /// See AbstractAttribute::initialize(...).
9996 void initialize(Attributor &A) override {
9997 if (getIRPosition().hasAttr({Attribute::NoUndef})) {
9998 indicateOptimisticFixpoint();
9999 return;
10000 }
10001 Value &V = getAssociatedValue();
10002 if (isa<UndefValue>(V))
10003 indicatePessimisticFixpoint();
10004 else if (isa<FreezeInst>(V))
10005 indicateOptimisticFixpoint();
10006 else if (getPositionKind() != IRPosition::IRP_RETURNED &&
10007 isGuaranteedNotToBeUndefOrPoison(&V))
10008 indicateOptimisticFixpoint();
10009 else
10010 AANoUndef::initialize(A);
10011 }
10012
10013 /// See followUsesInMBEC
10014 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10015 AANoUndef::StateType &State) {
10016 const Value *UseV = U->get();
10017 const DominatorTree *DT = nullptr;
10018 AssumptionCache *AC = nullptr;
10019 InformationCache &InfoCache = A.getInfoCache();
10020 if (Function *F = getAnchorScope()) {
10021 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10022 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10023 }
10024 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10025 bool TrackUse = false;
10026 // Track use for instructions which must produce undef or poison bits when
10027 // at least one operand contains such bits.
10028 if (isa<CastInst>(*I) || isa<GetElementPtrInst>(*I))
10029 TrackUse = true;
10030 return TrackUse;
10031 }
10032
10033 /// See AbstractAttribute::getAsStr().
10034 const std::string getAsStr() const override {
10035 return getAssumed() ? "noundef" : "may-undef-or-poison";
10036 }
10037
10038 ChangeStatus manifest(Attributor &A) override {
10039 // We don't manifest noundef attribute for dead positions because the
10040 // associated values with dead positions would be replaced with undef
10041 // values.
10042 bool UsedAssumedInformation = false;
10043 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10044 UsedAssumedInformation))
10045 return ChangeStatus::UNCHANGED;
10046 // A position whose simplified value does not have any value is
10047 // considered to be dead. We don't manifest noundef in such positions for
10048 // the same reason above.
10049 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10050 AA::Interprocedural)
10051 .has_value())
10052 return ChangeStatus::UNCHANGED;
10053 return AANoUndef::manifest(A);
10054 }
10055};
10056
10057struct AANoUndefFloating : public AANoUndefImpl {
10058 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10059 : AANoUndefImpl(IRP, A) {}
10060
10061 /// See AbstractAttribute::initialize(...).
10062 void initialize(Attributor &A) override {
10063 AANoUndefImpl::initialize(A);
10064 if (!getState().isAtFixpoint())
10065 if (Instruction *CtxI = getCtxI())
10066 followUsesInMBEC(*this, A, getState(), *CtxI);
10067 }
10068
10069 /// See AbstractAttribute::updateImpl(...).
10070 ChangeStatus updateImpl(Attributor &A) override {
10071
10072 SmallVector<AA::ValueAndContext> Values;
10073 bool UsedAssumedInformation = false;
10074 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10075 AA::AnyScope, UsedAssumedInformation)) {
10076 Values.push_back({getAssociatedValue(), getCtxI()});
10077 }
10078
10079 StateType T;
10080 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10081 const auto &AA = A.getAAFor<AANoUndef>(*this, IRPosition::value(V),
10082 DepClassTy::REQUIRED);
10083 if (this == &AA) {
10084 T.indicatePessimisticFixpoint();
10085 } else {
10086 const AANoUndef::StateType &S =
10087 static_cast<const AANoUndef::StateType &>(AA.getState());
10088 T ^= S;
10089 }
10090 return T.isValidState();
10091 };
10092
10093 for (const auto &VAC : Values)
10094 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10095 return indicatePessimisticFixpoint();
10096
10097 return clampStateAndIndicateChange(getState(), T);
10098 }
10099
10100 /// See AbstractAttribute::trackStatistics()
10101 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
); }
}
10102};
10103
10104struct AANoUndefReturned final
10105 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10106 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10107 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10108
10109 /// See AbstractAttribute::trackStatistics()
10110 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
); }
}
10111};
10112
10113struct AANoUndefArgument final
10114 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10115 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10116 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10117
10118 /// See AbstractAttribute::trackStatistics()
10119 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef){ static llvm::Statistic NumIRArguments_noundef = {"attributor"
, "NumIRArguments_noundef", ("Number of " "arguments" " marked '"
"noundef" "'")};; ++(NumIRArguments_noundef); }
}
10120};
10121
10122struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10123 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10124 : AANoUndefFloating(IRP, A) {}
10125
10126 /// See AbstractAttribute::trackStatistics()
10127 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); }
}
10128};
10129
10130struct AANoUndefCallSiteReturned final
10131 : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl> {
10132 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10133 : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl>(IRP, A) {}
10134
10135 /// See AbstractAttribute::trackStatistics()
10136 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); }
}
10137};
10138
10139struct AACallEdgesImpl : public AACallEdges {
10140 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10141
10142 const SetVector<Function *> &getOptimisticEdges() const override {
10143 return CalledFunctions;
10144 }
10145
10146 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10147
10148 bool hasNonAsmUnknownCallee() const override {
10149 return HasUnknownCalleeNonAsm;
10150 }
10151
10152 const std::string getAsStr() const override {
10153 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10154 std::to_string(CalledFunctions.size()) + "]";
10155 }
10156
10157 void trackStatistics() const override {}
10158
10159protected:
10160 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10161 if (CalledFunctions.insert(Fn)) {
10162 Change = ChangeStatus::CHANGED;
10163 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)
10164 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AACallEdges] New call edge: "
<< Fn->getName() << "\n"; } } while (false)
;
10165 }
10166 }
10167
10168 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10169 if (!HasUnknownCallee)
10170 Change = ChangeStatus::CHANGED;
10171 if (NonAsm && !HasUnknownCalleeNonAsm)
10172 Change = ChangeStatus::CHANGED;
10173 HasUnknownCalleeNonAsm |= NonAsm;
10174 HasUnknownCallee = true;
10175 }
10176
10177private:
10178 /// Optimistic set of functions that might be called by this position.
10179 SetVector<Function *> CalledFunctions;
10180
10181 /// Is there any call with a unknown callee.
10182 bool HasUnknownCallee = false;
10183
10184 /// Is there any call with a unknown callee, excluding any inline asm.
10185 bool HasUnknownCalleeNonAsm = false;
10186};
10187
10188struct AACallEdgesCallSite : public AACallEdgesImpl {
10189 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10190 : AACallEdgesImpl(IRP, A) {}
10191 /// See AbstractAttribute::updateImpl(...).
10192 ChangeStatus updateImpl(Attributor &A) override {
10193 ChangeStatus Change = ChangeStatus::UNCHANGED;
10194
10195 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10196 if (Function *Fn = dyn_cast<Function>(&V)) {
10197 addCalledFunction(Fn, Change);
10198 } else {
10199 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AACallEdges] Unrecognized value: "
<< V << "\n"; } } while (false)
;
10200 setHasUnknownCallee(true, Change);
10201 }
10202
10203 // Explore all values.
10204 return true;
10205 };
10206
10207 SmallVector<AA::ValueAndContext> Values;
10208 // Process any value that we might call.
10209 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10210 bool UsedAssumedInformation = false;
10211 Values.clear();
10212 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10213 AA::AnyScope, UsedAssumedInformation)) {
10214 Values.push_back({*V, CtxI});
10215 }
10216 for (auto &VAC : Values)
10217 VisitValue(*VAC.getValue(), VAC.getCtxI());
10218 };
10219
10220 CallBase *CB = cast<CallBase>(getCtxI());
10221
10222 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10223 if (IA->hasSideEffects() &&
10224 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10225 !hasAssumption(*CB, "ompx_no_call_asm")) {
10226 setHasUnknownCallee(false, Change);
10227 }
10228 return Change;
10229 }
10230
10231 // Process callee metadata if available.
10232 if (auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees)) {
10233 for (const auto &Op : MD->operands()) {
10234 Function *Callee = mdconst::dyn_extract_or_null<Function>(Op);
10235 if (Callee)
10236 addCalledFunction(Callee, Change);
10237 }
10238 return Change;
10239 }
10240
10241 // The most simple case.
10242 ProcessCalledOperand(CB->getCalledOperand(), CB);
10243
10244 // Process callback functions.
10245 SmallVector<const Use *, 4u> CallbackUses;
10246 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10247 for (const Use *U : CallbackUses)
10248 ProcessCalledOperand(U->get(), CB);
10249
10250 return Change;
10251 }
10252};
10253
10254struct AACallEdgesFunction : public AACallEdgesImpl {
10255 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10256 : AACallEdgesImpl(IRP, A) {}
10257
10258 /// See AbstractAttribute::updateImpl(...).
10259 ChangeStatus updateImpl(Attributor &A) override {
10260 ChangeStatus Change = ChangeStatus::UNCHANGED;
10261
10262 auto ProcessCallInst = [&](Instruction &Inst) {
10263 CallBase &CB = cast<CallBase>(Inst);
10264
10265 auto &CBEdges = A.getAAFor<AACallEdges>(
10266 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10267 if (CBEdges.hasNonAsmUnknownCallee())
10268 setHasUnknownCallee(true, Change);
10269 if (CBEdges.hasUnknownCallee())
10270 setHasUnknownCallee(false, Change);
10271
10272 for (Function *F : CBEdges.getOptimisticEdges())
10273 addCalledFunction(F, Change);
10274
10275 return true;
10276 };
10277
10278 // Visit all callable instructions.
10279 bool UsedAssumedInformation = false;
10280 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10281 UsedAssumedInformation,
10282 /* CheckBBLivenessOnly */ true)) {
10283 // If we haven't looked at all call like instructions, assume that there
10284 // are unknown callees.
10285 setHasUnknownCallee(true, Change);
10286 }
10287
10288 return Change;
10289 }
10290};
10291
10292/// -------------------AAInterFnReachability Attribute--------------------------
10293
10294struct AAInterFnReachabilityFunction
10295 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10296 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10297 : CachedReachabilityAA<AAInterFnReachability, Function>(IRP, A) {}
10298
10299 bool instructionCanReach(
10300 Attributor &A, const Instruction &From, const Function &To,
10301 const AA::InstExclusionSetTy *ExclusionSet,
10302 SmallPtrSet<const Function *, 16> *Visited) const override {
10303 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", 10303, __extension__
__PRETTY_FUNCTION__))
;
10304 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10305
10306 RQITy StackRQI(A, From, To, ExclusionSet);
10307 typename RQITy::Reachable Result;
10308 if (RQITy *RQIPtr = NonConstThis->checkQueryCache(A, StackRQI, Result))
10309 return NonConstThis->isReachableImpl(A, *RQIPtr);
10310 return Result == RQITy::Reachable::Yes;
10311 }
10312
10313 bool isReachableImpl(Attributor &A, RQITy &RQI) override {
10314 return isReachableImpl(A, RQI, nullptr);
10315 }
10316
10317 bool isReachableImpl(Attributor &A, RQITy &RQI,
10318 SmallPtrSet<const Function *, 16> *Visited) {
10319
10320 SmallPtrSet<const Function *, 16> LocalVisited;
10321 if (!Visited)
10322 Visited = &LocalVisited;
10323
10324 const auto &IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10325 *this, IRPosition::function(*RQI.From->getFunction()),
10326 DepClassTy::OPTIONAL);
10327
10328 // Determine call like instructions that we can reach from the inst.
10329 SmallVector<CallBase *> ReachableCallBases;
10330 auto CheckCallBase = [&](Instruction &CBInst) {
10331 if (IntraFnReachability.isAssumedReachable(A, *RQI.From, CBInst,
10332 RQI.ExclusionSet))
10333 ReachableCallBases.push_back(cast<CallBase>(&CBInst));
10334 return true;
10335 };
10336
10337 bool UsedAssumedInformation = false;
10338 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10339 UsedAssumedInformation,
10340 /* CheckBBLivenessOnly */ true))
10341 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10342
10343 for (CallBase *CB : ReachableCallBases) {
10344 auto &CBEdges = A.getAAFor<AACallEdges>(
10345 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10346 if (!CBEdges.getState().isValidState())
10347 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10348 // TODO Check To backwards in this case.
10349 if (CBEdges.hasUnknownCallee())
10350 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10351
10352 for (Function *Fn : CBEdges.getOptimisticEdges()) {
10353 if (Fn == RQI.To)
10354 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10355 if (!Visited->insert(Fn).second)
10356 continue;
10357 if (Fn->isDeclaration()) {
10358 if (Fn->hasFnAttribute(Attribute::NoCallback))
10359 continue;
10360 // TODO Check To backwards in this case.
10361 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10362 }
10363
10364 const AAInterFnReachability *InterFnReachability = this;
10365 if (Fn != getAnchorScope())
10366 InterFnReachability = &A.getAAFor<AAInterFnReachability>(
10367 *this, IRPosition::function(*Fn), DepClassTy::OPTIONAL);
10368
10369 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10370 if (InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10371 RQI.ExclusionSet, Visited))
10372 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10373 }
10374 }
10375
10376 return rememberResult(A, RQITy::Reachable::No, RQI);
10377 }
10378
10379 void trackStatistics() const override {}
10380
10381private:
10382 SmallVector<RQITy *> QueryVector;
10383 DenseSet<RQITy *> QueryCache;
10384};
10385} // namespace
10386
10387template <typename AAType>
10388static std::optional<Constant *>
10389askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA,
10390 const IRPosition &IRP, Type &Ty) {
10391 if (!Ty.isIntegerTy())
10392 return nullptr;
10393
10394 // This will also pass the call base context.
10395 const auto &AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10396
10397 std::optional<Constant *> COpt = AA.getAssumedConstant(A);
10398
10399 if (!COpt.has_value()) {
10400 A.recordDependence(AA, QueryingAA, DepClassTy::OPTIONAL);
10401 return std::nullopt;
10402 }
10403 if (auto *C = *COpt) {
10404 A.recordDependence(AA, QueryingAA, DepClassTy::OPTIONAL);
10405 return C;
10406 }
10407 return nullptr;
10408}
10409
10410Value *AAPotentialValues::getSingleValue(
10411 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10412 SmallVectorImpl<AA::ValueAndContext> &Values) {
10413 Type &Ty = *IRP.getAssociatedType();
10414 std::optional<Value *> V;
10415 for (auto &It : Values) {
10416 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10417 if (V.has_value() && !*V)
10418 break;
10419 }
10420 if (!V.has_value())
10421 return UndefValue::get(&Ty);
10422 return *V;
10423}
10424
10425namespace {
10426struct AAPotentialValuesImpl : AAPotentialValues {
10427 using StateType = PotentialLLVMValuesState;
10428
10429 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10430 : AAPotentialValues(IRP, A) {}
10431
10432 /// See AbstractAttribute::initialize(..).
10433 void initialize(Attributor &A) override {
10434 if (A.hasSimplificationCallback(getIRPosition())) {
10435 indicatePessimisticFixpoint();
10436 return;
10437 }
10438 Value *Stripped = getAssociatedValue().stripPointerCasts();
10439 auto *CE = dyn_cast<ConstantExpr>(Stripped);
10440 if (isa<Constant>(Stripped) &&
10441 (!CE || CE->getOpcode() != Instruction::ICmp)) {
10442 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10443 getAnchorScope());
10444 indicateOptimisticFixpoint();
10445 return;
10446 }
10447 AAPotentialValues::initialize(A);
10448 }
10449
10450 /// See AbstractAttribute::getAsStr().
10451 const std::string getAsStr() const override {
10452 std::string Str;
10453 llvm::raw_string_ostream OS(Str);
10454 OS << getState();
10455 return OS.str();
10456 }
10457
10458 template <typename AAType>
10459 static std::optional<Value *> askOtherAA(Attributor &A,
10460 const AbstractAttribute &AA,
10461 const IRPosition &IRP, Type &Ty) {
10462 if (isa<Constant>(IRP.getAssociatedValue()))
10463 return &IRP.getAssociatedValue();
10464 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10465 if (!C)
10466 return std::nullopt;
10467 if (*C)
10468 if (auto *CC = AA::getWithType(**C, Ty))
10469 return CC;
10470 return nullptr;
10471 }
10472
10473 void addValue(Attributor &A, StateType &State, Value &V,
10474 const Instruction *CtxI, AA::ValueScope S,
10475 Function *AnchorScope) const {
10476
10477 IRPosition ValIRP = IRPosition::value(V);
10478 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
10479 for (const auto &U : CB->args()) {
10480 if (U.get() != &V)
10481 continue;
10482 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
10483 break;
10484 }
10485 }
10486
10487 Value *VPtr = &V;
10488 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10489 Type &Ty = *getAssociatedType();
10490 std::optional<Value *> SimpleV =
10491 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
10492 if (SimpleV.has_value() && !*SimpleV) {
10493 auto &PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10494 *this, ValIRP, DepClassTy::OPTIONAL);
10495 if (PotentialConstantsAA.isValidState()) {
10496 for (const auto &It : PotentialConstantsAA.getAssumedSet())
10497 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
10498 if (PotentialConstantsAA.undefIsContained())
10499 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
10500 return;
10501 }
10502 }
10503 if (!SimpleV.has_value())
10504 return;
10505
10506 if (*SimpleV)
10507 VPtr = *SimpleV;
10508 }
10509
10510 if (isa<ConstantInt>(VPtr))
10511 CtxI = nullptr;
10512 if (!AA::isValidInScope(*VPtr, AnchorScope))
10513 S = AA::ValueScope(S | AA::Interprocedural);
10514
10515 State.unionAssumed({{*VPtr, CtxI}, S});
10516 }
10517
10518 /// Helper struct to tie a value+context pair together with the scope for
10519 /// which this is the simplified version.
10520 struct ItemInfo {
10521 AA::ValueAndContext I;
10522 AA::ValueScope S;
10523
10524 bool operator==(const ItemInfo &II) const {
10525 return II.I == I && II.S == S;
10526 };
10527 bool operator<(const ItemInfo &II) const {
10528 if (I == II.I)
10529 return S < II.S;
10530 return I < II.I;
10531 };
10532 };
10533
10534 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
10535 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10536 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
10537 if (!(CS & S))
10538 continue;
10539
10540 bool UsedAssumedInformation = false;
10541 SmallVector<AA::ValueAndContext> Values;
10542 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
10543 UsedAssumedInformation))
10544 return false;
10545
10546 for (auto &It : Values)
10547 ValueScopeMap[It] += CS;
10548 }
10549 for (auto &It : ValueScopeMap)
10550 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
10551 AA::ValueScope(It.second), getAnchorScope());
10552
10553 return true;
10554 }
10555
10556 void giveUpOnIntraprocedural(Attributor &A) {
10557 auto NewS = StateType::getBestState(getState());
10558 for (const auto &It : getAssumedSet()) {
10559 if (It.second == AA::Intraprocedural)
10560 continue;
10561 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
10562 AA::Interprocedural, getAnchorScope());
10563 }
10564 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", 10564, __extension__
__PRETTY_FUNCTION__))
;
10565 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
10566 getAnchorScope());
10567 getState() = NewS;
10568 }
10569
10570 /// See AbstractState::indicatePessimisticFixpoint(...).
10571 ChangeStatus indicatePessimisticFixpoint() override {
10572 getState() = StateType::getBestState(getState());
10573 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
10574 AAPotentialValues::indicateOptimisticFixpoint();
10575 return ChangeStatus::CHANGED;
10576 }
10577
10578 /// See AbstractAttribute::updateImpl(...).
10579 ChangeStatus updateImpl(Attributor &A) override {
10580 return indicatePessimisticFixpoint();
10581 }
10582
10583 /// See AbstractAttribute::manifest(...).
10584 ChangeStatus manifest(Attributor &A) override {
10585 SmallVector<AA::ValueAndContext> Values;
10586 for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {
10587 Values.clear();
10588 if (!getAssumedSimplifiedValues(A, Values, S))
10589 continue;
10590 Value &OldV = getAssociatedValue();
10591 if (isa<UndefValue>(OldV))
10592 continue;
10593 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
10594 if (!NewV || NewV == &OldV)
10595 continue;
10596 if (getCtxI() &&
10597 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
10598 continue;
10599 if (A.changeAfterManifest(getIRPosition(), *NewV))
10600 return ChangeStatus::CHANGED;
10601 }
10602 return ChangeStatus::UNCHANGED;
10603 }
10604
10605 bool getAssumedSimplifiedValues(Attributor &A,
10606 SmallVectorImpl<AA::ValueAndContext> &Values,
10607 AA::ValueScope S) const override {
10608 if (!isValidState())
10609 return false;
10610 for (const auto &It : getAssumedSet())
10611 if (It.second & S)
10612 Values.push_back(It.first);
10613 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", 10613, __extension__
__PRETTY_FUNCTION__))
;
10614 return true;
10615 }
10616};
10617
10618struct AAPotentialValuesFloating : AAPotentialValuesImpl {
10619 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
10620 : AAPotentialValuesImpl(IRP, A) {}
10621
10622 /// See AbstractAttribute::updateImpl(...).
10623 ChangeStatus updateImpl(Attributor &A) override {
10624 auto AssumedBefore = getAssumed();
10625
10626 genericValueTraversal(A);
10627
10628 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10629 : ChangeStatus::CHANGED;
10630 }
10631
10632 /// Helper struct to remember which AAIsDead instances we actually used.
10633 struct LivenessInfo {
10634 const AAIsDead *LivenessAA = nullptr;
10635 bool AnyDead = false;
10636 };
10637
10638 /// Check if \p Cmp is a comparison we can simplify.
10639 ///
10640 /// We handle multiple cases, one in which at least one operand is an
10641 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
10642 /// operand. Return true if successful, in that case Worklist will be updated.
10643 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
10644 CmpInst::Predicate Pred, ItemInfo II,
10645 SmallVectorImpl<ItemInfo> &Worklist) {
10646
10647 // Simplify the operands first.
10648 bool UsedAssumedInformation = false;
10649 const auto &SimplifiedLHS = A.getAssumedSimplified(
10650 IRPosition::value(*LHS, getCallBaseContext()), *this,
10651 UsedAssumedInformation, AA::Intraprocedural);
10652 if (!SimplifiedLHS.has_value())
10653 return true;
10654 if (!*SimplifiedLHS)
10655 return false;
10656 LHS = *SimplifiedLHS;
10657
10658 const auto &SimplifiedRHS = A.getAssumedSimplified(
10659 IRPosition::value(*RHS, getCallBaseContext()), *this,
10660 UsedAssumedInformation, AA::Intraprocedural);
10661 if (!SimplifiedRHS.has_value())
10662 return true;
10663 if (!*SimplifiedRHS)
10664 return false;
10665 RHS = *SimplifiedRHS;
10666
10667 LLVMContext &Ctx = LHS->getContext();
10668 // Handle the trivial case first in which we don't even need to think about
10669 // null or non-null.
10670 if (LHS == RHS &&
10671 (CmpInst::isTrueWhenEqual(Pred) || CmpInst::isFalseWhenEqual(Pred))) {
10672 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
10673 CmpInst::isTrueWhenEqual(Pred));
10674 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
10675 getAnchorScope());
10676 return true;
10677 }
10678
10679 // From now on we only handle equalities (==, !=).
10680 if (!CmpInst::isEquality(Pred))
10681 return false;
10682
10683 bool LHSIsNull = isa<ConstantPointerNull>(LHS);
10684 bool RHSIsNull = isa<ConstantPointerNull>(RHS);
10685 if (!LHSIsNull && !RHSIsNull)
10686 return false;
10687
10688 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
10689 // non-nullptr operand and if we assume it's non-null we can conclude the
10690 // result of the comparison.
10691 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", 10692, __extension__
__PRETTY_FUNCTION__))
10692 "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", 10692, __extension__
__PRETTY_FUNCTION__))
;
10693
10694 // The index is the operand that we assume is not null.
10695 unsigned PtrIdx = LHSIsNull;
10696 auto &PtrNonNullAA = A.getAAFor<AANonNull>(
10697 *this, IRPosition::value(*(PtrIdx ? RHS : LHS)), DepClassTy::REQUIRED);
10698 if (!PtrNonNullAA.isAssumedNonNull())
10699 return false;
10700
10701 // The new value depends on the predicate, true for != and false for ==.
10702 Constant *NewV =
10703 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
10704 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S, getAnchorScope());
10705 return true;
10706 }
10707
10708 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
10709 SmallVectorImpl<ItemInfo> &Worklist) {
10710 const Instruction *CtxI = II.I.getCtxI();
10711 bool UsedAssumedInformation = false;
10712
10713 std::optional<Constant *> C =
10714 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
10715 bool NoValueYet = !C.has_value();
10716 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
10717 return true;
10718 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
10719 if (CI->isZero())
10720 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
10721 else
10722 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
10723 } else if (&SI == &getAssociatedValue()) {
10724 // We could not simplify the condition, assume both values.
10725 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
10726 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
10727 } else {
10728 std::optional<Value *> SimpleV = A.getAssumedSimplified(
10729 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
10730 if (!SimpleV.has_value())
10731 return true;
10732 if (*SimpleV) {
10733 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
10734 return true;
10735 }
10736 return false;
10737 }
10738 return true;
10739 }
10740
10741 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
10742 SmallVectorImpl<ItemInfo> &Worklist) {
10743 SmallSetVector<Value *, 4> PotentialCopies;
10744 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
10745 bool UsedAssumedInformation = false;
10746 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
10747 PotentialValueOrigins, *this,
10748 UsedAssumedInformation,
10749 /* OnlyExact */ true)) {
10750 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)
10751 "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)
10752 << LI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Failed to get potentially "
"loaded values for load instruction " << LI << "\n"
; } } while (false)
;
10753 return false;
10754 }
10755
10756 // Do not simplify loads that are only used in llvm.assume if we cannot also
10757 // remove all stores that may feed into the load. The reason is that the
10758 // assume is probably worth something as long as the stores are around.
10759 InformationCache &InfoCache = A.getInfoCache();
10760 if (InfoCache.isOnlyUsedByAssume(LI)) {
10761 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
10762 if (!I)
10763 return true;
10764 if (auto *SI = dyn_cast<StoreInst>(I))
10765 return A.isAssumedDead(SI->getOperandUse(0), this,
10766 /* LivenessAA */ nullptr,
10767 UsedAssumedInformation,
10768 /* CheckBBLivenessOnly */ false);
10769 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
10770 UsedAssumedInformation,
10771 /* CheckBBLivenessOnly */ false);
10772 })) {
10773 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)
10774 "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)
10775 << 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)
;
10776 return false;
10777 }
10778 }
10779
10780 // Values have to be dynamically unique or we loose the fact that a
10781 // single llvm::Value might represent two runtime values (e.g.,
10782 // stack locations in different recursive calls).
10783 const Instruction *CtxI = II.I.getCtxI();
10784 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
10785 bool AllLocal = ScopeIsLocal;
10786 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
10787 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
10788 return AA::isDynamicallyUnique(A, *this, *PC);
10789 });
10790 if (!DynamicallyUnique) {
10791 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)
10792 "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)
10793 << LI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "[AAPotentialValues] Not all potentially loaded "
"values are dynamically unique: " << LI << "\n";
} } while (false)
;
10794 return false;
10795 }
10796
10797 for (auto *PotentialCopy : PotentialCopies) {
10798 if (AllLocal) {
10799 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
10800 } else {
10801 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
10802 }
10803 }
10804 if (!AllLocal && ScopeIsLocal)
10805 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
10806 return true;
10807 }
10808
10809 bool handlePHINode(
10810 Attributor &A, PHINode &PHI, ItemInfo II,
10811 SmallVectorImpl<ItemInfo> &Worklist,
10812 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
10813 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
10814 LivenessInfo &LI = LivenessAAs[&F];
10815 if (!LI.LivenessAA)
10816 LI.LivenessAA = &A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
10817 DepClassTy::NONE);
10818 return LI;
10819 };
10820
10821 if (&PHI == &getAssociatedValue()) {
10822 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
10823 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
10824 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
10825 if (LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
10826 LI.AnyDead = true;
10827 continue;
10828 }
10829 Worklist.push_back(
10830 {{*PHI.getIncomingValue(u), IncomingBB->getTerminator()}, II.S});
10831 }
10832 return true;
10833 }
10834
10835 bool UsedAssumedInformation = false;
10836 std::optional<Value *> SimpleV = A.getAssumedSimplified(
10837 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
10838 if (!SimpleV.has_value())
10839 return true;
10840 if (!(*SimpleV))
10841 return false;
10842 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
10843 return true;
10844 }
10845
10846 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
10847 /// simplify any operand of the instruction \p I. Return true if successful,
10848 /// in that case Worklist will be updated.
10849 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
10850 SmallVectorImpl<ItemInfo> &Worklist) {
10851 bool SomeSimplified = false;
10852 bool UsedAssumedInformation = false;
10853
10854 SmallVector<Value *, 8> NewOps(I.getNumOperands());
10855 int Idx = 0;
10856 for (Value *Op : I.operands()) {
10857 const auto &SimplifiedOp = A.getAssumedSimplified(
10858 IRPosition::value(*Op, getCallBaseContext()), *this,
10859 UsedAssumedInformation, AA::Intraprocedural);
10860 // If we are not sure about any operand we are not sure about the entire
10861 // instruction, we'll wait.
10862 if (!SimplifiedOp.has_value())
10863 return true;
10864
10865 if (*SimplifiedOp)
10866 NewOps[Idx] = *SimplifiedOp;
10867 else
10868 NewOps[Idx] = Op;
10869
10870 SomeSimplified |= (NewOps[Idx] != Op);
10871 ++Idx;
10872 }
10873
10874 // We won't bother with the InstSimplify interface if we didn't simplify any
10875 // operand ourselves.
10876 if (!SomeSimplified)
10877 return false;
10878
10879 InformationCache &InfoCache = A.getInfoCache();
10880 Function *F = I.getFunction();
10881 const auto *DT =
10882 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10883 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
10884 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10885 OptimizationRemarkEmitter *ORE = nullptr;
10886
10887 const DataLayout &DL = I.getModule()->getDataLayout();
10888 SimplifyQuery Q(DL, TLI, DT, AC, &I);
10889 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q, ORE);
10890 if (!NewV || NewV == &I)
10891 return false;
10892
10893 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)
10894 << *NewV << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Generic inst " << I <<
" assumed simplified to " << *NewV << "\n"; } } while
(false)
;
10895 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
10896 return true;
10897 }
10898
10899 bool simplifyInstruction(
10900 Attributor &A, Instruction &I, ItemInfo II,
10901 SmallVectorImpl<ItemInfo> &Worklist,
10902 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
10903 if (auto *CI = dyn_cast<CmpInst>(&I))
10904 if (handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
10905 CI->getPredicate(), II, Worklist))
10906 return true;
10907
10908 switch (I.getOpcode()) {
10909 case Instruction::Select:
10910 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
10911 case Instruction::PHI:
10912 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
10913 case Instruction::Load:
10914 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
10915 default:
10916 return handleGenericInst(A, I, II, Worklist);
10917 };
10918 return false;
10919 }
10920
10921 void genericValueTraversal(Attributor &A) {
10922 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
10923
10924 Value *InitialV = &getAssociatedValue();
10925 SmallSet<ItemInfo, 16> Visited;
10926 SmallVector<ItemInfo, 16> Worklist;
10927 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
10928
10929 int Iteration = 0;
10930 do {
10931 ItemInfo II = Worklist.pop_back_val();
10932 Value *V = II.I.getValue();
10933 assert(V)(static_cast <bool> (V) ? void (0) : __assert_fail ("V"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 10933, __extension__
__PRETTY_FUNCTION__))
;
10934 const Instruction *CtxI = II.I.getCtxI();
10935 AA::ValueScope S = II.S;
10936
10937 // Check if we should process the current value. To prevent endless
10938 // recursion keep a record of the values we followed!
10939 if (!Visited.insert(II).second)
10940 continue;
10941
10942 // Make sure we limit the compile time for complex expressions.
10943 if (Iteration++ >= MaxPotentialValuesIterations) {
10944 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)
10945 << Iteration << "!\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("attributor")) { dbgs() << "Generic value traversal reached iteration limit: "
<< Iteration << "!\n"; } } while (false)
;
10946 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
10947 continue;
10948 }
10949
10950 // Explicitly look through calls with a "returned" attribute if we do
10951 // not have a pointer as stripPointerCasts only works on them.
10952 Value *NewV = nullptr;
10953 if (V->getType()->isPointerTy()) {
10954 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
10955 } else {
10956 auto *CB = dyn_cast<CallBase>(V);
10957 if (CB && CB->getCalledFunction()) {
10958 for (Argument &Arg : CB->getCalledFunction()->args())
10959 if (Arg.hasReturnedAttr()) {
10960 NewV = CB->getArgOperand(Arg.getArgNo());
10961 break;
10962 }
10963 }
10964 }
10965 if (NewV && NewV != V) {
10966 Worklist.push_back({{*NewV, CtxI}, S});
10967 continue;
10968 }
10969
10970 if (auto *CE = dyn_cast<ConstantExpr>(V)) {
10971 if (CE->getOpcode() == Instruction::ICmp)
10972 if (handleCmp(A, *CE, CE->getOperand(0), CE->getOperand(1),
10973 CmpInst::Predicate(CE->getPredicate()), II, Worklist))
10974 continue;
10975 }
10976
10977 if (auto *I = dyn_cast<Instruction>(V)) {
10978 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
10979 continue;
10980 }
10981
10982 if (V != InitialV || isa<Argument>(V))
10983 if (recurseForValue(A, IRPosition::value(*V), II.S))
10984 continue;
10985
10986 // If we haven't stripped anything we give up.
10987 if (V == InitialV && CtxI == getCtxI()) {
10988 indicatePessimisticFixpoint();
10989 return;
10990 }
10991
10992 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
10993 } while (!Worklist.empty());
10994
10995 // If we actually used liveness information so we have to record a
10996 // dependence.
10997 for (auto &It : LivenessAAs)
10998 if (It.second.AnyDead)
10999 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
11000 }
11001
11002 /// See AbstractAttribute::trackStatistics()
11003 void trackStatistics() const override {
11004 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
); }
11005 }
11006};
11007
11008struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11009 using Base = AAPotentialValuesImpl;
11010 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11011 : Base(IRP, A) {}
11012
11013 /// See AbstractAttribute::initialize(..).
11014 void initialize(Attributor &A) override {
11015 auto &Arg = cast<Argument>(getAssociatedValue());
11016 if (Arg.hasPointeeInMemoryValueAttr())
11017 indicatePessimisticFixpoint();
11018 }
11019
11020 /// See AbstractAttribute::updateImpl(...).
11021 ChangeStatus updateImpl(Attributor &A) override {
11022 auto AssumedBefore = getAssumed();
11023
11024 unsigned CSArgNo = getCallSiteArgNo();
11025
11026 bool UsedAssumedInformation = false;
11027 SmallVector<AA::ValueAndContext> Values;
11028 auto CallSitePred = [&](AbstractCallSite ACS) {
11029 const auto CSArgIRP = IRPosition::callsite_argument(ACS, CSArgNo);
11030 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11031 return false;
11032
11033 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11034 AA::Interprocedural,
11035 UsedAssumedInformation))
11036 return false;
11037
11038 return isValidState();
11039 };
11040
11041 if (!A.checkForAllCallSites(CallSitePred, *this,
11042 /* RequireAllCallSites */ true,
11043 UsedAssumedInformation))
11044 return indicatePessimisticFixpoint();
11045
11046 Function *Fn = getAssociatedFunction();
11047 bool AnyNonLocal = false;
11048 for (auto &It : Values) {
11049 if (isa<Constant>(It.getValue())) {
11050 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11051 getAnchorScope());
11052 continue;
11053 }
11054 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11055 return indicatePessimisticFixpoint();
11056
11057 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11058 if (Arg->getParent() == Fn) {
11059 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11060 getAnchorScope());
11061 continue;
11062 }
11063 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11064 getAnchorScope());
11065 AnyNonLocal = true;
11066 }
11067 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", 11067, __extension__
__PRETTY_FUNCTION__))
;
11068 if (AnyNonLocal)
11069 giveUpOnIntraprocedural(A);
11070
11071 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11072 : ChangeStatus::CHANGED;
11073 }
11074
11075 /// See AbstractAttribute::trackStatistics()
11076 void trackStatistics() const override {
11077 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
); }
11078 }
11079};
11080
11081struct AAPotentialValuesReturned
11082 : AAReturnedFromReturnedValues<AAPotentialValues, AAPotentialValuesImpl> {
11083 using Base =
11084 AAReturnedFromReturnedValues<AAPotentialValues, AAPotentialValuesImpl>;
11085 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11086 : Base(IRP, A) {}
11087
11088 /// See AbstractAttribute::initialize(..).
11089 void initialize(Attributor &A) override {
11090 if (A.hasSimplificationCallback(getIRPosition()))
11091 indicatePessimisticFixpoint();
11092 else
11093 AAPotentialValues::initialize(A);
11094 }
11095
11096 ChangeStatus manifest(Attributor &A) override {
11097 // We queried AAValueSimplify for the returned values so they will be
11098 // replaced if a simplified form was found. Nothing to do here.
11099 return ChangeStatus::UNCHANGED;
11100 }
11101
11102 ChangeStatus indicatePessimisticFixpoint() override {
11103 return AAPotentialValues::indicatePessimisticFixpoint();
11104 }
11105
11106 /// See AbstractAttribute::trackStatistics()
11107 void trackStatistics() const override {
11108 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); }
11109 }
11110};
11111
11112struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11113 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11114 : AAPotentialValuesImpl(IRP, A) {}
11115
11116 /// See AbstractAttribute::updateImpl(...).
11117 ChangeStatus updateImpl(Attributor &A) override {
11118 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"
, 11119)
11119 "not be called")::llvm::llvm_unreachable_internal("AAPotentialValues(Function|CallSite)::updateImpl will "
"not be called", "llvm/lib/Transforms/IPO/AttributorAttributes.cpp"
, 11119)
;
11120 }
11121
11122 /// See AbstractAttribute::trackStatistics()
11123 void trackStatistics() const override {
11124 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
); }
11125 }
11126};
11127
11128struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11129 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11130 : AAPotentialValuesFunction(IRP, A) {}
11131
11132 /// See AbstractAttribute::trackStatistics()
11133 void trackStatistics() const override {
11134 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); }
11135 }
11136};
11137
11138struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11139 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11140 : AAPotentialValuesImpl(IRP, A) {}
11141
11142 /// See AbstractAttribute::updateImpl(...).
11143 ChangeStatus updateImpl(Attributor &A) override {
11144 auto AssumedBefore = getAssumed();
11145
11146 Function *Callee = getAssociatedFunction();
11147 if (!Callee)
11148 return indicatePessimisticFixpoint();
11149
11150 bool UsedAssumedInformation = false;
11151 auto *CB = cast<CallBase>(getCtxI());
11152 if (CB->isMustTailCall() &&
11153 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11154 UsedAssumedInformation))
11155 return indicatePessimisticFixpoint();
11156
11157 SmallVector<AA::ValueAndContext> Values;
11158 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11159 Values, AA::Intraprocedural,
11160 UsedAssumedInformation))
11161 return indicatePessimisticFixpoint();
11162
11163 Function *Caller = CB->getCaller();
11164
11165 bool AnyNonLocal = false;
11166 for (auto &It : Values) {
11167 Value *V = It.getValue();
11168 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11169 V, *CB, *this, UsedAssumedInformation);
11170 if (!CallerV.has_value()) {
11171 // Nothing to do as long as no value was determined.
11172 continue;
11173 }
11174 V = *CallerV ? *CallerV : V;
11175 if (AA::isDynamicallyUnique(A, *this, *V) &&
11176 AA::isValidInScope(*V, Caller)) {
11177 if (*CallerV) {
11178 SmallVector<AA::ValueAndContext> ArgValues;
11179 IRPosition IRP = IRPosition::value(*V);
11180 if (auto *Arg = dyn_cast<Argument>(V))
11181 if (Arg->getParent() == CB->getCalledFunction())
11182 IRP = IRPosition::callsite_argument(*CB, Arg->getArgNo());
11183 if (recurseForValue(A, IRP, AA::AnyScope))
11184 continue;
11185 }
11186 addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
11187 } else {
11188 AnyNonLocal = true;
11189 break;
11190 }
11191 }
11192 if (AnyNonLocal) {
11193 Values.clear();
11194 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11195 Values, AA::Interprocedural,
11196 UsedAssumedInformation))
11197 return indicatePessimisticFixpoint();
11198 AnyNonLocal = false;
11199 getState() = PotentialLLVMValuesState::getBestState();
11200 for (auto &It : Values) {
11201 Value *V = It.getValue();
11202 if (!AA::isDynamicallyUnique(A, *this, *V))
11203 return indicatePessimisticFixpoint();
11204 if (AA::isValidInScope(*V, Caller)) {
11205 addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
11206 } else {
11207 AnyNonLocal = true;
11208 addValue(A, getState(), *V, CB, AA::Interprocedural,
11209 getAnchorScope());
11210 }
11211 }
11212 if (AnyNonLocal)
11213 giveUpOnIntraprocedural(A);
11214 }
11215 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11216 : ChangeStatus::CHANGED;
11217 }
11218
11219 ChangeStatus indicatePessimisticFixpoint() override {
11220 return AAPotentialValues::indicatePessimisticFixpoint();
11221 }
11222
11223 /// See AbstractAttribute::trackStatistics()
11224 void trackStatistics() const override {
11225 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
); }
11226 }
11227};
11228
11229struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11230 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11231 : AAPotentialValuesFloating(IRP, A) {}
11232
11233 /// See AbstractAttribute::trackStatistics()
11234 void trackStatistics() const override {
11235 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); }
11236 }
11237};
11238} // namespace
11239
11240/// ---------------------- Assumption Propagation ------------------------------
11241namespace {
11242struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11243 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11244 const DenseSet<StringRef> &Known)
11245 : AAAssumptionInfo(IRP, A, Known) {}
11246
11247 bool hasAssumption(const StringRef Assumption) const override {
11248 return isValidState() && setContains(Assumption);
11249 }
11250
11251 /// See AbstractAttribute::getAsStr()
11252 const std::string getAsStr() const override {
11253 const SetContents &Known = getKnown();
11254 const SetContents &Assumed = getAssumed();
11255
11256 const std::string KnownStr =
11257 llvm::join(Known.getSet().begin(), Known.getSet().end(), ",");
11258 const std::string AssumedStr =
11259 (Assumed.isUniversal())
11260 ? "Universal"
11261 : llvm::join(Assumed.getSet().begin(), Assumed.getSet().end(), ",");
11262
11263 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11264 }
11265};
11266
11267/// Propagates assumption information from parent functions to all of their
11268/// successors. An assumption can be propagated if the containing function
11269/// dominates the called function.
11270///
11271/// We start with a "known" set of assumptions already valid for the associated
11272/// function and an "assumed" set that initially contains all possible
11273/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11274/// contents as concrete values are known. The concrete values are seeded by the
11275/// first nodes that are either entries into the call graph, or contains no
11276/// assumptions. Each node is updated as the intersection of the assumed state
11277/// with all of its predecessors.
11278struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11279 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11280 : AAAssumptionInfoImpl(IRP, A,
11281 getAssumptions(*IRP.getAssociatedFunction())) {}
11282
11283 /// See AbstractAttribute::manifest(...).
11284 ChangeStatus manifest(Attributor &A) override {
11285 const auto &Assumptions = getKnown();
11286
11287 // Don't manifest a universal set if it somehow made it here.
11288 if (Assumptions.isUniversal())
11289 return ChangeStatus::UNCHANGED;
11290
11291 Function *AssociatedFunction = getAssociatedFunction();
11292
11293 bool Changed = addAssumptions(*AssociatedFunction, Assumptions.getSet());
11294
11295 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11296 }
11297
11298 /// See AbstractAttribute::updateImpl(...).
11299 ChangeStatus updateImpl(Attributor &A) override {
11300 bool Changed = false;
11301
11302 auto CallSitePred = [&](AbstractCallSite ACS) {
11303 const auto &AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11304 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11305 DepClassTy::REQUIRED);
11306 // Get the set of assumptions shared by all of this function's callers.
11307 Changed |= getIntersection(AssumptionAA.getAssumed());
11308 return !getAssumed().empty() || !getKnown().empty();
11309 };
11310
11311 bool UsedAssumedInformation = false;
11312 // Get the intersection of all assumptions held by this node's predecessors.
11313 // If we don't know all the call sites then this is either an entry into the
11314 // call graph or an empty node. This node is known to only contain its own
11315 // assumptions and can be propagated to its successors.
11316 if (!A.checkForAllCallSites(CallSitePred, *this, true,
11317 UsedAssumedInformation))
11318 return indicatePessimisticFixpoint();
11319
11320 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11321 }
11322
11323 void trackStatistics() const override {}
11324};
11325
11326/// Assumption Info defined for call sites.
11327struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11328
11329 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11330 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11331
11332 /// See AbstractAttribute::initialize(...).
11333 void initialize(Attributor &A) override {
11334 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11335 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11336 }
11337
11338 /// See AbstractAttribute::manifest(...).
11339 ChangeStatus manifest(Attributor &A) override {
11340 // Don't manifest a universal set if it somehow made it here.
11341 if (getKnown().isUniversal())
11342 return ChangeStatus::UNCHANGED;
11343
11344 CallBase &AssociatedCall = cast<CallBase>(getAssociatedValue());
11345 bool Changed = addAssumptions(AssociatedCall, getAssumed().getSet());
11346
11347 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11348 }
11349
11350 /// See AbstractAttribute::updateImpl(...).
11351 ChangeStatus updateImpl(Attributor &A) override {
11352 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11353 auto &AssumptionAA =
11354 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11355 bool Changed = getIntersection(AssumptionAA.getAssumed());
11356 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11357 }
11358
11359 /// See AbstractAttribute::trackStatistics()
11360 void trackStatistics() const override {}
11361
11362private:
11363 /// Helper to initialized the known set as all the assumptions this call and
11364 /// the callee contain.
11365 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11366 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
11367 auto Assumptions = getAssumptions(CB);
11368 if (const Function *F = CB.getCaller())
11369 set_union(Assumptions, getAssumptions(*F));
11370 if (Function *F = IRP.getAssociatedFunction())
11371 set_union(Assumptions, getAssumptions(*F));
11372 return Assumptions;
11373 }
11374};
11375} // namespace
11376
11377AACallGraphNode *AACallEdgeIterator::operator*() const {
11378 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11379 &A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
11380}
11381
11382void AttributorCallGraph::print() { llvm::WriteGraph(outs(), this); }
11383
11384/// ------------------------ UnderlyingObjects ---------------------------------
11385
11386namespace {
11387struct AAUnderlyingObjectsImpl
11388 : StateWrapper<BooleanState, AAUnderlyingObjects> {
11389 using BaseTy = StateWrapper<BooleanState, AAUnderlyingObjects>;
11390 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
11391
11392 /// See AbstractAttribute::getAsStr().
11393 const std::string getAsStr() const override {
11394 return std::string("UnderlyingObjects ") +
11395 (isValidState()
11396 ? (std::string("inter #") +
11397 std::to_string(InterAssumedUnderlyingObjects.size()) +
11398 " objs" + std::string(", intra #") +
11399 std::to_string(IntraAssumedUnderlyingObjects.size()) +
11400 " objs")
11401 : "<invalid>");
11402 }
11403
11404 /// See AbstractAttribute::trackStatistics()
11405 void trackStatistics() const override {}
11406
11407 /// See AbstractAttribute::updateImpl(...).
11408 ChangeStatus updateImpl(Attributor &A) override {
11409 auto &Ptr = getAssociatedValue();
11410
11411 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11412 AA::ValueScope Scope) {
11413 bool UsedAssumedInformation = false;
11414 SmallPtrSet<Value *, 8> SeenObjects;
11415 SmallVector<AA::ValueAndContext> Values;
11416
11417 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
11418 Scope, UsedAssumedInformation))
11419 return UnderlyingObjects.insert(&Ptr);
11420
11421 bool Changed = false;
11422
11423 for (unsigned I = 0; I < Values.size(); ++I) {
11424 auto &VAC = Values[I];
11425 auto *Obj = VAC.getValue();
11426 Value *UO = getUnderlyingObject(Obj);
11427 if (UO && UO != VAC.getValue() && SeenObjects.insert(UO).second) {
11428 const auto &OtherAA = A.getAAFor<AAUnderlyingObjects>(
11429 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
11430 auto Pred = [&Values](Value &V) {
11431 Values.emplace_back(V, nullptr);
11432 return true;
11433 };
11434
11435 if (!OtherAA.forallUnderlyingObjects(Pred, Scope))
11436 llvm_unreachable(::llvm::llvm_unreachable_internal("The forall call should not return false at this position"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11437)
11437 "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", 11437)
;
11438
11439 continue;
11440 }
11441
11442 if (isa<SelectInst>(Obj) || isa<PHINode>(Obj)) {
11443 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope);
11444 continue;
11445 }
11446
11447 Changed |= UnderlyingObjects.insert(Obj);
11448 }
11449
11450 return Changed;
11451 };
11452
11453 bool Changed = false;
11454 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
11455 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
11456
11457 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11458 }
11459
11460 bool forallUnderlyingObjects(
11461 function_ref<bool(Value &)> Pred,
11462 AA::ValueScope Scope = AA::Interprocedural) const override {
11463 if (!isValidState())
11464 return Pred(getAssociatedValue());
11465
11466 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
11467 ? IntraAssumedUnderlyingObjects
11468 : InterAssumedUnderlyingObjects;
11469 for (Value *Obj : AssumedUnderlyingObjects)
11470 if (!Pred(*Obj))
11471 return false;
11472
11473 return true;
11474 }
11475
11476private:
11477 /// Handle the case where the value is not the actual underlying value, such
11478 /// as a phi node or a select instruction.
11479 bool handleIndirect(Attributor &A, Value &V,
11480 SmallSetVector<Value *, 8> &UnderlyingObjects,
11481 AA::ValueScope Scope) {
11482 bool Changed = false;
11483 const auto &AA = A.getAAFor<AAUnderlyingObjects>(
11484 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
11485 auto Pred = [&](Value &V) {
11486 Changed |= UnderlyingObjects.insert(&V);
11487 return true;
11488 };
11489 if (!AA.forallUnderlyingObjects(Pred, Scope))
11490 llvm_unreachable(::llvm::llvm_unreachable_internal("The forall call should not return false at this position"
, "llvm/lib/Transforms/IPO/AttributorAttributes.cpp", 11491)
11491 "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", 11491)
;
11492 return Changed;
11493 }
11494
11495 /// All the underlying objects collected so far via intra procedural scope.
11496 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11497 /// All the underlying objects collected so far via inter procedural scope.
11498 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11499};
11500
11501struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
11502 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
11503 : AAUnderlyingObjectsImpl(IRP, A) {}
11504};
11505
11506struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
11507 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
11508 : AAUnderlyingObjectsImpl(IRP, A) {}
11509};
11510
11511struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
11512 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
11513 : AAUnderlyingObjectsImpl(IRP, A) {}
11514};
11515
11516struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
11517 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
11518 : AAUnderlyingObjectsImpl(IRP, A) {}
11519};
11520
11521struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
11522 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
11523 : AAUnderlyingObjectsImpl(IRP, A) {}
11524};
11525
11526struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
11527 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
11528 : AAUnderlyingObjectsImpl(IRP, A) {}
11529};
11530
11531struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
11532 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
11533 : AAUnderlyingObjectsImpl(IRP, A) {}
11534};
11535}
11536
11537const char AAReturnedValues::ID = 0;
11538const char AANoUnwind::ID = 0;
11539const char AANoSync::ID = 0;
11540const char AANoFree::ID = 0;
11541const char AANonNull::ID = 0;
11542const char AANoRecurse::ID = 0;
11543const char AAWillReturn::ID = 0;
11544const char AAUndefinedBehavior::ID = 0;
11545const char AANoAlias::ID = 0;
11546const char AAIntraFnReachability::ID = 0;
11547const char AANoReturn::ID = 0;
11548const char AAIsDead::ID = 0;
11549const char AADereferenceable::ID = 0;
11550const char AAAlign::ID = 0;
11551const char AAInstanceInfo::ID = 0;
11552const char AANoCapture::ID = 0;
11553const char AAValueSimplify::ID = 0;
11554const char AAHeapToStack::ID = 0;
11555const char AAPrivatizablePtr::ID = 0;
11556const char AAMemoryBehavior::ID = 0;
11557const char AAMemoryLocation::ID = 0;
11558const char AAValueConstantRange::ID = 0;
11559const char AAPotentialConstantValues::ID = 0;
11560const char AAPotentialValues::ID = 0;
11561const char AANoUndef::ID = 0;
11562const char AACallEdges::ID = 0;
11563const char AAInterFnReachability::ID = 0;
11564const char AAPointerInfo::ID = 0;
11565const char AAAssumptionInfo::ID = 0;
11566const char AAUnderlyingObjects::ID = 0;
11567
11568// Macro magic to create the static generator function for attributes that
11569// follow the naming scheme.
11570
11571#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
11572 case IRPosition::PK: \
11573 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"
, 11573)
;
11574
11575#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
11576 case IRPosition::PK: \
11577 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
11578 ++NumAAs; \
11579 break;
11580
11581#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11582 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11583 CLASS *AA = nullptr; \
11584 switch (IRP.getPositionKind()) { \
11585 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11586 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
11587 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
11588 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11589 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
11590 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
11591 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11592 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11593 } \
11594 return *AA; \
11595 }
11596
11597#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11598 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11599 CLASS *AA = nullptr; \
11600 switch (IRP.getPositionKind()) { \
11601 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11602 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
11603 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
11604 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11605 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11606 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
11607 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11608 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11609 } \
11610 return *AA; \
11611 }
11612
11613#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11614 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11615 CLASS *AA = nullptr; \
11616 switch (IRP.getPositionKind()) { \
11617 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11618 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11619 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11620 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11621 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11622 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
11623 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11624 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11625 } \
11626 return *AA; \
11627 }
11628
11629#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11630 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11631 CLASS *AA = nullptr; \
11632 switch (IRP.getPositionKind()) { \
11633 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11634 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
11635 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
11636 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11637 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
11638 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
11639 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
11640 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11641 } \
11642 return *AA; \
11643 }
11644
11645#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11646 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11647 CLASS *AA = nullptr; \
11648 switch (IRP.getPositionKind()) { \
11649 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11650 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11651 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11652 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11653 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11654 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11655 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11656 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11657 } \
11658 return *AA; \
11659 }
11660
11661CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
11662CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
11663CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
11664CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
11665CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
11666CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues)
11667CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation)
11668CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges)
11669CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAssumptionInfo)
11670
11671CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
11672CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
11673CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPrivatizablePtr)
11674CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
11675CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
11676CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInstanceInfo)
11677CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
11678CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange)
11679CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialConstantValues)
11680CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues)
11681CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef)
11682CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo)
11683
11684CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)
11685CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
11686CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
11687CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUnderlyingObjects)
11688
11689CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)
11690CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior)
11691CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIntraFnReachability)
11692CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInterFnReachability)
11693
11694CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)
11695
11696#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
11697#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
11698#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
11699#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
11700#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
11701#undef SWITCH_PK_CREATE
11702#undef SWITCH_PK_INV

/build/source/llvm/include/llvm/Analysis/ValueTracking.h

1//===- llvm/Analysis/ValueTracking.h - Walk computations --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains routines that help analyze properties that chains of
10// computations have.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ANALYSIS_VALUETRACKING_H
15#define LLVM_ANALYSIS_VALUETRACKING_H
16
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/SmallSet.h"
19#include "llvm/IR/Constants.h"
20#include "llvm/IR/DataLayout.h"
21#include "llvm/IR/InstrTypes.h"
22#include "llvm/IR/Intrinsics.h"
23#include <cassert>
24#include <cstdint>
25
26namespace llvm {
27
28class Operator;
29class AddOperator;
30class AllocaInst;
31class APInt;
32class AssumptionCache;
33class DominatorTree;
34class GEPOperator;
35class LoadInst;
36class WithOverflowInst;
37struct KnownBits;
38class Loop;
39class LoopInfo;
40class MDNode;
41class OptimizationRemarkEmitter;
42class StringRef;
43class TargetLibraryInfo;
44class Value;
45
46constexpr unsigned MaxAnalysisRecursionDepth = 6;
47
48/// Determine which bits of V are known to be either zero or one and return
49/// them in the KnownZero/KnownOne bit sets.
50///
51/// This function is defined on values with integer type, values with pointer
52/// type, and vectors of integers. In the case
53/// where V is a vector, the known zero and known one values are the
54/// same width as the vector element, and the bit is set only if it is true
55/// for all of the elements in the vector.
56void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL,
57 unsigned Depth = 0, AssumptionCache *AC = nullptr,
58 const Instruction *CxtI = nullptr,
59 const DominatorTree *DT = nullptr,
60 OptimizationRemarkEmitter *ORE = nullptr,
61 bool UseInstrInfo = true);
62
63/// Determine which bits of V are known to be either zero or one and return
64/// them in the KnownZero/KnownOne bit sets.
65///
66/// This function is defined on values with integer type, values with pointer
67/// type, and vectors of integers. In the case
68/// where V is a vector, the known zero and known one values are the
69/// same width as the vector element, and the bit is set only if it is true
70/// for all of the demanded elements in the vector.
71void computeKnownBits(const Value *V, const APInt &DemandedElts,
72 KnownBits &Known, const DataLayout &DL,
73 unsigned Depth = 0, AssumptionCache *AC = nullptr,
74 const Instruction *CxtI = nullptr,
75 const DominatorTree *DT = nullptr,
76 OptimizationRemarkEmitter *ORE = nullptr,
77 bool UseInstrInfo = true);
78
79/// Returns the known bits rather than passing by reference.
80KnownBits computeKnownBits(const Value *V, const DataLayout &DL,
81 unsigned Depth = 0, AssumptionCache *AC = nullptr,
82 const Instruction *CxtI = nullptr,
83 const DominatorTree *DT = nullptr,
84 OptimizationRemarkEmitter *ORE = nullptr,
85 bool UseInstrInfo = true);
86
87/// Returns the known bits rather than passing by reference.
88KnownBits computeKnownBits(const Value *V, const APInt &DemandedElts,
89 const DataLayout &DL, unsigned Depth = 0,
90 AssumptionCache *AC = nullptr,
91 const Instruction *CxtI = nullptr,
92 const DominatorTree *DT = nullptr,
93 OptimizationRemarkEmitter *ORE = nullptr,
94 bool UseInstrInfo = true);
95
96/// Compute known bits from the range metadata.
97/// \p KnownZero the set of bits that are known to be zero
98/// \p KnownOne the set of bits that are known to be one
99void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, KnownBits &Known);
100
101/// Return true if LHS and RHS have no common bits set.
102bool haveNoCommonBitsSet(const Value *LHS, const Value *RHS,
103 const DataLayout &DL, AssumptionCache *AC = nullptr,
104 const Instruction *CxtI = nullptr,
105 const DominatorTree *DT = nullptr,
106 bool UseInstrInfo = true);
107
108/// Return true if the given value is known to have exactly one bit set when
109/// defined. For vectors return true if every element is known to be a power
110/// of two when defined. Supports values with integer or pointer type and
111/// vectors of integers. If 'OrZero' is set, then return true if the given
112/// value is either a power of two or zero.
113bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL,
114 bool OrZero = false, unsigned Depth = 0,
115 AssumptionCache *AC = nullptr,
116 const Instruction *CxtI = nullptr,
117 const DominatorTree *DT = nullptr,
118 bool UseInstrInfo = true);
119
120bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI);
121
122/// Return true if the given value is known to be non-zero when defined. For
123/// vectors, return true if every element is known to be non-zero when
124/// defined. For pointers, if the context instruction and dominator tree are
125/// specified, perform context-sensitive analysis and return true if the
126/// pointer couldn't possibly be null at the specified instruction.
127/// Supports values with integer or pointer type and vectors of integers.
128bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0,
129 AssumptionCache *AC = nullptr,
130 const Instruction *CxtI = nullptr,
131 const DominatorTree *DT = nullptr,
132 bool UseInstrInfo = true);
133
134/// Return true if the two given values are negation.
135/// Currently can recoginze Value pair:
136/// 1: <X, Y> if X = sub (0, Y) or Y = sub (0, X)
137/// 2: <X, Y> if X = sub (A, B) and Y = sub (B, A)
138bool isKnownNegation(const Value *X, const Value *Y, bool NeedNSW = false);
139
140/// Returns true if the give value is known to be non-negative.
141bool isKnownNonNegative(const Value *V, const DataLayout &DL,
142 unsigned Depth = 0, AssumptionCache *AC = nullptr,
143 const Instruction *CxtI = nullptr,
144 const DominatorTree *DT = nullptr,
145 bool UseInstrInfo = true);
146
147/// Returns true if the given value is known be positive (i.e. non-negative
148/// and non-zero).
149bool isKnownPositive(const Value *V, const DataLayout &DL, unsigned Depth = 0,
150 AssumptionCache *AC = nullptr,
151 const Instruction *CxtI = nullptr,
152 const DominatorTree *DT = nullptr,
153 bool UseInstrInfo = true);
154
155/// Returns true if the given value is known be negative (i.e. non-positive
156/// and non-zero).
157bool isKnownNegative(const Value *V, const DataLayout &DL, unsigned Depth = 0,
158 AssumptionCache *AC = nullptr,
159 const Instruction *CxtI = nullptr,
160 const DominatorTree *DT = nullptr,
161 bool UseInstrInfo = true);
162
163/// Return true if the given values are known to be non-equal when defined.
164/// Supports scalar integer types only.
165bool isKnownNonEqual(const Value *V1, const Value *V2, const DataLayout &DL,
166 AssumptionCache *AC = nullptr,
167 const Instruction *CxtI = nullptr,
168 const DominatorTree *DT = nullptr,
169 bool UseInstrInfo = true);
170
171/// Return true if 'V & Mask' is known to be zero. We use this predicate to
172/// simplify operations downstream. Mask is known to be zero for bits that V
173/// cannot have.
174///
175/// This function is defined on values with integer type, values with pointer
176/// type, and vectors of integers. In the case
177/// where V is a vector, the mask, known zero, and known one values are the
178/// same width as the vector element, and the bit is set only if it is true
179/// for all of the elements in the vector.
180bool MaskedValueIsZero(const Value *V, const APInt &Mask, const DataLayout &DL,
181 unsigned Depth = 0, AssumptionCache *AC = nullptr,
182 const Instruction *CxtI = nullptr,
183 const DominatorTree *DT = nullptr,
184 bool UseInstrInfo = true);
185
186/// Return the number of times the sign bit of the register is replicated into
187/// the other bits. We know that at least 1 bit is always equal to the sign
188/// bit (itself), but other cases can give us information. For example,
189/// immediately after an "ashr X, 2", we know that the top 3 bits are all
190/// equal to each other, so we return 3. For vectors, return the number of
191/// sign bits for the vector element with the mininum number of known sign
192/// bits.
193unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL,
194 unsigned Depth = 0, AssumptionCache *AC = nullptr,
195 const Instruction *CxtI = nullptr,
196 const DominatorTree *DT = nullptr,
197 bool UseInstrInfo = true);
198
199/// Get the upper bound on bit size for this Value \p Op as a signed integer.
200/// i.e. x == sext(trunc(x to MaxSignificantBits) to bitwidth(x)).
201/// Similar to the APInt::getSignificantBits function.
202unsigned ComputeMaxSignificantBits(const Value *Op, const DataLayout &DL,
203 unsigned Depth = 0,
204 AssumptionCache *AC = nullptr,
205 const Instruction *CxtI = nullptr,
206 const DominatorTree *DT = nullptr);
207
208/// Map a call instruction to an intrinsic ID. Libcalls which have equivalent
209/// intrinsics are treated as-if they were intrinsics.
210Intrinsic::ID getIntrinsicForCallSite(const CallBase &CB,
211 const TargetLibraryInfo *TLI);
212
213/// Return true if we can prove that the specified FP value is never equal to
214/// -0.0.
215bool CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI,
216 unsigned Depth = 0);
217
218/// Return true if we can prove that the specified FP value is either NaN or
219/// never less than -0.0.
220///
221/// NaN --> true
222/// +0 --> true
223/// -0 --> true
224/// x > +0 --> true
225/// x < -0 --> false
226bool CannotBeOrderedLessThanZero(const Value *V, const TargetLibraryInfo *TLI);
227
228/// Return true if the floating-point scalar value is not an infinity or if
229/// the floating-point vector value has no infinities. Return false if a value
230/// could ever be infinity.
231bool isKnownNeverInfinity(const Value *V, const TargetLibraryInfo *TLI,
232 unsigned Depth = 0);
233
234/// Return true if the floating-point scalar value is not a NaN or if the
235/// floating-point vector value has no NaN elements. Return false if a value
236/// could ever be NaN.
237bool isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
238 unsigned Depth = 0);
239
240/// Return true if we can prove that the specified FP value's sign bit is 0.
241///
242/// NaN --> true/false (depending on the NaN's sign bit)
243/// +0 --> true
244/// -0 --> false
245/// x > +0 --> true
246/// x < -0 --> false
247bool SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI);
248
249/// If the specified value can be set by repeating the same byte in memory,
250/// return the i8 value that it is represented with. This is true for all i8
251/// values obviously, but is also true for i32 0, i32 -1, i16 0xF0F0, double
252/// 0.0 etc. If the value can't be handled with a repeated byte store (e.g.
253/// i16 0x1234), return null. If the value is entirely undef and padding,
254/// return undef.
255Value *isBytewiseValue(Value *V, const DataLayout &DL);
256
257/// Given an aggregate and an sequence of indices, see if the scalar value
258/// indexed is already around as a register, for example if it were inserted
259/// directly into the aggregate.
260///
261/// If InsertBefore is not null, this function will duplicate (modified)
262/// insertvalues when a part of a nested struct is extracted.
263Value *FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range,
264 Instruction *InsertBefore = nullptr);
265
266/// Analyze the specified pointer to see if it can be expressed as a base
267/// pointer plus a constant offset. Return the base and offset to the caller.
268///
269/// This is a wrapper around Value::stripAndAccumulateConstantOffsets that
270/// creates and later unpacks the required APInt.
271inline Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
272 const DataLayout &DL,
273 bool AllowNonInbounds = true) {
274 APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
17
Called C++ object pointer is null
275 Value *Base =
276 Ptr->stripAndAccumulateConstantOffsets(DL, OffsetAPInt, AllowNonInbounds);
277
278 Offset = OffsetAPInt.getSExtValue();
279 return Base;
280}
281inline const Value *
282GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset,
283 const DataLayout &DL,
284 bool AllowNonInbounds = true) {
285 return GetPointerBaseWithConstantOffset(const_cast<Value *>(Ptr), Offset, DL,
15
Passing null pointer value via 1st parameter 'Ptr'
16
Calling 'GetPointerBaseWithConstantOffset'
286 AllowNonInbounds);
287}
288
289/// Returns true if the GEP is based on a pointer to a string (array of
290// \p CharSize integers) and is indexing into this string.
291bool isGEPBasedOnPointerToString(const GEPOperator *GEP, unsigned CharSize = 8);
292
293/// Represents offset+length into a ConstantDataArray.
294struct ConstantDataArraySlice {
295 /// ConstantDataArray pointer. nullptr indicates a zeroinitializer (a valid
296 /// initializer, it just doesn't fit the ConstantDataArray interface).
297 const ConstantDataArray *Array;
298
299 /// Slice starts at this Offset.
300 uint64_t Offset;
301
302 /// Length of the slice.
303 uint64_t Length;
304
305 /// Moves the Offset and adjusts Length accordingly.
306 void move(uint64_t Delta) {
307 assert(Delta < Length)(static_cast <bool> (Delta < Length) ? void (0) : __assert_fail
("Delta < Length", "llvm/include/llvm/Analysis/ValueTracking.h"
, 307, __extension__ __PRETTY_FUNCTION__))
;
308 Offset += Delta;
309 Length -= Delta;
310 }
311
312 /// Convenience accessor for elements in the slice.
313 uint64_t operator[](unsigned I) const {
314 return Array == nullptr ? 0 : Array->getElementAsInteger(I + Offset);
315 }
316};
317
318/// Returns true if the value \p V is a pointer into a ConstantDataArray.
319/// If successful \p Slice will point to a ConstantDataArray info object
320/// with an appropriate offset.
321bool getConstantDataArrayInfo(const Value *V, ConstantDataArraySlice &Slice,
322 unsigned ElementSize, uint64_t Offset = 0);
323
324/// This function computes the length of a null-terminated C string pointed to
325/// by V. If successful, it returns true and returns the string in Str. If
326/// unsuccessful, it returns false. This does not include the trailing null
327/// character by default. If TrimAtNul is set to false, then this returns any
328/// trailing null characters as well as any other characters that come after
329/// it.
330bool getConstantStringInfo(const Value *V, StringRef &Str,
331 bool TrimAtNul = true);
332
333/// If we can compute the length of the string pointed to by the specified
334/// pointer, return 'len+1'. If we can't, return 0.
335uint64_t GetStringLength(const Value *V, unsigned CharSize = 8);
336
337/// This function returns call pointer argument that is considered the same by
338/// aliasing rules. You CAN'T use it to replace one value with another. If
339/// \p MustPreserveNullness is true, the call must preserve the nullness of
340/// the pointer.
341const Value *getArgumentAliasingToReturnedPointer(const CallBase *Call,
342 bool MustPreserveNullness);
343inline Value *getArgumentAliasingToReturnedPointer(CallBase *Call,
344 bool MustPreserveNullness) {
345 return const_cast<Value *>(getArgumentAliasingToReturnedPointer(
346 const_cast<const CallBase *>(Call), MustPreserveNullness));
347}
348
349/// {launder,strip}.invariant.group returns pointer that aliases its argument,
350/// and it only captures pointer by returning it.
351/// These intrinsics are not marked as nocapture, because returning is
352/// considered as capture. The arguments are not marked as returned neither,
353/// because it would make it useless. If \p MustPreserveNullness is true,
354/// the intrinsic must preserve the nullness of the pointer.
355bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
356 const CallBase *Call, bool MustPreserveNullness);
357
358/// This method strips off any GEP address adjustments and pointer casts from
359/// the specified value, returning the original object being addressed. Note
360/// that the returned value has pointer type if the specified value does. If
361/// the MaxLookup value is non-zero, it limits the number of instructions to
362/// be stripped off.
363const Value *getUnderlyingObject(const Value *V, unsigned MaxLookup = 6);
364inline Value *getUnderlyingObject(Value *V, unsigned MaxLookup = 6) {
365 // Force const to avoid infinite recursion.
366 const Value *VConst = V;
367 return const_cast<Value *>(getUnderlyingObject(VConst, MaxLookup));
368}
369
370/// This method is similar to getUnderlyingObject except that it can
371/// look through phi and select instructions and return multiple objects.
372///
373/// If LoopInfo is passed, loop phis are further analyzed. If a pointer
374/// accesses different objects in each iteration, we don't look through the
375/// phi node. E.g. consider this loop nest:
376///
377/// int **A;
378/// for (i)
379/// for (j) {
380/// A[i][j] = A[i-1][j] * B[j]
381/// }
382///
383/// This is transformed by Load-PRE to stash away A[i] for the next iteration
384/// of the outer loop:
385///
386/// Curr = A[0]; // Prev_0
387/// for (i: 1..N) {
388/// Prev = Curr; // Prev = PHI (Prev_0, Curr)
389/// Curr = A[i];
390/// for (j: 0..N) {
391/// Curr[j] = Prev[j] * B[j]
392/// }
393/// }
394///
395/// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects
396/// should not assume that Curr and Prev share the same underlying object thus
397/// it shouldn't look through the phi above.
398void getUnderlyingObjects(const Value *V,
399 SmallVectorImpl<const Value *> &Objects,
400 LoopInfo *LI = nullptr, unsigned MaxLookup = 6);
401
402/// This is a wrapper around getUnderlyingObjects and adds support for basic
403/// ptrtoint+arithmetic+inttoptr sequences.
404bool getUnderlyingObjectsForCodeGen(const Value *V,
405 SmallVectorImpl<Value *> &Objects);
406
407/// Returns unique alloca where the value comes from, or nullptr.
408/// If OffsetZero is true check that V points to the begining of the alloca.
409AllocaInst *findAllocaForValue(Value *V, bool OffsetZero = false);
410inline const AllocaInst *findAllocaForValue(const Value *V,
411 bool OffsetZero = false) {
412 return findAllocaForValue(const_cast<Value *>(V), OffsetZero);
413}
414
415/// Return true if the only users of this pointer are lifetime markers.
416bool onlyUsedByLifetimeMarkers(const Value *V);
417
418/// Return true if the only users of this pointer are lifetime markers or
419/// droppable instructions.
420bool onlyUsedByLifetimeMarkersOrDroppableInsts(const Value *V);
421
422/// Return true if speculation of the given load must be suppressed to avoid
423/// ordering or interfering with an active sanitizer. If not suppressed,
424/// dereferenceability and alignment must be proven separately. Note: This
425/// is only needed for raw reasoning; if you use the interface below
426/// (isSafeToSpeculativelyExecute), this is handled internally.
427bool mustSuppressSpeculation(const LoadInst &LI);
428
429/// Return true if the instruction does not have any effects besides
430/// calculating the result and does not have undefined behavior.
431///
432/// This method never returns true for an instruction that returns true for
433/// mayHaveSideEffects; however, this method also does some other checks in
434/// addition. It checks for undefined behavior, like dividing by zero or
435/// loading from an invalid pointer (but not for undefined results, like a
436/// shift with a shift amount larger than the width of the result). It checks
437/// for malloc and alloca because speculatively executing them might cause a
438/// memory leak. It also returns false for instructions related to control
439/// flow, specifically terminators and PHI nodes.
440///
441/// If the CtxI is specified this method performs context-sensitive analysis
442/// and returns true if it is safe to execute the instruction immediately
443/// before the CtxI.
444///
445/// If the CtxI is NOT specified this method only looks at the instruction
446/// itself and its operands, so if this method returns true, it is safe to
447/// move the instruction as long as the correct dominance relationships for
448/// the operands and users hold.
449///
450/// This method can return true for instructions that read memory;
451/// for such instructions, moving them may change the resulting value.
452bool isSafeToSpeculativelyExecute(const Instruction *I,
453 const Instruction *CtxI = nullptr,
454 AssumptionCache *AC = nullptr,
455 const DominatorTree *DT = nullptr,
456 const TargetLibraryInfo *TLI = nullptr);
457
458/// This returns the same result as isSafeToSpeculativelyExecute if Opcode is
459/// the actual opcode of Inst. If the provided and actual opcode differ, the
460/// function (virtually) overrides the opcode of Inst with the provided
461/// Opcode. There are come constraints in this case:
462/// * If Opcode has a fixed number of operands (eg, as binary operators do),
463/// then Inst has to have at least as many leading operands. The function
464/// will ignore all trailing operands beyond that number.
465/// * If Opcode allows for an arbitrary number of operands (eg, as CallInsts
466/// do), then all operands are considered.
467/// * The virtual instruction has to satisfy all typing rules of the provided
468/// Opcode.
469/// * This function is pessimistic in the following sense: If one actually
470/// materialized the virtual instruction, then isSafeToSpeculativelyExecute
471/// may say that the materialized instruction is speculatable whereas this
472/// function may have said that the instruction wouldn't be speculatable.
473/// This behavior is a shortcoming in the current implementation and not
474/// intentional.
475bool isSafeToSpeculativelyExecuteWithOpcode(
476 unsigned Opcode, const Instruction *Inst, const Instruction *CtxI = nullptr,
477 AssumptionCache *AC = nullptr, const DominatorTree *DT = nullptr,
478 const TargetLibraryInfo *TLI = nullptr);
479
480/// Returns true if the result or effects of the given instructions \p I
481/// depend values not reachable through the def use graph.
482/// * Memory dependence arises for example if the instruction reads from
483/// memory or may produce effects or undefined behaviour. Memory dependent
484/// instructions generally cannot be reorderd with respect to other memory
485/// dependent instructions.
486/// * Control dependence arises for example if the instruction may fault
487/// if lifted above a throwing call or infinite loop.
488bool mayHaveNonDefUseDependency(const Instruction &I);
489
490/// Return true if it is an intrinsic that cannot be speculated but also
491/// cannot trap.
492bool isAssumeLikeIntrinsic(const Instruction *I);
493
494/// Return true if it is valid to use the assumptions provided by an
495/// assume intrinsic, I, at the point in the control-flow identified by the
496/// context instruction, CxtI.
497bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI,
498 const DominatorTree *DT = nullptr);
499
500enum class OverflowResult {
501 /// Always overflows in the direction of signed/unsigned min value.
502 AlwaysOverflowsLow,
503 /// Always overflows in the direction of signed/unsigned max value.
504 AlwaysOverflowsHigh,
505 /// May or may not overflow.
506 MayOverflow,
507 /// Never overflows.
508 NeverOverflows,
509};
510
511OverflowResult computeOverflowForUnsignedMul(const Value *LHS, const Value *RHS,
512 const DataLayout &DL,
513 AssumptionCache *AC,
514 const Instruction *CxtI,
515 const DominatorTree *DT,
516 bool UseInstrInfo = true);
517OverflowResult computeOverflowForSignedMul(const Value *LHS, const Value *RHS,
518 const DataLayout &DL,
519 AssumptionCache *AC,
520 const Instruction *CxtI,
521 const DominatorTree *DT,
522 bool UseInstrInfo = true);
523OverflowResult computeOverflowForUnsignedAdd(const Value *LHS, const Value *RHS,
524 const DataLayout &DL,
525 AssumptionCache *AC,
526 const Instruction *CxtI,
527 const DominatorTree *DT,
528 bool UseInstrInfo = true);
529OverflowResult computeOverflowForSignedAdd(const Value *LHS, const Value *RHS,
530 const DataLayout &DL,
531 AssumptionCache *AC = nullptr,
532 const Instruction *CxtI = nullptr,
533 const DominatorTree *DT = nullptr);
534/// This version also leverages the sign bit of Add if known.
535OverflowResult computeOverflowForSignedAdd(const AddOperator *Add,
536 const DataLayout &DL,
537 AssumptionCache *AC = nullptr,
538 const Instruction *CxtI = nullptr,
539 const DominatorTree *DT = nullptr);
540OverflowResult computeOverflowForUnsignedSub(const Value *LHS, const Value *RHS,
541 const DataLayout &DL,
542 AssumptionCache *AC,
543 const Instruction *CxtI,
544 const DominatorTree *DT);
545OverflowResult computeOverflowForSignedSub(const Value *LHS, const Value *RHS,
546 const DataLayout &DL,
547 AssumptionCache *AC,
548 const Instruction *CxtI,
549 const DominatorTree *DT);
550
551/// Returns true if the arithmetic part of the \p WO 's result is
552/// used only along the paths control dependent on the computation
553/// not overflowing, \p WO being an <op>.with.overflow intrinsic.
554bool isOverflowIntrinsicNoWrap(const WithOverflowInst *WO,
555 const DominatorTree &DT);
556
557/// Determine the possible constant range of an integer or vector of integer
558/// value. This is intended as a cheap, non-recursive check.
559ConstantRange computeConstantRange(const Value *V, bool ForSigned,
560 bool UseInstrInfo = true,
561 AssumptionCache *AC = nullptr,
562 const Instruction *CtxI = nullptr,
563 const DominatorTree *DT = nullptr,
564 unsigned Depth = 0);
565
566/// Return true if this function can prove that the instruction I will
567/// always transfer execution to one of its successors (including the next
568/// instruction that follows within a basic block). E.g. this is not
569/// guaranteed for function calls that could loop infinitely.
570///
571/// In other words, this function returns false for instructions that may
572/// transfer execution or fail to transfer execution in a way that is not
573/// captured in the CFG nor in the sequence of instructions within a basic
574/// block.
575///
576/// Undefined behavior is assumed not to happen, so e.g. division is
577/// guaranteed to transfer execution to the following instruction even
578/// though division by zero might cause undefined behavior.
579bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I);
580
581/// Returns true if this block does not contain a potential implicit exit.
582/// This is equivelent to saying that all instructions within the basic block
583/// are guaranteed to transfer execution to their successor within the basic
584/// block. This has the same assumptions w.r.t. undefined behavior as the
585/// instruction variant of this function.
586bool isGuaranteedToTransferExecutionToSuccessor(const BasicBlock *BB);
587
588/// Return true if every instruction in the range (Begin, End) is
589/// guaranteed to transfer execution to its static successor. \p ScanLimit
590/// bounds the search to avoid scanning huge blocks.
591bool isGuaranteedToTransferExecutionToSuccessor(
592 BasicBlock::const_iterator Begin, BasicBlock::const_iterator End,
593 unsigned ScanLimit = 32);
594
595/// Same as previous, but with range expressed via iterator_range.
596bool isGuaranteedToTransferExecutionToSuccessor(
597 iterator_range<BasicBlock::const_iterator> Range, unsigned ScanLimit = 32);
598
599/// Return true if this function can prove that the instruction I
600/// is executed for every iteration of the loop L.
601///
602/// Note that this currently only considers the loop header.
603bool isGuaranteedToExecuteForEveryIteration(const Instruction *I,
604 const Loop *L);
605
606/// Return true if \p PoisonOp's user yields poison or raises UB if its
607/// operand \p PoisonOp is poison.
608///
609/// If \p PoisonOp is a vector or an aggregate and the operation's result is a
610/// single value, any poison element in /p PoisonOp should make the result
611/// poison or raise UB.
612///
613/// To filter out operands that raise UB on poison, you can use
614/// getGuaranteedNonPoisonOp.
615bool propagatesPoison(const Use &PoisonOp);
616
617/// Insert operands of I into Ops such that I will trigger undefined behavior
618/// if I is executed and that operand has a poison value.
619void getGuaranteedNonPoisonOps(const Instruction *I,
620 SmallVectorImpl<const Value *> &Ops);
621
622/// Insert operands of I into Ops such that I will trigger undefined behavior
623/// if I is executed and that operand is not a well-defined value
624/// (i.e. has undef bits or poison).
625void getGuaranteedWellDefinedOps(const Instruction *I,
626 SmallVectorImpl<const Value *> &Ops);
627
628/// Return true if the given instruction must trigger undefined behavior
629/// when I is executed with any operands which appear in KnownPoison holding
630/// a poison value at the point of execution.
631bool mustTriggerUB(const Instruction *I,
632 const SmallSet<const Value *, 16> &KnownPoison);
633
634/// Return true if this function can prove that if Inst is executed
635/// and yields a poison value or undef bits, then that will trigger
636/// undefined behavior.
637///
638/// Note that this currently only considers the basic block that is
639/// the parent of Inst.
640bool programUndefinedIfUndefOrPoison(const Instruction *Inst);
641bool programUndefinedIfPoison(const Instruction *Inst);
642
643/// canCreateUndefOrPoison returns true if Op can create undef or poison from
644/// non-undef & non-poison operands.
645/// For vectors, canCreateUndefOrPoison returns true if there is potential
646/// poison or undef in any element of the result when vectors without
647/// undef/poison poison are given as operands.
648/// For example, given `Op = shl <2 x i32> %x, <0, 32>`, this function returns
649/// true. If Op raises immediate UB but never creates poison or undef
650/// (e.g. sdiv I, 0), canCreatePoison returns false.
651///
652/// \p ConsiderFlagsAndMetadata controls whether poison producing flags and
653/// metadata on the instruction are considered. This can be used to see if the
654/// instruction could still introduce undef or poison even without poison
655/// generating flags and metadata which might be on the instruction.
656/// (i.e. could the result of Op->dropPoisonGeneratingFlags() still create
657/// poison or undef)
658///
659/// canCreatePoison returns true if Op can create poison from non-poison
660/// operands.
661bool canCreateUndefOrPoison(const Operator *Op,
662 bool ConsiderFlagsAndMetadata = true);
663bool canCreatePoison(const Operator *Op, bool ConsiderFlagsAndMetadata = true);
664
665/// Return true if V is poison given that ValAssumedPoison is already poison.
666/// For example, if ValAssumedPoison is `icmp X, 10` and V is `icmp X, 5`,
667/// impliesPoison returns true.
668bool impliesPoison(const Value *ValAssumedPoison, const Value *V);
669
670/// Return true if this function can prove that V does not have undef bits
671/// and is never poison. If V is an aggregate value or vector, check whether
672/// all elements (except padding) are not undef or poison.
673/// Note that this is different from canCreateUndefOrPoison because the
674/// function assumes Op's operands are not poison/undef.
675///
676/// If CtxI and DT are specified this method performs flow-sensitive analysis
677/// and returns true if it is guaranteed to be never undef or poison
678/// immediately before the CtxI.
679bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
680 AssumptionCache *AC = nullptr,
681 const Instruction *CtxI = nullptr,
682 const DominatorTree *DT = nullptr,
683 unsigned Depth = 0);
684bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC = nullptr,
685 const Instruction *CtxI = nullptr,
686 const DominatorTree *DT = nullptr,
687 unsigned Depth = 0);
688
689/// Specific patterns of select instructions we can match.
690enum SelectPatternFlavor {
691 SPF_UNKNOWN = 0,
692 SPF_SMIN, /// Signed minimum
693 SPF_UMIN, /// Unsigned minimum
694 SPF_SMAX, /// Signed maximum
695 SPF_UMAX, /// Unsigned maximum
696 SPF_FMINNUM, /// Floating point minnum
697 SPF_FMAXNUM, /// Floating point maxnum
698 SPF_ABS, /// Absolute value
699 SPF_NABS /// Negated absolute value
700};
701
702/// Behavior when a floating point min/max is given one NaN and one
703/// non-NaN as input.
704enum SelectPatternNaNBehavior {
705 SPNB_NA = 0, /// NaN behavior not applicable.
706 SPNB_RETURNS_NAN, /// Given one NaN input, returns the NaN.
707 SPNB_RETURNS_OTHER, /// Given one NaN input, returns the non-NaN.
708 SPNB_RETURNS_ANY /// Given one NaN input, can return either (or
709 /// it has been determined that no operands can
710 /// be NaN).
711};
712
713struct SelectPatternResult {
714 SelectPatternFlavor Flavor;
715 SelectPatternNaNBehavior NaNBehavior; /// Only applicable if Flavor is
716 /// SPF_FMINNUM or SPF_FMAXNUM.
717 bool Ordered; /// When implementing this min/max pattern as
718 /// fcmp; select, does the fcmp have to be
719 /// ordered?
720
721 /// Return true if \p SPF is a min or a max pattern.
722 static bool isMinOrMax(SelectPatternFlavor SPF) {
723 return SPF != SPF_UNKNOWN && SPF != SPF_ABS && SPF != SPF_NABS;
724 }
725};
726
727/// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind
728/// and providing the out parameter results if we successfully match.
729///
730/// For ABS/NABS, LHS will be set to the input to the abs idiom. RHS will be
731/// the negation instruction from the idiom.
732///
733/// If CastOp is not nullptr, also match MIN/MAX idioms where the type does
734/// not match that of the original select. If this is the case, the cast
735/// operation (one of Trunc,SExt,Zext) that must be done to transform the
736/// type of LHS and RHS into the type of V is returned in CastOp.
737///
738/// For example:
739/// %1 = icmp slt i32 %a, i32 4
740/// %2 = sext i32 %a to i64
741/// %3 = select i1 %1, i64 %2, i64 4
742///
743/// -> LHS = %a, RHS = i32 4, *CastOp = Instruction::SExt
744///
745SelectPatternResult matchSelectPattern(Value *V, Value *&LHS, Value *&RHS,
746 Instruction::CastOps *CastOp = nullptr,
747 unsigned Depth = 0);
748
749inline SelectPatternResult matchSelectPattern(const Value *V, const Value *&LHS,
750 const Value *&RHS) {
751 Value *L = const_cast<Value *>(LHS);
752 Value *R = const_cast<Value *>(RHS);
753 auto Result = matchSelectPattern(const_cast<Value *>(V), L, R);
754 LHS = L;
755 RHS = R;
756 return Result;
757}
758
759/// Determine the pattern that a select with the given compare as its
760/// predicate and given values as its true/false operands would match.
761SelectPatternResult matchDecomposedSelectPattern(
762 CmpInst *CmpI, Value *TrueVal, Value *FalseVal, Value *&LHS, Value *&RHS,
763 Instruction::CastOps *CastOp = nullptr, unsigned Depth = 0);
764
765/// Return the canonical comparison predicate for the specified
766/// minimum/maximum flavor.
767CmpInst::Predicate getMinMaxPred(SelectPatternFlavor SPF, bool Ordered = false);
768
769/// Return the inverse minimum/maximum flavor of the specified flavor.
770/// For example, signed minimum is the inverse of signed maximum.
771SelectPatternFlavor getInverseMinMaxFlavor(SelectPatternFlavor SPF);
772
773Intrinsic::ID getInverseMinMaxIntrinsic(Intrinsic::ID MinMaxID);
774
775/// Return the minimum or maximum constant value for the specified integer
776/// min/max flavor and type.
777APInt getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth);
778
779/// Check if the values in \p VL are select instructions that can be converted
780/// to a min or max (vector) intrinsic. Returns the intrinsic ID, if such a
781/// conversion is possible, together with a bool indicating whether all select
782/// conditions are only used by the selects. Otherwise return
783/// Intrinsic::not_intrinsic.
784std::pair<Intrinsic::ID, bool>
785canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL);
786
787/// Attempt to match a simple first order recurrence cycle of the form:
788/// %iv = phi Ty [%Start, %Entry], [%Inc, %backedge]
789/// %inc = binop %iv, %step
790/// OR
791/// %iv = phi Ty [%Start, %Entry], [%Inc, %backedge]
792/// %inc = binop %step, %iv
793///
794/// A first order recurrence is a formula with the form: X_n = f(X_(n-1))
795///
796/// A couple of notes on subtleties in that definition:
797/// * The Step does not have to be loop invariant. In math terms, it can
798/// be a free variable. We allow recurrences with both constant and
799/// variable coefficients. Callers may wish to filter cases where Step
800/// does not dominate P.
801/// * For non-commutative operators, we will match both forms. This
802/// results in some odd recurrence structures. Callers may wish to filter
803/// out recurrences where the phi is not the LHS of the returned operator.
804/// * Because of the structure matched, the caller can assume as a post
805/// condition of the match the presence of a Loop with P's parent as it's
806/// header *except* in unreachable code. (Dominance decays in unreachable
807/// code.)
808///
809/// NOTE: This is intentional simple. If you want the ability to analyze
810/// non-trivial loop conditons, see ScalarEvolution instead.
811bool matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, Value *&Start,
812 Value *&Step);
813
814/// Analogous to the above, but starting from the binary operator
815bool matchSimpleRecurrence(const BinaryOperator *I, PHINode *&P, Value *&Start,
816 Value *&Step);
817
818/// Return true if RHS is known to be implied true by LHS. Return false if
819/// RHS is known to be implied false by LHS. Otherwise, return std::nullopt if
820/// no implication can be made. A & B must be i1 (boolean) values or a vector of
821/// such values. Note that the truth table for implication is the same as <=u on
822/// i1 values (but not
823/// <=s!). The truth table for both is:
824/// | T | F (B)
825/// T | T | F
826/// F | T | T
827/// (A)
828std::optional<bool> isImpliedCondition(const Value *LHS, const Value *RHS,
829 const DataLayout &DL,
830 bool LHSIsTrue = true,
831 unsigned Depth = 0);
832std::optional<bool> isImpliedCondition(const Value *LHS,
833 CmpInst::Predicate RHSPred,
834 const Value *RHSOp0, const Value *RHSOp1,
835 const DataLayout &DL,
836 bool LHSIsTrue = true,
837 unsigned Depth = 0);
838
839/// Return the boolean condition value in the context of the given instruction
840/// if it is known based on dominating conditions.
841std::optional<bool> isImpliedByDomCondition(const Value *Cond,
842 const Instruction *ContextI,
843 const DataLayout &DL);
844std::optional<bool> isImpliedByDomCondition(CmpInst::Predicate Pred,
845 const Value *LHS, const Value *RHS,
846 const Instruction *ContextI,
847 const DataLayout &DL);
848
849/// If Ptr1 is provably equal to Ptr2 plus a constant offset, return that
850/// offset. For example, Ptr1 might be &A[42], and Ptr2 might be &A[40]. In
851/// this case offset would be -8.
852std::optional<int64_t> isPointerOffset(const Value *Ptr1, const Value *Ptr2,
853 const DataLayout &DL);
854} // end namespace llvm
855
856#endif // LLVM_ANALYSIS_VALUETRACKING_H