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
71 using namespace llvm;
72
73 #define DEBUG_TYPE "attributor"
74
75 static cl::opt<bool> ManifestInternal(
76 "attributor-manifest-internal", cl::Hidden,
77 cl::desc("Manifest Attributor internal string attributes."),
78 cl::init(false));
79
80 static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128),
81 cl::Hidden);
82
83 template <>
84 unsigned llvm::PotentialConstantIntValuesState::MaxPotentialValues = 0;
85
86 template <> unsigned llvm::PotentialLLVMValuesState::MaxPotentialValues = -1;
87
88 static 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
95 static 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
101 STATISTIC(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) \
117 ("Number of " #TYPE " marked '" #NAME "'")
118 #define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
119 #define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
120 #define STATS_DECL(NAME, TYPE, MSG) \
121 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
122 #define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
123 #define STATS_DECLTRACK(NAME, TYPE, MSG) \
124 { \
125 STATS_DECL(NAME, TYPE, MSG) \
126 STATS_TRACK(NAME, TYPE) \
127 }
128 #define STATS_DECLTRACK_ARG_ATTR(NAME) \
129 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
130 #define STATS_DECLTRACK_CSARG_ATTR(NAME) \
131 STATS_DECLTRACK(NAME, CSArguments, \
132 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
133 #define STATS_DECLTRACK_FN_ATTR(NAME) \
134 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
135 #define STATS_DECLTRACK_CS_ATTR(NAME) \
136 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
137 #define STATS_DECLTRACK_FNRET_ATTR(NAME) \
138 STATS_DECLTRACK(NAME, FunctionReturn, \
139 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
140 #define STATS_DECLTRACK_CSRET_ATTR(NAME) \
141 STATS_DECLTRACK(NAME, CSReturn, \
142 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
143 #define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
144 STATS_DECLTRACK(NAME, Floating, \
145 ("Number of floating values known to be '" #NAME "'"))
146
147 // Specialization of the operator<< for abstract attributes subclasses. This
148 // disambiguates situations where multiple operators are applicable.
149 namespace 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
155 PIPE_OPERATOR(AAIsDead)
PIPE_OPERATOR(AANoUnwind)156 PIPE_OPERATOR(AANoUnwind)
157 PIPE_OPERATOR(AANoSync)
158 PIPE_OPERATOR(AANoRecurse)
159 PIPE_OPERATOR(AAWillReturn)
160 PIPE_OPERATOR(AANoReturn)
161 PIPE_OPERATOR(AAReturnedValues)
162 PIPE_OPERATOR(AANonNull)
163 PIPE_OPERATOR(AANoAlias)
164 PIPE_OPERATOR(AADereferenceable)
165 PIPE_OPERATOR(AAAlign)
166 PIPE_OPERATOR(AAInstanceInfo)
167 PIPE_OPERATOR(AANoCapture)
168 PIPE_OPERATOR(AAValueSimplify)
169 PIPE_OPERATOR(AANoFree)
170 PIPE_OPERATOR(AAHeapToStack)
171 PIPE_OPERATOR(AAIntraFnReachability)
172 PIPE_OPERATOR(AAMemoryBehavior)
173 PIPE_OPERATOR(AAMemoryLocation)
174 PIPE_OPERATOR(AAValueConstantRange)
175 PIPE_OPERATOR(AAPrivatizablePtr)
176 PIPE_OPERATOR(AAUndefinedBehavior)
177 PIPE_OPERATOR(AAPotentialConstantValues)
178 PIPE_OPERATOR(AAPotentialValues)
179 PIPE_OPERATOR(AANoUndef)
180 PIPE_OPERATOR(AACallEdges)
181 PIPE_OPERATOR(AAInterFnReachability)
182 PIPE_OPERATOR(AAPointerInfo)
183 PIPE_OPERATOR(AAAssumptionInfo)
184 PIPE_OPERATOR(AAUnderlyingObjects)
185
186 #undef PIPE_OPERATOR
187
188 template <>
189 ChangeStatus 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.
isDenselyPacked(Type * Ty,const DataLayout & DL)200 static 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.
getPointerOperand(const Instruction * I,bool AllowVolatile)241 static 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.
constructPointer(Type * ResTy,Type * PtrElemTy,Value * Ptr,int64_t Offset,IRBuilder<NoFolder> & IRB,const DataLayout & DL)273 static 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!");
277 LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
278 << "-bytes as " << *ResTy << "\n");
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");
308 return Ptr;
309 }
310
311 static const Value *
stripAndAccumulateOffsets(Attributor & A,const AbstractAttribute & QueryingAA,const Value * Val,const DataLayout & DL,APInt & Offset,bool GetMinOffset,bool AllowNonInbounds,bool UseAssumed=false)312 stripAndAccumulateOffsets(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
343 static const Value *
getMinimalBaseOfPointer(Attributor & A,const AbstractAttribute & QueryingAA,const Value * Ptr,int64_t & BytesOffset,const DataLayout & DL,bool AllowNonInbounds=false)344 getMinimalBaseOfPointer(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.
358 template <typename AAType, typename StateType = typename AAType::StateType>
clampReturnedValueStates(Attributor & A,const AAType & QueryingAA,StateType & S,const IRPosition::CallBaseContext * CBContext=nullptr)359 static 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 "
363 << QueryingAA << " into " << S << "\n");
364
365 assert((QueryingAA.getIRPosition().getPositionKind() ==
366 IRPosition::IRP_RETURNED ||
367 QueryingAA.getIRPosition().getPositionKind() ==
368 IRPosition::IRP_CALL_SITE_RETURNED) &&
369 "Can only clamp returned value states for a function returned or call "
370 "site returned position!");
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()
382 << " @ " << RVPos << "\n");
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: " << T
388 << "\n");
389 return T->isValidState();
390 };
391
392 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA))
393 S.indicatePessimisticFixpoint();
394 else if (T)
395 S ^= *T;
396 }
397
398 namespace {
399 /// Helper class for generic deduction: return value -> returned position.
400 template <typename AAType, typename BaseType,
401 typename StateType = typename BaseType::StateType,
402 bool PropagateCallBaseContext = false>
403 struct AAReturnedFromReturnedValues : public BaseType {
AAReturnedFromReturnedValues__anon641416290311::AAReturnedFromReturnedValues404 AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
405 : BaseType(IRP, A) {}
406
407 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416290311::AAReturnedFromReturnedValues408 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.
421 template <typename AAType, typename StateType = typename AAType::StateType>
clampCallSiteArgumentStates(Attributor & A,const AAType & QueryingAA,StateType & S)422 static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
423 StateType &S) {
424 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
425 << QueryingAA << " into " << S << "\n");
426
427 assert(QueryingAA.getIRPosition().getPositionKind() ==
428 IRPosition::IRP_ARGUMENT &&
429 "Can only clamp call site argument states for an argument position!");
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()
448 << " AA: " << AA.getAsStr() << " @" << ACSArgPos << "\n");
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: " << T
454 << "\n");
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.
468 template <typename AAType, typename BaseType,
469 typename StateType = typename AAType::StateType>
getArgumentStateFromCallBaseContext(Attributor & A,BaseType & QueryingAttribute,IRPosition & Pos,StateType & State)470 bool getArgumentStateFromCallBaseContext(Attributor &A,
471 BaseType &QueryingAttribute,
472 IRPosition &Pos, StateType &State) {
473 assert((Pos.getPositionKind() == IRPosition::IRP_ARGUMENT) &&
474 "Expected an 'argument' position !");
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!");
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"
489 << "Position:" << Pos << "CB Arg state:" << CBArgumentState
490 << "\n");
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.
498 template <typename AAType, typename BaseType,
499 typename StateType = typename AAType::StateType,
500 bool BridgeCallBaseContext = false>
501 struct AAArgumentFromCallSiteArguments : public BaseType {
AAArgumentFromCallSiteArguments__anon641416290311::AAArgumentFromCallSiteArguments502 AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
503 : BaseType(IRP, A) {}
504
505 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416290311::AAArgumentFromCallSiteArguments506 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.
525 template <typename AAType, typename BaseType,
526 typename StateType = typename BaseType::StateType,
527 bool IntroduceCallBaseContext = false>
528 struct AACallSiteReturnedFromReturned : public BaseType {
AACallSiteReturnedFromReturned__anon641416290311::AACallSiteReturnedFromReturned529 AACallSiteReturnedFromReturned(const IRPosition &IRP, Attributor &A)
530 : BaseType(IRP, A) {}
531
532 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416290311::AACallSiteReturnedFromReturned533 ChangeStatus updateImpl(Attributor &A) override {
534 assert(this->getIRPosition().getPositionKind() ==
535 IRPosition::IRP_CALL_SITE_RETURNED &&
536 "Can only wrap function returned positions for call site returned "
537 "positions!");
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:"
548 << CBContext << "\n");
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.
558 template <class AAType, typename StateType = typename AAType::StateType>
followUsesInContext(AAType & AA,Attributor & A,MustBeExecutedContextExplorer & Explorer,const Instruction * CtxI,SetVector<const Use * > & Uses,StateType & State)559 static 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 ///
585 template <class AAType, typename StateType = typename AAType::StateType>
followUsesInMBEC(AAType & AA,Attributor & A,StateType & S,Instruction & CtxI)586 static 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
671 namespace llvm {
672 namespace AA {
673 namespace PointerInfo {
674
675 struct State;
676
677 } // namespace PointerInfo
678 } // namespace AA
679
680 /// Helper for AA::PointerInfo::Access DenseMap/Set usage.
681 template <>
682 struct 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.
691 template <> struct DenseMapInfo<AA::RangeTy> {
getEmptyKeyllvm::DenseMapInfo692 static inline AA::RangeTy getEmptyKey() {
693 auto EmptyKey = DenseMapInfo<int64_t>::getEmptyKey();
694 return AA::RangeTy{EmptyKey, EmptyKey};
695 }
696
getTombstoneKeyllvm::DenseMapInfo697 static inline AA::RangeTy getTombstoneKey() {
698 auto TombstoneKey = DenseMapInfo<int64_t>::getTombstoneKey();
699 return AA::RangeTy{TombstoneKey, TombstoneKey};
700 }
701
getHashValuellvm::DenseMapInfo702 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
isEqualllvm::DenseMapInfo708 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
715 struct 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.
727 struct AA::PointerInfo::State : public AbstractState {
728 /// Return the best possible representable state.
getBestStateAA::PointerInfo::State729 static State getBestState(const State &SIS) { return State(); }
730
731 /// Return the worst possible representable state.
getWorstStateAA::PointerInfo::State732 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
getAssumedAA::PointerInfo::State741 const State &getAssumed() const { return *this; }
742
743 /// See AbstractState::isValidState().
isValidStateAA::PointerInfo::State744 bool isValidState() const override { return BS.isValidState(); }
745
746 /// See AbstractState::isAtFixpoint().
isAtFixpointAA::PointerInfo::State747 bool isAtFixpoint() const override { return BS.isAtFixpoint(); }
748
749 /// See AbstractState::indicateOptimisticFixpoint().
indicateOptimisticFixpointAA::PointerInfo::State750 ChangeStatus indicateOptimisticFixpoint() override {
751 BS.indicateOptimisticFixpoint();
752 return ChangeStatus::UNCHANGED;
753 }
754
755 /// See AbstractState::indicatePessimisticFixpoint().
indicatePessimisticFixpointAA::PointerInfo::State756 ChangeStatus indicatePessimisticFixpoint() override {
757 BS.indicatePessimisticFixpoint();
758 return ChangeStatus::CHANGED;
759 }
760
operator =AA::PointerInfo::State761 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
operator =AA::PointerInfo::State771 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;
beginAA::PointerInfo::State797 const_bin_iterator begin() const { return OffsetBins.begin(); }
endAA::PointerInfo::State798 const_bin_iterator end() const { return OffsetBins.end(); }
799
getAccessAA::PointerInfo::State800 const AAPointerInfo::Access &getAccess(unsigned Index) const {
801 return AccessList[Index];
802 }
803
804 protected:
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.
forallInterferingAccessesAA::PointerInfo::State822 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.
forallInterferingAccessesAA::PointerInfo::State843 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
865 private:
866 /// State to track fixpoint and validity.
867 BooleanState BS;
868 };
869
addAccess(Attributor & A,const AAPointerInfo::RangeList & Ranges,Instruction & I,std::optional<Value * > Content,AAPointerInfo::AccessKind Kind,Type * Ty,Instruction * RemoteI)870 ChangeStatus 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(
891 if (ToAdd.size())
892 dbgs() << "[AAPointerInfo] Inserting access in new offset bins\n";
893 );
894
895 for (auto Key : ToAdd) {
896 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
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) &&
904 "New Access should have been at AccIndex");
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(
927 if (ToRemove.size())
928 dbgs() << "[AAPointerInfo] Removing access from old offset bins\n";
929 );
930
931 for (auto Key : ToRemove) {
932 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
933 assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");
934 auto &Bin = OffsetBins[Key];
935 assert(Bin.count(AccIndex) &&
936 "Expected bin to actually contain the Access.");
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
948 namespace {
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.
953 struct OffsetInfo {
954 using VecTy = SmallVector<int64_t>;
955 using const_iterator = VecTy::const_iterator;
956 VecTy Offsets;
957
begin__anon641416290711::OffsetInfo958 const_iterator begin() const { return Offsets.begin(); }
end__anon641416290711::OffsetInfo959 const_iterator end() const { return Offsets.end(); }
960
operator ==__anon641416290711::OffsetInfo961 bool operator==(const OffsetInfo &RHS) const {
962 return Offsets == RHS.Offsets;
963 }
964
operator !=__anon641416290711::OffsetInfo965 bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }
966
insert__anon641416290711::OffsetInfo967 void insert(int64_t Offset) { Offsets.push_back(Offset); }
isUnassigned__anon641416290711::OffsetInfo968 bool isUnassigned() const { return Offsets.size() == 0; }
969
isUnknown__anon641416290711::OffsetInfo970 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
setUnknown__anon641416290711::OffsetInfo978 void setUnknown() {
979 Offsets.clear();
980 Offsets.push_back(AA::RangeTy::Unknown);
981 }
982
addToAll__anon641416290711::OffsetInfo983 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.
merge__anon641416290711::OffsetInfo993 void merge(const OffsetInfo &R) { Offsets.append(R.Offsets); }
994 };
995
996 #ifndef NDEBUG
operator <<(raw_ostream & OS,const OffsetInfo & OI)997 static 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
1008 struct AAPointerInfoImpl
1009 : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1010 using BaseTy = StateWrapper<AA::PointerInfo::State, AAPointerInfo>;
AAPointerInfoImpl__anon641416290711::AAPointerInfoImpl1011 AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
1012
1013 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416290711::AAPointerInfoImpl1014 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(...).
manifest__anon641416290711::AAPointerInfoImpl1022 ChangeStatus manifest(Attributor &A) override {
1023 return AAPointerInfo::manifest(A);
1024 }
1025
forallInterferingAccesses__anon641416290711::AAPointerInfoImpl1026 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
forallInterferingAccesses__anon641416290711::AAPointerInfoImpl1033 bool forallInterferingAccesses(
1034 Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
1035 function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
1036 AA::RangeTy &Range) const override {
1037 HasBeenWrittenTo = false;
1038
1039 SmallPtrSet<const Access *, 8> DominatingWrites;
1040 SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;
1041
1042 Function &Scope = *I.getFunction();
1043 const auto &NoSyncAA = A.getAAFor<AANoSync>(
1044 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1045 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
1046 IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);
1047 bool AllInSameNoSyncFn = NoSyncAA.isAssumedNoSync();
1048 bool InstIsExecutedByInitialThreadOnly =
1049 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);
1050 bool InstIsExecutedInAlignedRegion =
1051 ExecDomainAA && ExecDomainAA->isExecutedInAlignedRegion(A, I);
1052 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1053 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1054
1055 InformationCache &InfoCache = A.getInfoCache();
1056 bool IsThreadLocalObj =
1057 AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);
1058
1059 // Helper to determine if we need to consider threading, which we cannot
1060 // right now. However, if the function is (assumed) nosync or the thread
1061 // executing all instructions is the main thread only we can ignore
1062 // threading. Also, thread-local objects do not require threading reasoning.
1063 // Finally, we can ignore threading if either access is executed in an
1064 // aligned region.
1065 auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
1066 if (IsThreadLocalObj || AllInSameNoSyncFn)
1067 return true;
1068 const auto *FnExecDomainAA =
1069 I.getFunction() == &Scope
1070 ? ExecDomainAA
1071 : A.lookupAAFor<AAExecutionDomain>(
1072 IRPosition::function(*I.getFunction()), &QueryingAA,
1073 DepClassTy::NONE);
1074 if (!FnExecDomainAA)
1075 return false;
1076 if (InstIsExecutedInAlignedRegion ||
1077 FnExecDomainAA->isExecutedInAlignedRegion(A, I)) {
1078 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1079 return true;
1080 }
1081 if (InstIsExecutedByInitialThreadOnly &&
1082 FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
1083 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1084 return true;
1085 }
1086 return false;
1087 };
1088
1089 // Helper to determine if the access is executed by the same thread as the
1090 // given instruction, for now it is sufficient to avoid any potential
1091 // threading effects as we cannot deal with them anyway.
1092 auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
1093 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1094 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1095 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1096 };
1097
1098 // TODO: Use inter-procedural reachability and dominance.
1099 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
1100 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1101
1102 const bool FindInterferingWrites = I.mayReadFromMemory();
1103 const bool FindInterferingReads = I.mayWriteToMemory();
1104 const bool UseDominanceReasoning =
1105 FindInterferingWrites && NoRecurseAA.isKnownNoRecurse();
1106 const DominatorTree *DT =
1107 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);
1108
1109 // Helper to check if a value has "kernel lifetime", that is it will not
1110 // outlive a GPU kernel. This is true for shared, constant, and local
1111 // globals on AMD and NVIDIA GPUs.
1112 auto HasKernelLifetime = [&](Value *V, Module &M) {
1113 Triple T(M.getTargetTriple());
1114 if (!(T.isAMDGPU() || T.isNVPTX()))
1115 return false;
1116 switch (AA::GPUAddressSpace(V->getType()->getPointerAddressSpace())) {
1117 case AA::GPUAddressSpace::Shared:
1118 case AA::GPUAddressSpace::Constant:
1119 case AA::GPUAddressSpace::Local:
1120 return true;
1121 default:
1122 return false;
1123 };
1124 };
1125
1126 // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
1127 // to determine if we should look at reachability from the callee. For
1128 // certain pointers we know the lifetime and we do not have to step into the
1129 // callee to determine reachability as the pointer would be dead in the
1130 // callee. See the conditional initialization below.
1131 std::function<bool(const Function &)> IsLiveInCalleeCB;
1132
1133 if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {
1134 // If the alloca containing function is not recursive the alloca
1135 // must be dead in the callee.
1136 const Function *AIFn = AI->getFunction();
1137 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
1138 *this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL);
1139 if (NoRecurseAA.isAssumedNoRecurse()) {
1140 IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
1141 }
1142 } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {
1143 // If the global has kernel lifetime we can stop if we reach a kernel
1144 // as it is "dead" in the (unknown) callees.
1145 if (HasKernelLifetime(GV, *GV->getParent()))
1146 IsLiveInCalleeCB = [](const Function &Fn) {
1147 return !Fn.hasFnAttribute("kernel");
1148 };
1149 }
1150
1151 // Set of accesses/instructions that will overwrite the result and are
1152 // therefore blockers in the reachability traversal.
1153 AA::InstExclusionSetTy ExclusionSet;
1154
1155 auto AccessCB = [&](const Access &Acc, bool Exact) {
1156 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
1157 if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))
1158 ExclusionSet.insert(Acc.getRemoteInst());
1159 }
1160
1161 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1162 (!FindInterferingReads || !Acc.isRead()))
1163 return true;
1164
1165 bool Dominates = FindInterferingWrites && DT && Exact &&
1166 Acc.isMustAccess() &&
1167 (Acc.getRemoteInst()->getFunction() == &Scope) &&
1168 DT->dominates(Acc.getRemoteInst(), &I);
1169 if (Dominates)
1170 DominatingWrites.insert(&Acc);
1171
1172 // Track if all interesting accesses are in the same `nosync` function as
1173 // the given instruction.
1174 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;
1175
1176 InterferingAccesses.push_back({&Acc, Exact});
1177 return true;
1178 };
1179 if (!State::forallInterferingAccesses(I, AccessCB, Range))
1180 return false;
1181
1182 HasBeenWrittenTo = !DominatingWrites.empty();
1183
1184 // Dominating writes form a chain, find the least/lowest member.
1185 Instruction *LeastDominatingWriteInst = nullptr;
1186 for (const Access *Acc : DominatingWrites) {
1187 if (!LeastDominatingWriteInst) {
1188 LeastDominatingWriteInst = Acc->getRemoteInst();
1189 } else if (DT->dominates(LeastDominatingWriteInst,
1190 Acc->getRemoteInst())) {
1191 LeastDominatingWriteInst = Acc->getRemoteInst();
1192 }
1193 }
1194
1195 // Helper to determine if we can skip a specific write access.
1196 auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
1197 if (!CanIgnoreThreading(Acc))
1198 return false;
1199
1200 // Check read (RAW) dependences and write (WAR) dependences as necessary.
1201 // If we successfully excluded all effects we are interested in, the
1202 // access can be skipped.
1203 bool ReadChecked = !FindInterferingReads;
1204 bool WriteChecked = !FindInterferingWrites;
1205
1206 // If the instruction cannot reach the access, the former does not
1207 // interfere with what the access reads.
1208 if (!ReadChecked) {
1209 if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,
1210 &ExclusionSet, IsLiveInCalleeCB))
1211 ReadChecked = true;
1212 }
1213 // If the instruction cannot be reach from the access, the latter does not
1214 // interfere with what the instruction reads.
1215 if (!WriteChecked) {
1216 if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,
1217 &ExclusionSet, IsLiveInCalleeCB))
1218 WriteChecked = true;
1219 }
1220
1221 // If we still might be affected by the write of the access but there are
1222 // dominating writes in the function of the instruction
1223 // (HasBeenWrittenTo), we can try to reason that the access is overwritten
1224 // by them. This would have happend above if they are all in the same
1225 // function, so we only check the inter-procedural case. Effectively, we
1226 // want to show that there is no call after the dominting write that might
1227 // reach the access, and when it returns reach the instruction with the
1228 // updated value. To this end, we iterate all call sites, check if they
1229 // might reach the instruction without going through another access
1230 // (ExclusionSet) and at the same time might reach the access. However,
1231 // that is all part of AAInterFnReachability.
1232 if (!WriteChecked && HasBeenWrittenTo &&
1233 Acc.getRemoteInst()->getFunction() != &Scope) {
1234
1235 const auto &FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
1236 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1237
1238 // Without going backwards in the call tree, can we reach the access
1239 // from the least dominating write. Do not allow to pass the instruction
1240 // itself either.
1241 bool Inserted = ExclusionSet.insert(&I).second;
1242
1243 if (!FnReachabilityAA.instructionCanReach(
1244 A, *LeastDominatingWriteInst,
1245 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1246 WriteChecked = true;
1247
1248 if (Inserted)
1249 ExclusionSet.erase(&I);
1250 }
1251
1252 if (ReadChecked && WriteChecked)
1253 return true;
1254
1255 if (!DT || !UseDominanceReasoning)
1256 return false;
1257 if (!DominatingWrites.count(&Acc))
1258 return false;
1259 return LeastDominatingWriteInst != Acc.getRemoteInst();
1260 };
1261
1262 // Run the user callback on all accesses we cannot skip and return if
1263 // that succeeded for all or not.
1264 for (auto &It : InterferingAccesses) {
1265 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1266 !CanSkipAccess(*It.first, It.second)) {
1267 if (!UserCB(*It.first, It.second))
1268 return false;
1269 }
1270 }
1271 return true;
1272 }
1273
translateAndAddStateFromCallee__anon641416290711::AAPointerInfoImpl1274 ChangeStatus translateAndAddStateFromCallee(Attributor &A,
1275 const AAPointerInfo &OtherAA,
1276 CallBase &CB) {
1277 using namespace AA::PointerInfo;
1278 if (!OtherAA.getState().isValidState() || !isValidState())
1279 return indicatePessimisticFixpoint();
1280
1281 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1282 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1283
1284 // Combine the accesses bin by bin.
1285 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1286 const auto &State = OtherAAImpl.getState();
1287 for (const auto &It : State) {
1288 for (auto Index : It.getSecond()) {
1289 const auto &RAcc = State.getAccess(Index);
1290 if (IsByval && !RAcc.isRead())
1291 continue;
1292 bool UsedAssumedInformation = false;
1293 AccessKind AK = RAcc.getKind();
1294 auto Content = A.translateArgumentToCallSiteContent(
1295 RAcc.getContent(), CB, *this, UsedAssumedInformation);
1296 AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1297 AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1298
1299 Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,
1300 RAcc.getType(), RAcc.getRemoteInst());
1301 }
1302 }
1303 return Changed;
1304 }
1305
translateAndAddState__anon641416290711::AAPointerInfoImpl1306 ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
1307 const OffsetInfo &Offsets, CallBase &CB) {
1308 using namespace AA::PointerInfo;
1309 if (!OtherAA.getState().isValidState() || !isValidState())
1310 return indicatePessimisticFixpoint();
1311
1312 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1313
1314 // Combine the accesses bin by bin.
1315 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1316 const auto &State = OtherAAImpl.getState();
1317 for (const auto &It : State) {
1318 for (auto Index : It.getSecond()) {
1319 const auto &RAcc = State.getAccess(Index);
1320 for (auto Offset : Offsets) {
1321 auto NewRanges = Offset == AA::RangeTy::Unknown
1322 ? AA::RangeTy::getUnknown()
1323 : RAcc.getRanges();
1324 if (!NewRanges.isUnknown()) {
1325 NewRanges.addToAllOffsets(Offset);
1326 }
1327 Changed |=
1328 addAccess(A, NewRanges, CB, RAcc.getContent(), RAcc.getKind(),
1329 RAcc.getType(), RAcc.getRemoteInst());
1330 }
1331 }
1332 }
1333 return Changed;
1334 }
1335
1336 /// Statistic tracking for all AAPointerInfo implementations.
1337 /// See AbstractAttribute::trackStatistics().
trackPointerInfoStatistics__anon641416290711::AAPointerInfoImpl1338 void trackPointerInfoStatistics(const IRPosition &IRP) const {}
1339
1340 /// Dump the state into \p O.
dumpState__anon641416290711::AAPointerInfoImpl1341 void dumpState(raw_ostream &O) {
1342 for (auto &It : OffsetBins) {
1343 O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
1344 << "] : " << It.getSecond().size() << "\n";
1345 for (auto AccIndex : It.getSecond()) {
1346 auto &Acc = AccessList[AccIndex];
1347 O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
1348 if (Acc.getLocalInst() != Acc.getRemoteInst())
1349 O << " --> " << *Acc.getRemoteInst()
1350 << "\n";
1351 if (!Acc.isWrittenValueYetUndetermined()) {
1352 if (Acc.getWrittenValue())
1353 O << " - c: " << *Acc.getWrittenValue() << "\n";
1354 else
1355 O << " - c: <unknown>\n";
1356 }
1357 }
1358 }
1359 }
1360 };
1361
1362 struct AAPointerInfoFloating : public AAPointerInfoImpl {
1363 using AccessKind = AAPointerInfo::AccessKind;
AAPointerInfoFloating__anon641416290711::AAPointerInfoFloating1364 AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
1365 : AAPointerInfoImpl(IRP, A) {}
1366
1367 /// Deal with an access and signal if it was handled successfully.
handleAccess__anon641416290711::AAPointerInfoFloating1368 bool handleAccess(Attributor &A, Instruction &I,
1369 std::optional<Value *> Content, AccessKind Kind,
1370 SmallVectorImpl<int64_t> &Offsets, ChangeStatus &Changed,
1371 Type &Ty) {
1372 using namespace AA::PointerInfo;
1373 auto Size = AA::RangeTy::Unknown;
1374 const DataLayout &DL = A.getDataLayout();
1375 TypeSize AccessSize = DL.getTypeStoreSize(&Ty);
1376 if (!AccessSize.isScalable())
1377 Size = AccessSize.getFixedValue();
1378
1379 // Make a strictly ascending list of offsets as required by addAccess()
1380 llvm::sort(Offsets);
1381 auto *Last = std::unique(Offsets.begin(), Offsets.end());
1382 Offsets.erase(Last, Offsets.end());
1383
1384 VectorType *VT = dyn_cast<VectorType>(&Ty);
1385 if (!VT || VT->getElementCount().isScalable() ||
1386 !Content.value_or(nullptr) || !isa<Constant>(*Content) ||
1387 (*Content)->getType() != VT ||
1388 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1389 Changed = Changed | addAccess(A, {Offsets, Size}, I, Content, Kind, &Ty);
1390 } else {
1391 // Handle vector stores with constant content element-wise.
1392 // TODO: We could look for the elements or create instructions
1393 // representing them.
1394 // TODO: We need to push the Content into the range abstraction
1395 // (AA::RangeTy) to allow different content values for different
1396 // ranges. ranges. Hence, support vectors storing different values.
1397 Type *ElementType = VT->getElementType();
1398 int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();
1399 auto *ConstContent = cast<Constant>(*Content);
1400 Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());
1401 SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());
1402
1403 for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1404 Value *ElementContent = ConstantExpr::getExtractElement(
1405 ConstContent, ConstantInt::get(Int32Ty, i));
1406
1407 // Add the element access.
1408 Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,
1409 ElementContent, Kind, ElementType);
1410
1411 // Advance the offsets for the next element.
1412 for (auto &ElementOffset : ElementOffsets)
1413 ElementOffset += ElementSize;
1414 }
1415 }
1416 return true;
1417 };
1418
1419 /// See AbstractAttribute::updateImpl(...).
1420 ChangeStatus updateImpl(Attributor &A) override;
1421
1422 /// If the indices to \p GEP can be traced to constants, incorporate all
1423 /// of these into \p UsrOI.
1424 ///
1425 /// \return true iff \p UsrOI is updated.
1426 bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
1427 OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
1428 const GEPOperator *GEP);
1429
1430 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416290711::AAPointerInfoFloating1431 void trackStatistics() const override {
1432 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1433 }
1434 };
1435
collectConstantsForGEP(Attributor & A,const DataLayout & DL,OffsetInfo & UsrOI,const OffsetInfo & PtrOI,const GEPOperator * GEP)1436 bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
1437 const DataLayout &DL,
1438 OffsetInfo &UsrOI,
1439 const OffsetInfo &PtrOI,
1440 const GEPOperator *GEP) {
1441 unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
1442 MapVector<Value *, APInt> VariableOffsets;
1443 APInt ConstantOffset(BitWidth, 0);
1444
1445 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1446 "Don't look for constant values if the offset has already been "
1447 "determined to be unknown.");
1448
1449 if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
1450 UsrOI.setUnknown();
1451 return true;
1452 }
1453
1454 LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "
1455 << (VariableOffsets.empty() ? "" : "not") << " constant "
1456 << *GEP << "\n");
1457
1458 auto Union = PtrOI;
1459 Union.addToAll(ConstantOffset.getSExtValue());
1460
1461 // Each VI in VariableOffsets has a set of potential constant values. Every
1462 // combination of elements, picked one each from these sets, is separately
1463 // added to the original set of offsets, thus resulting in more offsets.
1464 for (const auto &VI : VariableOffsets) {
1465 auto &PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
1466 *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);
1467 if (!PotentialConstantsAA.isValidState()) {
1468 UsrOI.setUnknown();
1469 return true;
1470 }
1471
1472 // UndefValue is treated as a zero, which leaves Union as is.
1473 if (PotentialConstantsAA.undefIsContained())
1474 continue;
1475
1476 // We need at least one constant in every set to compute an actual offset.
1477 // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
1478 // don't actually exist. In other words, the absence of constant values
1479 // implies that the operation can be assumed dead for now.
1480 auto &AssumedSet = PotentialConstantsAA.getAssumedSet();
1481 if (AssumedSet.empty())
1482 return false;
1483
1484 OffsetInfo Product;
1485 for (const auto &ConstOffset : AssumedSet) {
1486 auto CopyPerOffset = Union;
1487 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1488 VI.second.getZExtValue());
1489 Product.merge(CopyPerOffset);
1490 }
1491 Union = Product;
1492 }
1493
1494 UsrOI = std::move(Union);
1495 return true;
1496 }
1497
updateImpl(Attributor & A)1498 ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
1499 using namespace AA::PointerInfo;
1500 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1501 const DataLayout &DL = A.getDataLayout();
1502 Value &AssociatedValue = getAssociatedValue();
1503
1504 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1505 OffsetInfoMap[&AssociatedValue].insert(0);
1506
1507 auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
1508 // One does not simply walk into a map and assign a reference to a possibly
1509 // new location. That can cause an invalidation before the assignment
1510 // happens, like so:
1511 //
1512 // OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
1513 //
1514 // The RHS is a reference that may be invalidated by an insertion caused by
1515 // the LHS. So we ensure that the side-effect of the LHS happens first.
1516 auto &UsrOI = OffsetInfoMap[Usr];
1517 auto &PtrOI = OffsetInfoMap[CurPtr];
1518 assert(!PtrOI.isUnassigned() &&
1519 "Cannot pass through if the input Ptr was not visited!");
1520 UsrOI = PtrOI;
1521 Follow = true;
1522 return true;
1523 };
1524
1525 const auto *F = getAnchorScope();
1526 const auto *CI =
1527 F ? A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(*F)
1528 : nullptr;
1529 const auto *TLI =
1530 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
1531
1532 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1533 Value *CurPtr = U.get();
1534 User *Usr = U.getUser();
1535 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usr
1536 << "\n");
1537 assert(OffsetInfoMap.count(CurPtr) &&
1538 "The current pointer offset should have been seeded!");
1539
1540 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
1541 if (CE->isCast())
1542 return HandlePassthroughUser(Usr, CurPtr, Follow);
1543 if (CE->isCompare())
1544 return true;
1545 if (!isa<GEPOperator>(CE)) {
1546 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CE
1547 << "\n");
1548 return false;
1549 }
1550 }
1551 if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {
1552 // Note the order here, the Usr access might change the map, CurPtr is
1553 // already in it though.
1554 auto &UsrOI = OffsetInfoMap[Usr];
1555 auto &PtrOI = OffsetInfoMap[CurPtr];
1556
1557 if (UsrOI.isUnknown())
1558 return true;
1559
1560 if (PtrOI.isUnknown()) {
1561 Follow = true;
1562 UsrOI.setUnknown();
1563 return true;
1564 }
1565
1566 Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
1567 return true;
1568 }
1569 if (isa<PtrToIntInst>(Usr))
1570 return false;
1571 if (isa<CastInst>(Usr) || isa<SelectInst>(Usr) || isa<ReturnInst>(Usr))
1572 return HandlePassthroughUser(Usr, CurPtr, Follow);
1573
1574 // For PHIs we need to take care of the recurrence explicitly as the value
1575 // might change while we iterate through a loop. For now, we give up if
1576 // the PHI is not invariant.
1577 if (isa<PHINode>(Usr)) {
1578 // Note the order here, the Usr access might change the map, CurPtr is
1579 // already in it though.
1580 bool IsFirstPHIUser = !OffsetInfoMap.count(Usr);
1581 auto &UsrOI = OffsetInfoMap[Usr];
1582 auto &PtrOI = OffsetInfoMap[CurPtr];
1583
1584 // Check if the PHI operand has already an unknown offset as we can't
1585 // improve on that anymore.
1586 if (PtrOI.isUnknown()) {
1587 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "
1588 << *CurPtr << " in " << *Usr << "\n");
1589 Follow = !UsrOI.isUnknown();
1590 UsrOI.setUnknown();
1591 return true;
1592 }
1593
1594 // Check if the PHI is invariant (so far).
1595 if (UsrOI == PtrOI) {
1596 assert(!PtrOI.isUnassigned() &&
1597 "Cannot assign if the current Ptr was not visited!");
1598 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)");
1599 return true;
1600 }
1601
1602 // Check if the PHI operand can be traced back to AssociatedValue.
1603 APInt Offset(
1604 DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),
1605 0);
1606 Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
1607 DL, Offset, /* AllowNonInbounds */ true);
1608 auto It = OffsetInfoMap.find(CurPtrBase);
1609 if (It == OffsetInfoMap.end()) {
1610 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "
1611 << *CurPtr << " in " << *Usr << "\n");
1612 UsrOI.setUnknown();
1613 Follow = true;
1614 return true;
1615 }
1616
1617 auto mayBeInCycleHeader = [](const CycleInfo *CI, const Instruction *I) {
1618 if (!CI)
1619 return true;
1620 auto *BB = I->getParent();
1621 auto *C = CI->getCycle(BB);
1622 if (!C)
1623 return false;
1624 return BB == C->getHeader();
1625 };
1626
1627 // Check if the PHI operand is not dependent on the PHI itself. Every
1628 // recurrence is a cyclic net of PHIs in the data flow, and has an
1629 // equivalent Cycle in the control flow. One of those PHIs must be in the
1630 // header of that control flow Cycle. This is independent of the choice of
1631 // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
1632 // every Cycle header; if such a node is marked unknown, this will
1633 // eventually propagate through the whole net of PHIs in the recurrence.
1634 if (mayBeInCycleHeader(CI, cast<Instruction>(Usr))) {
1635 auto BaseOI = It->getSecond();
1636 BaseOI.addToAll(Offset.getZExtValue());
1637 if (IsFirstPHIUser || BaseOI == UsrOI) {
1638 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtr
1639 << " in " << *Usr << "\n");
1640 return HandlePassthroughUser(Usr, CurPtr, Follow);
1641 }
1642
1643 LLVM_DEBUG(
1644 dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
1645 << *CurPtr << " in " << *Usr << "\n");
1646 UsrOI.setUnknown();
1647 Follow = true;
1648 return true;
1649 }
1650
1651 UsrOI.merge(PtrOI);
1652 Follow = true;
1653 return true;
1654 }
1655
1656 if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {
1657 // If the access is to a pointer that may or may not be the associated
1658 // value, e.g. due to a PHI, we cannot assume it will be read.
1659 AccessKind AK = AccessKind::AK_R;
1660 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1661 AK = AccessKind(AK | AccessKind::AK_MUST);
1662 else
1663 AK = AccessKind(AK | AccessKind::AK_MAY);
1664 if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,
1665 OffsetInfoMap[CurPtr].Offsets, Changed,
1666 *LoadI->getType()))
1667 return false;
1668
1669 auto IsAssumption = [](Instruction &I) {
1670 if (auto *II = dyn_cast<IntrinsicInst>(&I))
1671 return II->isAssumeLikeIntrinsic();
1672 return false;
1673 };
1674
1675 auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
1676 // Check if the assumption and the load are executed together without
1677 // memory modification.
1678 do {
1679 if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
1680 return true;
1681 FromI = FromI->getNextNonDebugInstruction();
1682 } while (FromI && FromI != ToI);
1683 return false;
1684 };
1685
1686 BasicBlock *BB = LoadI->getParent();
1687 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1688 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1689 return false;
1690 BasicBlock *IntrBB = IntrI.getParent();
1691 if (IntrI.getParent() == BB) {
1692 if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(), &IntrI))
1693 return false;
1694 } else {
1695 auto PredIt = pred_begin(IntrBB);
1696 if ((*PredIt) != BB)
1697 return false;
1698 if (++PredIt != pred_end(IntrBB))
1699 return false;
1700 for (auto *SuccBB : successors(BB)) {
1701 if (SuccBB == IntrBB)
1702 continue;
1703 if (isa<UnreachableInst>(SuccBB->getTerminator()))
1704 continue;
1705 return false;
1706 }
1707 if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(),
1708 BB->getTerminator()))
1709 return false;
1710 if (IsImpactedInRange(&IntrBB->front(), &IntrI))
1711 return false;
1712 }
1713 return true;
1714 };
1715
1716 std::pair<Value *, IntrinsicInst *> Assumption;
1717 for (const Use &LoadU : LoadI->uses()) {
1718 if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {
1719 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1720 continue;
1721 for (const Use &CmpU : CmpI->uses()) {
1722 if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {
1723 if (!IsValidAssume(*IntrI))
1724 continue;
1725 int Idx = CmpI->getOperandUse(0) == LoadU;
1726 Assumption = {CmpI->getOperand(Idx), IntrI};
1727 break;
1728 }
1729 }
1730 }
1731 if (Assumption.first)
1732 break;
1733 }
1734
1735 // Check if we found an assumption associated with this load.
1736 if (!Assumption.first || !Assumption.second)
1737 return true;
1738
1739 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "
1740 << *Assumption.second << ": " << *LoadI
1741 << " == " << *Assumption.first << "\n");
1742
1743 return handleAccess(
1744 A, *Assumption.second, Assumption.first, AccessKind::AK_ASSUMPTION,
1745 OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());
1746 }
1747
1748 auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
1749 ArrayRef<Value *> OtherOps, AccessKind AK) {
1750 for (auto *OtherOp : OtherOps) {
1751 if (OtherOp == CurPtr) {
1752 LLVM_DEBUG(
1753 dbgs()
1754 << "[AAPointerInfo] Escaping use in store like instruction " << I
1755 << "\n");
1756 return false;
1757 }
1758 }
1759
1760 // If the access is to a pointer that may or may not be the associated
1761 // value, e.g. due to a PHI, we cannot assume it will be written.
1762 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1763 AK = AccessKind(AK | AccessKind::AK_MUST);
1764 else
1765 AK = AccessKind(AK | AccessKind::AK_MAY);
1766 bool UsedAssumedInformation = false;
1767 std::optional<Value *> Content = nullptr;
1768 if (ValueOp)
1769 Content = A.getAssumedSimplified(
1770 *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
1771 return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1772 Changed, ValueTy);
1773 };
1774
1775 if (auto *StoreI = dyn_cast<StoreInst>(Usr))
1776 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1777 *StoreI->getValueOperand()->getType(),
1778 {StoreI->getValueOperand()}, AccessKind::AK_W);
1779 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
1780 return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
1781 {RMWI->getValOperand()}, AccessKind::AK_RW);
1782 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
1783 return HandleStoreLike(
1784 *CXI, nullptr, *CXI->getNewValOperand()->getType(),
1785 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1786 AccessKind::AK_RW);
1787
1788 if (auto *CB = dyn_cast<CallBase>(Usr)) {
1789 if (CB->isLifetimeStartOrEnd())
1790 return true;
1791 if (getFreedOperand(CB, TLI) == U)
1792 return true;
1793 if (CB->isArgOperand(&U)) {
1794 unsigned ArgNo = CB->getArgOperandNo(&U);
1795 const auto &CSArgPI = A.getAAFor<AAPointerInfo>(
1796 *this, IRPosition::callsite_argument(*CB, ArgNo),
1797 DepClassTy::REQUIRED);
1798 Changed = translateAndAddState(A, CSArgPI, OffsetInfoMap[CurPtr], *CB) |
1799 Changed;
1800 return isValidState();
1801 }
1802 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CB
1803 << "\n");
1804 // TODO: Allow some call uses
1805 return false;
1806 }
1807
1808 LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n");
1809 return false;
1810 };
1811 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
1812 assert(OffsetInfoMap.count(OldU) && "Old use should be known already!");
1813 if (OffsetInfoMap.count(NewU)) {
1814 LLVM_DEBUG({
1815 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1816 dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
1817 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]
1818 << "\n";
1819 }
1820 });
1821 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1822 }
1823 OffsetInfoMap[NewU] = OffsetInfoMap[OldU];
1824 return true;
1825 };
1826 if (!A.checkForAllUses(UsePred, *this, AssociatedValue,
1827 /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,
1828 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
1829 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n");
1830 return indicatePessimisticFixpoint();
1831 }
1832
1833 LLVM_DEBUG({
1834 dbgs() << "Accesses by bin after update:\n";
1835 dumpState(dbgs());
1836 });
1837
1838 return Changed;
1839 }
1840
1841 struct AAPointerInfoReturned final : AAPointerInfoImpl {
AAPointerInfoReturned__anon641416290711::AAPointerInfoReturned1842 AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
1843 : AAPointerInfoImpl(IRP, A) {}
1844
1845 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416290711::AAPointerInfoReturned1846 ChangeStatus updateImpl(Attributor &A) override {
1847 return indicatePessimisticFixpoint();
1848 }
1849
1850 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416290711::AAPointerInfoReturned1851 void trackStatistics() const override {
1852 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1853 }
1854 };
1855
1856 struct AAPointerInfoArgument final : AAPointerInfoFloating {
AAPointerInfoArgument__anon641416290711::AAPointerInfoArgument1857 AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
1858 : AAPointerInfoFloating(IRP, A) {}
1859
1860 /// See AbstractAttribute::initialize(...).
initialize__anon641416290711::AAPointerInfoArgument1861 void initialize(Attributor &A) override {
1862 AAPointerInfoFloating::initialize(A);
1863 if (getAnchorScope()->isDeclaration())
1864 indicatePessimisticFixpoint();
1865 }
1866
1867 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416290711::AAPointerInfoArgument1868 void trackStatistics() const override {
1869 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1870 }
1871 };
1872
1873 struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
AAPointerInfoCallSiteArgument__anon641416290711::AAPointerInfoCallSiteArgument1874 AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
1875 : AAPointerInfoFloating(IRP, A) {}
1876
1877 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416290711::AAPointerInfoCallSiteArgument1878 ChangeStatus updateImpl(Attributor &A) override {
1879 using namespace AA::PointerInfo;
1880 // We handle memory intrinsics explicitly, at least the first (=
1881 // destination) and second (=source) arguments as we know how they are
1882 // accessed.
1883 if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
1884 ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
1885 int64_t LengthVal = AA::RangeTy::Unknown;
1886 if (Length)
1887 LengthVal = Length->getSExtValue();
1888 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1889 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1890 if (ArgNo > 1) {
1891 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
1892 << *MI << "\n");
1893 return indicatePessimisticFixpoint();
1894 } else {
1895 auto Kind =
1896 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1897 Changed =
1898 Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);
1899 }
1900 LLVM_DEBUG({
1901 dbgs() << "Accesses by bin after update:\n";
1902 dumpState(dbgs());
1903 });
1904
1905 return Changed;
1906 }
1907
1908 // TODO: Once we have call site specific value information we can provide
1909 // call site specific liveness information and then it makes
1910 // sense to specialize attributes for call sites arguments instead of
1911 // redirecting requests to the callee argument.
1912 Argument *Arg = getAssociatedArgument();
1913 if (Arg) {
1914 const IRPosition &ArgPos = IRPosition::argument(*Arg);
1915 auto &ArgAA =
1916 A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
1917 if (ArgAA.getState().isValidState())
1918 return translateAndAddStateFromCallee(A, ArgAA,
1919 *cast<CallBase>(getCtxI()));
1920 if (!Arg->getParent()->isDeclaration())
1921 return indicatePessimisticFixpoint();
1922 }
1923
1924 const auto &NoCaptureAA =
1925 A.getAAFor<AANoCapture>(*this, getIRPosition(), DepClassTy::OPTIONAL);
1926
1927 if (!NoCaptureAA.isAssumedNoCapture())
1928 return indicatePessimisticFixpoint();
1929
1930 bool IsKnown = false;
1931 if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
1932 return ChangeStatus::UNCHANGED;
1933 bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);
1934 auto Kind =
1935 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
1936 return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,
1937 nullptr);
1938 }
1939
1940 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416290711::AAPointerInfoCallSiteArgument1941 void trackStatistics() const override {
1942 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1943 }
1944 };
1945
1946 struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
AAPointerInfoCallSiteReturned__anon641416290711::AAPointerInfoCallSiteReturned1947 AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
1948 : AAPointerInfoFloating(IRP, A) {}
1949
1950 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416290711::AAPointerInfoCallSiteReturned1951 void trackStatistics() const override {
1952 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1953 }
1954 };
1955 } // namespace
1956
1957 /// -----------------------NoUnwind Function Attribute--------------------------
1958
1959 namespace {
1960 struct AANoUnwindImpl : AANoUnwind {
AANoUnwindImpl__anon641416291711::AANoUnwindImpl1961 AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}
1962
getAsStr__anon641416291711::AANoUnwindImpl1963 const std::string getAsStr() const override {
1964 return getAssumed() ? "nounwind" : "may-unwind";
1965 }
1966
1967 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291711::AANoUnwindImpl1968 ChangeStatus updateImpl(Attributor &A) override {
1969 auto Opcodes = {
1970 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
1971 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
1972 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
1973
1974 auto CheckForNoUnwind = [&](Instruction &I) {
1975 if (!I.mayThrow())
1976 return true;
1977
1978 if (const auto *CB = dyn_cast<CallBase>(&I)) {
1979 const auto &NoUnwindAA = A.getAAFor<AANoUnwind>(
1980 *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);
1981 return NoUnwindAA.isAssumedNoUnwind();
1982 }
1983 return false;
1984 };
1985
1986 bool UsedAssumedInformation = false;
1987 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
1988 UsedAssumedInformation))
1989 return indicatePessimisticFixpoint();
1990
1991 return ChangeStatus::UNCHANGED;
1992 }
1993 };
1994
1995 struct AANoUnwindFunction final : public AANoUnwindImpl {
AANoUnwindFunction__anon641416291711::AANoUnwindFunction1996 AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
1997 : AANoUnwindImpl(IRP, A) {}
1998
1999 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291711::AANoUnwindFunction2000 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
2001 };
2002
2003 /// NoUnwind attribute deduction for a call sites.
2004 struct AANoUnwindCallSite final : AANoUnwindImpl {
AANoUnwindCallSite__anon641416291711::AANoUnwindCallSite2005 AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
2006 : AANoUnwindImpl(IRP, A) {}
2007
2008 /// See AbstractAttribute::initialize(...).
initialize__anon641416291711::AANoUnwindCallSite2009 void initialize(Attributor &A) override {
2010 AANoUnwindImpl::initialize(A);
2011 Function *F = getAssociatedFunction();
2012 if (!F || F->isDeclaration())
2013 indicatePessimisticFixpoint();
2014 }
2015
2016 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291711::AANoUnwindCallSite2017 ChangeStatus updateImpl(Attributor &A) override {
2018 // TODO: Once we have call site specific value information we can provide
2019 // call site specific liveness information and then it makes
2020 // sense to specialize attributes for call sites arguments instead of
2021 // redirecting requests to the callee argument.
2022 Function *F = getAssociatedFunction();
2023 const IRPosition &FnPos = IRPosition::function(*F);
2024 auto &FnAA = A.getAAFor<AANoUnwind>(*this, FnPos, DepClassTy::REQUIRED);
2025 return clampStateAndIndicateChange(getState(), FnAA.getState());
2026 }
2027
2028 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291711::AANoUnwindCallSite2029 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }
2030 };
2031 } // namespace
2032
2033 /// --------------------- Function Return Values -------------------------------
2034
2035 namespace {
2036 /// "Attribute" that collects all potential returned values and the return
2037 /// instructions that they arise from.
2038 ///
2039 /// If there is a unique returned value R, the manifest method will:
2040 /// - mark R with the "returned" attribute, if R is an argument.
2041 class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
2042
2043 /// Mapping of values potentially returned by the associated function to the
2044 /// return instructions that might return them.
2045 MapVector<Value *, SmallSetVector<ReturnInst *, 4>> ReturnedValues;
2046
2047 /// State flags
2048 ///
2049 ///{
2050 bool IsFixed = false;
2051 bool IsValidState = true;
2052 ///}
2053
2054 public:
AAReturnedValuesImpl(const IRPosition & IRP,Attributor & A)2055 AAReturnedValuesImpl(const IRPosition &IRP, Attributor &A)
2056 : AAReturnedValues(IRP, A) {}
2057
2058 /// See AbstractAttribute::initialize(...).
initialize(Attributor & A)2059 void initialize(Attributor &A) override {
2060 // Reset the state.
2061 IsFixed = false;
2062 IsValidState = true;
2063 ReturnedValues.clear();
2064
2065 Function *F = getAssociatedFunction();
2066 if (!F || F->isDeclaration()) {
2067 indicatePessimisticFixpoint();
2068 return;
2069 }
2070 assert(!F->getReturnType()->isVoidTy() &&
2071 "Did not expect a void return type!");
2072
2073 // The map from instruction opcodes to those instructions in the function.
2074 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
2075
2076 // Look through all arguments, if one is marked as returned we are done.
2077 for (Argument &Arg : F->args()) {
2078 if (Arg.hasReturnedAttr()) {
2079 auto &ReturnInstSet = ReturnedValues[&Arg];
2080 if (auto *Insts = OpcodeInstMap.lookup(Instruction::Ret))
2081 for (Instruction *RI : *Insts)
2082 ReturnInstSet.insert(cast<ReturnInst>(RI));
2083
2084 indicateOptimisticFixpoint();
2085 return;
2086 }
2087 }
2088
2089 if (!A.isFunctionIPOAmendable(*F))
2090 indicatePessimisticFixpoint();
2091 }
2092
2093 /// See AbstractAttribute::manifest(...).
2094 ChangeStatus manifest(Attributor &A) override;
2095
2096 /// See AbstractAttribute::getState(...).
getState()2097 AbstractState &getState() override { return *this; }
2098
2099 /// See AbstractAttribute::getState(...).
getState() const2100 const AbstractState &getState() const override { return *this; }
2101
2102 /// See AbstractAttribute::updateImpl(Attributor &A).
2103 ChangeStatus updateImpl(Attributor &A) override;
2104
returned_values()2105 llvm::iterator_range<iterator> returned_values() override {
2106 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
2107 }
2108
returned_values() const2109 llvm::iterator_range<const_iterator> returned_values() const override {
2110 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
2111 }
2112
2113 /// Return the number of potential return values, -1 if unknown.
getNumReturnValues() const2114 size_t getNumReturnValues() const override {
2115 return isValidState() ? ReturnedValues.size() : -1;
2116 }
2117
2118 /// Return an assumed unique return value if a single candidate is found. If
2119 /// there cannot be one, return a nullptr. If it is not clear yet, return
2120 /// std::nullopt.
2121 std::optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
2122
2123 /// See AbstractState::checkForAllReturnedValues(...).
2124 bool checkForAllReturnedValuesAndReturnInsts(
2125 function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred)
2126 const override;
2127
2128 /// Pretty print the attribute similar to the IR representation.
2129 const std::string getAsStr() const override;
2130
2131 /// See AbstractState::isAtFixpoint().
isAtFixpoint() const2132 bool isAtFixpoint() const override { return IsFixed; }
2133
2134 /// See AbstractState::isValidState().
isValidState() const2135 bool isValidState() const override { return IsValidState; }
2136
2137 /// See AbstractState::indicateOptimisticFixpoint(...).
indicateOptimisticFixpoint()2138 ChangeStatus indicateOptimisticFixpoint() override {
2139 IsFixed = true;
2140 return ChangeStatus::UNCHANGED;
2141 }
2142
indicatePessimisticFixpoint()2143 ChangeStatus indicatePessimisticFixpoint() override {
2144 IsFixed = true;
2145 IsValidState = false;
2146 return ChangeStatus::CHANGED;
2147 }
2148 };
2149
manifest(Attributor & A)2150 ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
2151 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2152
2153 // Bookkeeping.
2154 assert(isValidState());
2155 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,
2156 "Number of function with known return values");
2157
2158 // Check if we have an assumed unique return value that we could manifest.
2159 std::optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
2160
2161 if (!UniqueRV || !*UniqueRV)
2162 return Changed;
2163
2164 // Bookkeeping.
2165 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
2166 "Number of function with unique return");
2167 // If the assumed unique return value is an argument, annotate it.
2168 if (auto *UniqueRVArg = dyn_cast<Argument>(*UniqueRV)) {
2169 if (UniqueRVArg->getType()->canLosslesslyBitCastTo(
2170 getAssociatedFunction()->getReturnType())) {
2171 getIRPosition() = IRPosition::argument(*UniqueRVArg);
2172 Changed = IRAttribute::manifest(A);
2173 }
2174 }
2175 return Changed;
2176 }
2177
getAsStr() const2178 const std::string AAReturnedValuesImpl::getAsStr() const {
2179 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
2180 (isValidState() ? std::to_string(getNumReturnValues()) : "?") + ")";
2181 }
2182
2183 std::optional<Value *>
getAssumedUniqueReturnValue(Attributor & A) const2184 AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
2185 // If checkForAllReturnedValues provides a unique value, ignoring potential
2186 // undef values that can also be present, it is assumed to be the actual
2187 // return value and forwarded to the caller of this method. If there are
2188 // multiple, a nullptr is returned indicating there cannot be a unique
2189 // returned value.
2190 std::optional<Value *> UniqueRV;
2191 Type *Ty = getAssociatedFunction()->getReturnType();
2192
2193 auto Pred = [&](Value &RV) -> bool {
2194 UniqueRV = AA::combineOptionalValuesInAAValueLatice(UniqueRV, &RV, Ty);
2195 return UniqueRV != std::optional<Value *>(nullptr);
2196 };
2197
2198 if (!A.checkForAllReturnedValues(Pred, *this))
2199 UniqueRV = nullptr;
2200
2201 return UniqueRV;
2202 }
2203
checkForAllReturnedValuesAndReturnInsts(function_ref<bool (Value &,const SmallSetVector<ReturnInst *,4> &)> Pred) const2204 bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
2205 function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> Pred)
2206 const {
2207 if (!isValidState())
2208 return false;
2209
2210 // Check all returned values but ignore call sites as long as we have not
2211 // encountered an overdefined one during an update.
2212 for (const auto &It : ReturnedValues) {
2213 Value *RV = It.first;
2214 if (!Pred(*RV, It.second))
2215 return false;
2216 }
2217
2218 return true;
2219 }
2220
updateImpl(Attributor & A)2221 ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
2222 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2223
2224 SmallVector<AA::ValueAndContext> Values;
2225 bool UsedAssumedInformation = false;
2226 auto ReturnInstCB = [&](Instruction &I) {
2227 ReturnInst &Ret = cast<ReturnInst>(I);
2228 Values.clear();
2229 if (!A.getAssumedSimplifiedValues(IRPosition::value(*Ret.getReturnValue()),
2230 *this, Values, AA::Intraprocedural,
2231 UsedAssumedInformation))
2232 Values.push_back({*Ret.getReturnValue(), Ret});
2233
2234 for (auto &VAC : Values) {
2235 assert(AA::isValidInScope(*VAC.getValue(), Ret.getFunction()) &&
2236 "Assumed returned value should be valid in function scope!");
2237 if (ReturnedValues[VAC.getValue()].insert(&Ret))
2238 Changed = ChangeStatus::CHANGED;
2239 }
2240 return true;
2241 };
2242
2243 // Discover returned values from all live returned instructions in the
2244 // associated function.
2245 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
2246 UsedAssumedInformation))
2247 return indicatePessimisticFixpoint();
2248 return Changed;
2249 }
2250
2251 struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
AAReturnedValuesFunction__anon641416291911::AAReturnedValuesFunction2252 AAReturnedValuesFunction(const IRPosition &IRP, Attributor &A)
2253 : AAReturnedValuesImpl(IRP, A) {}
2254
2255 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291911::AAReturnedValuesFunction2256 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned) }
2257 };
2258
2259 /// Returned values information for a call sites.
2260 struct AAReturnedValuesCallSite final : AAReturnedValuesImpl {
AAReturnedValuesCallSite__anon641416291911::AAReturnedValuesCallSite2261 AAReturnedValuesCallSite(const IRPosition &IRP, Attributor &A)
2262 : AAReturnedValuesImpl(IRP, A) {}
2263
2264 /// See AbstractAttribute::initialize(...).
initialize__anon641416291911::AAReturnedValuesCallSite2265 void initialize(Attributor &A) override {
2266 // TODO: Once we have call site specific value information we can provide
2267 // call site specific liveness information and then it makes
2268 // sense to specialize attributes for call sites instead of
2269 // redirecting requests to the callee.
2270 llvm_unreachable("Abstract attributes for returned values are not "
2271 "supported for call sites yet!");
2272 }
2273
2274 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291911::AAReturnedValuesCallSite2275 ChangeStatus updateImpl(Attributor &A) override {
2276 return indicatePessimisticFixpoint();
2277 }
2278
2279 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291911::AAReturnedValuesCallSite2280 void trackStatistics() const override {}
2281 };
2282 } // namespace
2283
2284 /// ------------------------ NoSync Function Attribute -------------------------
2285
isAlignedBarrier(const CallBase & CB,bool ExecutedAligned)2286 bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
2287 switch (CB.getIntrinsicID()) {
2288 case Intrinsic::nvvm_barrier0:
2289 case Intrinsic::nvvm_barrier0_and:
2290 case Intrinsic::nvvm_barrier0_or:
2291 case Intrinsic::nvvm_barrier0_popc:
2292 return true;
2293 case Intrinsic::amdgcn_s_barrier:
2294 if (ExecutedAligned)
2295 return true;
2296 break;
2297 default:
2298 break;
2299 }
2300 return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));
2301 }
2302
isNonRelaxedAtomic(const Instruction * I)2303 bool AANoSync::isNonRelaxedAtomic(const Instruction *I) {
2304 if (!I->isAtomic())
2305 return false;
2306
2307 if (auto *FI = dyn_cast<FenceInst>(I))
2308 // All legal orderings for fence are stronger than monotonic.
2309 return FI->getSyncScopeID() != SyncScope::SingleThread;
2310 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
2311 // Unordered is not a legal ordering for cmpxchg.
2312 return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
2313 AI->getFailureOrdering() != AtomicOrdering::Monotonic);
2314 }
2315
2316 AtomicOrdering Ordering;
2317 switch (I->getOpcode()) {
2318 case Instruction::AtomicRMW:
2319 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
2320 break;
2321 case Instruction::Store:
2322 Ordering = cast<StoreInst>(I)->getOrdering();
2323 break;
2324 case Instruction::Load:
2325 Ordering = cast<LoadInst>(I)->getOrdering();
2326 break;
2327 default:
2328 llvm_unreachable(
2329 "New atomic operations need to be known in the attributor.");
2330 }
2331
2332 return (Ordering != AtomicOrdering::Unordered &&
2333 Ordering != AtomicOrdering::Monotonic);
2334 }
2335
2336 /// Return true if this intrinsic is nosync. This is only used for intrinsics
2337 /// which would be nosync except that they have a volatile flag. All other
2338 /// intrinsics are simply annotated with the nosync attribute in Intrinsics.td.
isNoSyncIntrinsic(const Instruction * I)2339 bool AANoSync::isNoSyncIntrinsic(const Instruction *I) {
2340 if (auto *MI = dyn_cast<MemIntrinsic>(I))
2341 return !MI->isVolatile();
2342 return false;
2343 }
2344
2345 namespace {
2346 struct AANoSyncImpl : AANoSync {
AANoSyncImpl__anon641416291c11::AANoSyncImpl2347 AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}
2348
getAsStr__anon641416291c11::AANoSyncImpl2349 const std::string getAsStr() const override {
2350 return getAssumed() ? "nosync" : "may-sync";
2351 }
2352
2353 /// See AbstractAttribute::updateImpl(...).
2354 ChangeStatus updateImpl(Attributor &A) override;
2355 };
2356
updateImpl(Attributor & A)2357 ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
2358
2359 auto CheckRWInstForNoSync = [&](Instruction &I) {
2360 return AA::isNoSyncInst(A, I, *this);
2361 };
2362
2363 auto CheckForNoSync = [&](Instruction &I) {
2364 // At this point we handled all read/write effects and they are all
2365 // nosync, so they can be skipped.
2366 if (I.mayReadOrWriteMemory())
2367 return true;
2368
2369 // non-convergent and readnone imply nosync.
2370 return !cast<CallBase>(I).isConvergent();
2371 };
2372
2373 bool UsedAssumedInformation = false;
2374 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
2375 UsedAssumedInformation) ||
2376 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
2377 UsedAssumedInformation))
2378 return indicatePessimisticFixpoint();
2379
2380 return ChangeStatus::UNCHANGED;
2381 }
2382
2383 struct AANoSyncFunction final : public AANoSyncImpl {
AANoSyncFunction__anon641416291c11::AANoSyncFunction2384 AANoSyncFunction(const IRPosition &IRP, Attributor &A)
2385 : AANoSyncImpl(IRP, A) {}
2386
2387 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291c11::AANoSyncFunction2388 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
2389 };
2390
2391 /// NoSync attribute deduction for a call sites.
2392 struct AANoSyncCallSite final : AANoSyncImpl {
AANoSyncCallSite__anon641416291c11::AANoSyncCallSite2393 AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
2394 : AANoSyncImpl(IRP, A) {}
2395
2396 /// See AbstractAttribute::initialize(...).
initialize__anon641416291c11::AANoSyncCallSite2397 void initialize(Attributor &A) override {
2398 AANoSyncImpl::initialize(A);
2399 Function *F = getAssociatedFunction();
2400 if (!F || F->isDeclaration())
2401 indicatePessimisticFixpoint();
2402 }
2403
2404 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291c11::AANoSyncCallSite2405 ChangeStatus updateImpl(Attributor &A) override {
2406 // TODO: Once we have call site specific value information we can provide
2407 // call site specific liveness information and then it makes
2408 // sense to specialize attributes for call sites arguments instead of
2409 // redirecting requests to the callee argument.
2410 Function *F = getAssociatedFunction();
2411 const IRPosition &FnPos = IRPosition::function(*F);
2412 auto &FnAA = A.getAAFor<AANoSync>(*this, FnPos, DepClassTy::REQUIRED);
2413 return clampStateAndIndicateChange(getState(), FnAA.getState());
2414 }
2415
2416 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291c11::AANoSyncCallSite2417 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }
2418 };
2419 } // namespace
2420
2421 /// ------------------------ No-Free Attributes ----------------------------
2422
2423 namespace {
2424 struct AANoFreeImpl : public AANoFree {
AANoFreeImpl__anon641416291f11::AANoFreeImpl2425 AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}
2426
2427 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291f11::AANoFreeImpl2428 ChangeStatus updateImpl(Attributor &A) override {
2429 auto CheckForNoFree = [&](Instruction &I) {
2430 const auto &CB = cast<CallBase>(I);
2431 if (CB.hasFnAttr(Attribute::NoFree))
2432 return true;
2433
2434 const auto &NoFreeAA = A.getAAFor<AANoFree>(
2435 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
2436 return NoFreeAA.isAssumedNoFree();
2437 };
2438
2439 bool UsedAssumedInformation = false;
2440 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
2441 UsedAssumedInformation))
2442 return indicatePessimisticFixpoint();
2443 return ChangeStatus::UNCHANGED;
2444 }
2445
2446 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416291f11::AANoFreeImpl2447 const std::string getAsStr() const override {
2448 return getAssumed() ? "nofree" : "may-free";
2449 }
2450 };
2451
2452 struct AANoFreeFunction final : public AANoFreeImpl {
AANoFreeFunction__anon641416291f11::AANoFreeFunction2453 AANoFreeFunction(const IRPosition &IRP, Attributor &A)
2454 : AANoFreeImpl(IRP, A) {}
2455
2456 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291f11::AANoFreeFunction2457 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
2458 };
2459
2460 /// NoFree attribute deduction for a call sites.
2461 struct AANoFreeCallSite final : AANoFreeImpl {
AANoFreeCallSite__anon641416291f11::AANoFreeCallSite2462 AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
2463 : AANoFreeImpl(IRP, A) {}
2464
2465 /// See AbstractAttribute::initialize(...).
initialize__anon641416291f11::AANoFreeCallSite2466 void initialize(Attributor &A) override {
2467 AANoFreeImpl::initialize(A);
2468 Function *F = getAssociatedFunction();
2469 if (!F || F->isDeclaration())
2470 indicatePessimisticFixpoint();
2471 }
2472
2473 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291f11::AANoFreeCallSite2474 ChangeStatus updateImpl(Attributor &A) override {
2475 // TODO: Once we have call site specific value information we can provide
2476 // call site specific liveness information and then it makes
2477 // sense to specialize attributes for call sites arguments instead of
2478 // redirecting requests to the callee argument.
2479 Function *F = getAssociatedFunction();
2480 const IRPosition &FnPos = IRPosition::function(*F);
2481 auto &FnAA = A.getAAFor<AANoFree>(*this, FnPos, DepClassTy::REQUIRED);
2482 return clampStateAndIndicateChange(getState(), FnAA.getState());
2483 }
2484
2485 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291f11::AANoFreeCallSite2486 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
2487 };
2488
2489 /// NoFree attribute for floating values.
2490 struct AANoFreeFloating : AANoFreeImpl {
AANoFreeFloating__anon641416291f11::AANoFreeFloating2491 AANoFreeFloating(const IRPosition &IRP, Attributor &A)
2492 : AANoFreeImpl(IRP, A) {}
2493
2494 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291f11::AANoFreeFloating2495 void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}
2496
2497 /// See Abstract Attribute::updateImpl(...).
updateImpl__anon641416291f11::AANoFreeFloating2498 ChangeStatus updateImpl(Attributor &A) override {
2499 const IRPosition &IRP = getIRPosition();
2500
2501 const auto &NoFreeAA = A.getAAFor<AANoFree>(
2502 *this, IRPosition::function_scope(IRP), DepClassTy::OPTIONAL);
2503 if (NoFreeAA.isAssumedNoFree())
2504 return ChangeStatus::UNCHANGED;
2505
2506 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2507 auto Pred = [&](const Use &U, bool &Follow) -> bool {
2508 Instruction *UserI = cast<Instruction>(U.getUser());
2509 if (auto *CB = dyn_cast<CallBase>(UserI)) {
2510 if (CB->isBundleOperand(&U))
2511 return false;
2512 if (!CB->isArgOperand(&U))
2513 return true;
2514 unsigned ArgNo = CB->getArgOperandNo(&U);
2515
2516 const auto &NoFreeArg = A.getAAFor<AANoFree>(
2517 *this, IRPosition::callsite_argument(*CB, ArgNo),
2518 DepClassTy::REQUIRED);
2519 return NoFreeArg.isAssumedNoFree();
2520 }
2521
2522 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
2523 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
2524 Follow = true;
2525 return true;
2526 }
2527 if (isa<StoreInst>(UserI) || isa<LoadInst>(UserI) ||
2528 isa<ReturnInst>(UserI))
2529 return true;
2530
2531 // Unknown user.
2532 return false;
2533 };
2534 if (!A.checkForAllUses(Pred, *this, AssociatedValue))
2535 return indicatePessimisticFixpoint();
2536
2537 return ChangeStatus::UNCHANGED;
2538 }
2539 };
2540
2541 /// NoFree attribute for a call site argument.
2542 struct AANoFreeArgument final : AANoFreeFloating {
AANoFreeArgument__anon641416291f11::AANoFreeArgument2543 AANoFreeArgument(const IRPosition &IRP, Attributor &A)
2544 : AANoFreeFloating(IRP, A) {}
2545
2546 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291f11::AANoFreeArgument2547 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }
2548 };
2549
2550 /// NoFree attribute for call site arguments.
2551 struct AANoFreeCallSiteArgument final : AANoFreeFloating {
AANoFreeCallSiteArgument__anon641416291f11::AANoFreeCallSiteArgument2552 AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
2553 : AANoFreeFloating(IRP, A) {}
2554
2555 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291f11::AANoFreeCallSiteArgument2556 ChangeStatus updateImpl(Attributor &A) override {
2557 // TODO: Once we have call site specific value information we can provide
2558 // call site specific liveness information and then it makes
2559 // sense to specialize attributes for call sites arguments instead of
2560 // redirecting requests to the callee argument.
2561 Argument *Arg = getAssociatedArgument();
2562 if (!Arg)
2563 return indicatePessimisticFixpoint();
2564 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2565 auto &ArgAA = A.getAAFor<AANoFree>(*this, ArgPos, DepClassTy::REQUIRED);
2566 return clampStateAndIndicateChange(getState(), ArgAA.getState());
2567 }
2568
2569 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291f11::AANoFreeCallSiteArgument2570 void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nofree)};
2571 };
2572
2573 /// NoFree attribute for function return value.
2574 struct AANoFreeReturned final : AANoFreeFloating {
AANoFreeReturned__anon641416291f11::AANoFreeReturned2575 AANoFreeReturned(const IRPosition &IRP, Attributor &A)
2576 : AANoFreeFloating(IRP, A) {
2577 llvm_unreachable("NoFree is not applicable to function returns!");
2578 }
2579
2580 /// See AbstractAttribute::initialize(...).
initialize__anon641416291f11::AANoFreeReturned2581 void initialize(Attributor &A) override {
2582 llvm_unreachable("NoFree is not applicable to function returns!");
2583 }
2584
2585 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416291f11::AANoFreeReturned2586 ChangeStatus updateImpl(Attributor &A) override {
2587 llvm_unreachable("NoFree is not applicable to function returns!");
2588 }
2589
2590 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291f11::AANoFreeReturned2591 void trackStatistics() const override {}
2592 };
2593
2594 /// NoFree attribute deduction for a call site return value.
2595 struct AANoFreeCallSiteReturned final : AANoFreeFloating {
AANoFreeCallSiteReturned__anon641416291f11::AANoFreeCallSiteReturned2596 AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
2597 : AANoFreeFloating(IRP, A) {}
2598
manifest__anon641416291f11::AANoFreeCallSiteReturned2599 ChangeStatus manifest(Attributor &A) override {
2600 return ChangeStatus::UNCHANGED;
2601 }
2602 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416291f11::AANoFreeCallSiteReturned2603 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }
2604 };
2605 } // namespace
2606
2607 /// ------------------------ NonNull Argument Attribute ------------------------
2608 namespace {
getKnownNonNullAndDerefBytesForUse(Attributor & A,const AbstractAttribute & QueryingAA,Value & AssociatedValue,const Use * U,const Instruction * I,bool & IsNonNull,bool & TrackUse)2609 static int64_t getKnownNonNullAndDerefBytesForUse(
2610 Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
2611 const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
2612 TrackUse = false;
2613
2614 const Value *UseV = U->get();
2615 if (!UseV->getType()->isPointerTy())
2616 return 0;
2617
2618 // We need to follow common pointer manipulation uses to the accesses they
2619 // feed into. We can try to be smart to avoid looking through things we do not
2620 // like for now, e.g., non-inbounds GEPs.
2621 if (isa<CastInst>(I)) {
2622 TrackUse = true;
2623 return 0;
2624 }
2625
2626 if (isa<GetElementPtrInst>(I)) {
2627 TrackUse = true;
2628 return 0;
2629 }
2630
2631 Type *PtrTy = UseV->getType();
2632 const Function *F = I->getFunction();
2633 bool NullPointerIsDefined =
2634 F ? llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()) : true;
2635 const DataLayout &DL = A.getInfoCache().getDL();
2636 if (const auto *CB = dyn_cast<CallBase>(I)) {
2637 if (CB->isBundleOperand(U)) {
2638 if (RetainedKnowledge RK = getKnowledgeFromUse(
2639 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2640 IsNonNull |=
2641 (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);
2642 return RK.ArgValue;
2643 }
2644 return 0;
2645 }
2646
2647 if (CB->isCallee(U)) {
2648 IsNonNull |= !NullPointerIsDefined;
2649 return 0;
2650 }
2651
2652 unsigned ArgNo = CB->getArgOperandNo(U);
2653 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
2654 // As long as we only use known information there is no need to track
2655 // dependences here.
2656 auto &DerefAA =
2657 A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
2658 IsNonNull |= DerefAA.isKnownNonNull();
2659 return DerefAA.getKnownDereferenceableBytes();
2660 }
2661
2662 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
2663 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
2664 return 0;
2665
2666 int64_t Offset;
2667 const Value *Base =
2668 getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);
2669 if (Base && Base == &AssociatedValue) {
2670 int64_t DerefBytes = Loc->Size.getValue() + Offset;
2671 IsNonNull |= !NullPointerIsDefined;
2672 return std::max(int64_t(0), DerefBytes);
2673 }
2674
2675 /// Corner case when an offset is 0.
2676 Base = GetPointerBaseWithConstantOffset(Loc->Ptr, Offset, DL,
2677 /*AllowNonInbounds*/ true);
2678 if (Base && Base == &AssociatedValue && Offset == 0) {
2679 int64_t DerefBytes = Loc->Size.getValue();
2680 IsNonNull |= !NullPointerIsDefined;
2681 return std::max(int64_t(0), DerefBytes);
2682 }
2683
2684 return 0;
2685 }
2686
2687 struct AANonNullImpl : AANonNull {
AANonNullImpl__anon641416292211::AANonNullImpl2688 AANonNullImpl(const IRPosition &IRP, Attributor &A)
2689 : AANonNull(IRP, A),
2690 NullIsDefined(NullPointerIsDefined(
2691 getAnchorScope(),
2692 getAssociatedValue().getType()->getPointerAddressSpace())) {}
2693
2694 /// See AbstractAttribute::initialize(...).
initialize__anon641416292211::AANonNullImpl2695 void initialize(Attributor &A) override {
2696 Value &V = *getAssociatedValue().stripPointerCasts();
2697 if (!NullIsDefined &&
2698 hasAttr({Attribute::NonNull, Attribute::Dereferenceable},
2699 /* IgnoreSubsumingPositions */ false, &A)) {
2700 indicateOptimisticFixpoint();
2701 return;
2702 }
2703
2704 if (isa<ConstantPointerNull>(V)) {
2705 indicatePessimisticFixpoint();
2706 return;
2707 }
2708
2709 AANonNull::initialize(A);
2710
2711 bool CanBeNull, CanBeFreed;
2712 if (V.getPointerDereferenceableBytes(A.getDataLayout(), CanBeNull,
2713 CanBeFreed)) {
2714 if (!CanBeNull) {
2715 indicateOptimisticFixpoint();
2716 return;
2717 }
2718 }
2719
2720 if (isa<GlobalValue>(V)) {
2721 indicatePessimisticFixpoint();
2722 return;
2723 }
2724
2725 if (Instruction *CtxI = getCtxI())
2726 followUsesInMBEC(*this, A, getState(), *CtxI);
2727 }
2728
2729 /// See followUsesInMBEC
followUseInMBEC__anon641416292211::AANonNullImpl2730 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
2731 AANonNull::StateType &State) {
2732 bool IsNonNull = false;
2733 bool TrackUse = false;
2734 getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,
2735 IsNonNull, TrackUse);
2736 State.setKnown(IsNonNull);
2737 return TrackUse;
2738 }
2739
2740 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416292211::AANonNullImpl2741 const std::string getAsStr() const override {
2742 return getAssumed() ? "nonnull" : "may-null";
2743 }
2744
2745 /// Flag to determine if the underlying value can be null and still allow
2746 /// valid accesses.
2747 const bool NullIsDefined;
2748 };
2749
2750 /// NonNull attribute for a floating value.
2751 struct AANonNullFloating : public AANonNullImpl {
AANonNullFloating__anon641416292211::AANonNullFloating2752 AANonNullFloating(const IRPosition &IRP, Attributor &A)
2753 : AANonNullImpl(IRP, A) {}
2754
2755 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292211::AANonNullFloating2756 ChangeStatus updateImpl(Attributor &A) override {
2757 const DataLayout &DL = A.getDataLayout();
2758
2759 bool Stripped;
2760 bool UsedAssumedInformation = false;
2761 SmallVector<AA::ValueAndContext> Values;
2762 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
2763 AA::AnyScope, UsedAssumedInformation)) {
2764 Values.push_back({getAssociatedValue(), getCtxI()});
2765 Stripped = false;
2766 } else {
2767 Stripped = Values.size() != 1 ||
2768 Values.front().getValue() != &getAssociatedValue();
2769 }
2770
2771 DominatorTree *DT = nullptr;
2772 AssumptionCache *AC = nullptr;
2773 InformationCache &InfoCache = A.getInfoCache();
2774 if (const Function *Fn = getAnchorScope()) {
2775 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*Fn);
2776 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*Fn);
2777 }
2778
2779 AANonNull::StateType T;
2780 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
2781 const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V),
2782 DepClassTy::REQUIRED);
2783 if (!Stripped && this == &AA) {
2784 if (!isKnownNonZero(&V, DL, 0, AC, CtxI, DT))
2785 T.indicatePessimisticFixpoint();
2786 } else {
2787 // Use abstract attribute information.
2788 const AANonNull::StateType &NS = AA.getState();
2789 T ^= NS;
2790 }
2791 return T.isValidState();
2792 };
2793
2794 for (const auto &VAC : Values)
2795 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
2796 return indicatePessimisticFixpoint();
2797
2798 return clampStateAndIndicateChange(getState(), T);
2799 }
2800
2801 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292211::AANonNullFloating2802 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2803 };
2804
2805 /// NonNull attribute for function return value.
2806 struct AANonNullReturned final
2807 : AAReturnedFromReturnedValues<AANonNull, AANonNull> {
AANonNullReturned__anon641416292211::AANonNullReturned2808 AANonNullReturned(const IRPosition &IRP, Attributor &A)
2809 : AAReturnedFromReturnedValues<AANonNull, AANonNull>(IRP, A) {}
2810
2811 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416292211::AANonNullReturned2812 const std::string getAsStr() const override {
2813 return getAssumed() ? "nonnull" : "may-null";
2814 }
2815
2816 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292211::AANonNullReturned2817 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2818 };
2819
2820 /// NonNull attribute for function argument.
2821 struct AANonNullArgument final
2822 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
AANonNullArgument__anon641416292211::AANonNullArgument2823 AANonNullArgument(const IRPosition &IRP, Attributor &A)
2824 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}
2825
2826 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292211::AANonNullArgument2827 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
2828 };
2829
2830 struct AANonNullCallSiteArgument final : AANonNullFloating {
AANonNullCallSiteArgument__anon641416292211::AANonNullCallSiteArgument2831 AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
2832 : AANonNullFloating(IRP, A) {}
2833
2834 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292211::AANonNullCallSiteArgument2835 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
2836 };
2837
2838 /// NonNull attribute for a call site return position.
2839 struct AANonNullCallSiteReturned final
2840 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl> {
AANonNullCallSiteReturned__anon641416292211::AANonNullCallSiteReturned2841 AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
2842 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl>(IRP, A) {}
2843
2844 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292211::AANonNullCallSiteReturned2845 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
2846 };
2847 } // namespace
2848
2849 /// ------------------------ No-Recurse Attributes ----------------------------
2850
2851 namespace {
2852 struct AANoRecurseImpl : public AANoRecurse {
AANoRecurseImpl__anon641416292411::AANoRecurseImpl2853 AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}
2854
2855 /// See AbstractAttribute::getAsStr()
getAsStr__anon641416292411::AANoRecurseImpl2856 const std::string getAsStr() const override {
2857 return getAssumed() ? "norecurse" : "may-recurse";
2858 }
2859 };
2860
2861 struct AANoRecurseFunction final : AANoRecurseImpl {
AANoRecurseFunction__anon641416292411::AANoRecurseFunction2862 AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
2863 : AANoRecurseImpl(IRP, A) {}
2864
2865 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292411::AANoRecurseFunction2866 ChangeStatus updateImpl(Attributor &A) override {
2867
2868 // If all live call sites are known to be no-recurse, we are as well.
2869 auto CallSitePred = [&](AbstractCallSite ACS) {
2870 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
2871 *this, IRPosition::function(*ACS.getInstruction()->getFunction()),
2872 DepClassTy::NONE);
2873 return NoRecurseAA.isKnownNoRecurse();
2874 };
2875 bool UsedAssumedInformation = false;
2876 if (A.checkForAllCallSites(CallSitePred, *this, true,
2877 UsedAssumedInformation)) {
2878 // If we know all call sites and all are known no-recurse, we are done.
2879 // If all known call sites, which might not be all that exist, are known
2880 // to be no-recurse, we are not done but we can continue to assume
2881 // no-recurse. If one of the call sites we have not visited will become
2882 // live, another update is triggered.
2883 if (!UsedAssumedInformation)
2884 indicateOptimisticFixpoint();
2885 return ChangeStatus::UNCHANGED;
2886 }
2887
2888 const AAInterFnReachability &EdgeReachability =
2889 A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),
2890 DepClassTy::REQUIRED);
2891 if (EdgeReachability.canReach(A, *getAnchorScope()))
2892 return indicatePessimisticFixpoint();
2893 return ChangeStatus::UNCHANGED;
2894 }
2895
trackStatistics__anon641416292411::AANoRecurseFunction2896 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
2897 };
2898
2899 /// NoRecurse attribute deduction for a call sites.
2900 struct AANoRecurseCallSite final : AANoRecurseImpl {
AANoRecurseCallSite__anon641416292411::AANoRecurseCallSite2901 AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
2902 : AANoRecurseImpl(IRP, A) {}
2903
2904 /// See AbstractAttribute::initialize(...).
initialize__anon641416292411::AANoRecurseCallSite2905 void initialize(Attributor &A) override {
2906 AANoRecurseImpl::initialize(A);
2907 Function *F = getAssociatedFunction();
2908 if (!F || F->isDeclaration())
2909 indicatePessimisticFixpoint();
2910 }
2911
2912 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292411::AANoRecurseCallSite2913 ChangeStatus updateImpl(Attributor &A) override {
2914 // TODO: Once we have call site specific value information we can provide
2915 // call site specific liveness information and then it makes
2916 // sense to specialize attributes for call sites arguments instead of
2917 // redirecting requests to the callee argument.
2918 Function *F = getAssociatedFunction();
2919 const IRPosition &FnPos = IRPosition::function(*F);
2920 auto &FnAA = A.getAAFor<AANoRecurse>(*this, FnPos, DepClassTy::REQUIRED);
2921 return clampStateAndIndicateChange(getState(), FnAA.getState());
2922 }
2923
2924 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292411::AANoRecurseCallSite2925 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }
2926 };
2927 } // namespace
2928
2929 /// -------------------- Undefined-Behavior Attributes ------------------------
2930
2931 namespace {
2932 struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
AAUndefinedBehaviorImpl__anon641416292611::AAUndefinedBehaviorImpl2933 AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
2934 : AAUndefinedBehavior(IRP, A) {}
2935
2936 /// See AbstractAttribute::updateImpl(...).
2937 // through a pointer (i.e. also branches etc.)
updateImpl__anon641416292611::AAUndefinedBehaviorImpl2938 ChangeStatus updateImpl(Attributor &A) override {
2939 const size_t UBPrevSize = KnownUBInsts.size();
2940 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2941
2942 auto InspectMemAccessInstForUB = [&](Instruction &I) {
2943 // Lang ref now states volatile store is not UB, let's skip them.
2944 if (I.isVolatile() && I.mayWriteToMemory())
2945 return true;
2946
2947 // Skip instructions that are already saved.
2948 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2949 return true;
2950
2951 // If we reach here, we know we have an instruction
2952 // that accesses memory through a pointer operand,
2953 // for which getPointerOperand() should give it to us.
2954 Value *PtrOp =
2955 const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));
2956 assert(PtrOp &&
2957 "Expected pointer operand of memory accessing instruction");
2958
2959 // Either we stopped and the appropriate action was taken,
2960 // or we got back a simplified value to continue.
2961 std::optional<Value *> SimplifiedPtrOp =
2962 stopOnUndefOrAssumed(A, PtrOp, &I);
2963 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2964 return true;
2965 const Value *PtrOpVal = *SimplifiedPtrOp;
2966
2967 // A memory access through a pointer is considered UB
2968 // only if the pointer has constant null value.
2969 // TODO: Expand it to not only check constant values.
2970 if (!isa<ConstantPointerNull>(PtrOpVal)) {
2971 AssumedNoUBInsts.insert(&I);
2972 return true;
2973 }
2974 const Type *PtrTy = PtrOpVal->getType();
2975
2976 // Because we only consider instructions inside functions,
2977 // assume that a parent function exists.
2978 const Function *F = I.getFunction();
2979
2980 // A memory access using constant null pointer is only considered UB
2981 // if null pointer is _not_ defined for the target platform.
2982 if (llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()))
2983 AssumedNoUBInsts.insert(&I);
2984 else
2985 KnownUBInsts.insert(&I);
2986 return true;
2987 };
2988
2989 auto InspectBrInstForUB = [&](Instruction &I) {
2990 // A conditional branch instruction is considered UB if it has `undef`
2991 // condition.
2992
2993 // Skip instructions that are already saved.
2994 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2995 return true;
2996
2997 // We know we have a branch instruction.
2998 auto *BrInst = cast<BranchInst>(&I);
2999
3000 // Unconditional branches are never considered UB.
3001 if (BrInst->isUnconditional())
3002 return true;
3003
3004 // Either we stopped and the appropriate action was taken,
3005 // or we got back a simplified value to continue.
3006 std::optional<Value *> SimplifiedCond =
3007 stopOnUndefOrAssumed(A, BrInst->getCondition(), BrInst);
3008 if (!SimplifiedCond || !*SimplifiedCond)
3009 return true;
3010 AssumedNoUBInsts.insert(&I);
3011 return true;
3012 };
3013
3014 auto InspectCallSiteForUB = [&](Instruction &I) {
3015 // Check whether a callsite always cause UB or not
3016
3017 // Skip instructions that are already saved.
3018 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3019 return true;
3020
3021 // Check nonnull and noundef argument attribute violation for each
3022 // callsite.
3023 CallBase &CB = cast<CallBase>(I);
3024 Function *Callee = CB.getCalledFunction();
3025 if (!Callee)
3026 return true;
3027 for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
3028 // If current argument is known to be simplified to null pointer and the
3029 // corresponding argument position is known to have nonnull attribute,
3030 // the argument is poison. Furthermore, if the argument is poison and
3031 // the position is known to have noundef attriubte, this callsite is
3032 // considered UB.
3033 if (idx >= Callee->arg_size())
3034 break;
3035 Value *ArgVal = CB.getArgOperand(idx);
3036 if (!ArgVal)
3037 continue;
3038 // Here, we handle three cases.
3039 // (1) Not having a value means it is dead. (we can replace the value
3040 // with undef)
3041 // (2) Simplified to undef. The argument violate noundef attriubte.
3042 // (3) Simplified to null pointer where known to be nonnull.
3043 // The argument is a poison value and violate noundef attribute.
3044 IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
3045 auto &NoUndefAA =
3046 A.getAAFor<AANoUndef>(*this, CalleeArgumentIRP, DepClassTy::NONE);
3047 if (!NoUndefAA.isKnownNoUndef())
3048 continue;
3049 bool UsedAssumedInformation = false;
3050 std::optional<Value *> SimplifiedVal =
3051 A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,
3052 UsedAssumedInformation, AA::Interprocedural);
3053 if (UsedAssumedInformation)
3054 continue;
3055 if (SimplifiedVal && !*SimplifiedVal)
3056 return true;
3057 if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {
3058 KnownUBInsts.insert(&I);
3059 continue;
3060 }
3061 if (!ArgVal->getType()->isPointerTy() ||
3062 !isa<ConstantPointerNull>(**SimplifiedVal))
3063 continue;
3064 auto &NonNullAA =
3065 A.getAAFor<AANonNull>(*this, CalleeArgumentIRP, DepClassTy::NONE);
3066 if (NonNullAA.isKnownNonNull())
3067 KnownUBInsts.insert(&I);
3068 }
3069 return true;
3070 };
3071
3072 auto InspectReturnInstForUB = [&](Instruction &I) {
3073 auto &RI = cast<ReturnInst>(I);
3074 // Either we stopped and the appropriate action was taken,
3075 // or we got back a simplified return value to continue.
3076 std::optional<Value *> SimplifiedRetValue =
3077 stopOnUndefOrAssumed(A, RI.getReturnValue(), &I);
3078 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3079 return true;
3080
3081 // Check if a return instruction always cause UB or not
3082 // Note: It is guaranteed that the returned position of the anchor
3083 // scope has noundef attribute when this is called.
3084 // We also ensure the return position is not "assumed dead"
3085 // because the returned value was then potentially simplified to
3086 // `undef` in AAReturnedValues without removing the `noundef`
3087 // attribute yet.
3088
3089 // When the returned position has noundef attriubte, UB occurs in the
3090 // following cases.
3091 // (1) Returned value is known to be undef.
3092 // (2) The value is known to be a null pointer and the returned
3093 // position has nonnull attribute (because the returned value is
3094 // poison).
3095 if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {
3096 auto &NonNullAA = A.getAAFor<AANonNull>(
3097 *this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE);
3098 if (NonNullAA.isKnownNonNull())
3099 KnownUBInsts.insert(&I);
3100 }
3101
3102 return true;
3103 };
3104
3105 bool UsedAssumedInformation = false;
3106 A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
3107 {Instruction::Load, Instruction::Store,
3108 Instruction::AtomicCmpXchg,
3109 Instruction::AtomicRMW},
3110 UsedAssumedInformation,
3111 /* CheckBBLivenessOnly */ true);
3112 A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},
3113 UsedAssumedInformation,
3114 /* CheckBBLivenessOnly */ true);
3115 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
3116 UsedAssumedInformation);
3117
3118 // If the returned position of the anchor scope has noundef attriubte, check
3119 // all returned instructions.
3120 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3121 const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
3122 if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
3123 auto &RetPosNoUndefAA =
3124 A.getAAFor<AANoUndef>(*this, ReturnIRP, DepClassTy::NONE);
3125 if (RetPosNoUndefAA.isKnownNoUndef())
3126 A.checkForAllInstructions(InspectReturnInstForUB, *this,
3127 {Instruction::Ret}, UsedAssumedInformation,
3128 /* CheckBBLivenessOnly */ true);
3129 }
3130 }
3131
3132 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3133 UBPrevSize != KnownUBInsts.size())
3134 return ChangeStatus::CHANGED;
3135 return ChangeStatus::UNCHANGED;
3136 }
3137
isKnownToCauseUB__anon641416292611::AAUndefinedBehaviorImpl3138 bool isKnownToCauseUB(Instruction *I) const override {
3139 return KnownUBInsts.count(I);
3140 }
3141
isAssumedToCauseUB__anon641416292611::AAUndefinedBehaviorImpl3142 bool isAssumedToCauseUB(Instruction *I) const override {
3143 // In simple words, if an instruction is not in the assumed to _not_
3144 // cause UB, then it is assumed UB (that includes those
3145 // in the KnownUBInsts set). The rest is boilerplate
3146 // is to ensure that it is one of the instructions we test
3147 // for UB.
3148
3149 switch (I->getOpcode()) {
3150 case Instruction::Load:
3151 case Instruction::Store:
3152 case Instruction::AtomicCmpXchg:
3153 case Instruction::AtomicRMW:
3154 return !AssumedNoUBInsts.count(I);
3155 case Instruction::Br: {
3156 auto *BrInst = cast<BranchInst>(I);
3157 if (BrInst->isUnconditional())
3158 return false;
3159 return !AssumedNoUBInsts.count(I);
3160 } break;
3161 default:
3162 return false;
3163 }
3164 return false;
3165 }
3166
manifest__anon641416292611::AAUndefinedBehaviorImpl3167 ChangeStatus manifest(Attributor &A) override {
3168 if (KnownUBInsts.empty())
3169 return ChangeStatus::UNCHANGED;
3170 for (Instruction *I : KnownUBInsts)
3171 A.changeToUnreachableAfterManifest(I);
3172 return ChangeStatus::CHANGED;
3173 }
3174
3175 /// See AbstractAttribute::getAsStr()
getAsStr__anon641416292611::AAUndefinedBehaviorImpl3176 const std::string getAsStr() const override {
3177 return getAssumed() ? "undefined-behavior" : "no-ub";
3178 }
3179
3180 /// Note: The correctness of this analysis depends on the fact that the
3181 /// following 2 sets will stop changing after some point.
3182 /// "Change" here means that their size changes.
3183 /// The size of each set is monotonically increasing
3184 /// (we only add items to them) and it is upper bounded by the number of
3185 /// instructions in the processed function (we can never save more
3186 /// elements in either set than this number). Hence, at some point,
3187 /// they will stop increasing.
3188 /// Consequently, at some point, both sets will have stopped
3189 /// changing, effectively making the analysis reach a fixpoint.
3190
3191 /// Note: These 2 sets are disjoint and an instruction can be considered
3192 /// one of 3 things:
3193 /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
3194 /// the KnownUBInsts set.
3195 /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
3196 /// has a reason to assume it).
3197 /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
3198 /// could not find a reason to assume or prove that it can cause UB,
3199 /// hence it assumes it doesn't. We have a set for these instructions
3200 /// so that we don't reprocess them in every update.
3201 /// Note however that instructions in this set may cause UB.
3202
3203 protected:
3204 /// A set of all live instructions _known_ to cause UB.
3205 SmallPtrSet<Instruction *, 8> KnownUBInsts;
3206
3207 private:
3208 /// A set of all the (live) instructions that are assumed to _not_ cause UB.
3209 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3210
3211 // Should be called on updates in which if we're processing an instruction
3212 // \p I that depends on a value \p V, one of the following has to happen:
3213 // - If the value is assumed, then stop.
3214 // - If the value is known but undef, then consider it UB.
3215 // - Otherwise, do specific processing with the simplified value.
3216 // We return std::nullopt in the first 2 cases to signify that an appropriate
3217 // action was taken and the caller should stop.
3218 // Otherwise, we return the simplified value that the caller should
3219 // use for specific processing.
stopOnUndefOrAssumed__anon641416292611::AAUndefinedBehaviorImpl3220 std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
3221 Instruction *I) {
3222 bool UsedAssumedInformation = false;
3223 std::optional<Value *> SimplifiedV =
3224 A.getAssumedSimplified(IRPosition::value(*V), *this,
3225 UsedAssumedInformation, AA::Interprocedural);
3226 if (!UsedAssumedInformation) {
3227 // Don't depend on assumed values.
3228 if (!SimplifiedV) {
3229 // If it is known (which we tested above) but it doesn't have a value,
3230 // then we can assume `undef` and hence the instruction is UB.
3231 KnownUBInsts.insert(I);
3232 return std::nullopt;
3233 }
3234 if (!*SimplifiedV)
3235 return nullptr;
3236 V = *SimplifiedV;
3237 }
3238 if (isa<UndefValue>(V)) {
3239 KnownUBInsts.insert(I);
3240 return std::nullopt;
3241 }
3242 return V;
3243 }
3244 };
3245
3246 struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
AAUndefinedBehaviorFunction__anon641416292611::AAUndefinedBehaviorFunction3247 AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
3248 : AAUndefinedBehaviorImpl(IRP, A) {}
3249
3250 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292611::AAUndefinedBehaviorFunction3251 void trackStatistics() const override {
3252 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3253 "Number of instructions known to have UB");
3254 BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) +=
3255 KnownUBInsts.size();
3256 }
3257 };
3258 } // namespace
3259
3260 /// ------------------------ Will-Return Attributes ----------------------------
3261
3262 namespace {
3263 // Helper function that checks whether a function has any cycle which we don't
3264 // know if it is bounded or not.
3265 // Loops with maximum trip count are considered bounded, any other cycle not.
mayContainUnboundedCycle(Function & F,Attributor & A)3266 static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
3267 ScalarEvolution *SE =
3268 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
3269 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
3270 // If either SCEV or LoopInfo is not available for the function then we assume
3271 // any cycle to be unbounded cycle.
3272 // We use scc_iterator which uses Tarjan algorithm to find all the maximal
3273 // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
3274 if (!SE || !LI) {
3275 for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
3276 if (SCCI.hasCycle())
3277 return true;
3278 return false;
3279 }
3280
3281 // If there's irreducible control, the function may contain non-loop cycles.
3282 if (mayContainIrreducibleControl(F, LI))
3283 return true;
3284
3285 // Any loop that does not have a max trip count is considered unbounded cycle.
3286 for (auto *L : LI->getLoopsInPreorder()) {
3287 if (!SE->getSmallConstantMaxTripCount(L))
3288 return true;
3289 }
3290 return false;
3291 }
3292
3293 struct AAWillReturnImpl : public AAWillReturn {
AAWillReturnImpl__anon641416292b11::AAWillReturnImpl3294 AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
3295 : AAWillReturn(IRP, A) {}
3296
3297 /// See AbstractAttribute::initialize(...).
initialize__anon641416292b11::AAWillReturnImpl3298 void initialize(Attributor &A) override {
3299 AAWillReturn::initialize(A);
3300
3301 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ true)) {
3302 indicateOptimisticFixpoint();
3303 return;
3304 }
3305 }
3306
3307 /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
isImpliedByMustprogressAndReadonly__anon641416292b11::AAWillReturnImpl3308 bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
3309 // Check for `mustprogress` in the scope and the associated function which
3310 // might be different if this is a call site.
3311 if ((!getAnchorScope() || !getAnchorScope()->mustProgress()) &&
3312 (!getAssociatedFunction() || !getAssociatedFunction()->mustProgress()))
3313 return false;
3314
3315 bool IsKnown;
3316 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3317 return IsKnown || !KnownOnly;
3318 return false;
3319 }
3320
3321 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292b11::AAWillReturnImpl3322 ChangeStatus updateImpl(Attributor &A) override {
3323 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3324 return ChangeStatus::UNCHANGED;
3325
3326 auto CheckForWillReturn = [&](Instruction &I) {
3327 IRPosition IPos = IRPosition::callsite_function(cast<CallBase>(I));
3328 const auto &WillReturnAA =
3329 A.getAAFor<AAWillReturn>(*this, IPos, DepClassTy::REQUIRED);
3330 if (WillReturnAA.isKnownWillReturn())
3331 return true;
3332 if (!WillReturnAA.isAssumedWillReturn())
3333 return false;
3334 const auto &NoRecurseAA =
3335 A.getAAFor<AANoRecurse>(*this, IPos, DepClassTy::REQUIRED);
3336 return NoRecurseAA.isAssumedNoRecurse();
3337 };
3338
3339 bool UsedAssumedInformation = false;
3340 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
3341 UsedAssumedInformation))
3342 return indicatePessimisticFixpoint();
3343
3344 return ChangeStatus::UNCHANGED;
3345 }
3346
3347 /// See AbstractAttribute::getAsStr()
getAsStr__anon641416292b11::AAWillReturnImpl3348 const std::string getAsStr() const override {
3349 return getAssumed() ? "willreturn" : "may-noreturn";
3350 }
3351 };
3352
3353 struct AAWillReturnFunction final : AAWillReturnImpl {
AAWillReturnFunction__anon641416292b11::AAWillReturnFunction3354 AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
3355 : AAWillReturnImpl(IRP, A) {}
3356
3357 /// See AbstractAttribute::initialize(...).
initialize__anon641416292b11::AAWillReturnFunction3358 void initialize(Attributor &A) override {
3359 AAWillReturnImpl::initialize(A);
3360
3361 Function *F = getAnchorScope();
3362 if (!F || F->isDeclaration() || mayContainUnboundedCycle(*F, A))
3363 indicatePessimisticFixpoint();
3364 }
3365
3366 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292b11::AAWillReturnFunction3367 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
3368 };
3369
3370 /// WillReturn attribute deduction for a call sites.
3371 struct AAWillReturnCallSite final : AAWillReturnImpl {
AAWillReturnCallSite__anon641416292b11::AAWillReturnCallSite3372 AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)
3373 : AAWillReturnImpl(IRP, A) {}
3374
3375 /// See AbstractAttribute::initialize(...).
initialize__anon641416292b11::AAWillReturnCallSite3376 void initialize(Attributor &A) override {
3377 AAWillReturnImpl::initialize(A);
3378 Function *F = getAssociatedFunction();
3379 if (!F || !A.isFunctionIPOAmendable(*F))
3380 indicatePessimisticFixpoint();
3381 }
3382
3383 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292b11::AAWillReturnCallSite3384 ChangeStatus updateImpl(Attributor &A) override {
3385 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3386 return ChangeStatus::UNCHANGED;
3387
3388 // TODO: Once we have call site specific value information we can provide
3389 // call site specific liveness information and then it makes
3390 // sense to specialize attributes for call sites arguments instead of
3391 // redirecting requests to the callee argument.
3392 Function *F = getAssociatedFunction();
3393 const IRPosition &FnPos = IRPosition::function(*F);
3394 auto &FnAA = A.getAAFor<AAWillReturn>(*this, FnPos, DepClassTy::REQUIRED);
3395 return clampStateAndIndicateChange(getState(), FnAA.getState());
3396 }
3397
3398 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292b11::AAWillReturnCallSite3399 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }
3400 };
3401 } // namespace
3402
3403 /// -------------------AAIntraFnReachability Attribute--------------------------
3404
3405 /// All information associated with a reachability query. This boilerplate code
3406 /// is used by both AAIntraFnReachability and AAInterFnReachability, with
3407 /// different \p ToTy values.
3408 template <typename ToTy> struct ReachabilityQueryInfo {
3409 enum class Reachable {
3410 No,
3411 Yes,
3412 };
3413
3414 /// Start here,
3415 const Instruction *From = nullptr;
3416 /// reach this place,
3417 const ToTy *To = nullptr;
3418 /// without going through any of these instructions,
3419 const AA::InstExclusionSetTy *ExclusionSet = nullptr;
3420 /// and remember if it worked:
3421 Reachable Result = Reachable::No;
3422
ReachabilityQueryInfoReachabilityQueryInfo3423 ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
3424 : From(From), To(To) {}
3425
3426 /// Constructor replacement to ensure unique and stable sets are used for the
3427 /// cache.
ReachabilityQueryInfoReachabilityQueryInfo3428 ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To,
3429 const AA::InstExclusionSetTy *ES)
3430 : From(&From), To(&To), ExclusionSet(ES) {
3431
3432 if (ExclusionSet && !ExclusionSet->empty()) {
3433 ExclusionSet =
3434 A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ExclusionSet);
3435 } else {
3436 ExclusionSet = nullptr;
3437 }
3438 }
3439
ReachabilityQueryInfoReachabilityQueryInfo3440 ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
3441 : From(RQI.From), To(RQI.To), ExclusionSet(RQI.ExclusionSet) {
3442 assert(RQI.Result == Reachable::No &&
3443 "Didn't expect to copy an explored RQI!");
3444 }
3445 };
3446
3447 namespace llvm {
3448 template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
3449 using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;
3450 using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;
3451
3452 static ReachabilityQueryInfo<ToTy> EmptyKey;
3453 static ReachabilityQueryInfo<ToTy> TombstoneKey;
3454
getEmptyKeyllvm::DenseMapInfo3455 static inline ReachabilityQueryInfo<ToTy> *getEmptyKey() { return &EmptyKey; }
getTombstoneKeyllvm::DenseMapInfo3456 static inline ReachabilityQueryInfo<ToTy> *getTombstoneKey() {
3457 return &TombstoneKey;
3458 }
getHashValuellvm::DenseMapInfo3459 static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
3460 unsigned H = PairDMI ::getHashValue({RQI->From, RQI->To});
3461 H += InstSetDMI::getHashValue(RQI->ExclusionSet);
3462 return H;
3463 }
isEqualllvm::DenseMapInfo3464 static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
3465 const ReachabilityQueryInfo<ToTy> *RHS) {
3466 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3467 return false;
3468 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3469 }
3470 };
3471
3472 #define DefineKeys(ToTy) \
3473 template <> \
3474 ReachabilityQueryInfo<ToTy> \
3475 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::EmptyKey = \
3476 ReachabilityQueryInfo<ToTy>( \
3477 DenseMapInfo<const Instruction *>::getEmptyKey(), \
3478 DenseMapInfo<const ToTy *>::getEmptyKey()); \
3479 template <> \
3480 ReachabilityQueryInfo<ToTy> \
3481 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::TombstoneKey = \
3482 ReachabilityQueryInfo<ToTy>( \
3483 DenseMapInfo<const Instruction *>::getTombstoneKey(), \
3484 DenseMapInfo<const ToTy *>::getTombstoneKey());
3485
3486 DefineKeys(Instruction) DefineKeys(Function)
3487 #undef DefineKeys
3488
3489 } // namespace llvm
3490
3491 namespace {
3492
3493 template <typename BaseTy, typename ToTy>
3494 struct CachedReachabilityAA : public BaseTy {
3495 using RQITy = ReachabilityQueryInfo<ToTy>;
3496
3497 CachedReachabilityAA<BaseTy, ToTy>(const IRPosition &IRP, Attributor &A)
3498 : BaseTy(IRP, A) {}
3499
3500 /// See AbstractAttribute::isQueryAA.
isQueryAA__anon641416292d11::CachedReachabilityAA3501 bool isQueryAA() const override { return true; }
3502
3503 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292d11::CachedReachabilityAA3504 ChangeStatus updateImpl(Attributor &A) override {
3505 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3506 InUpdate = true;
3507 for (RQITy *RQI : QueryVector) {
3508 if (RQI->Result == RQITy::Reachable::No && isReachableImpl(A, *RQI))
3509 Changed = ChangeStatus::CHANGED;
3510 }
3511 InUpdate = false;
3512 return Changed;
3513 }
3514
3515 virtual bool isReachableImpl(Attributor &A, RQITy &RQI) = 0;
3516
rememberResult__anon641416292d11::CachedReachabilityAA3517 bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
3518 RQITy &RQI) {
3519 if (Result == RQITy::Reachable::No) {
3520 if (!InUpdate)
3521 A.registerForUpdate(*this);
3522 return false;
3523 }
3524 assert(RQI.Result == RQITy::Reachable::No && "Already reachable?");
3525 RQI.Result = Result;
3526 return true;
3527 }
3528
getAsStr__anon641416292d11::CachedReachabilityAA3529 const std::string getAsStr() const override {
3530 // TODO: Return the number of reachable queries.
3531 return "#queries(" + std::to_string(QueryVector.size()) + ")";
3532 }
3533
checkQueryCache__anon641416292d11::CachedReachabilityAA3534 RQITy *checkQueryCache(Attributor &A, RQITy &StackRQI,
3535 typename RQITy::Reachable &Result) {
3536 if (!this->getState().isValidState()) {
3537 Result = RQITy::Reachable::Yes;
3538 return nullptr;
3539 }
3540
3541 auto It = QueryCache.find(&StackRQI);
3542 if (It != QueryCache.end()) {
3543 Result = (*It)->Result;
3544 return nullptr;
3545 }
3546
3547 RQITy *RQIPtr = new (A.Allocator) RQITy(StackRQI);
3548 QueryVector.push_back(RQIPtr);
3549 QueryCache.insert(RQIPtr);
3550 return RQIPtr;
3551 }
3552
3553 private:
3554 bool InUpdate = false;
3555 SmallVector<RQITy *> QueryVector;
3556 DenseSet<RQITy *> QueryCache;
3557 };
3558
3559 struct AAIntraFnReachabilityFunction final
3560 : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
AAIntraFnReachabilityFunction__anon641416292d11::AAIntraFnReachabilityFunction3561 AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
3562 : CachedReachabilityAA<AAIntraFnReachability, Instruction>(IRP, A) {}
3563
isAssumedReachable__anon641416292d11::AAIntraFnReachabilityFunction3564 bool isAssumedReachable(
3565 Attributor &A, const Instruction &From, const Instruction &To,
3566 const AA::InstExclusionSetTy *ExclusionSet) const override {
3567 auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
3568 if (&From == &To)
3569 return true;
3570
3571 RQITy StackRQI(A, From, To, ExclusionSet);
3572 typename RQITy::Reachable Result;
3573 if (RQITy *RQIPtr = NonConstThis->checkQueryCache(A, StackRQI, Result)) {
3574 return NonConstThis->isReachableImpl(A, *RQIPtr);
3575 }
3576 return Result == RQITy::Reachable::Yes;
3577 }
3578
isReachableImpl__anon641416292d11::AAIntraFnReachabilityFunction3579 bool isReachableImpl(Attributor &A, RQITy &RQI) override {
3580 const Instruction *Origin = RQI.From;
3581
3582 auto WillReachInBlock = [=](const Instruction &From, const Instruction &To,
3583 const AA::InstExclusionSetTy *ExclusionSet) {
3584 const Instruction *IP = &From;
3585 while (IP && IP != &To) {
3586 if (ExclusionSet && IP != Origin && ExclusionSet->count(IP))
3587 break;
3588 IP = IP->getNextNode();
3589 }
3590 return IP == &To;
3591 };
3592
3593 const BasicBlock *FromBB = RQI.From->getParent();
3594 const BasicBlock *ToBB = RQI.To->getParent();
3595 assert(FromBB->getParent() == ToBB->getParent() &&
3596 "Not an intra-procedural query!");
3597
3598 // Check intra-block reachability, however, other reaching paths are still
3599 // possible.
3600 if (FromBB == ToBB &&
3601 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3602 return rememberResult(A, RQITy::Reachable::Yes, RQI);
3603
3604 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3605 if (RQI.ExclusionSet)
3606 for (auto *I : *RQI.ExclusionSet)
3607 ExclusionBlocks.insert(I->getParent());
3608
3609 // Check if we make it out of the FromBB block at all.
3610 if (ExclusionBlocks.count(FromBB) &&
3611 !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
3612 RQI.ExclusionSet))
3613 return rememberResult(A, RQITy::Reachable::No, RQI);
3614
3615 SmallPtrSet<const BasicBlock *, 16> Visited;
3616 SmallVector<const BasicBlock *, 16> Worklist;
3617 Worklist.push_back(FromBB);
3618
3619 auto &LivenessAA =
3620 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3621 while (!Worklist.empty()) {
3622 const BasicBlock *BB = Worklist.pop_back_val();
3623 if (!Visited.insert(BB).second)
3624 continue;
3625 for (const BasicBlock *SuccBB : successors(BB)) {
3626 if (LivenessAA.isEdgeDead(BB, SuccBB))
3627 continue;
3628 if (SuccBB == ToBB &&
3629 WillReachInBlock(SuccBB->front(), *RQI.To, RQI.ExclusionSet))
3630 return rememberResult(A, RQITy::Reachable::Yes, RQI);
3631 if (ExclusionBlocks.count(SuccBB))
3632 continue;
3633 Worklist.push_back(SuccBB);
3634 }
3635 }
3636
3637 return rememberResult(A, RQITy::Reachable::No, RQI);
3638 }
3639
3640 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292d11::AAIntraFnReachabilityFunction3641 void trackStatistics() const override {}
3642 };
3643 } // namespace
3644
3645 /// ------------------------ NoAlias Argument Attribute ------------------------
3646
3647 namespace {
3648 struct AANoAliasImpl : AANoAlias {
AANoAliasImpl__anon641416292f11::AANoAliasImpl3649 AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
3650 assert(getAssociatedType()->isPointerTy() &&
3651 "Noalias is a pointer attribute");
3652 }
3653
getAsStr__anon641416292f11::AANoAliasImpl3654 const std::string getAsStr() const override {
3655 return getAssumed() ? "noalias" : "may-alias";
3656 }
3657 };
3658
3659 /// NoAlias attribute for a floating value.
3660 struct AANoAliasFloating final : AANoAliasImpl {
AANoAliasFloating__anon641416292f11::AANoAliasFloating3661 AANoAliasFloating(const IRPosition &IRP, Attributor &A)
3662 : AANoAliasImpl(IRP, A) {}
3663
3664 /// See AbstractAttribute::initialize(...).
initialize__anon641416292f11::AANoAliasFloating3665 void initialize(Attributor &A) override {
3666 AANoAliasImpl::initialize(A);
3667 Value *Val = &getAssociatedValue();
3668 do {
3669 CastInst *CI = dyn_cast<CastInst>(Val);
3670 if (!CI)
3671 break;
3672 Value *Base = CI->getOperand(0);
3673 if (!Base->hasOneUse())
3674 break;
3675 Val = Base;
3676 } while (true);
3677
3678 if (!Val->getType()->isPointerTy()) {
3679 indicatePessimisticFixpoint();
3680 return;
3681 }
3682
3683 if (isa<AllocaInst>(Val))
3684 indicateOptimisticFixpoint();
3685 else if (isa<ConstantPointerNull>(Val) &&
3686 !NullPointerIsDefined(getAnchorScope(),
3687 Val->getType()->getPointerAddressSpace()))
3688 indicateOptimisticFixpoint();
3689 else if (Val != &getAssociatedValue()) {
3690 const auto &ValNoAliasAA = A.getAAFor<AANoAlias>(
3691 *this, IRPosition::value(*Val), DepClassTy::OPTIONAL);
3692 if (ValNoAliasAA.isKnownNoAlias())
3693 indicateOptimisticFixpoint();
3694 }
3695 }
3696
3697 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292f11::AANoAliasFloating3698 ChangeStatus updateImpl(Attributor &A) override {
3699 // TODO: Implement this.
3700 return indicatePessimisticFixpoint();
3701 }
3702
3703 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292f11::AANoAliasFloating3704 void trackStatistics() const override {
3705 STATS_DECLTRACK_FLOATING_ATTR(noalias)
3706 }
3707 };
3708
3709 /// NoAlias attribute for an argument.
3710 struct AANoAliasArgument final
3711 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3712 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
AANoAliasArgument__anon641416292f11::AANoAliasArgument3713 AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
3714
3715 /// See AbstractAttribute::initialize(...).
initialize__anon641416292f11::AANoAliasArgument3716 void initialize(Attributor &A) override {
3717 Base::initialize(A);
3718 // See callsite argument attribute and callee argument attribute.
3719 if (hasAttr({Attribute::ByVal}))
3720 indicateOptimisticFixpoint();
3721 }
3722
3723 /// See AbstractAttribute::update(...).
updateImpl__anon641416292f11::AANoAliasArgument3724 ChangeStatus updateImpl(Attributor &A) override {
3725 // We have to make sure no-alias on the argument does not break
3726 // synchronization when this is a callback argument, see also [1] below.
3727 // If synchronization cannot be affected, we delegate to the base updateImpl
3728 // function, otherwise we give up for now.
3729
3730 // If the function is no-sync, no-alias cannot break synchronization.
3731 const auto &NoSyncAA =
3732 A.getAAFor<AANoSync>(*this, IRPosition::function_scope(getIRPosition()),
3733 DepClassTy::OPTIONAL);
3734 if (NoSyncAA.isAssumedNoSync())
3735 return Base::updateImpl(A);
3736
3737 // If the argument is read-only, no-alias cannot break synchronization.
3738 bool IsKnown;
3739 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3740 return Base::updateImpl(A);
3741
3742 // If the argument is never passed through callbacks, no-alias cannot break
3743 // synchronization.
3744 bool UsedAssumedInformation = false;
3745 if (A.checkForAllCallSites(
3746 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,
3747 true, UsedAssumedInformation))
3748 return Base::updateImpl(A);
3749
3750 // TODO: add no-alias but make sure it doesn't break synchronization by
3751 // introducing fake uses. See:
3752 // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
3753 // International Workshop on OpenMP 2018,
3754 // http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf
3755
3756 return indicatePessimisticFixpoint();
3757 }
3758
3759 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292f11::AANoAliasArgument3760 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
3761 };
3762
3763 struct AANoAliasCallSiteArgument final : AANoAliasImpl {
AANoAliasCallSiteArgument__anon641416292f11::AANoAliasCallSiteArgument3764 AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
3765 : AANoAliasImpl(IRP, A) {}
3766
3767 /// See AbstractAttribute::initialize(...).
initialize__anon641416292f11::AANoAliasCallSiteArgument3768 void initialize(Attributor &A) override {
3769 // See callsite argument attribute and callee argument attribute.
3770 const auto &CB = cast<CallBase>(getAnchorValue());
3771 if (CB.paramHasAttr(getCallSiteArgNo(), Attribute::NoAlias))
3772 indicateOptimisticFixpoint();
3773 Value &Val = getAssociatedValue();
3774 if (isa<ConstantPointerNull>(Val) &&
3775 !NullPointerIsDefined(getAnchorScope(),
3776 Val.getType()->getPointerAddressSpace()))
3777 indicateOptimisticFixpoint();
3778 }
3779
3780 /// Determine if the underlying value may alias with the call site argument
3781 /// \p OtherArgNo of \p ICS (= the underlying call site).
mayAliasWithArgument__anon641416292f11::AANoAliasCallSiteArgument3782 bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
3783 const AAMemoryBehavior &MemBehaviorAA,
3784 const CallBase &CB, unsigned OtherArgNo) {
3785 // We do not need to worry about aliasing with the underlying IRP.
3786 if (this->getCalleeArgNo() == (int)OtherArgNo)
3787 return false;
3788
3789 // If it is not a pointer or pointer vector we do not alias.
3790 const Value *ArgOp = CB.getArgOperand(OtherArgNo);
3791 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
3792 return false;
3793
3794 auto &CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
3795 *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);
3796
3797 // If the argument is readnone, there is no read-write aliasing.
3798 if (CBArgMemBehaviorAA.isAssumedReadNone()) {
3799 A.recordDependence(CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3800 return false;
3801 }
3802
3803 // If the argument is readonly and the underlying value is readonly, there
3804 // is no read-write aliasing.
3805 bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
3806 if (CBArgMemBehaviorAA.isAssumedReadOnly() && IsReadOnly) {
3807 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3808 A.recordDependence(CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3809 return false;
3810 }
3811
3812 // We have to utilize actual alias analysis queries so we need the object.
3813 if (!AAR)
3814 AAR = A.getInfoCache().getAAResultsForFunction(*getAnchorScope());
3815
3816 // Try to rule it out at the call site.
3817 bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);
3818 LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "
3819 "callsite arguments: "
3820 << getAssociatedValue() << " " << *ArgOp << " => "
3821 << (IsAliasing ? "" : "no-") << "alias \n");
3822
3823 return IsAliasing;
3824 }
3825
3826 bool
isKnownNoAliasDueToNoAliasPreservation__anon641416292f11::AANoAliasCallSiteArgument3827 isKnownNoAliasDueToNoAliasPreservation(Attributor &A, AAResults *&AAR,
3828 const AAMemoryBehavior &MemBehaviorAA,
3829 const AANoAlias &NoAliasAA) {
3830 // We can deduce "noalias" if the following conditions hold.
3831 // (i) Associated value is assumed to be noalias in the definition.
3832 // (ii) Associated value is assumed to be no-capture in all the uses
3833 // possibly executed before this callsite.
3834 // (iii) There is no other pointer argument which could alias with the
3835 // value.
3836
3837 bool AssociatedValueIsNoAliasAtDef = NoAliasAA.isAssumedNoAlias();
3838 if (!AssociatedValueIsNoAliasAtDef) {
3839 LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()
3840 << " is not no-alias at the definition\n");
3841 return false;
3842 }
3843
3844 auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
3845 const auto &DerefAA = A.getAAFor<AADereferenceable>(
3846 *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
3847 return DerefAA.getAssumedDereferenceableBytes();
3848 };
3849
3850 A.recordDependence(NoAliasAA, *this, DepClassTy::OPTIONAL);
3851
3852 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3853 const Function *ScopeFn = VIRP.getAnchorScope();
3854 auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, VIRP, DepClassTy::NONE);
3855 // Check whether the value is captured in the scope using AANoCapture.
3856 // Look at CFG and check only uses possibly executed before this
3857 // callsite.
3858 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
3859 Instruction *UserI = cast<Instruction>(U.getUser());
3860
3861 // If UserI is the curr instruction and there is a single potential use of
3862 // the value in UserI we allow the use.
3863 // TODO: We should inspect the operands and allow those that cannot alias
3864 // with the value.
3865 if (UserI == getCtxI() && UserI->getNumOperands() == 1)
3866 return true;
3867
3868 if (ScopeFn) {
3869 if (auto *CB = dyn_cast<CallBase>(UserI)) {
3870 if (CB->isArgOperand(&U)) {
3871
3872 unsigned ArgNo = CB->getArgOperandNo(&U);
3873
3874 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
3875 *this, IRPosition::callsite_argument(*CB, ArgNo),
3876 DepClassTy::OPTIONAL);
3877
3878 if (NoCaptureAA.isAssumedNoCapture())
3879 return true;
3880 }
3881 }
3882
3883 if (!AA::isPotentiallyReachable(
3884 A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,
3885 [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
3886 return true;
3887 }
3888
3889 // TODO: We should track the capturing uses in AANoCapture but the problem
3890 // is CGSCC runs. For those we would need to "allow" AANoCapture for
3891 // a value in the module slice.
3892 switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
3893 case UseCaptureKind::NO_CAPTURE:
3894 return true;
3895 case UseCaptureKind::MAY_CAPTURE:
3896 LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserI
3897 << "\n");
3898 return false;
3899 case UseCaptureKind::PASSTHROUGH:
3900 Follow = true;
3901 return true;
3902 }
3903 llvm_unreachable("unknown UseCaptureKind");
3904 };
3905
3906 if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
3907 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
3908 LLVM_DEBUG(
3909 dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
3910 << " cannot be noalias as it is potentially captured\n");
3911 return false;
3912 }
3913 }
3914 A.recordDependence(NoCaptureAA, *this, DepClassTy::OPTIONAL);
3915
3916 // Check there is no other pointer argument which could alias with the
3917 // value passed at this call site.
3918 // TODO: AbstractCallSite
3919 const auto &CB = cast<CallBase>(getAnchorValue());
3920 for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
3921 if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
3922 return false;
3923
3924 return true;
3925 }
3926
3927 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292f11::AANoAliasCallSiteArgument3928 ChangeStatus updateImpl(Attributor &A) override {
3929 // If the argument is readnone we are done as there are no accesses via the
3930 // argument.
3931 auto &MemBehaviorAA =
3932 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
3933 if (MemBehaviorAA.isAssumedReadNone()) {
3934 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3935 return ChangeStatus::UNCHANGED;
3936 }
3937
3938 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3939 const auto &NoAliasAA =
3940 A.getAAFor<AANoAlias>(*this, VIRP, DepClassTy::NONE);
3941
3942 AAResults *AAR = nullptr;
3943 if (isKnownNoAliasDueToNoAliasPreservation(A, AAR, MemBehaviorAA,
3944 NoAliasAA)) {
3945 LLVM_DEBUG(
3946 dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n");
3947 return ChangeStatus::UNCHANGED;
3948 }
3949
3950 return indicatePessimisticFixpoint();
3951 }
3952
3953 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292f11::AANoAliasCallSiteArgument3954 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }
3955 };
3956
3957 /// NoAlias attribute for function return value.
3958 struct AANoAliasReturned final : AANoAliasImpl {
AANoAliasReturned__anon641416292f11::AANoAliasReturned3959 AANoAliasReturned(const IRPosition &IRP, Attributor &A)
3960 : AANoAliasImpl(IRP, A) {}
3961
3962 /// See AbstractAttribute::initialize(...).
initialize__anon641416292f11::AANoAliasReturned3963 void initialize(Attributor &A) override {
3964 AANoAliasImpl::initialize(A);
3965 Function *F = getAssociatedFunction();
3966 if (!F || F->isDeclaration())
3967 indicatePessimisticFixpoint();
3968 }
3969
3970 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292f11::AANoAliasReturned3971 ChangeStatus updateImpl(Attributor &A) override {
3972
3973 auto CheckReturnValue = [&](Value &RV) -> bool {
3974 if (Constant *C = dyn_cast<Constant>(&RV))
3975 if (C->isNullValue() || isa<UndefValue>(C))
3976 return true;
3977
3978 /// For now, we can only deduce noalias if we have call sites.
3979 /// FIXME: add more support.
3980 if (!isa<CallBase>(&RV))
3981 return false;
3982
3983 const IRPosition &RVPos = IRPosition::value(RV);
3984 const auto &NoAliasAA =
3985 A.getAAFor<AANoAlias>(*this, RVPos, DepClassTy::REQUIRED);
3986 if (!NoAliasAA.isAssumedNoAlias())
3987 return false;
3988
3989 const auto &NoCaptureAA =
3990 A.getAAFor<AANoCapture>(*this, RVPos, DepClassTy::REQUIRED);
3991 return NoCaptureAA.isAssumedNoCaptureMaybeReturned();
3992 };
3993
3994 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
3995 return indicatePessimisticFixpoint();
3996
3997 return ChangeStatus::UNCHANGED;
3998 }
3999
4000 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292f11::AANoAliasReturned4001 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
4002 };
4003
4004 /// NoAlias attribute deduction for a call site return value.
4005 struct AANoAliasCallSiteReturned final : AANoAliasImpl {
AANoAliasCallSiteReturned__anon641416292f11::AANoAliasCallSiteReturned4006 AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
4007 : AANoAliasImpl(IRP, A) {}
4008
4009 /// See AbstractAttribute::initialize(...).
initialize__anon641416292f11::AANoAliasCallSiteReturned4010 void initialize(Attributor &A) override {
4011 AANoAliasImpl::initialize(A);
4012 Function *F = getAssociatedFunction();
4013 if (!F || F->isDeclaration())
4014 indicatePessimisticFixpoint();
4015 }
4016
4017 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416292f11::AANoAliasCallSiteReturned4018 ChangeStatus updateImpl(Attributor &A) override {
4019 // TODO: Once we have call site specific value information we can provide
4020 // call site specific liveness information and then it makes
4021 // sense to specialize attributes for call sites arguments instead of
4022 // redirecting requests to the callee argument.
4023 Function *F = getAssociatedFunction();
4024 const IRPosition &FnPos = IRPosition::returned(*F);
4025 auto &FnAA = A.getAAFor<AANoAlias>(*this, FnPos, DepClassTy::REQUIRED);
4026 return clampStateAndIndicateChange(getState(), FnAA.getState());
4027 }
4028
4029 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416292f11::AANoAliasCallSiteReturned4030 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }
4031 };
4032 } // namespace
4033
4034 /// -------------------AAIsDead Function Attribute-----------------------
4035
4036 namespace {
4037 struct AAIsDeadValueImpl : public AAIsDead {
AAIsDeadValueImpl__anon641416293511::AAIsDeadValueImpl4038 AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4039
4040 /// See AbstractAttribute::initialize(...).
initialize__anon641416293511::AAIsDeadValueImpl4041 void initialize(Attributor &A) override {
4042 if (auto *Scope = getAnchorScope())
4043 if (!A.isRunOn(*Scope))
4044 indicatePessimisticFixpoint();
4045 }
4046
4047 /// See AAIsDead::isAssumedDead().
isAssumedDead__anon641416293511::AAIsDeadValueImpl4048 bool isAssumedDead() const override { return isAssumed(IS_DEAD); }
4049
4050 /// See AAIsDead::isKnownDead().
isKnownDead__anon641416293511::AAIsDeadValueImpl4051 bool isKnownDead() const override { return isKnown(IS_DEAD); }
4052
4053 /// See AAIsDead::isAssumedDead(BasicBlock *).
isAssumedDead__anon641416293511::AAIsDeadValueImpl4054 bool isAssumedDead(const BasicBlock *BB) const override { return false; }
4055
4056 /// See AAIsDead::isKnownDead(BasicBlock *).
isKnownDead__anon641416293511::AAIsDeadValueImpl4057 bool isKnownDead(const BasicBlock *BB) const override { return false; }
4058
4059 /// See AAIsDead::isAssumedDead(Instruction *I).
isAssumedDead__anon641416293511::AAIsDeadValueImpl4060 bool isAssumedDead(const Instruction *I) const override {
4061 return I == getCtxI() && isAssumedDead();
4062 }
4063
4064 /// See AAIsDead::isKnownDead(Instruction *I).
isKnownDead__anon641416293511::AAIsDeadValueImpl4065 bool isKnownDead(const Instruction *I) const override {
4066 return isAssumedDead(I) && isKnownDead();
4067 }
4068
4069 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416293511::AAIsDeadValueImpl4070 const std::string getAsStr() const override {
4071 return isAssumedDead() ? "assumed-dead" : "assumed-live";
4072 }
4073
4074 /// Check if all uses are assumed dead.
areAllUsesAssumedDead__anon641416293511::AAIsDeadValueImpl4075 bool areAllUsesAssumedDead(Attributor &A, Value &V) {
4076 // Callers might not check the type, void has no uses.
4077 if (V.getType()->isVoidTy() || V.use_empty())
4078 return true;
4079
4080 // If we replace a value with a constant there are no uses left afterwards.
4081 if (!isa<Constant>(V)) {
4082 if (auto *I = dyn_cast<Instruction>(&V))
4083 if (!A.isRunOn(*I->getFunction()))
4084 return false;
4085 bool UsedAssumedInformation = false;
4086 std::optional<Constant *> C =
4087 A.getAssumedConstant(V, *this, UsedAssumedInformation);
4088 if (!C || *C)
4089 return true;
4090 }
4091
4092 auto UsePred = [&](const Use &U, bool &Follow) { return false; };
4093 // Explicitly set the dependence class to required because we want a long
4094 // chain of N dependent instructions to be considered live as soon as one is
4095 // without going through N update cycles. This is not required for
4096 // correctness.
4097 return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,
4098 DepClassTy::REQUIRED,
4099 /* IgnoreDroppableUses */ false);
4100 }
4101
4102 /// Determine if \p I is assumed to be side-effect free.
isAssumedSideEffectFree__anon641416293511::AAIsDeadValueImpl4103 bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
4104 if (!I || wouldInstructionBeTriviallyDead(I))
4105 return true;
4106
4107 auto *CB = dyn_cast<CallBase>(I);
4108 if (!CB || isa<IntrinsicInst>(CB))
4109 return false;
4110
4111 const IRPosition &CallIRP = IRPosition::callsite_function(*CB);
4112 const auto &NoUnwindAA =
4113 A.getAndUpdateAAFor<AANoUnwind>(*this, CallIRP, DepClassTy::NONE);
4114 if (!NoUnwindAA.isAssumedNoUnwind())
4115 return false;
4116 if (!NoUnwindAA.isKnownNoUnwind())
4117 A.recordDependence(NoUnwindAA, *this, DepClassTy::OPTIONAL);
4118
4119 bool IsKnown;
4120 return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);
4121 }
4122 };
4123
4124 struct AAIsDeadFloating : public AAIsDeadValueImpl {
AAIsDeadFloating__anon641416293511::AAIsDeadFloating4125 AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
4126 : AAIsDeadValueImpl(IRP, A) {}
4127
4128 /// See AbstractAttribute::initialize(...).
initialize__anon641416293511::AAIsDeadFloating4129 void initialize(Attributor &A) override {
4130 AAIsDeadValueImpl::initialize(A);
4131
4132 if (isa<UndefValue>(getAssociatedValue())) {
4133 indicatePessimisticFixpoint();
4134 return;
4135 }
4136
4137 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4138 if (!isAssumedSideEffectFree(A, I)) {
4139 if (!isa_and_nonnull<StoreInst>(I))
4140 indicatePessimisticFixpoint();
4141 else
4142 removeAssumedBits(HAS_NO_EFFECT);
4143 }
4144 }
4145
isDeadStore__anon641416293511::AAIsDeadFloating4146 bool isDeadStore(Attributor &A, StoreInst &SI,
4147 SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
4148 // Lang ref now states volatile store is not UB/dead, let's skip them.
4149 if (SI.isVolatile())
4150 return false;
4151
4152 // If we are collecting assumes to be deleted we are in the manifest stage.
4153 // It's problematic to collect the potential copies again now so we use the
4154 // cached ones.
4155 bool UsedAssumedInformation = false;
4156 if (!AssumeOnlyInst) {
4157 PotentialCopies.clear();
4158 if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,
4159 UsedAssumedInformation)) {
4160 LLVM_DEBUG(
4161 dbgs()
4162 << "[AAIsDead] Could not determine potential copies of store!\n");
4163 return false;
4164 }
4165 }
4166 LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()
4167 << " potential copies.\n");
4168
4169 InformationCache &InfoCache = A.getInfoCache();
4170 return llvm::all_of(PotentialCopies, [&](Value *V) {
4171 if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,
4172 UsedAssumedInformation))
4173 return true;
4174 if (auto *LI = dyn_cast<LoadInst>(V)) {
4175 if (llvm::all_of(LI->uses(), [&](const Use &U) {
4176 auto &UserI = cast<Instruction>(*U.getUser());
4177 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4178 if (AssumeOnlyInst)
4179 AssumeOnlyInst->insert(&UserI);
4180 return true;
4181 }
4182 return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);
4183 })) {
4184 return true;
4185 }
4186 }
4187 LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *V
4188 << " is assumed live!\n");
4189 return false;
4190 });
4191 }
4192
4193 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416293511::AAIsDeadFloating4194 const std::string getAsStr() const override {
4195 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4196 if (isa_and_nonnull<StoreInst>(I))
4197 if (isValidState())
4198 return "assumed-dead-store";
4199 return AAIsDeadValueImpl::getAsStr();
4200 }
4201
4202 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416293511::AAIsDeadFloating4203 ChangeStatus updateImpl(Attributor &A) override {
4204 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4205 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
4206 if (!isDeadStore(A, *SI))
4207 return indicatePessimisticFixpoint();
4208 } else {
4209 if (!isAssumedSideEffectFree(A, I))
4210 return indicatePessimisticFixpoint();
4211 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4212 return indicatePessimisticFixpoint();
4213 }
4214 return ChangeStatus::UNCHANGED;
4215 }
4216
isRemovableStore__anon641416293511::AAIsDeadFloating4217 bool isRemovableStore() const override {
4218 return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());
4219 }
4220
4221 /// See AbstractAttribute::manifest(...).
manifest__anon641416293511::AAIsDeadFloating4222 ChangeStatus manifest(Attributor &A) override {
4223 Value &V = getAssociatedValue();
4224 if (auto *I = dyn_cast<Instruction>(&V)) {
4225 // If we get here we basically know the users are all dead. We check if
4226 // isAssumedSideEffectFree returns true here again because it might not be
4227 // the case and only the users are dead but the instruction (=call) is
4228 // still needed.
4229 if (auto *SI = dyn_cast<StoreInst>(I)) {
4230 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4231 bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);
4232 (void)IsDead;
4233 assert(IsDead && "Store was assumed to be dead!");
4234 A.deleteAfterManifest(*I);
4235 for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
4236 Instruction *AOI = AssumeOnlyInst[i];
4237 for (auto *Usr : AOI->users())
4238 AssumeOnlyInst.insert(cast<Instruction>(Usr));
4239 A.deleteAfterManifest(*AOI);
4240 }
4241 return ChangeStatus::CHANGED;
4242 }
4243 if (isAssumedSideEffectFree(A, I) && !isa<InvokeInst>(I)) {
4244 A.deleteAfterManifest(*I);
4245 return ChangeStatus::CHANGED;
4246 }
4247 }
4248 return ChangeStatus::UNCHANGED;
4249 }
4250
4251 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416293511::AAIsDeadFloating4252 void trackStatistics() const override {
4253 STATS_DECLTRACK_FLOATING_ATTR(IsDead)
4254 }
4255
4256 private:
4257 // The potential copies of a dead store, used for deletion during manifest.
4258 SmallSetVector<Value *, 4> PotentialCopies;
4259 };
4260
4261 struct AAIsDeadArgument : public AAIsDeadFloating {
AAIsDeadArgument__anon641416293511::AAIsDeadArgument4262 AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
4263 : AAIsDeadFloating(IRP, A) {}
4264
4265 /// See AbstractAttribute::initialize(...).
initialize__anon641416293511::AAIsDeadArgument4266 void initialize(Attributor &A) override {
4267 AAIsDeadFloating::initialize(A);
4268 if (!A.isFunctionIPOAmendable(*getAnchorScope()))
4269 indicatePessimisticFixpoint();
4270 }
4271
4272 /// See AbstractAttribute::manifest(...).
manifest__anon641416293511::AAIsDeadArgument4273 ChangeStatus manifest(Attributor &A) override {
4274 Argument &Arg = *getAssociatedArgument();
4275 if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
4276 if (A.registerFunctionSignatureRewrite(
4277 Arg, /* ReplacementTypes */ {},
4278 Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{},
4279 Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) {
4280 return ChangeStatus::CHANGED;
4281 }
4282 return ChangeStatus::UNCHANGED;
4283 }
4284
4285 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416293511::AAIsDeadArgument4286 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) }
4287 };
4288
4289 struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
AAIsDeadCallSiteArgument__anon641416293511::AAIsDeadCallSiteArgument4290 AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
4291 : AAIsDeadValueImpl(IRP, A) {}
4292
4293 /// See AbstractAttribute::initialize(...).
initialize__anon641416293511::AAIsDeadCallSiteArgument4294 void initialize(Attributor &A) override {
4295 AAIsDeadValueImpl::initialize(A);
4296 if (isa<UndefValue>(getAssociatedValue()))
4297 indicatePessimisticFixpoint();
4298 }
4299
4300 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416293511::AAIsDeadCallSiteArgument4301 ChangeStatus updateImpl(Attributor &A) override {
4302 // TODO: Once we have call site specific value information we can provide
4303 // call site specific liveness information and then it makes
4304 // sense to specialize attributes for call sites arguments instead of
4305 // redirecting requests to the callee argument.
4306 Argument *Arg = getAssociatedArgument();
4307 if (!Arg)
4308 return indicatePessimisticFixpoint();
4309 const IRPosition &ArgPos = IRPosition::argument(*Arg);
4310 auto &ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);
4311 return clampStateAndIndicateChange(getState(), ArgAA.getState());
4312 }
4313
4314 /// See AbstractAttribute::manifest(...).
manifest__anon641416293511::AAIsDeadCallSiteArgument4315 ChangeStatus manifest(Attributor &A) override {
4316 CallBase &CB = cast<CallBase>(getAnchorValue());
4317 Use &U = CB.getArgOperandUse(getCallSiteArgNo());
4318 assert(!isa<UndefValue>(U.get()) &&
4319 "Expected undef values to be filtered out!");
4320 UndefValue &UV = *UndefValue::get(U->getType());
4321 if (A.changeUseAfterManifest(U, UV))
4322 return ChangeStatus::CHANGED;
4323 return ChangeStatus::UNCHANGED;
4324 }
4325
4326 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416293511::AAIsDeadCallSiteArgument4327 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) }
4328 };
4329
4330 struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
AAIsDeadCallSiteReturned__anon641416293511::AAIsDeadCallSiteReturned4331 AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
4332 : AAIsDeadFloating(IRP, A) {}
4333
4334 /// See AAIsDead::isAssumedDead().
isAssumedDead__anon641416293511::AAIsDeadCallSiteReturned4335 bool isAssumedDead() const override {
4336 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4337 }
4338
4339 /// See AbstractAttribute::initialize(...).
initialize__anon641416293511::AAIsDeadCallSiteReturned4340 void initialize(Attributor &A) override {
4341 AAIsDeadFloating::initialize(A);
4342 if (isa<UndefValue>(getAssociatedValue())) {
4343 indicatePessimisticFixpoint();
4344 return;
4345 }
4346
4347 // We track this separately as a secondary state.
4348 IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());
4349 }
4350
4351 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416293511::AAIsDeadCallSiteReturned4352 ChangeStatus updateImpl(Attributor &A) override {
4353 ChangeStatus Changed = ChangeStatus::UNCHANGED;
4354 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {
4355 IsAssumedSideEffectFree = false;
4356 Changed = ChangeStatus::CHANGED;
4357 }
4358 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4359 return indicatePessimisticFixpoint();
4360 return Changed;
4361 }
4362
4363 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416293511::AAIsDeadCallSiteReturned4364 void trackStatistics() const override {
4365 if (IsAssumedSideEffectFree)
4366 STATS_DECLTRACK_CSRET_ATTR(IsDead)
4367 else
4368 STATS_DECLTRACK_CSRET_ATTR(UnusedResult)
4369 }
4370
4371 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416293511::AAIsDeadCallSiteReturned4372 const std::string getAsStr() const override {
4373 return isAssumedDead()
4374 ? "assumed-dead"
4375 : (getAssumed() ? "assumed-dead-users" : "assumed-live");
4376 }
4377
4378 private:
4379 bool IsAssumedSideEffectFree = true;
4380 };
4381
4382 struct AAIsDeadReturned : public AAIsDeadValueImpl {
AAIsDeadReturned__anon641416293511::AAIsDeadReturned4383 AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
4384 : AAIsDeadValueImpl(IRP, A) {}
4385
4386 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416293511::AAIsDeadReturned4387 ChangeStatus updateImpl(Attributor &A) override {
4388
4389 bool UsedAssumedInformation = false;
4390 A.checkForAllInstructions([](Instruction &) { return true; }, *this,
4391 {Instruction::Ret}, UsedAssumedInformation);
4392
4393 auto PredForCallSite = [&](AbstractCallSite ACS) {
4394 if (ACS.isCallbackCall() || !ACS.getInstruction())
4395 return false;
4396 return areAllUsesAssumedDead(A, *ACS.getInstruction());
4397 };
4398
4399 if (!A.checkForAllCallSites(PredForCallSite, *this, true,
4400 UsedAssumedInformation))
4401 return indicatePessimisticFixpoint();
4402
4403 return ChangeStatus::UNCHANGED;
4404 }
4405
4406 /// See AbstractAttribute::manifest(...).
manifest__anon641416293511::AAIsDeadReturned4407 ChangeStatus manifest(Attributor &A) override {
4408 // TODO: Rewrite the signature to return void?
4409 bool AnyChange = false;
4410 UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());
4411 auto RetInstPred = [&](Instruction &I) {
4412 ReturnInst &RI = cast<ReturnInst>(I);
4413 if (!isa<UndefValue>(RI.getReturnValue()))
4414 AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
4415 return true;
4416 };
4417 bool UsedAssumedInformation = false;
4418 A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
4419 UsedAssumedInformation);
4420 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4421 }
4422
4423 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416293511::AAIsDeadReturned4424 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) }
4425 };
4426
4427 struct AAIsDeadFunction : public AAIsDead {
AAIsDeadFunction__anon641416293511::AAIsDeadFunction4428 AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4429
4430 /// See AbstractAttribute::initialize(...).
initialize__anon641416293511::AAIsDeadFunction4431 void initialize(Attributor &A) override {
4432 Function *F = getAnchorScope();
4433 if (!F || F->isDeclaration() || !A.isRunOn(*F)) {
4434 indicatePessimisticFixpoint();
4435 return;
4436 }
4437 if (!isAssumedDeadInternalFunction(A)) {
4438 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4439 assumeLive(A, F->getEntryBlock());
4440 }
4441 }
4442
isAssumedDeadInternalFunction__anon641416293511::AAIsDeadFunction4443 bool isAssumedDeadInternalFunction(Attributor &A) {
4444 if (!getAnchorScope()->hasLocalLinkage())
4445 return false;
4446 bool UsedAssumedInformation = false;
4447 return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,
4448 true, UsedAssumedInformation);
4449 }
4450
4451 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416293511::AAIsDeadFunction4452 const std::string getAsStr() const override {
4453 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
4454 std::to_string(getAnchorScope()->size()) + "][#TBEP " +
4455 std::to_string(ToBeExploredFrom.size()) + "][#KDE " +
4456 std::to_string(KnownDeadEnds.size()) + "]";
4457 }
4458
4459 /// See AbstractAttribute::manifest(...).
manifest__anon641416293511::AAIsDeadFunction4460 ChangeStatus manifest(Attributor &A) override {
4461 assert(getState().isValidState() &&
4462 "Attempted to manifest an invalid state!");
4463
4464 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
4465 Function &F = *getAnchorScope();
4466
4467 if (AssumedLiveBlocks.empty()) {
4468 A.deleteAfterManifest(F);
4469 return ChangeStatus::CHANGED;
4470 }
4471
4472 // Flag to determine if we can change an invoke to a call assuming the
4473 // callee is nounwind. This is not possible if the personality of the
4474 // function allows to catch asynchronous exceptions.
4475 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
4476
4477 KnownDeadEnds.set_union(ToBeExploredFrom);
4478 for (const Instruction *DeadEndI : KnownDeadEnds) {
4479 auto *CB = dyn_cast<CallBase>(DeadEndI);
4480 if (!CB)
4481 continue;
4482 const auto &NoReturnAA = A.getAndUpdateAAFor<AANoReturn>(
4483 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
4484 bool MayReturn = !NoReturnAA.isAssumedNoReturn();
4485 if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))
4486 continue;
4487
4488 if (auto *II = dyn_cast<InvokeInst>(DeadEndI))
4489 A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));
4490 else
4491 A.changeToUnreachableAfterManifest(
4492 const_cast<Instruction *>(DeadEndI->getNextNode()));
4493 HasChanged = ChangeStatus::CHANGED;
4494 }
4495
4496 STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.");
4497 for (BasicBlock &BB : F)
4498 if (!AssumedLiveBlocks.count(&BB)) {
4499 A.deleteAfterManifest(BB);
4500 ++BUILD_STAT_NAME(AAIsDead, BasicBlock);
4501 HasChanged = ChangeStatus::CHANGED;
4502 }
4503
4504 return HasChanged;
4505 }
4506
4507 /// See AbstractAttribute::updateImpl(...).
4508 ChangeStatus updateImpl(Attributor &A) override;
4509
isEdgeDead__anon641416293511::AAIsDeadFunction4510 bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
4511 assert(From->getParent() == getAnchorScope() &&
4512 To->getParent() == getAnchorScope() &&
4513 "Used AAIsDead of the wrong function");
4514 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4515 }
4516
4517 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416293511::AAIsDeadFunction4518 void trackStatistics() const override {}
4519
4520 /// Returns true if the function is assumed dead.
isAssumedDead__anon641416293511::AAIsDeadFunction4521 bool isAssumedDead() const override { return false; }
4522
4523 /// See AAIsDead::isKnownDead().
isKnownDead__anon641416293511::AAIsDeadFunction4524 bool isKnownDead() const override { return false; }
4525
4526 /// See AAIsDead::isAssumedDead(BasicBlock *).
isAssumedDead__anon641416293511::AAIsDeadFunction4527 bool isAssumedDead(const BasicBlock *BB) const override {
4528 assert(BB->getParent() == getAnchorScope() &&
4529 "BB must be in the same anchor scope function.");
4530
4531 if (!getAssumed())
4532 return false;
4533 return !AssumedLiveBlocks.count(BB);
4534 }
4535
4536 /// See AAIsDead::isKnownDead(BasicBlock *).
isKnownDead__anon641416293511::AAIsDeadFunction4537 bool isKnownDead(const BasicBlock *BB) const override {
4538 return getKnown() && isAssumedDead(BB);
4539 }
4540
4541 /// See AAIsDead::isAssumed(Instruction *I).
isAssumedDead__anon641416293511::AAIsDeadFunction4542 bool isAssumedDead(const Instruction *I) const override {
4543 assert(I->getParent()->getParent() == getAnchorScope() &&
4544 "Instruction must be in the same anchor scope function.");
4545
4546 if (!getAssumed())
4547 return false;
4548
4549 // If it is not in AssumedLiveBlocks then it for sure dead.
4550 // Otherwise, it can still be after noreturn call in a live block.
4551 if (!AssumedLiveBlocks.count(I->getParent()))
4552 return true;
4553
4554 // If it is not after a liveness barrier it is live.
4555 const Instruction *PrevI = I->getPrevNode();
4556 while (PrevI) {
4557 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4558 return true;
4559 PrevI = PrevI->getPrevNode();
4560 }
4561 return false;
4562 }
4563
4564 /// See AAIsDead::isKnownDead(Instruction *I).
isKnownDead__anon641416293511::AAIsDeadFunction4565 bool isKnownDead(const Instruction *I) const override {
4566 return getKnown() && isAssumedDead(I);
4567 }
4568
4569 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
4570 /// that internal function called from \p BB should now be looked at.
assumeLive__anon641416293511::AAIsDeadFunction4571 bool assumeLive(Attributor &A, const BasicBlock &BB) {
4572 if (!AssumedLiveBlocks.insert(&BB).second)
4573 return false;
4574
4575 // We assume that all of BB is (probably) live now and if there are calls to
4576 // internal functions we will assume that those are now live as well. This
4577 // is a performance optimization for blocks with calls to a lot of internal
4578 // functions. It can however cause dead functions to be treated as live.
4579 for (const Instruction &I : BB)
4580 if (const auto *CB = dyn_cast<CallBase>(&I))
4581 if (const Function *F = CB->getCalledFunction())
4582 if (F->hasLocalLinkage())
4583 A.markLiveInternalFunction(*F);
4584 return true;
4585 }
4586
4587 /// Collection of instructions that need to be explored again, e.g., we
4588 /// did assume they do not transfer control to (one of their) successors.
4589 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4590
4591 /// Collection of instructions that are known to not transfer control.
4592 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4593
4594 /// Collection of all assumed live edges
4595 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4596
4597 /// Collection of all assumed live BasicBlocks.
4598 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4599 };
4600
4601 static bool
identifyAliveSuccessors(Attributor & A,const CallBase & CB,AbstractAttribute & AA,SmallVectorImpl<const Instruction * > & AliveSuccessors)4602 identifyAliveSuccessors(Attributor &A, const CallBase &CB,
4603 AbstractAttribute &AA,
4604 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4605 const IRPosition &IPos = IRPosition::callsite_function(CB);
4606
4607 const auto &NoReturnAA =
4608 A.getAndUpdateAAFor<AANoReturn>(AA, IPos, DepClassTy::OPTIONAL);
4609 if (NoReturnAA.isAssumedNoReturn())
4610 return !NoReturnAA.isKnownNoReturn();
4611 if (CB.isTerminator())
4612 AliveSuccessors.push_back(&CB.getSuccessor(0)->front());
4613 else
4614 AliveSuccessors.push_back(CB.getNextNode());
4615 return false;
4616 }
4617
4618 static bool
identifyAliveSuccessors(Attributor & A,const InvokeInst & II,AbstractAttribute & AA,SmallVectorImpl<const Instruction * > & AliveSuccessors)4619 identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
4620 AbstractAttribute &AA,
4621 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4622 bool UsedAssumedInformation =
4623 identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);
4624
4625 // First, determine if we can change an invoke to a call assuming the
4626 // callee is nounwind. This is not possible if the personality of the
4627 // function allows to catch asynchronous exceptions.
4628 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {
4629 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4630 } else {
4631 const IRPosition &IPos = IRPosition::callsite_function(II);
4632 const auto &AANoUnw =
4633 A.getAndUpdateAAFor<AANoUnwind>(AA, IPos, DepClassTy::OPTIONAL);
4634 if (AANoUnw.isAssumedNoUnwind()) {
4635 UsedAssumedInformation |= !AANoUnw.isKnownNoUnwind();
4636 } else {
4637 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4638 }
4639 }
4640 return UsedAssumedInformation;
4641 }
4642
4643 static bool
identifyAliveSuccessors(Attributor & A,const BranchInst & BI,AbstractAttribute & AA,SmallVectorImpl<const Instruction * > & AliveSuccessors)4644 identifyAliveSuccessors(Attributor &A, const BranchInst &BI,
4645 AbstractAttribute &AA,
4646 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4647 bool UsedAssumedInformation = false;
4648 if (BI.getNumSuccessors() == 1) {
4649 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4650 } else {
4651 std::optional<Constant *> C =
4652 A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);
4653 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4654 // No value yet, assume both edges are dead.
4655 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4656 const BasicBlock *SuccBB =
4657 BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());
4658 AliveSuccessors.push_back(&SuccBB->front());
4659 } else {
4660 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4661 AliveSuccessors.push_back(&BI.getSuccessor(1)->front());
4662 UsedAssumedInformation = false;
4663 }
4664 }
4665 return UsedAssumedInformation;
4666 }
4667
4668 static bool
identifyAliveSuccessors(Attributor & A,const SwitchInst & SI,AbstractAttribute & AA,SmallVectorImpl<const Instruction * > & AliveSuccessors)4669 identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
4670 AbstractAttribute &AA,
4671 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4672 bool UsedAssumedInformation = false;
4673 std::optional<Constant *> C =
4674 A.getAssumedConstant(*SI.getCondition(), AA, UsedAssumedInformation);
4675 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4676 // No value yet, assume all edges are dead.
4677 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4678 for (const auto &CaseIt : SI.cases()) {
4679 if (CaseIt.getCaseValue() == *C) {
4680 AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());
4681 return UsedAssumedInformation;
4682 }
4683 }
4684 AliveSuccessors.push_back(&SI.getDefaultDest()->front());
4685 return UsedAssumedInformation;
4686 } else {
4687 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4688 AliveSuccessors.push_back(&SuccBB->front());
4689 }
4690 return UsedAssumedInformation;
4691 }
4692
updateImpl(Attributor & A)4693 ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
4694 ChangeStatus Change = ChangeStatus::UNCHANGED;
4695
4696 if (AssumedLiveBlocks.empty()) {
4697 if (isAssumedDeadInternalFunction(A))
4698 return ChangeStatus::UNCHANGED;
4699
4700 Function *F = getAnchorScope();
4701 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4702 assumeLive(A, F->getEntryBlock());
4703 Change = ChangeStatus::CHANGED;
4704 }
4705
4706 LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"
4707 << getAnchorScope()->size() << "] BBs and "
4708 << ToBeExploredFrom.size() << " exploration points and "
4709 << KnownDeadEnds.size() << " known dead ends\n");
4710
4711 // Copy and clear the list of instructions we need to explore from. It is
4712 // refilled with instructions the next update has to look at.
4713 SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
4714 ToBeExploredFrom.end());
4715 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4716
4717 SmallVector<const Instruction *, 8> AliveSuccessors;
4718 while (!Worklist.empty()) {
4719 const Instruction *I = Worklist.pop_back_val();
4720 LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n");
4721
4722 // Fast forward for uninteresting instructions. We could look for UB here
4723 // though.
4724 while (!I->isTerminator() && !isa<CallBase>(I))
4725 I = I->getNextNode();
4726
4727 AliveSuccessors.clear();
4728
4729 bool UsedAssumedInformation = false;
4730 switch (I->getOpcode()) {
4731 // TODO: look for (assumed) UB to backwards propagate "deadness".
4732 default:
4733 assert(I->isTerminator() &&
4734 "Expected non-terminators to be handled already!");
4735 for (const BasicBlock *SuccBB : successors(I->getParent()))
4736 AliveSuccessors.push_back(&SuccBB->front());
4737 break;
4738 case Instruction::Call:
4739 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),
4740 *this, AliveSuccessors);
4741 break;
4742 case Instruction::Invoke:
4743 UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),
4744 *this, AliveSuccessors);
4745 break;
4746 case Instruction::Br:
4747 UsedAssumedInformation = identifyAliveSuccessors(A, cast<BranchInst>(*I),
4748 *this, AliveSuccessors);
4749 break;
4750 case Instruction::Switch:
4751 UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),
4752 *this, AliveSuccessors);
4753 break;
4754 }
4755
4756 if (UsedAssumedInformation) {
4757 NewToBeExploredFrom.insert(I);
4758 } else if (AliveSuccessors.empty() ||
4759 (I->isTerminator() &&
4760 AliveSuccessors.size() < I->getNumSuccessors())) {
4761 if (KnownDeadEnds.insert(I))
4762 Change = ChangeStatus::CHANGED;
4763 }
4764
4765 LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "
4766 << AliveSuccessors.size() << " UsedAssumedInformation: "
4767 << UsedAssumedInformation << "\n");
4768
4769 for (const Instruction *AliveSuccessor : AliveSuccessors) {
4770 if (!I->isTerminator()) {
4771 assert(AliveSuccessors.size() == 1 &&
4772 "Non-terminator expected to have a single successor!");
4773 Worklist.push_back(AliveSuccessor);
4774 } else {
4775 // record the assumed live edge
4776 auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());
4777 if (AssumedLiveEdges.insert(Edge).second)
4778 Change = ChangeStatus::CHANGED;
4779 if (assumeLive(A, *AliveSuccessor->getParent()))
4780 Worklist.push_back(AliveSuccessor);
4781 }
4782 }
4783 }
4784
4785 // Check if the content of ToBeExploredFrom changed, ignore the order.
4786 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4787 llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {
4788 return !ToBeExploredFrom.count(I);
4789 })) {
4790 Change = ChangeStatus::CHANGED;
4791 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4792 }
4793
4794 // If we know everything is live there is no need to query for liveness.
4795 // Instead, indicating a pessimistic fixpoint will cause the state to be
4796 // "invalid" and all queries to be answered conservatively without lookups.
4797 // To be in this state we have to (1) finished the exploration and (3) not
4798 // discovered any non-trivial dead end and (2) not ruled unreachable code
4799 // dead.
4800 if (ToBeExploredFrom.empty() &&
4801 getAnchorScope()->size() == AssumedLiveBlocks.size() &&
4802 llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {
4803 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4804 }))
4805 return indicatePessimisticFixpoint();
4806 return Change;
4807 }
4808
4809 /// Liveness information for a call sites.
4810 struct AAIsDeadCallSite final : AAIsDeadFunction {
AAIsDeadCallSite__anon641416293511::AAIsDeadCallSite4811 AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
4812 : AAIsDeadFunction(IRP, A) {}
4813
4814 /// See AbstractAttribute::initialize(...).
initialize__anon641416293511::AAIsDeadCallSite4815 void initialize(Attributor &A) override {
4816 // TODO: Once we have call site specific value information we can provide
4817 // call site specific liveness information and then it makes
4818 // sense to specialize attributes for call sites instead of
4819 // redirecting requests to the callee.
4820 llvm_unreachable("Abstract attributes for liveness are not "
4821 "supported for call sites yet!");
4822 }
4823
4824 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416293511::AAIsDeadCallSite4825 ChangeStatus updateImpl(Attributor &A) override {
4826 return indicatePessimisticFixpoint();
4827 }
4828
4829 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416293511::AAIsDeadCallSite4830 void trackStatistics() const override {}
4831 };
4832 } // namespace
4833
4834 /// -------------------- Dereferenceable Argument Attribute --------------------
4835
4836 namespace {
4837 struct AADereferenceableImpl : AADereferenceable {
AADereferenceableImpl__anon641416294011::AADereferenceableImpl4838 AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
4839 : AADereferenceable(IRP, A) {}
4840 using StateType = DerefState;
4841
4842 /// See AbstractAttribute::initialize(...).
initialize__anon641416294011::AADereferenceableImpl4843 void initialize(Attributor &A) override {
4844 Value &V = *getAssociatedValue().stripPointerCasts();
4845 SmallVector<Attribute, 4> Attrs;
4846 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4847 Attrs, /* IgnoreSubsumingPositions */ false, &A);
4848 for (const Attribute &Attr : Attrs)
4849 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4850
4851 const IRPosition &IRP = this->getIRPosition();
4852 NonNullAA = &A.getAAFor<AANonNull>(*this, IRP, DepClassTy::NONE);
4853
4854 bool CanBeNull, CanBeFreed;
4855 takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(
4856 A.getDataLayout(), CanBeNull, CanBeFreed));
4857
4858 bool IsFnInterface = IRP.isFnInterfaceKind();
4859 Function *FnScope = IRP.getAnchorScope();
4860 if (IsFnInterface && (!FnScope || !A.isFunctionIPOAmendable(*FnScope))) {
4861 indicatePessimisticFixpoint();
4862 return;
4863 }
4864
4865 if (Instruction *CtxI = getCtxI())
4866 followUsesInMBEC(*this, A, getState(), *CtxI);
4867 }
4868
4869 /// See AbstractAttribute::getState()
4870 /// {
getState__anon641416294011::AADereferenceableImpl4871 StateType &getState() override { return *this; }
getState__anon641416294011::AADereferenceableImpl4872 const StateType &getState() const override { return *this; }
4873 /// }
4874
4875 /// Helper function for collecting accessed bytes in must-be-executed-context
addAccessedBytesForUse__anon641416294011::AADereferenceableImpl4876 void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
4877 DerefState &State) {
4878 const Value *UseV = U->get();
4879 if (!UseV->getType()->isPointerTy())
4880 return;
4881
4882 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
4883 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
4884 return;
4885
4886 int64_t Offset;
4887 const Value *Base = GetPointerBaseWithConstantOffset(
4888 Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);
4889 if (Base && Base == &getAssociatedValue())
4890 State.addAccessedBytes(Offset, Loc->Size.getValue());
4891 }
4892
4893 /// See followUsesInMBEC
followUseInMBEC__anon641416294011::AADereferenceableImpl4894 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
4895 AADereferenceable::StateType &State) {
4896 bool IsNonNull = false;
4897 bool TrackUse = false;
4898 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4899 A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);
4900 LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytes
4901 << " for instruction " << *I << "\n");
4902
4903 addAccessedBytesForUse(A, U, I, State);
4904 State.takeKnownDerefBytesMaximum(DerefBytes);
4905 return TrackUse;
4906 }
4907
4908 /// See AbstractAttribute::manifest(...).
manifest__anon641416294011::AADereferenceableImpl4909 ChangeStatus manifest(Attributor &A) override {
4910 ChangeStatus Change = AADereferenceable::manifest(A);
4911 if (isAssumedNonNull() && hasAttr(Attribute::DereferenceableOrNull)) {
4912 removeAttrs({Attribute::DereferenceableOrNull});
4913 return ChangeStatus::CHANGED;
4914 }
4915 return Change;
4916 }
4917
getDeducedAttributes__anon641416294011::AADereferenceableImpl4918 void getDeducedAttributes(LLVMContext &Ctx,
4919 SmallVectorImpl<Attribute> &Attrs) const override {
4920 // TODO: Add *_globally support
4921 if (isAssumedNonNull())
4922 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
4923 Ctx, getAssumedDereferenceableBytes()));
4924 else
4925 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
4926 Ctx, getAssumedDereferenceableBytes()));
4927 }
4928
4929 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416294011::AADereferenceableImpl4930 const std::string getAsStr() const override {
4931 if (!getAssumedDereferenceableBytes())
4932 return "unknown-dereferenceable";
4933 return std::string("dereferenceable") +
4934 (isAssumedNonNull() ? "" : "_or_null") +
4935 (isAssumedGlobal() ? "_globally" : "") + "<" +
4936 std::to_string(getKnownDereferenceableBytes()) + "-" +
4937 std::to_string(getAssumedDereferenceableBytes()) + ">";
4938 }
4939 };
4940
4941 /// Dereferenceable attribute for a floating value.
4942 struct AADereferenceableFloating : AADereferenceableImpl {
AADereferenceableFloating__anon641416294011::AADereferenceableFloating4943 AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
4944 : AADereferenceableImpl(IRP, A) {}
4945
4946 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294011::AADereferenceableFloating4947 ChangeStatus updateImpl(Attributor &A) override {
4948
4949 bool Stripped;
4950 bool UsedAssumedInformation = false;
4951 SmallVector<AA::ValueAndContext> Values;
4952 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
4953 AA::AnyScope, UsedAssumedInformation)) {
4954 Values.push_back({getAssociatedValue(), getCtxI()});
4955 Stripped = false;
4956 } else {
4957 Stripped = Values.size() != 1 ||
4958 Values.front().getValue() != &getAssociatedValue();
4959 }
4960
4961 const DataLayout &DL = A.getDataLayout();
4962 DerefState T;
4963
4964 auto VisitValueCB = [&](const Value &V) -> bool {
4965 unsigned IdxWidth =
4966 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
4967 APInt Offset(IdxWidth, 0);
4968 const Value *Base = stripAndAccumulateOffsets(
4969 A, *this, &V, DL, Offset, /* GetMinOffset */ false,
4970 /* AllowNonInbounds */ true);
4971
4972 const auto &AA = A.getAAFor<AADereferenceable>(
4973 *this, IRPosition::value(*Base), DepClassTy::REQUIRED);
4974 int64_t DerefBytes = 0;
4975 if (!Stripped && this == &AA) {
4976 // Use IR information if we did not strip anything.
4977 // TODO: track globally.
4978 bool CanBeNull, CanBeFreed;
4979 DerefBytes =
4980 Base->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);
4981 T.GlobalState.indicatePessimisticFixpoint();
4982 } else {
4983 const DerefState &DS = AA.getState();
4984 DerefBytes = DS.DerefBytesState.getAssumed();
4985 T.GlobalState &= DS.GlobalState;
4986 }
4987
4988 // For now we do not try to "increase" dereferenceability due to negative
4989 // indices as we first have to come up with code to deal with loops and
4990 // for overflows of the dereferenceable bytes.
4991 int64_t OffsetSExt = Offset.getSExtValue();
4992 if (OffsetSExt < 0)
4993 OffsetSExt = 0;
4994
4995 T.takeAssumedDerefBytesMinimum(
4996 std::max(int64_t(0), DerefBytes - OffsetSExt));
4997
4998 if (this == &AA) {
4999 if (!Stripped) {
5000 // If nothing was stripped IR information is all we got.
5001 T.takeKnownDerefBytesMaximum(
5002 std::max(int64_t(0), DerefBytes - OffsetSExt));
5003 T.indicatePessimisticFixpoint();
5004 } else if (OffsetSExt > 0) {
5005 // If something was stripped but there is circular reasoning we look
5006 // for the offset. If it is positive we basically decrease the
5007 // dereferenceable bytes in a circular loop now, which will simply
5008 // drive them down to the known value in a very slow way which we
5009 // can accelerate.
5010 T.indicatePessimisticFixpoint();
5011 }
5012 }
5013
5014 return T.isValidState();
5015 };
5016
5017 for (const auto &VAC : Values)
5018 if (!VisitValueCB(*VAC.getValue()))
5019 return indicatePessimisticFixpoint();
5020
5021 return clampStateAndIndicateChange(getState(), T);
5022 }
5023
5024 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294011::AADereferenceableFloating5025 void trackStatistics() const override {
5026 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
5027 }
5028 };
5029
5030 /// Dereferenceable attribute for a return value.
5031 struct AADereferenceableReturned final
5032 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
AADereferenceableReturned__anon641416294011::AADereferenceableReturned5033 AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
5034 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>(
5035 IRP, A) {}
5036
5037 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294011::AADereferenceableReturned5038 void trackStatistics() const override {
5039 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
5040 }
5041 };
5042
5043 /// Dereferenceable attribute for an argument
5044 struct AADereferenceableArgument final
5045 : AAArgumentFromCallSiteArguments<AADereferenceable,
5046 AADereferenceableImpl> {
5047 using Base =
5048 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
AADereferenceableArgument__anon641416294011::AADereferenceableArgument5049 AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
5050 : Base(IRP, A) {}
5051
5052 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294011::AADereferenceableArgument5053 void trackStatistics() const override {
5054 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
5055 }
5056 };
5057
5058 /// Dereferenceable attribute for a call site argument.
5059 struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
AADereferenceableCallSiteArgument__anon641416294011::AADereferenceableCallSiteArgument5060 AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
5061 : AADereferenceableFloating(IRP, A) {}
5062
5063 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294011::AADereferenceableCallSiteArgument5064 void trackStatistics() const override {
5065 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
5066 }
5067 };
5068
5069 /// Dereferenceable attribute deduction for a call site return value.
5070 struct AADereferenceableCallSiteReturned final
5071 : AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl> {
5072 using Base =
5073 AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl>;
AADereferenceableCallSiteReturned__anon641416294011::AADereferenceableCallSiteReturned5074 AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
5075 : Base(IRP, A) {}
5076
5077 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294011::AADereferenceableCallSiteReturned5078 void trackStatistics() const override {
5079 STATS_DECLTRACK_CS_ATTR(dereferenceable);
5080 }
5081 };
5082 } // namespace
5083
5084 // ------------------------ Align Argument Attribute ------------------------
5085
5086 namespace {
getKnownAlignForUse(Attributor & A,AAAlign & QueryingAA,Value & AssociatedValue,const Use * U,const Instruction * I,bool & TrackUse)5087 static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
5088 Value &AssociatedValue, const Use *U,
5089 const Instruction *I, bool &TrackUse) {
5090 // We need to follow common pointer manipulation uses to the accesses they
5091 // feed into.
5092 if (isa<CastInst>(I)) {
5093 // Follow all but ptr2int casts.
5094 TrackUse = !isa<PtrToIntInst>(I);
5095 return 0;
5096 }
5097 if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
5098 if (GEP->hasAllConstantIndices())
5099 TrackUse = true;
5100 return 0;
5101 }
5102
5103 MaybeAlign MA;
5104 if (const auto *CB = dyn_cast<CallBase>(I)) {
5105 if (CB->isBundleOperand(U) || CB->isCallee(U))
5106 return 0;
5107
5108 unsigned ArgNo = CB->getArgOperandNo(U);
5109 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
5110 // As long as we only use known information there is no need to track
5111 // dependences here.
5112 auto &AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);
5113 MA = MaybeAlign(AlignAA.getKnownAlign());
5114 }
5115
5116 const DataLayout &DL = A.getDataLayout();
5117 const Value *UseV = U->get();
5118 if (auto *SI = dyn_cast<StoreInst>(I)) {
5119 if (SI->getPointerOperand() == UseV)
5120 MA = SI->getAlign();
5121 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
5122 if (LI->getPointerOperand() == UseV)
5123 MA = LI->getAlign();
5124 }
5125
5126 if (!MA || *MA <= QueryingAA.getKnownAlign())
5127 return 0;
5128
5129 unsigned Alignment = MA->value();
5130 int64_t Offset;
5131
5132 if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
5133 if (Base == &AssociatedValue) {
5134 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5135 // So we can say that the maximum power of two which is a divisor of
5136 // gcd(Offset, Alignment) is an alignment.
5137
5138 uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);
5139 Alignment = llvm::PowerOf2Floor(gcd);
5140 }
5141 }
5142
5143 return Alignment;
5144 }
5145
5146 struct AAAlignImpl : AAAlign {
AAAlignImpl__anon641416294211::AAAlignImpl5147 AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}
5148
5149 /// See AbstractAttribute::initialize(...).
initialize__anon641416294211::AAAlignImpl5150 void initialize(Attributor &A) override {
5151 SmallVector<Attribute, 4> Attrs;
5152 getAttrs({Attribute::Alignment}, Attrs);
5153 for (const Attribute &Attr : Attrs)
5154 takeKnownMaximum(Attr.getValueAsInt());
5155
5156 Value &V = *getAssociatedValue().stripPointerCasts();
5157 takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());
5158
5159 if (getIRPosition().isFnInterfaceKind() &&
5160 (!getAnchorScope() ||
5161 !A.isFunctionIPOAmendable(*getAssociatedFunction()))) {
5162 indicatePessimisticFixpoint();
5163 return;
5164 }
5165
5166 if (Instruction *CtxI = getCtxI())
5167 followUsesInMBEC(*this, A, getState(), *CtxI);
5168 }
5169
5170 /// See AbstractAttribute::manifest(...).
manifest__anon641416294211::AAAlignImpl5171 ChangeStatus manifest(Attributor &A) override {
5172 ChangeStatus LoadStoreChanged = ChangeStatus::UNCHANGED;
5173
5174 // Check for users that allow alignment annotations.
5175 Value &AssociatedValue = getAssociatedValue();
5176 for (const Use &U : AssociatedValue.uses()) {
5177 if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
5178 if (SI->getPointerOperand() == &AssociatedValue)
5179 if (SI->getAlign() < getAssumedAlign()) {
5180 STATS_DECLTRACK(AAAlign, Store,
5181 "Number of times alignment added to a store");
5182 SI->setAlignment(getAssumedAlign());
5183 LoadStoreChanged = ChangeStatus::CHANGED;
5184 }
5185 } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
5186 if (LI->getPointerOperand() == &AssociatedValue)
5187 if (LI->getAlign() < getAssumedAlign()) {
5188 LI->setAlignment(getAssumedAlign());
5189 STATS_DECLTRACK(AAAlign, Load,
5190 "Number of times alignment added to a load");
5191 LoadStoreChanged = ChangeStatus::CHANGED;
5192 }
5193 }
5194 }
5195
5196 ChangeStatus Changed = AAAlign::manifest(A);
5197
5198 Align InheritAlign =
5199 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5200 if (InheritAlign >= getAssumedAlign())
5201 return LoadStoreChanged;
5202 return Changed | LoadStoreChanged;
5203 }
5204
5205 // TODO: Provide a helper to determine the implied ABI alignment and check in
5206 // the existing manifest method and a new one for AAAlignImpl that value
5207 // to avoid making the alignment explicit if it did not improve.
5208
5209 /// See AbstractAttribute::getDeducedAttributes
getDeducedAttributes__anon641416294211::AAAlignImpl5210 void getDeducedAttributes(LLVMContext &Ctx,
5211 SmallVectorImpl<Attribute> &Attrs) const override {
5212 if (getAssumedAlign() > 1)
5213 Attrs.emplace_back(
5214 Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
5215 }
5216
5217 /// See followUsesInMBEC
followUseInMBEC__anon641416294211::AAAlignImpl5218 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5219 AAAlign::StateType &State) {
5220 bool TrackUse = false;
5221
5222 unsigned int KnownAlign =
5223 getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
5224 State.takeKnownMaximum(KnownAlign);
5225
5226 return TrackUse;
5227 }
5228
5229 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416294211::AAAlignImpl5230 const std::string getAsStr() const override {
5231 return "align<" + std::to_string(getKnownAlign().value()) + "-" +
5232 std::to_string(getAssumedAlign().value()) + ">";
5233 }
5234 };
5235
5236 /// Align attribute for a floating value.
5237 struct AAAlignFloating : AAAlignImpl {
AAAlignFloating__anon641416294211::AAAlignFloating5238 AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}
5239
5240 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294211::AAAlignFloating5241 ChangeStatus updateImpl(Attributor &A) override {
5242 const DataLayout &DL = A.getDataLayout();
5243
5244 bool Stripped;
5245 bool UsedAssumedInformation = false;
5246 SmallVector<AA::ValueAndContext> Values;
5247 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5248 AA::AnyScope, UsedAssumedInformation)) {
5249 Values.push_back({getAssociatedValue(), getCtxI()});
5250 Stripped = false;
5251 } else {
5252 Stripped = Values.size() != 1 ||
5253 Values.front().getValue() != &getAssociatedValue();
5254 }
5255
5256 StateType T;
5257 auto VisitValueCB = [&](Value &V) -> bool {
5258 if (isa<UndefValue>(V) || isa<ConstantPointerNull>(V))
5259 return true;
5260 const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),
5261 DepClassTy::REQUIRED);
5262 if (!Stripped && this == &AA) {
5263 int64_t Offset;
5264 unsigned Alignment = 1;
5265 if (const Value *Base =
5266 GetPointerBaseWithConstantOffset(&V, Offset, DL)) {
5267 // TODO: Use AAAlign for the base too.
5268 Align PA = Base->getPointerAlignment(DL);
5269 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5270 // So we can say that the maximum power of two which is a divisor of
5271 // gcd(Offset, Alignment) is an alignment.
5272
5273 uint32_t gcd =
5274 std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));
5275 Alignment = llvm::PowerOf2Floor(gcd);
5276 } else {
5277 Alignment = V.getPointerAlignment(DL).value();
5278 }
5279 // Use only IR information if we did not strip anything.
5280 T.takeKnownMaximum(Alignment);
5281 T.indicatePessimisticFixpoint();
5282 } else {
5283 // Use abstract attribute information.
5284 const AAAlign::StateType &DS = AA.getState();
5285 T ^= DS;
5286 }
5287 return T.isValidState();
5288 };
5289
5290 for (const auto &VAC : Values) {
5291 if (!VisitValueCB(*VAC.getValue()))
5292 return indicatePessimisticFixpoint();
5293 }
5294
5295 // TODO: If we know we visited all incoming values, thus no are assumed
5296 // dead, we can take the known information from the state T.
5297 return clampStateAndIndicateChange(getState(), T);
5298 }
5299
5300 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294211::AAAlignFloating5301 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
5302 };
5303
5304 /// Align attribute for function return value.
5305 struct AAAlignReturned final
5306 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5307 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
AAAlignReturned__anon641416294211::AAAlignReturned5308 AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5309
5310 /// See AbstractAttribute::initialize(...).
initialize__anon641416294211::AAAlignReturned5311 void initialize(Attributor &A) override {
5312 Base::initialize(A);
5313 Function *F = getAssociatedFunction();
5314 if (!F || F->isDeclaration())
5315 indicatePessimisticFixpoint();
5316 }
5317
5318 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294211::AAAlignReturned5319 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
5320 };
5321
5322 /// Align attribute for function argument.
5323 struct AAAlignArgument final
5324 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5325 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
AAAlignArgument__anon641416294211::AAAlignArgument5326 AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5327
5328 /// See AbstractAttribute::manifest(...).
manifest__anon641416294211::AAAlignArgument5329 ChangeStatus manifest(Attributor &A) override {
5330 // If the associated argument is involved in a must-tail call we give up
5331 // because we would need to keep the argument alignments of caller and
5332 // callee in-sync. Just does not seem worth the trouble right now.
5333 if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5334 return ChangeStatus::UNCHANGED;
5335 return Base::manifest(A);
5336 }
5337
5338 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294211::AAAlignArgument5339 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
5340 };
5341
5342 struct AAAlignCallSiteArgument final : AAAlignFloating {
AAAlignCallSiteArgument__anon641416294211::AAAlignCallSiteArgument5343 AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
5344 : AAAlignFloating(IRP, A) {}
5345
5346 /// See AbstractAttribute::manifest(...).
manifest__anon641416294211::AAAlignCallSiteArgument5347 ChangeStatus manifest(Attributor &A) override {
5348 // If the associated argument is involved in a must-tail call we give up
5349 // because we would need to keep the argument alignments of caller and
5350 // callee in-sync. Just does not seem worth the trouble right now.
5351 if (Argument *Arg = getAssociatedArgument())
5352 if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5353 return ChangeStatus::UNCHANGED;
5354 ChangeStatus Changed = AAAlignImpl::manifest(A);
5355 Align InheritAlign =
5356 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5357 if (InheritAlign >= getAssumedAlign())
5358 Changed = ChangeStatus::UNCHANGED;
5359 return Changed;
5360 }
5361
5362 /// See AbstractAttribute::updateImpl(Attributor &A).
updateImpl__anon641416294211::AAAlignCallSiteArgument5363 ChangeStatus updateImpl(Attributor &A) override {
5364 ChangeStatus Changed = AAAlignFloating::updateImpl(A);
5365 if (Argument *Arg = getAssociatedArgument()) {
5366 // We only take known information from the argument
5367 // so we do not need to track a dependence.
5368 const auto &ArgAlignAA = A.getAAFor<AAAlign>(
5369 *this, IRPosition::argument(*Arg), DepClassTy::NONE);
5370 takeKnownMaximum(ArgAlignAA.getKnownAlign().value());
5371 }
5372 return Changed;
5373 }
5374
5375 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294211::AAAlignCallSiteArgument5376 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
5377 };
5378
5379 /// Align attribute deduction for a call site return value.
5380 struct AAAlignCallSiteReturned final
5381 : AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl> {
5382 using Base = AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl>;
AAAlignCallSiteReturned__anon641416294211::AAAlignCallSiteReturned5383 AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
5384 : Base(IRP, A) {}
5385
5386 /// See AbstractAttribute::initialize(...).
initialize__anon641416294211::AAAlignCallSiteReturned5387 void initialize(Attributor &A) override {
5388 Base::initialize(A);
5389 Function *F = getAssociatedFunction();
5390 if (!F || F->isDeclaration())
5391 indicatePessimisticFixpoint();
5392 }
5393
5394 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294211::AAAlignCallSiteReturned5395 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
5396 };
5397 } // namespace
5398
5399 /// ------------------ Function No-Return Attribute ----------------------------
5400 namespace {
5401 struct AANoReturnImpl : public AANoReturn {
AANoReturnImpl__anon641416294411::AANoReturnImpl5402 AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}
5403
5404 /// See AbstractAttribute::initialize(...).
initialize__anon641416294411::AANoReturnImpl5405 void initialize(Attributor &A) override {
5406 AANoReturn::initialize(A);
5407 Function *F = getAssociatedFunction();
5408 if (!F || F->isDeclaration())
5409 indicatePessimisticFixpoint();
5410 }
5411
5412 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416294411::AANoReturnImpl5413 const std::string getAsStr() const override {
5414 return getAssumed() ? "noreturn" : "may-return";
5415 }
5416
5417 /// See AbstractAttribute::updateImpl(Attributor &A).
updateImpl__anon641416294411::AANoReturnImpl5418 ChangeStatus updateImpl(Attributor &A) override {
5419 auto CheckForNoReturn = [](Instruction &) { return false; };
5420 bool UsedAssumedInformation = false;
5421 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
5422 {(unsigned)Instruction::Ret},
5423 UsedAssumedInformation))
5424 return indicatePessimisticFixpoint();
5425 return ChangeStatus::UNCHANGED;
5426 }
5427 };
5428
5429 struct AANoReturnFunction final : AANoReturnImpl {
AANoReturnFunction__anon641416294411::AANoReturnFunction5430 AANoReturnFunction(const IRPosition &IRP, Attributor &A)
5431 : AANoReturnImpl(IRP, A) {}
5432
5433 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294411::AANoReturnFunction5434 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
5435 };
5436
5437 /// NoReturn attribute deduction for a call sites.
5438 struct AANoReturnCallSite final : AANoReturnImpl {
AANoReturnCallSite__anon641416294411::AANoReturnCallSite5439 AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
5440 : AANoReturnImpl(IRP, A) {}
5441
5442 /// See AbstractAttribute::initialize(...).
initialize__anon641416294411::AANoReturnCallSite5443 void initialize(Attributor &A) override {
5444 AANoReturnImpl::initialize(A);
5445 if (Function *F = getAssociatedFunction()) {
5446 const IRPosition &FnPos = IRPosition::function(*F);
5447 auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos, DepClassTy::REQUIRED);
5448 if (!FnAA.isAssumedNoReturn())
5449 indicatePessimisticFixpoint();
5450 }
5451 }
5452
5453 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294411::AANoReturnCallSite5454 ChangeStatus updateImpl(Attributor &A) override {
5455 // TODO: Once we have call site specific value information we can provide
5456 // call site specific liveness information and then it makes
5457 // sense to specialize attributes for call sites arguments instead of
5458 // redirecting requests to the callee argument.
5459 Function *F = getAssociatedFunction();
5460 const IRPosition &FnPos = IRPosition::function(*F);
5461 auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos, DepClassTy::REQUIRED);
5462 return clampStateAndIndicateChange(getState(), FnAA.getState());
5463 }
5464
5465 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294411::AANoReturnCallSite5466 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
5467 };
5468 } // namespace
5469
5470 /// ----------------------- Instance Info ---------------------------------
5471
5472 namespace {
5473 /// A class to hold the state of for no-capture attributes.
5474 struct AAInstanceInfoImpl : public AAInstanceInfo {
AAInstanceInfoImpl__anon641416294611::AAInstanceInfoImpl5475 AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
5476 : AAInstanceInfo(IRP, A) {}
5477
5478 /// See AbstractAttribute::initialize(...).
initialize__anon641416294611::AAInstanceInfoImpl5479 void initialize(Attributor &A) override {
5480 Value &V = getAssociatedValue();
5481 if (auto *C = dyn_cast<Constant>(&V)) {
5482 if (C->isThreadDependent())
5483 indicatePessimisticFixpoint();
5484 else
5485 indicateOptimisticFixpoint();
5486 return;
5487 }
5488 if (auto *CB = dyn_cast<CallBase>(&V))
5489 if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
5490 !CB->mayReadFromMemory()) {
5491 indicateOptimisticFixpoint();
5492 return;
5493 }
5494 }
5495
5496 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294611::AAInstanceInfoImpl5497 ChangeStatus updateImpl(Attributor &A) override {
5498 ChangeStatus Changed = ChangeStatus::UNCHANGED;
5499
5500 Value &V = getAssociatedValue();
5501 const Function *Scope = nullptr;
5502 if (auto *I = dyn_cast<Instruction>(&V))
5503 Scope = I->getFunction();
5504 if (auto *A = dyn_cast<Argument>(&V)) {
5505 Scope = A->getParent();
5506 if (!Scope->hasLocalLinkage())
5507 return Changed;
5508 }
5509 if (!Scope)
5510 return indicateOptimisticFixpoint();
5511
5512 auto &NoRecurseAA = A.getAAFor<AANoRecurse>(
5513 *this, IRPosition::function(*Scope), DepClassTy::OPTIONAL);
5514 if (NoRecurseAA.isAssumedNoRecurse())
5515 return Changed;
5516
5517 auto UsePred = [&](const Use &U, bool &Follow) {
5518 const Instruction *UserI = dyn_cast<Instruction>(U.getUser());
5519 if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||
5520 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
5521 Follow = true;
5522 return true;
5523 }
5524 if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||
5525 (isa<StoreInst>(UserI) &&
5526 cast<StoreInst>(UserI)->getValueOperand() != U.get()))
5527 return true;
5528 if (auto *CB = dyn_cast<CallBase>(UserI)) {
5529 // This check is not guaranteeing uniqueness but for now that we cannot
5530 // end up with two versions of \p U thinking it was one.
5531 if (!CB->getCalledFunction() ||
5532 !CB->getCalledFunction()->hasLocalLinkage())
5533 return true;
5534 if (!CB->isArgOperand(&U))
5535 return false;
5536 const auto &ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
5537 *this, IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U)),
5538 DepClassTy::OPTIONAL);
5539 if (!ArgInstanceInfoAA.isAssumedUniqueForAnalysis())
5540 return false;
5541 // If this call base might reach the scope again we might forward the
5542 // argument back here. This is very conservative.
5543 if (AA::isPotentiallyReachable(
5544 A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,
5545 [Scope](const Function &Fn) { return &Fn != Scope; }))
5546 return false;
5547 return true;
5548 }
5549 return false;
5550 };
5551
5552 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
5553 if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {
5554 auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
5555 if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&
5556 AA::isDynamicallyUnique(A, *this, *Ptr))
5557 return true;
5558 }
5559 return false;
5560 };
5561
5562 if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,
5563 DepClassTy::OPTIONAL,
5564 /* IgnoreDroppableUses */ true, EquivalentUseCB))
5565 return indicatePessimisticFixpoint();
5566
5567 return Changed;
5568 }
5569
5570 /// See AbstractState::getAsStr().
getAsStr__anon641416294611::AAInstanceInfoImpl5571 const std::string getAsStr() const override {
5572 return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
5573 }
5574
5575 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294611::AAInstanceInfoImpl5576 void trackStatistics() const override {}
5577 };
5578
5579 /// InstanceInfo attribute for floating values.
5580 struct AAInstanceInfoFloating : AAInstanceInfoImpl {
AAInstanceInfoFloating__anon641416294611::AAInstanceInfoFloating5581 AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
5582 : AAInstanceInfoImpl(IRP, A) {}
5583 };
5584
5585 /// NoCapture attribute for function arguments.
5586 struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
AAInstanceInfoArgument__anon641416294611::AAInstanceInfoArgument5587 AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
5588 : AAInstanceInfoFloating(IRP, A) {}
5589 };
5590
5591 /// InstanceInfo attribute for call site arguments.
5592 struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
AAInstanceInfoCallSiteArgument__anon641416294611::AAInstanceInfoCallSiteArgument5593 AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
5594 : AAInstanceInfoImpl(IRP, A) {}
5595
5596 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294611::AAInstanceInfoCallSiteArgument5597 ChangeStatus updateImpl(Attributor &A) override {
5598 // TODO: Once we have call site specific value information we can provide
5599 // call site specific liveness information and then it makes
5600 // sense to specialize attributes for call sites arguments instead of
5601 // redirecting requests to the callee argument.
5602 Argument *Arg = getAssociatedArgument();
5603 if (!Arg)
5604 return indicatePessimisticFixpoint();
5605 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5606 auto &ArgAA =
5607 A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);
5608 return clampStateAndIndicateChange(getState(), ArgAA.getState());
5609 }
5610 };
5611
5612 /// InstanceInfo attribute for function return value.
5613 struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
AAInstanceInfoReturned__anon641416294611::AAInstanceInfoReturned5614 AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
5615 : AAInstanceInfoImpl(IRP, A) {
5616 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5617 }
5618
5619 /// See AbstractAttribute::initialize(...).
initialize__anon641416294611::AAInstanceInfoReturned5620 void initialize(Attributor &A) override {
5621 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5622 }
5623
5624 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294611::AAInstanceInfoReturned5625 ChangeStatus updateImpl(Attributor &A) override {
5626 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5627 }
5628 };
5629
5630 /// InstanceInfo attribute deduction for a call site return value.
5631 struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
AAInstanceInfoCallSiteReturned__anon641416294611::AAInstanceInfoCallSiteReturned5632 AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
5633 : AAInstanceInfoFloating(IRP, A) {}
5634 };
5635 } // namespace
5636
5637 /// ----------------------- Variable Capturing ---------------------------------
5638
5639 namespace {
5640 /// A class to hold the state of for no-capture attributes.
5641 struct AANoCaptureImpl : public AANoCapture {
AANoCaptureImpl__anon641416294a11::AANoCaptureImpl5642 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5643
5644 /// See AbstractAttribute::initialize(...).
initialize__anon641416294a11::AANoCaptureImpl5645 void initialize(Attributor &A) override {
5646 if (hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ true)) {
5647 indicateOptimisticFixpoint();
5648 return;
5649 }
5650 Function *AnchorScope = getAnchorScope();
5651 if (isFnInterfaceKind() &&
5652 (!AnchorScope || !A.isFunctionIPOAmendable(*AnchorScope))) {
5653 indicatePessimisticFixpoint();
5654 return;
5655 }
5656
5657 // You cannot "capture" null in the default address space.
5658 if (isa<ConstantPointerNull>(getAssociatedValue()) &&
5659 getAssociatedValue().getType()->getPointerAddressSpace() == 0) {
5660 indicateOptimisticFixpoint();
5661 return;
5662 }
5663
5664 const Function *F =
5665 isArgumentPosition() ? getAssociatedFunction() : AnchorScope;
5666
5667 // Check what state the associated function can actually capture.
5668 if (F)
5669 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
5670 else
5671 indicatePessimisticFixpoint();
5672 }
5673
5674 /// See AbstractAttribute::updateImpl(...).
5675 ChangeStatus updateImpl(Attributor &A) override;
5676
5677 /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
getDeducedAttributes__anon641416294a11::AANoCaptureImpl5678 void getDeducedAttributes(LLVMContext &Ctx,
5679 SmallVectorImpl<Attribute> &Attrs) const override {
5680 if (!isAssumedNoCaptureMaybeReturned())
5681 return;
5682
5683 if (isArgumentPosition()) {
5684 if (isAssumedNoCapture())
5685 Attrs.emplace_back(Attribute::get(Ctx, Attribute::NoCapture));
5686 else if (ManifestInternal)
5687 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
5688 }
5689 }
5690
5691 /// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
5692 /// depending on the ability of the function associated with \p IRP to capture
5693 /// state in memory and through "returning/throwing", respectively.
determineFunctionCaptureCapabilities__anon641416294a11::AANoCaptureImpl5694 static void determineFunctionCaptureCapabilities(const IRPosition &IRP,
5695 const Function &F,
5696 BitIntegerState &State) {
5697 // TODO: Once we have memory behavior attributes we should use them here.
5698
5699 // If we know we cannot communicate or write to memory, we do not care about
5700 // ptr2int anymore.
5701 if (F.onlyReadsMemory() && F.doesNotThrow() &&
5702 F.getReturnType()->isVoidTy()) {
5703 State.addKnownBits(NO_CAPTURE);
5704 return;
5705 }
5706
5707 // A function cannot capture state in memory if it only reads memory, it can
5708 // however return/throw state and the state might be influenced by the
5709 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5710 if (F.onlyReadsMemory())
5711 State.addKnownBits(NOT_CAPTURED_IN_MEM);
5712
5713 // A function cannot communicate state back if it does not through
5714 // exceptions and doesn not return values.
5715 if (F.doesNotThrow() && F.getReturnType()->isVoidTy())
5716 State.addKnownBits(NOT_CAPTURED_IN_RET);
5717
5718 // Check existing "returned" attributes.
5719 int ArgNo = IRP.getCalleeArgNo();
5720 if (F.doesNotThrow() && ArgNo >= 0) {
5721 for (unsigned u = 0, e = F.arg_size(); u < e; ++u)
5722 if (F.hasParamAttribute(u, Attribute::Returned)) {
5723 if (u == unsigned(ArgNo))
5724 State.removeAssumedBits(NOT_CAPTURED_IN_RET);
5725 else if (F.onlyReadsMemory())
5726 State.addKnownBits(NO_CAPTURE);
5727 else
5728 State.addKnownBits(NOT_CAPTURED_IN_RET);
5729 break;
5730 }
5731 }
5732 }
5733
5734 /// See AbstractState::getAsStr().
getAsStr__anon641416294a11::AANoCaptureImpl5735 const std::string getAsStr() const override {
5736 if (isKnownNoCapture())
5737 return "known not-captured";
5738 if (isAssumedNoCapture())
5739 return "assumed not-captured";
5740 if (isKnownNoCaptureMaybeReturned())
5741 return "known not-captured-maybe-returned";
5742 if (isAssumedNoCaptureMaybeReturned())
5743 return "assumed not-captured-maybe-returned";
5744 return "assumed-captured";
5745 }
5746
5747 /// Check the use \p U and update \p State accordingly. Return true if we
5748 /// should continue to update the state.
checkUse__anon641416294a11::AANoCaptureImpl5749 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
5750 bool &Follow) {
5751 Instruction *UInst = cast<Instruction>(U.getUser());
5752 LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "
5753 << *UInst << "\n");
5754
5755 // Deal with ptr2int by following uses.
5756 if (isa<PtrToIntInst>(UInst)) {
5757 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
5758 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5759 /* Return */ true);
5760 }
5761
5762 // For stores we already checked if we can follow them, if they make it
5763 // here we give up.
5764 if (isa<StoreInst>(UInst))
5765 return isCapturedIn(State, /* Memory */ true, /* Integer */ false,
5766 /* Return */ false);
5767
5768 // Explicitly catch return instructions.
5769 if (isa<ReturnInst>(UInst)) {
5770 if (UInst->getFunction() == getAnchorScope())
5771 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5772 /* Return */ true);
5773 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5774 /* Return */ true);
5775 }
5776
5777 // For now we only use special logic for call sites. However, the tracker
5778 // itself knows about a lot of other non-capturing cases already.
5779 auto *CB = dyn_cast<CallBase>(UInst);
5780 if (!CB || !CB->isArgOperand(&U))
5781 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5782 /* Return */ true);
5783
5784 unsigned ArgNo = CB->getArgOperandNo(&U);
5785 const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
5786 // If we have a abstract no-capture attribute for the argument we can use
5787 // it to justify a non-capture attribute here. This allows recursion!
5788 auto &ArgNoCaptureAA =
5789 A.getAAFor<AANoCapture>(*this, CSArgPos, DepClassTy::REQUIRED);
5790 if (ArgNoCaptureAA.isAssumedNoCapture())
5791 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5792 /* Return */ false);
5793 if (ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
5794 Follow = true;
5795 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5796 /* Return */ false);
5797 }
5798
5799 // Lastly, we could not find a reason no-capture can be assumed so we don't.
5800 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5801 /* Return */ true);
5802 }
5803
5804 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
5805 /// \p CapturedInRet, then return true if we should continue updating the
5806 /// state.
isCapturedIn__anon641416294a11::AANoCaptureImpl5807 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
5808 bool CapturedInInt, bool CapturedInRet) {
5809 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
5810 << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
5811 if (CapturedInMem)
5812 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
5813 if (CapturedInInt)
5814 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
5815 if (CapturedInRet)
5816 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
5817 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
5818 }
5819 };
5820
updateImpl(Attributor & A)5821 ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
5822 const IRPosition &IRP = getIRPosition();
5823 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
5824 : &IRP.getAssociatedValue();
5825 if (!V)
5826 return indicatePessimisticFixpoint();
5827
5828 const Function *F =
5829 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
5830 assert(F && "Expected a function!");
5831 const IRPosition &FnPos = IRPosition::function(*F);
5832
5833 AANoCapture::StateType T;
5834
5835 // Readonly means we cannot capture through memory.
5836 bool IsKnown;
5837 if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
5838 T.addKnownBits(NOT_CAPTURED_IN_MEM);
5839 if (IsKnown)
5840 addKnownBits(NOT_CAPTURED_IN_MEM);
5841 }
5842
5843 // Make sure all returned values are different than the underlying value.
5844 // TODO: we could do this in a more sophisticated way inside
5845 // AAReturnedValues, e.g., track all values that escape through returns
5846 // directly somehow.
5847 auto CheckReturnedArgs = [&](const AAReturnedValues &RVAA) {
5848 if (!RVAA.getState().isValidState())
5849 return false;
5850 bool SeenConstant = false;
5851 for (const auto &It : RVAA.returned_values()) {
5852 if (isa<Constant>(It.first)) {
5853 if (SeenConstant)
5854 return false;
5855 SeenConstant = true;
5856 } else if (!isa<Argument>(It.first) ||
5857 It.first == getAssociatedArgument())
5858 return false;
5859 }
5860 return true;
5861 };
5862
5863 const auto &NoUnwindAA =
5864 A.getAAFor<AANoUnwind>(*this, FnPos, DepClassTy::OPTIONAL);
5865 if (NoUnwindAA.isAssumedNoUnwind()) {
5866 bool IsVoidTy = F->getReturnType()->isVoidTy();
5867 const AAReturnedValues *RVAA =
5868 IsVoidTy ? nullptr
5869 : &A.getAAFor<AAReturnedValues>(*this, FnPos,
5870
5871 DepClassTy::OPTIONAL);
5872 if (IsVoidTy || CheckReturnedArgs(*RVAA)) {
5873 T.addKnownBits(NOT_CAPTURED_IN_RET);
5874 if (T.isKnown(NOT_CAPTURED_IN_MEM))
5875 return ChangeStatus::UNCHANGED;
5876 if (NoUnwindAA.isKnownNoUnwind() &&
5877 (IsVoidTy || RVAA->getState().isAtFixpoint())) {
5878 addKnownBits(NOT_CAPTURED_IN_RET);
5879 if (isKnown(NOT_CAPTURED_IN_MEM))
5880 return indicateOptimisticFixpoint();
5881 }
5882 }
5883 }
5884
5885 auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
5886 const auto &DerefAA = A.getAAFor<AADereferenceable>(
5887 *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
5888 return DerefAA.getAssumedDereferenceableBytes();
5889 };
5890
5891 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
5892 switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
5893 case UseCaptureKind::NO_CAPTURE:
5894 return true;
5895 case UseCaptureKind::MAY_CAPTURE:
5896 return checkUse(A, T, U, Follow);
5897 case UseCaptureKind::PASSTHROUGH:
5898 Follow = true;
5899 return true;
5900 }
5901 llvm_unreachable("Unexpected use capture kind!");
5902 };
5903
5904 if (!A.checkForAllUses(UseCheck, *this, *V))
5905 return indicatePessimisticFixpoint();
5906
5907 AANoCapture::StateType &S = getState();
5908 auto Assumed = S.getAssumed();
5909 S.intersectAssumedBits(T.getAssumed());
5910 if (!isAssumedNoCaptureMaybeReturned())
5911 return indicatePessimisticFixpoint();
5912 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
5913 : ChangeStatus::CHANGED;
5914 }
5915
5916 /// NoCapture attribute for function arguments.
5917 struct AANoCaptureArgument final : AANoCaptureImpl {
AANoCaptureArgument__anon641416294a11::AANoCaptureArgument5918 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
5919 : AANoCaptureImpl(IRP, A) {}
5920
5921 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294a11::AANoCaptureArgument5922 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
5923 };
5924
5925 /// NoCapture attribute for call site arguments.
5926 struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
AANoCaptureCallSiteArgument__anon641416294a11::AANoCaptureCallSiteArgument5927 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
5928 : AANoCaptureImpl(IRP, A) {}
5929
5930 /// See AbstractAttribute::initialize(...).
initialize__anon641416294a11::AANoCaptureCallSiteArgument5931 void initialize(Attributor &A) override {
5932 if (Argument *Arg = getAssociatedArgument())
5933 if (Arg->hasByValAttr())
5934 indicateOptimisticFixpoint();
5935 AANoCaptureImpl::initialize(A);
5936 }
5937
5938 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294a11::AANoCaptureCallSiteArgument5939 ChangeStatus updateImpl(Attributor &A) override {
5940 // TODO: Once we have call site specific value information we can provide
5941 // call site specific liveness information and then it makes
5942 // sense to specialize attributes for call sites arguments instead of
5943 // redirecting requests to the callee argument.
5944 Argument *Arg = getAssociatedArgument();
5945 if (!Arg)
5946 return indicatePessimisticFixpoint();
5947 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5948 auto &ArgAA = A.getAAFor<AANoCapture>(*this, ArgPos, DepClassTy::REQUIRED);
5949 return clampStateAndIndicateChange(getState(), ArgAA.getState());
5950 }
5951
5952 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294a11::AANoCaptureCallSiteArgument5953 void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nocapture)};
5954 };
5955
5956 /// NoCapture attribute for floating values.
5957 struct AANoCaptureFloating final : AANoCaptureImpl {
AANoCaptureFloating__anon641416294a11::AANoCaptureFloating5958 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
5959 : AANoCaptureImpl(IRP, A) {}
5960
5961 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294a11::AANoCaptureFloating5962 void trackStatistics() const override {
5963 STATS_DECLTRACK_FLOATING_ATTR(nocapture)
5964 }
5965 };
5966
5967 /// NoCapture attribute for function return value.
5968 struct AANoCaptureReturned final : AANoCaptureImpl {
AANoCaptureReturned__anon641416294a11::AANoCaptureReturned5969 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
5970 : AANoCaptureImpl(IRP, A) {
5971 llvm_unreachable("NoCapture is not applicable to function returns!");
5972 }
5973
5974 /// See AbstractAttribute::initialize(...).
initialize__anon641416294a11::AANoCaptureReturned5975 void initialize(Attributor &A) override {
5976 llvm_unreachable("NoCapture is not applicable to function returns!");
5977 }
5978
5979 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294a11::AANoCaptureReturned5980 ChangeStatus updateImpl(Attributor &A) override {
5981 llvm_unreachable("NoCapture is not applicable to function returns!");
5982 }
5983
5984 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294a11::AANoCaptureReturned5985 void trackStatistics() const override {}
5986 };
5987
5988 /// NoCapture attribute deduction for a call site return value.
5989 struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
AANoCaptureCallSiteReturned__anon641416294a11::AANoCaptureCallSiteReturned5990 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
5991 : AANoCaptureImpl(IRP, A) {}
5992
5993 /// See AbstractAttribute::initialize(...).
initialize__anon641416294a11::AANoCaptureCallSiteReturned5994 void initialize(Attributor &A) override {
5995 const Function *F = getAnchorScope();
5996 // Check what state the associated function can actually capture.
5997 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
5998 }
5999
6000 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294a11::AANoCaptureCallSiteReturned6001 void trackStatistics() const override {
6002 STATS_DECLTRACK_CSRET_ATTR(nocapture)
6003 }
6004 };
6005 } // namespace
6006
6007 /// ------------------ Value Simplify Attribute ----------------------------
6008
unionAssumed(std::optional<Value * > Other)6009 bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6010 // FIXME: Add a typecast support.
6011 SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
6012 SimplifiedAssociatedValue, Other, Ty);
6013 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6014 return false;
6015
6016 LLVM_DEBUG({
6017 if (SimplifiedAssociatedValue)
6018 dbgs() << "[ValueSimplify] is assumed to be "
6019 << **SimplifiedAssociatedValue << "\n";
6020 else
6021 dbgs() << "[ValueSimplify] is assumed to be <none>\n";
6022 });
6023 return true;
6024 }
6025
6026 namespace {
6027 struct AAValueSimplifyImpl : AAValueSimplify {
AAValueSimplifyImpl__anon641416294e11::AAValueSimplifyImpl6028 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6029 : AAValueSimplify(IRP, A) {}
6030
6031 /// See AbstractAttribute::initialize(...).
initialize__anon641416294e11::AAValueSimplifyImpl6032 void initialize(Attributor &A) override {
6033 if (getAssociatedValue().getType()->isVoidTy())
6034 indicatePessimisticFixpoint();
6035 if (A.hasSimplificationCallback(getIRPosition()))
6036 indicatePessimisticFixpoint();
6037 }
6038
6039 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416294e11::AAValueSimplifyImpl6040 const std::string getAsStr() const override {
6041 LLVM_DEBUG({
6042 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";
6043 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6044 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";
6045 });
6046 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6047 : "not-simple";
6048 }
6049
6050 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294e11::AAValueSimplifyImpl6051 void trackStatistics() const override {}
6052
6053 /// See AAValueSimplify::getAssumedSimplifiedValue()
6054 std::optional<Value *>
getAssumedSimplifiedValue__anon641416294e11::AAValueSimplifyImpl6055 getAssumedSimplifiedValue(Attributor &A) const override {
6056 return SimplifiedAssociatedValue;
6057 }
6058
6059 /// Ensure the return value is \p V with type \p Ty, if not possible return
6060 /// nullptr. If \p Check is true we will only verify such an operation would
6061 /// suceed and return a non-nullptr value if that is the case. No IR is
6062 /// generated or modified.
ensureType__anon641416294e11::AAValueSimplifyImpl6063 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6064 bool Check) {
6065 if (auto *TypedV = AA::getWithType(V, Ty))
6066 return TypedV;
6067 if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
6068 return Check ? &V
6069 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(&V, &Ty,
6070 "", CtxI);
6071 return nullptr;
6072 }
6073
6074 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6075 /// If \p Check is true we will only verify such an operation would suceed and
6076 /// return a non-nullptr value if that is the case. No IR is generated or
6077 /// modified.
reproduceInst__anon641416294e11::AAValueSimplifyImpl6078 static Value *reproduceInst(Attributor &A,
6079 const AbstractAttribute &QueryingAA,
6080 Instruction &I, Type &Ty, Instruction *CtxI,
6081 bool Check, ValueToValueMapTy &VMap) {
6082 assert(CtxI && "Cannot reproduce an instruction without context!");
6083 if (Check && (I.mayReadFromMemory() ||
6084 !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
6085 /* TLI */ nullptr)))
6086 return nullptr;
6087 for (Value *Op : I.operands()) {
6088 Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
6089 if (!NewOp) {
6090 assert(Check && "Manifest of new value unexpectedly failed!");
6091 return nullptr;
6092 }
6093 if (!Check)
6094 VMap[Op] = NewOp;
6095 }
6096 if (Check)
6097 return &I;
6098
6099 Instruction *CloneI = I.clone();
6100 // TODO: Try to salvage debug information here.
6101 CloneI->setDebugLoc(DebugLoc());
6102 VMap[&I] = CloneI;
6103 CloneI->insertBefore(CtxI);
6104 RemapInstruction(CloneI, VMap);
6105 return CloneI;
6106 }
6107
6108 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6109 /// If \p Check is true we will only verify such an operation would suceed and
6110 /// return a non-nullptr value if that is the case. No IR is generated or
6111 /// modified.
reproduceValue__anon641416294e11::AAValueSimplifyImpl6112 static Value *reproduceValue(Attributor &A,
6113 const AbstractAttribute &QueryingAA, Value &V,
6114 Type &Ty, Instruction *CtxI, bool Check,
6115 ValueToValueMapTy &VMap) {
6116 if (const auto &NewV = VMap.lookup(&V))
6117 return NewV;
6118 bool UsedAssumedInformation = false;
6119 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6120 V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6121 if (!SimpleV.has_value())
6122 return PoisonValue::get(&Ty);
6123 Value *EffectiveV = &V;
6124 if (*SimpleV)
6125 EffectiveV = *SimpleV;
6126 if (auto *C = dyn_cast<Constant>(EffectiveV))
6127 return C;
6128 if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
6129 A.getInfoCache()))
6130 return ensureType(A, *EffectiveV, Ty, CtxI, Check);
6131 if (auto *I = dyn_cast<Instruction>(EffectiveV))
6132 if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
6133 return ensureType(A, *NewV, Ty, CtxI, Check);
6134 return nullptr;
6135 }
6136
6137 /// Return a value we can use as replacement for the associated one, or
6138 /// nullptr if we don't have one that makes sense.
manifestReplacementValue__anon641416294e11::AAValueSimplifyImpl6139 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6140 Value *NewV = SimplifiedAssociatedValue
6141 ? *SimplifiedAssociatedValue
6142 : UndefValue::get(getAssociatedType());
6143 if (NewV && NewV != &getAssociatedValue()) {
6144 ValueToValueMapTy VMap;
6145 // First verify we can reprduce the value with the required type at the
6146 // context location before we actually start modifying the IR.
6147 if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6148 /* CheckOnly */ true, VMap))
6149 return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6150 /* CheckOnly */ false, VMap);
6151 }
6152 return nullptr;
6153 }
6154
6155 /// Helper function for querying AAValueSimplify and updating candidate.
6156 /// \param IRP The value position we are trying to unify with SimplifiedValue
checkAndUpdate__anon641416294e11::AAValueSimplifyImpl6157 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6158 const IRPosition &IRP, bool Simplify = true) {
6159 bool UsedAssumedInformation = false;
6160 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6161 if (Simplify)
6162 QueryingValueSimplified = A.getAssumedSimplified(
6163 IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6164 return unionAssumed(QueryingValueSimplified);
6165 }
6166
6167 /// Returns a candidate is found or not
askSimplifiedValueFor__anon641416294e11::AAValueSimplifyImpl6168 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6169 if (!getAssociatedValue().getType()->isIntegerTy())
6170 return false;
6171
6172 // This will also pass the call base context.
6173 const auto &AA =
6174 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6175
6176 std::optional<Constant *> COpt = AA.getAssumedConstant(A);
6177
6178 if (!COpt) {
6179 SimplifiedAssociatedValue = std::nullopt;
6180 A.recordDependence(AA, *this, DepClassTy::OPTIONAL);
6181 return true;
6182 }
6183 if (auto *C = *COpt) {
6184 SimplifiedAssociatedValue = C;
6185 A.recordDependence(AA, *this, DepClassTy::OPTIONAL);
6186 return true;
6187 }
6188 return false;
6189 }
6190
askSimplifiedValueForOtherAAs__anon641416294e11::AAValueSimplifyImpl6191 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6192 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6193 return true;
6194 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6195 return true;
6196 return false;
6197 }
6198
6199 /// See AbstractAttribute::manifest(...).
manifest__anon641416294e11::AAValueSimplifyImpl6200 ChangeStatus manifest(Attributor &A) override {
6201 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6202 for (auto &U : getAssociatedValue().uses()) {
6203 // Check if we need to adjust the insertion point to make sure the IR is
6204 // valid.
6205 Instruction *IP = dyn_cast<Instruction>(U.getUser());
6206 if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
6207 IP = PHI->getIncomingBlock(U)->getTerminator();
6208 if (auto *NewV = manifestReplacementValue(A, IP)) {
6209 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()
6210 << " -> " << *NewV << " :: " << *this << "\n");
6211 if (A.changeUseAfterManifest(U, *NewV))
6212 Changed = ChangeStatus::CHANGED;
6213 }
6214 }
6215
6216 return Changed | AAValueSimplify::manifest(A);
6217 }
6218
6219 /// See AbstractState::indicatePessimisticFixpoint(...).
indicatePessimisticFixpoint__anon641416294e11::AAValueSimplifyImpl6220 ChangeStatus indicatePessimisticFixpoint() override {
6221 SimplifiedAssociatedValue = &getAssociatedValue();
6222 return AAValueSimplify::indicatePessimisticFixpoint();
6223 }
6224 };
6225
6226 struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
AAValueSimplifyArgument__anon641416294e11::AAValueSimplifyArgument6227 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6228 : AAValueSimplifyImpl(IRP, A) {}
6229
initialize__anon641416294e11::AAValueSimplifyArgument6230 void initialize(Attributor &A) override {
6231 AAValueSimplifyImpl::initialize(A);
6232 if (!getAnchorScope() || getAnchorScope()->isDeclaration())
6233 indicatePessimisticFixpoint();
6234 if (hasAttr({Attribute::InAlloca, Attribute::Preallocated,
6235 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6236 /* IgnoreSubsumingPositions */ true))
6237 indicatePessimisticFixpoint();
6238 }
6239
6240 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294e11::AAValueSimplifyArgument6241 ChangeStatus updateImpl(Attributor &A) override {
6242 // Byval is only replacable if it is readonly otherwise we would write into
6243 // the replaced value and not the copy that byval creates implicitly.
6244 Argument *Arg = getAssociatedArgument();
6245 if (Arg->hasByValAttr()) {
6246 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6247 // there is no race by not copying a constant byval.
6248 bool IsKnown;
6249 if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
6250 return indicatePessimisticFixpoint();
6251 }
6252
6253 auto Before = SimplifiedAssociatedValue;
6254
6255 auto PredForCallSite = [&](AbstractCallSite ACS) {
6256 const IRPosition &ACSArgPos =
6257 IRPosition::callsite_argument(ACS, getCallSiteArgNo());
6258 // Check if a coresponding argument was found or if it is on not
6259 // associated (which can happen for callback calls).
6260 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6261 return false;
6262
6263 // Simplify the argument operand explicitly and check if the result is
6264 // valid in the current scope. This avoids refering to simplified values
6265 // in other functions, e.g., we don't want to say a an argument in a
6266 // static function is actually an argument in a different function.
6267 bool UsedAssumedInformation = false;
6268 std::optional<Constant *> SimpleArgOp =
6269 A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
6270 if (!SimpleArgOp)
6271 return true;
6272 if (!*SimpleArgOp)
6273 return false;
6274 if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
6275 return false;
6276 return unionAssumed(*SimpleArgOp);
6277 };
6278
6279 // Generate a answer specific to a call site context.
6280 bool Success;
6281 bool UsedAssumedInformation = false;
6282 if (hasCallBaseContext() &&
6283 getCallBaseContext()->getCalledFunction() == Arg->getParent())
6284 Success = PredForCallSite(
6285 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6286 else
6287 Success = A.checkForAllCallSites(PredForCallSite, *this, true,
6288 UsedAssumedInformation);
6289
6290 if (!Success)
6291 if (!askSimplifiedValueForOtherAAs(A))
6292 return indicatePessimisticFixpoint();
6293
6294 // If a candidate was found in this update, return CHANGED.
6295 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6296 : ChangeStatus ::CHANGED;
6297 }
6298
6299 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294e11::AAValueSimplifyArgument6300 void trackStatistics() const override {
6301 STATS_DECLTRACK_ARG_ATTR(value_simplify)
6302 }
6303 };
6304
6305 struct AAValueSimplifyReturned : AAValueSimplifyImpl {
AAValueSimplifyReturned__anon641416294e11::AAValueSimplifyReturned6306 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6307 : AAValueSimplifyImpl(IRP, A) {}
6308
6309 /// See AAValueSimplify::getAssumedSimplifiedValue()
6310 std::optional<Value *>
getAssumedSimplifiedValue__anon641416294e11::AAValueSimplifyReturned6311 getAssumedSimplifiedValue(Attributor &A) const override {
6312 if (!isValidState())
6313 return nullptr;
6314 return SimplifiedAssociatedValue;
6315 }
6316
6317 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294e11::AAValueSimplifyReturned6318 ChangeStatus updateImpl(Attributor &A) override {
6319 auto Before = SimplifiedAssociatedValue;
6320
6321 auto ReturnInstCB = [&](Instruction &I) {
6322 auto &RI = cast<ReturnInst>(I);
6323 return checkAndUpdate(
6324 A, *this,
6325 IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
6326 };
6327
6328 bool UsedAssumedInformation = false;
6329 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
6330 UsedAssumedInformation))
6331 if (!askSimplifiedValueForOtherAAs(A))
6332 return indicatePessimisticFixpoint();
6333
6334 // If a candidate was found in this update, return CHANGED.
6335 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6336 : ChangeStatus ::CHANGED;
6337 }
6338
manifest__anon641416294e11::AAValueSimplifyReturned6339 ChangeStatus manifest(Attributor &A) override {
6340 // We queried AAValueSimplify for the returned values so they will be
6341 // replaced if a simplified form was found. Nothing to do here.
6342 return ChangeStatus::UNCHANGED;
6343 }
6344
6345 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294e11::AAValueSimplifyReturned6346 void trackStatistics() const override {
6347 STATS_DECLTRACK_FNRET_ATTR(value_simplify)
6348 }
6349 };
6350
6351 struct AAValueSimplifyFloating : AAValueSimplifyImpl {
AAValueSimplifyFloating__anon641416294e11::AAValueSimplifyFloating6352 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6353 : AAValueSimplifyImpl(IRP, A) {}
6354
6355 /// See AbstractAttribute::initialize(...).
initialize__anon641416294e11::AAValueSimplifyFloating6356 void initialize(Attributor &A) override {
6357 AAValueSimplifyImpl::initialize(A);
6358 Value &V = getAnchorValue();
6359
6360 // TODO: add other stuffs
6361 if (isa<Constant>(V))
6362 indicatePessimisticFixpoint();
6363 }
6364
6365 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294e11::AAValueSimplifyFloating6366 ChangeStatus updateImpl(Attributor &A) override {
6367 auto Before = SimplifiedAssociatedValue;
6368 if (!askSimplifiedValueForOtherAAs(A))
6369 return indicatePessimisticFixpoint();
6370
6371 // If a candidate was found in this update, return CHANGED.
6372 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6373 : ChangeStatus ::CHANGED;
6374 }
6375
6376 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294e11::AAValueSimplifyFloating6377 void trackStatistics() const override {
6378 STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
6379 }
6380 };
6381
6382 struct AAValueSimplifyFunction : AAValueSimplifyImpl {
AAValueSimplifyFunction__anon641416294e11::AAValueSimplifyFunction6383 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6384 : AAValueSimplifyImpl(IRP, A) {}
6385
6386 /// See AbstractAttribute::initialize(...).
initialize__anon641416294e11::AAValueSimplifyFunction6387 void initialize(Attributor &A) override {
6388 SimplifiedAssociatedValue = nullptr;
6389 indicateOptimisticFixpoint();
6390 }
6391 /// See AbstractAttribute::initialize(...).
updateImpl__anon641416294e11::AAValueSimplifyFunction6392 ChangeStatus updateImpl(Attributor &A) override {
6393 llvm_unreachable(
6394 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6395 }
6396 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294e11::AAValueSimplifyFunction6397 void trackStatistics() const override {
6398 STATS_DECLTRACK_FN_ATTR(value_simplify)
6399 }
6400 };
6401
6402 struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
AAValueSimplifyCallSite__anon641416294e11::AAValueSimplifyCallSite6403 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6404 : AAValueSimplifyFunction(IRP, A) {}
6405 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416294e11::AAValueSimplifyCallSite6406 void trackStatistics() const override {
6407 STATS_DECLTRACK_CS_ATTR(value_simplify)
6408 }
6409 };
6410
6411 struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
AAValueSimplifyCallSiteReturned__anon641416294e11::AAValueSimplifyCallSiteReturned6412 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6413 : AAValueSimplifyImpl(IRP, A) {}
6414
initialize__anon641416294e11::AAValueSimplifyCallSiteReturned6415 void initialize(Attributor &A) override {
6416 AAValueSimplifyImpl::initialize(A);
6417 Function *Fn = getAssociatedFunction();
6418 if (!Fn) {
6419 indicatePessimisticFixpoint();
6420 return;
6421 }
6422 for (Argument &Arg : Fn->args()) {
6423 if (Arg.hasReturnedAttr()) {
6424 auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
6425 Arg.getArgNo());
6426 if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_ARGUMENT &&
6427 checkAndUpdate(A, *this, IRP))
6428 indicateOptimisticFixpoint();
6429 else
6430 indicatePessimisticFixpoint();
6431 return;
6432 }
6433 }
6434 }
6435
6436 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416294e11::AAValueSimplifyCallSiteReturned6437 ChangeStatus updateImpl(Attributor &A) override {
6438 auto Before = SimplifiedAssociatedValue;
6439 auto &RetAA = A.getAAFor<AAReturnedValues>(
6440 *this, IRPosition::function(*getAssociatedFunction()),
6441 DepClassTy::REQUIRED);
6442 auto PredForReturned =
6443 [&](Value &RetVal, const SmallSetVector<ReturnInst *, 4> &RetInsts) {
6444 bool UsedAssumedInformation = false;
6445 std::optional<Value *> CSRetVal =
6446 A.translateArgumentToCallSiteContent(
6447 &RetVal, *cast<CallBase>(getCtxI()), *this,
6448 UsedAssumedInformation);
6449 SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
6450 SimplifiedAssociatedValue, CSRetVal, getAssociatedType());
6451 return SimplifiedAssociatedValue != std::optional<Value *>(nullptr);
6452 };
6453 if (!RetAA.checkForAllReturnedValuesAndReturnInsts(PredForReturned))
6454 if (!askSimplifiedValueForOtherAAs(A))
6455 return indicatePessimisticFixpoint();
6456 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6457 : ChangeStatus ::CHANGED;
6458 }
6459
trackStatistics__anon641416294e11::AAValueSimplifyCallSiteReturned6460 void trackStatistics() const override {
6461 STATS_DECLTRACK_CSRET_ATTR(value_simplify)
6462 }
6463 };
6464
6465 struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
AAValueSimplifyCallSiteArgument__anon641416294e11::AAValueSimplifyCallSiteArgument6466 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6467 : AAValueSimplifyFloating(IRP, A) {}
6468
6469 /// See AbstractAttribute::manifest(...).
manifest__anon641416294e11::AAValueSimplifyCallSiteArgument6470 ChangeStatus manifest(Attributor &A) override {
6471 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6472 // TODO: We should avoid simplification duplication to begin with.
6473 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6474 IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
6475 if (FloatAA && FloatAA->getState().isValidState())
6476 return Changed;
6477
6478 if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
6479 Use &U = cast<CallBase>(&getAnchorValue())
6480 ->getArgOperandUse(getCallSiteArgNo());
6481 if (A.changeUseAfterManifest(U, *NewV))
6482 Changed = ChangeStatus::CHANGED;
6483 }
6484
6485 return Changed | AAValueSimplify::manifest(A);
6486 }
6487
trackStatistics__anon641416294e11::AAValueSimplifyCallSiteArgument6488 void trackStatistics() const override {
6489 STATS_DECLTRACK_CSARG_ATTR(value_simplify)
6490 }
6491 };
6492 } // namespace
6493
6494 /// ----------------------- Heap-To-Stack Conversion ---------------------------
6495 namespace {
6496 struct AAHeapToStackFunction final : public AAHeapToStack {
6497
6498 struct AllocationInfo {
6499 /// The call that allocates the memory.
6500 CallBase *const CB;
6501
6502 /// The library function id for the allocation.
6503 LibFunc LibraryFunctionId = NotLibFunc;
6504
6505 /// The status wrt. a rewrite.
6506 enum {
6507 STACK_DUE_TO_USE,
6508 STACK_DUE_TO_FREE,
6509 INVALID,
6510 } Status = STACK_DUE_TO_USE;
6511
6512 /// Flag to indicate if we encountered a use that might free this allocation
6513 /// but which is not in the deallocation infos.
6514 bool HasPotentiallyFreeingUnknownUses = false;
6515
6516 /// Flag to indicate that we should place the new alloca in the function
6517 /// entry block rather than where the call site (CB) is.
6518 bool MoveAllocaIntoEntry = true;
6519
6520 /// The set of free calls that use this allocation.
6521 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6522 };
6523
6524 struct DeallocationInfo {
6525 /// The call that deallocates the memory.
6526 CallBase *const CB;
6527 /// The value freed by the call.
6528 Value *FreedOp;
6529
6530 /// Flag to indicate if we don't know all objects this deallocation might
6531 /// free.
6532 bool MightFreeUnknownObjects = false;
6533
6534 /// The set of allocation calls that are potentially freed.
6535 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6536 };
6537
AAHeapToStackFunction__anon641416295211::AAHeapToStackFunction6538 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6539 : AAHeapToStack(IRP, A) {}
6540
~AAHeapToStackFunction__anon641416295211::AAHeapToStackFunction6541 ~AAHeapToStackFunction() {
6542 // Ensure we call the destructor so we release any memory allocated in the
6543 // sets.
6544 for (auto &It : AllocationInfos)
6545 It.second->~AllocationInfo();
6546 for (auto &It : DeallocationInfos)
6547 It.second->~DeallocationInfo();
6548 }
6549
initialize__anon641416295211::AAHeapToStackFunction6550 void initialize(Attributor &A) override {
6551 AAHeapToStack::initialize(A);
6552
6553 const Function *F = getAnchorScope();
6554 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6555
6556 auto AllocationIdentifierCB = [&](Instruction &I) {
6557 CallBase *CB = dyn_cast<CallBase>(&I);
6558 if (!CB)
6559 return true;
6560 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6561 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
6562 return true;
6563 }
6564 // To do heap to stack, we need to know that the allocation itself is
6565 // removable once uses are rewritten, and that we can initialize the
6566 // alloca to the same pattern as the original allocation result.
6567 if (isRemovableAlloc(CB, TLI)) {
6568 auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
6569 if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
6570 AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
6571 AllocationInfos[CB] = AI;
6572 if (TLI)
6573 TLI->getLibFunc(*CB, AI->LibraryFunctionId);
6574 }
6575 }
6576 return true;
6577 };
6578
6579 bool UsedAssumedInformation = false;
6580 bool Success = A.checkForAllCallLikeInstructions(
6581 AllocationIdentifierCB, *this, UsedAssumedInformation,
6582 /* CheckBBLivenessOnly */ false,
6583 /* CheckPotentiallyDead */ true);
6584 (void)Success;
6585 assert(Success && "Did not expect the call base visit callback to fail!");
6586
6587 Attributor::SimplifictionCallbackTy SCB =
6588 [](const IRPosition &, const AbstractAttribute *,
6589 bool &) -> std::optional<Value *> { return nullptr; };
6590 for (const auto &It : AllocationInfos)
6591 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6592 SCB);
6593 for (const auto &It : DeallocationInfos)
6594 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6595 SCB);
6596 }
6597
getAsStr__anon641416295211::AAHeapToStackFunction6598 const std::string getAsStr() const override {
6599 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6600 for (const auto &It : AllocationInfos) {
6601 if (It.second->Status == AllocationInfo::INVALID)
6602 ++NumInvalidMallocs;
6603 else
6604 ++NumH2SMallocs;
6605 }
6606 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
6607 std::to_string(NumInvalidMallocs);
6608 }
6609
6610 /// See AbstractAttribute::trackStatistics().
trackStatistics__anon641416295211::AAHeapToStackFunction6611 void trackStatistics() const override {
6612 STATS_DECL(
6613 MallocCalls, Function,
6614 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6615 for (const auto &It : AllocationInfos)
6616 if (It.second->Status != AllocationInfo::INVALID)
6617 ++BUILD_STAT_NAME(MallocCalls, Function);
6618 }
6619
isAssumedHeapToStack__anon641416295211::AAHeapToStackFunction6620 bool isAssumedHeapToStack(const CallBase &CB) const override {
6621 if (isValidState())
6622 if (AllocationInfo *AI =
6623 AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
6624 return AI->Status != AllocationInfo::INVALID;
6625 return false;
6626 }
6627
isAssumedHeapToStackRemovedFree__anon641416295211::AAHeapToStackFunction6628 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6629 if (!isValidState())
6630 return false;
6631
6632 for (const auto &It : AllocationInfos) {
6633 AllocationInfo &AI = *It.second;
6634 if (AI.Status == AllocationInfo::INVALID)
6635 continue;
6636
6637 if (AI.PotentialFreeCalls.count(&CB))
6638 return true;
6639 }
6640
6641 return false;
6642 }
6643
manifest__anon641416295211::AAHeapToStackFunction6644 ChangeStatus manifest(Attributor &A) override {
6645 assert(getState().isValidState() &&
6646 "Attempted to manifest an invalid state!");
6647
6648 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6649 Function *F = getAnchorScope();
6650 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6651
6652 for (auto &It : AllocationInfos) {
6653 AllocationInfo &AI = *It.second;
6654 if (AI.Status == AllocationInfo::INVALID)
6655 continue;
6656
6657 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6658 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
6659 A.deleteAfterManifest(*FreeCall);
6660 HasChanged = ChangeStatus::CHANGED;
6661 }
6662
6663 LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB
6664 << "\n");
6665
6666 auto Remark = [&](OptimizationRemark OR) {
6667 LibFunc IsAllocShared;
6668 if (TLI->getLibFunc(*AI.CB, IsAllocShared))
6669 if (IsAllocShared == LibFunc___kmpc_alloc_shared)
6670 return OR << "Moving globalized variable to the stack.";
6671 return OR << "Moving memory allocation from the heap to the stack.";
6672 };
6673 if (AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
6674 A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
6675 else
6676 A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);
6677
6678 const DataLayout &DL = A.getInfoCache().getDL();
6679 Value *Size;
6680 std::optional<APInt> SizeAPI = getSize(A, *this, AI);
6681 if (SizeAPI) {
6682 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6683 } else {
6684 LLVMContext &Ctx = AI.CB->getContext();
6685 ObjectSizeOpts Opts;
6686 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts);
6687 SizeOffsetEvalType SizeOffsetPair = Eval.compute(AI.CB);
6688 assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&
6689 cast<ConstantInt>(SizeOffsetPair.second)->isZero());
6690 Size = SizeOffsetPair.first;
6691 }
6692
6693 Instruction *IP =
6694 AI.MoveAllocaIntoEntry ? &F->getEntryBlock().front() : AI.CB;
6695
6696 Align Alignment(1);
6697 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6698 Alignment = std::max(Alignment, *RetAlign);
6699 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
6700 std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
6701 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6702 "Expected an alignment during manifest!");
6703 Alignment =
6704 std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
6705 }
6706
6707 // TODO: Hoist the alloca towards the function entry.
6708 unsigned AS = DL.getAllocaAddrSpace();
6709 Instruction *Alloca =
6710 new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
6711 AI.CB->getName() + ".h2s", IP);
6712
6713 if (Alloca->getType() != AI.CB->getType())
6714 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6715 Alloca, AI.CB->getType(), "malloc_cast", AI.CB);
6716
6717 auto *I8Ty = Type::getInt8Ty(F->getContext());
6718 auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
6719 assert(InitVal &&
6720 "Must be able to materialize initial memory state of allocation");
6721
6722 A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);
6723
6724 if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
6725 auto *NBB = II->getNormalDest();
6726 BranchInst::Create(NBB, AI.CB->getParent());
6727 A.deleteAfterManifest(*AI.CB);
6728 } else {
6729 A.deleteAfterManifest(*AI.CB);
6730 }
6731
6732 // Initialize the alloca with the same value as used by the allocation
6733 // function. We can skip undef as the initial value of an alloc is
6734 // undef, and the memset would simply end up being DSEd.
6735 if (!isa<UndefValue>(InitVal)) {
6736 IRBuilder<> Builder(Alloca->getNextNode());
6737 // TODO: Use alignment above if align!=1
6738 Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
6739 }
6740 HasChanged = ChangeStatus::CHANGED;
6741 }
6742
6743 return HasChanged;
6744 }
6745
getAPInt__anon641416295211::AAHeapToStackFunction6746 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
6747 Value &V) {
6748 bool UsedAssumedInformation = false;
6749 std::optional<Constant *> SimpleV =
6750 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6751 if (!SimpleV)
6752 return APInt(64, 0);
6753 if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
6754 return CI->getValue();
6755 return std::nullopt;
6756 }
6757
getSize__anon641416295211::AAHeapToStackFunction6758 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
6759 AllocationInfo &AI) {
6760 auto Mapper = [&](const Value *V) -> const Value * {
6761 bool UsedAssumedInformation = false;
6762 if (std::optional<Constant *> SimpleV =
6763 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6764 if (*SimpleV)
6765 return *SimpleV;
6766 return V;
6767 };
6768
6769 const Function *F = getAnchorScope();
6770 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6771 return getAllocSize(AI.CB, TLI, Mapper);
6772 }
6773
6774 /// Collection of all malloc-like calls in a function with associated
6775 /// information.
6776 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6777
6778 /// Collection of all free-like calls in a function with associated
6779 /// information.
6780 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6781
6782 ChangeStatus updateImpl(Attributor &A) override;
6783 };
6784
updateImpl(Attributor & A)6785 ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
6786 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6787 const Function *F = getAnchorScope();
6788 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6789
6790 const auto &LivenessAA =
6791 A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);
6792
6793 MustBeExecutedContextExplorer &Explorer =
6794 A.getInfoCache().getMustBeExecutedContextExplorer();
6795
6796 bool StackIsAccessibleByOtherThreads =
6797 A.getInfoCache().stackIsAccessibleByOtherThreads();
6798
6799 LoopInfo *LI =
6800 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6801 std::optional<bool> MayContainIrreducibleControl;
6802 auto IsInLoop = [&](BasicBlock &BB) {
6803 if (&F->getEntryBlock() == &BB)
6804 return false;
6805 if (!MayContainIrreducibleControl.has_value())
6806 MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
6807 if (*MayContainIrreducibleControl)
6808 return true;
6809 if (!LI)
6810 return true;
6811 return LI->getLoopFor(&BB) != nullptr;
6812 };
6813
6814 // Flag to ensure we update our deallocation information at most once per
6815 // updateImpl call and only if we use the free check reasoning.
6816 bool HasUpdatedFrees = false;
6817
6818 auto UpdateFrees = [&]() {
6819 HasUpdatedFrees = true;
6820
6821 for (auto &It : DeallocationInfos) {
6822 DeallocationInfo &DI = *It.second;
6823 // For now we cannot use deallocations that have unknown inputs, skip
6824 // them.
6825 if (DI.MightFreeUnknownObjects)
6826 continue;
6827
6828 // No need to analyze dead calls, ignore them instead.
6829 bool UsedAssumedInformation = false;
6830 if (A.isAssumedDead(*DI.CB, this, &LivenessAA, UsedAssumedInformation,
6831 /* CheckBBLivenessOnly */ true))
6832 continue;
6833
6834 // Use the non-optimistic version to get the freed object.
6835 Value *Obj = getUnderlyingObject(DI.FreedOp);
6836 if (!Obj) {
6837 LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");
6838 DI.MightFreeUnknownObjects = true;
6839 continue;
6840 }
6841
6842 // Free of null and undef can be ignored as no-ops (or UB in the latter
6843 // case).
6844 if (isa<ConstantPointerNull>(Obj) || isa<UndefValue>(Obj))
6845 continue;
6846
6847 CallBase *ObjCB = dyn_cast<CallBase>(Obj);
6848 if (!ObjCB) {
6849 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj
6850 << "\n");
6851 DI.MightFreeUnknownObjects = true;
6852 continue;
6853 }
6854
6855 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
6856 if (!AI) {
6857 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj
6858 << "\n");
6859 DI.MightFreeUnknownObjects = true;
6860 continue;
6861 }
6862
6863 DI.PotentialAllocationCalls.insert(ObjCB);
6864 }
6865 };
6866
6867 auto FreeCheck = [&](AllocationInfo &AI) {
6868 // If the stack is not accessible by other threads, the "must-free" logic
6869 // doesn't apply as the pointer could be shared and needs to be places in
6870 // "shareable" memory.
6871 if (!StackIsAccessibleByOtherThreads) {
6872 auto &NoSyncAA =
6873 A.getAAFor<AANoSync>(*this, getIRPosition(), DepClassTy::OPTIONAL);
6874 if (!NoSyncAA.isAssumedNoSync()) {
6875 LLVM_DEBUG(
6876 dbgs() << "[H2S] found an escaping use, stack is not accessible by "
6877 "other threads and function is not nosync:\n");
6878 return false;
6879 }
6880 }
6881 if (!HasUpdatedFrees)
6882 UpdateFrees();
6883
6884 // TODO: Allow multi exit functions that have different free calls.
6885 if (AI.PotentialFreeCalls.size() != 1) {
6886 LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "
6887 << AI.PotentialFreeCalls.size() << "\n");
6888 return false;
6889 }
6890 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
6891 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
6892 if (!DI) {
6893 LLVM_DEBUG(
6894 dbgs() << "[H2S] unique free call was not known as deallocation call "
6895 << *UniqueFree << "\n");
6896 return false;
6897 }
6898 if (DI->MightFreeUnknownObjects) {
6899 LLVM_DEBUG(
6900 dbgs() << "[H2S] unique free call might free unknown allocations\n");
6901 return false;
6902 }
6903 if (DI->PotentialAllocationCalls.empty())
6904 return true;
6905 if (DI->PotentialAllocationCalls.size() > 1) {
6906 LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "
6907 << DI->PotentialAllocationCalls.size()
6908 << " different allocations\n");
6909 return false;
6910 }
6911 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
6912 LLVM_DEBUG(
6913 dbgs()
6914 << "[H2S] unique free call not known to free this allocation but "
6915 << **DI->PotentialAllocationCalls.begin() << "\n");
6916 return false;
6917 }
6918 Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
6919 if (!Explorer.findInContextOf(UniqueFree, CtxI)) {
6920 LLVM_DEBUG(
6921 dbgs()
6922 << "[H2S] unique free call might not be executed with the allocation "
6923 << *UniqueFree << "\n");
6924 return false;
6925 }
6926 return true;
6927 };
6928
6929 auto UsesCheck = [&](AllocationInfo &AI) {
6930 bool ValidUsesOnly = true;
6931
6932 auto Pred = [&](const Use &U, bool &Follow) -> bool {
6933 Instruction *UserI = cast<Instruction>(U.getUser());
6934 if (isa<LoadInst>(UserI))
6935 return true;
6936 if (auto *SI = dyn_cast<StoreInst>(UserI)) {
6937 if (SI->getValueOperand() == U.get()) {
6938 LLVM_DEBUG(dbgs()
6939 << "[H2S] escaping store to memory: " << *UserI << "\n");
6940 ValidUsesOnly = false;
6941 } else {
6942 // A store into the malloc'ed memory is fine.
6943 }
6944 return true;
6945 }
6946 if (auto *CB = dyn_cast<CallBase>(UserI)) {
6947 if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
6948 return true;
6949 if (DeallocationInfos.count(CB)) {
6950 AI.PotentialFreeCalls.insert(CB);
6951 return true;
6952 }
6953
6954 unsigned ArgNo = CB->getArgOperandNo(&U);
6955
6956 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
6957 *this, IRPosition::callsite_argument(*CB, ArgNo),
6958 DepClassTy::OPTIONAL);
6959
6960 // If a call site argument use is nofree, we are fine.
6961 const auto &ArgNoFreeAA = A.getAAFor<AANoFree>(
6962 *this, IRPosition::callsite_argument(*CB, ArgNo),
6963 DepClassTy::OPTIONAL);
6964
6965 bool MaybeCaptured = !NoCaptureAA.isAssumedNoCapture();
6966 bool MaybeFreed = !ArgNoFreeAA.isAssumedNoFree();
6967 if (MaybeCaptured ||
6968 (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
6969 MaybeFreed)) {
6970 AI.HasPotentiallyFreeingUnknownUses |= MaybeFreed;
6971
6972 // Emit a missed remark if this is missed OpenMP globalization.
6973 auto Remark = [&](OptimizationRemarkMissed ORM) {
6974 return ORM
6975 << "Could not move globalized variable to the stack. "
6976 "Variable is potentially captured in call. Mark "
6977 "parameter as `__attribute__((noescape))` to override.";
6978 };
6979
6980 if (ValidUsesOnly &&
6981 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
6982 A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);
6983
6984 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
6985 ValidUsesOnly = false;
6986 }
6987 return true;
6988 }
6989
6990 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
6991 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
6992 Follow = true;
6993 return true;
6994 }
6995 // Unknown user for which we can not track uses further (in a way that
6996 // makes sense).
6997 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
6998 ValidUsesOnly = false;
6999 return true;
7000 };
7001 if (!A.checkForAllUses(Pred, *this, *AI.CB))
7002 return false;
7003 return ValidUsesOnly;
7004 };
7005
7006 // The actual update starts here. We look at all allocations and depending on
7007 // their status perform the appropriate check(s).
7008 for (auto &It : AllocationInfos) {
7009 AllocationInfo &AI = *It.second;
7010 if (AI.Status == AllocationInfo::INVALID)
7011 continue;
7012
7013 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
7014 std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
7015 if (!APAlign) {
7016 // Can't generate an alloca which respects the required alignment
7017 // on the allocation.
7018 LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB
7019 << "\n");
7020 AI.Status = AllocationInfo::INVALID;
7021 Changed = ChangeStatus::CHANGED;
7022 continue;
7023 }
7024 if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
7025 !APAlign->isPowerOf2()) {
7026 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign
7027 << "\n");
7028 AI.Status = AllocationInfo::INVALID;
7029 Changed = ChangeStatus::CHANGED;
7030 continue;
7031 }
7032 }
7033
7034 std::optional<APInt> Size = getSize(A, *this, AI);
7035 if (MaxHeapToStackSize != -1) {
7036 if (!Size || Size->ugt(MaxHeapToStackSize)) {
7037 LLVM_DEBUG({
7038 if (!Size)
7039 dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";
7040 else
7041 dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "
7042 << MaxHeapToStackSize << "\n";
7043 });
7044
7045 AI.Status = AllocationInfo::INVALID;
7046 Changed = ChangeStatus::CHANGED;
7047 continue;
7048 }
7049 }
7050
7051 switch (AI.Status) {
7052 case AllocationInfo::STACK_DUE_TO_USE:
7053 if (UsesCheck(AI))
7054 break;
7055 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7056 [[fallthrough]];
7057 case AllocationInfo::STACK_DUE_TO_FREE:
7058 if (FreeCheck(AI))
7059 break;
7060 AI.Status = AllocationInfo::INVALID;
7061 Changed = ChangeStatus::CHANGED;
7062 break;
7063 case AllocationInfo::INVALID:
7064 llvm_unreachable("Invalid allocations should never reach this point!");
7065 };
7066
7067 // Check if we still think we can move it into the entry block. If the
7068 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7069 // ignore the potential compilations associated with loops.
7070 bool IsGlobalizedLocal =
7071 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared;
7072 if (AI.MoveAllocaIntoEntry &&
7073 (!Size.has_value() ||
7074 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7075 AI.MoveAllocaIntoEntry = false;
7076 }
7077
7078 return Changed;
7079 }
7080 } // namespace
7081
7082 /// ----------------------- Privatizable Pointers ------------------------------
7083 namespace {
7084 struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
AAPrivatizablePtrImpl__anon641416295e11::AAPrivatizablePtrImpl7085 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7086 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7087
indicatePessimisticFixpoint__anon641416295e11::AAPrivatizablePtrImpl7088 ChangeStatus indicatePessimisticFixpoint() override {
7089 AAPrivatizablePtr::indicatePessimisticFixpoint();
7090 PrivatizableType = nullptr;
7091 return ChangeStatus::CHANGED;
7092 }
7093
7094 /// Identify the type we can chose for a private copy of the underlying
7095 /// argument. None means it is not clear yet, nullptr means there is none.
7096 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7097
7098 /// Return a privatizable type that encloses both T0 and T1.
7099 /// TODO: This is merely a stub for now as we should manage a mapping as well.
combineTypes__anon641416295e11::AAPrivatizablePtrImpl7100 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7101 std::optional<Type *> T1) {
7102 if (!T0)
7103 return T1;
7104 if (!T1)
7105 return T0;
7106 if (T0 == T1)
7107 return T0;
7108 return nullptr;
7109 }
7110
getPrivatizableType__anon641416295e11::AAPrivatizablePtrImpl7111 std::optional<Type *> getPrivatizableType() const override {
7112 return PrivatizableType;
7113 }
7114
getAsStr__anon641416295e11::AAPrivatizablePtrImpl7115 const std::string getAsStr() const override {
7116 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7117 }
7118
7119 protected:
7120 std::optional<Type *> PrivatizableType;
7121 };
7122
7123 // TODO: Do this for call site arguments (probably also other values) as well.
7124
7125 struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
AAPrivatizablePtrArgument__anon641416295e11::AAPrivatizablePtrArgument7126 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7127 : AAPrivatizablePtrImpl(IRP, A) {}
7128
7129 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
identifyPrivatizableType__anon641416295e11::AAPrivatizablePtrArgument7130 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7131 // If this is a byval argument and we know all the call sites (so we can
7132 // rewrite them), there is no need to check them explicitly.
7133 bool UsedAssumedInformation = false;
7134 SmallVector<Attribute, 1> Attrs;
7135 getAttrs({Attribute::ByVal}, Attrs, /* IgnoreSubsumingPositions */ true);
7136 if (!Attrs.empty() &&
7137 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
7138 true, UsedAssumedInformation))
7139 return Attrs[0].getValueAsType();
7140
7141 std::optional<Type *> Ty;
7142 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7143
7144 // Make sure the associated call site argument has the same type at all call
7145 // sites and it is an allocation we know is safe to privatize, for now that
7146 // means we only allow alloca instructions.
7147 // TODO: We can additionally analyze the accesses in the callee to create
7148 // the type from that information instead. That is a little more
7149 // involved and will be done in a follow up patch.
7150 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7151 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7152 // Check if a coresponding argument was found or if it is one not
7153 // associated (which can happen for callback calls).
7154 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7155 return false;
7156
7157 // Check that all call sites agree on a type.
7158 auto &PrivCSArgAA =
7159 A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
7160 std::optional<Type *> CSTy = PrivCSArgAA.getPrivatizableType();
7161
7162 LLVM_DEBUG({
7163 dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
7164 if (CSTy && *CSTy)
7165 (*CSTy)->print(dbgs());
7166 else if (CSTy)
7167 dbgs() << "<nullptr>";
7168 else
7169 dbgs() << "<none>";
7170 });
7171
7172 Ty = combineTypes(Ty, CSTy);
7173
7174 LLVM_DEBUG({
7175 dbgs() << " : New Type: ";
7176 if (Ty && *Ty)
7177 (*Ty)->print(dbgs());
7178 else if (Ty)
7179 dbgs() << "<nullptr>";
7180 else
7181 dbgs() << "<none>";
7182 dbgs() << "\n";
7183 });
7184
7185 return !Ty || *Ty;
7186 };
7187
7188 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7189 UsedAssumedInformation))
7190 return nullptr;
7191 return Ty;
7192 }
7193
7194 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416295e11::AAPrivatizablePtrArgument7195 ChangeStatus updateImpl(Attributor &A) override {
7196 PrivatizableType = identifyPrivatizableType(A);
7197 if (!PrivatizableType)
7198 return ChangeStatus::UNCHANGED;
7199 if (!*PrivatizableType)
7200 return indicatePessimisticFixpoint();
7201
7202 // The dependence is optional so we don't give up once we give up on the
7203 // alignment.
7204 A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
7205 DepClassTy::OPTIONAL);
7206
7207 // Avoid arguments with padding for now.
7208 if (!getIRPosition().hasAttr(Attribute::ByVal) &&
7209 !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
7210 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
7211 return indicatePessimisticFixpoint();
7212 }
7213
7214 // Collect the types that will replace the privatizable type in the function
7215 // signature.
7216 SmallVector<Type *, 16> ReplacementTypes;
7217 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7218
7219 // Verify callee and caller agree on how the promoted argument would be
7220 // passed.
7221 Function &Fn = *getIRPosition().getAnchorScope();
7222 const auto *TTI =
7223 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7224 if (!TTI) {
7225 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
7226 << Fn.getName() << "\n");
7227 return indicatePessimisticFixpoint();
7228 }
7229
7230 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7231 CallBase *CB = ACS.getInstruction();
7232 return TTI->areTypesABICompatible(
7233 CB->getCaller(), CB->getCalledFunction(), ReplacementTypes);
7234 };
7235 bool UsedAssumedInformation = false;
7236 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7237 UsedAssumedInformation)) {
7238 LLVM_DEBUG(
7239 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
7240 << Fn.getName() << "\n");
7241 return indicatePessimisticFixpoint();
7242 }
7243
7244 // Register a rewrite of the argument.
7245 Argument *Arg = getAssociatedArgument();
7246 if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7247 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");
7248 return indicatePessimisticFixpoint();
7249 }
7250
7251 unsigned ArgNo = Arg->getArgNo();
7252
7253 // Helper to check if for the given call site the associated argument is
7254 // passed to a callback where the privatization would be different.
7255 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7256 SmallVector<const Use *, 4> CallbackUses;
7257 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7258 for (const Use *U : CallbackUses) {
7259 AbstractCallSite CBACS(U);
7260 assert(CBACS && CBACS.isCallbackCall());
7261 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7262 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7263
7264 LLVM_DEBUG({
7265 dbgs()
7266 << "[AAPrivatizablePtr] Argument " << *Arg
7267 << "check if can be privatized in the context of its parent ("
7268 << Arg->getParent()->getName()
7269 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7270 "callback ("
7271 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7272 << ")\n[AAPrivatizablePtr] " << CBArg << " : "
7273 << CBACS.getCallArgOperand(CBArg) << " vs "
7274 << CB.getArgOperand(ArgNo) << "\n"
7275 << "[AAPrivatizablePtr] " << CBArg << " : "
7276 << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";
7277 });
7278
7279 if (CBArgNo != int(ArgNo))
7280 continue;
7281 const auto &CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7282 *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
7283 if (CBArgPrivAA.isValidState()) {
7284 auto CBArgPrivTy = CBArgPrivAA.getPrivatizableType();
7285 if (!CBArgPrivTy)
7286 continue;
7287 if (*CBArgPrivTy == PrivatizableType)
7288 continue;
7289 }
7290
7291 LLVM_DEBUG({
7292 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7293 << " cannot be privatized in the context of its parent ("
7294 << Arg->getParent()->getName()
7295 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7296 "callback ("
7297 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7298 << ").\n[AAPrivatizablePtr] for which the argument "
7299 "privatization is not compatible.\n";
7300 });
7301 return false;
7302 }
7303 }
7304 return true;
7305 };
7306
7307 // Helper to check if for the given call site the associated argument is
7308 // passed to a direct call where the privatization would be different.
7309 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7310 CallBase *DC = cast<CallBase>(ACS.getInstruction());
7311 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7312 assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&
7313 "Expected a direct call operand for callback call operand");
7314
7315 LLVM_DEBUG({
7316 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7317 << " check if be privatized in the context of its parent ("
7318 << Arg->getParent()->getName()
7319 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7320 "direct call of ("
7321 << DCArgNo << "@" << DC->getCalledFunction()->getName()
7322 << ").\n";
7323 });
7324
7325 Function *DCCallee = DC->getCalledFunction();
7326 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7327 const auto &DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7328 *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
7329 DepClassTy::REQUIRED);
7330 if (DCArgPrivAA.isValidState()) {
7331 auto DCArgPrivTy = DCArgPrivAA.getPrivatizableType();
7332 if (!DCArgPrivTy)
7333 return true;
7334 if (*DCArgPrivTy == PrivatizableType)
7335 return true;
7336 }
7337 }
7338
7339 LLVM_DEBUG({
7340 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7341 << " cannot be privatized in the context of its parent ("
7342 << Arg->getParent()->getName()
7343 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7344 "direct call of ("
7345 << ACS.getInstruction()->getCalledFunction()->getName()
7346 << ").\n[AAPrivatizablePtr] for which the argument "
7347 "privatization is not compatible.\n";
7348 });
7349 return false;
7350 };
7351
7352 // Helper to check if the associated argument is used at the given abstract
7353 // call site in a way that is incompatible with the privatization assumed
7354 // here.
7355 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7356 if (ACS.isDirectCall())
7357 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7358 if (ACS.isCallbackCall())
7359 return IsCompatiblePrivArgOfDirectCS(ACS);
7360 return false;
7361 };
7362
7363 if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
7364 UsedAssumedInformation))
7365 return indicatePessimisticFixpoint();
7366
7367 return ChangeStatus::UNCHANGED;
7368 }
7369
7370 /// Given a type to private \p PrivType, collect the constituates (which are
7371 /// used) in \p ReplacementTypes.
7372 static void
identifyReplacementTypes__anon641416295e11::AAPrivatizablePtrArgument7373 identifyReplacementTypes(Type *PrivType,
7374 SmallVectorImpl<Type *> &ReplacementTypes) {
7375 // TODO: For now we expand the privatization type to the fullest which can
7376 // lead to dead arguments that need to be removed later.
7377 assert(PrivType && "Expected privatizable type!");
7378
7379 // Traverse the type, extract constituate types on the outermost level.
7380 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7381 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7382 ReplacementTypes.push_back(PrivStructType->getElementType(u));
7383 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7384 ReplacementTypes.append(PrivArrayType->getNumElements(),
7385 PrivArrayType->getElementType());
7386 } else {
7387 ReplacementTypes.push_back(PrivType);
7388 }
7389 }
7390
7391 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7392 /// The values needed are taken from the arguments of \p F starting at
7393 /// position \p ArgNo.
createInitialization__anon641416295e11::AAPrivatizablePtrArgument7394 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7395 unsigned ArgNo, Instruction &IP) {
7396 assert(PrivType && "Expected privatizable type!");
7397
7398 IRBuilder<NoFolder> IRB(&IP);
7399 const DataLayout &DL = F.getParent()->getDataLayout();
7400
7401 // Traverse the type, build GEPs and stores.
7402 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7403 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7404 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7405 Type *PointeeTy = PrivStructType->getElementType(u)->getPointerTo();
7406 Value *Ptr =
7407 constructPointer(PointeeTy, PrivType, &Base,
7408 PrivStructLayout->getElementOffset(u), IRB, DL);
7409 new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
7410 }
7411 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7412 Type *PointeeTy = PrivArrayType->getElementType();
7413 Type *PointeePtrTy = PointeeTy->getPointerTo();
7414 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7415 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7416 Value *Ptr = constructPointer(PointeePtrTy, PrivType, &Base,
7417 u * PointeeTySize, IRB, DL);
7418 new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
7419 }
7420 } else {
7421 new StoreInst(F.getArg(ArgNo), &Base, &IP);
7422 }
7423 }
7424
7425 /// Extract values from \p Base according to the type \p PrivType at the
7426 /// call position \p ACS. The values are appended to \p ReplacementValues.
createReplacementValues__anon641416295e11::AAPrivatizablePtrArgument7427 void createReplacementValues(Align Alignment, Type *PrivType,
7428 AbstractCallSite ACS, Value *Base,
7429 SmallVectorImpl<Value *> &ReplacementValues) {
7430 assert(Base && "Expected base value!");
7431 assert(PrivType && "Expected privatizable type!");
7432 Instruction *IP = ACS.getInstruction();
7433
7434 IRBuilder<NoFolder> IRB(IP);
7435 const DataLayout &DL = IP->getModule()->getDataLayout();
7436
7437 Type *PrivPtrType = PrivType->getPointerTo();
7438 if (Base->getType() != PrivPtrType)
7439 Base = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7440 Base, PrivPtrType, "", ACS.getInstruction());
7441
7442 // Traverse the type, build GEPs and loads.
7443 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7444 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7445 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7446 Type *PointeeTy = PrivStructType->getElementType(u);
7447 Value *Ptr =
7448 constructPointer(PointeeTy->getPointerTo(), PrivType, Base,
7449 PrivStructLayout->getElementOffset(u), IRB, DL);
7450 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
7451 L->setAlignment(Alignment);
7452 ReplacementValues.push_back(L);
7453 }
7454 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7455 Type *PointeeTy = PrivArrayType->getElementType();
7456 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7457 Type *PointeePtrTy = PointeeTy->getPointerTo();
7458 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7459 Value *Ptr = constructPointer(PointeePtrTy, PrivType, Base,
7460 u * PointeeTySize, IRB, DL);
7461 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
7462 L->setAlignment(Alignment);
7463 ReplacementValues.push_back(L);
7464 }
7465 } else {
7466 LoadInst *L = new LoadInst(PrivType, Base, "", IP);
7467 L->setAlignment(Alignment);
7468 ReplacementValues.push_back(L);
7469 }
7470 }
7471
7472 /// See AbstractAttribute::manifest(...)
manifest__anon641416295e11::AAPrivatizablePtrArgument7473 ChangeStatus manifest(Attributor &A) override {
7474 if (!PrivatizableType)
7475 return ChangeStatus::UNCHANGED;
7476 assert(*PrivatizableType && "Expected privatizable type!");
7477
7478 // Collect all tail calls in the function as we cannot allow new allocas to
7479 // escape into tail recursion.
7480 // TODO: Be smarter about new allocas escaping into tail calls.
7481 SmallVector<CallInst *, 16> TailCalls;
7482 bool UsedAssumedInformation = false;
7483 if (!A.checkForAllInstructions(
7484 [&](Instruction &I) {
7485 CallInst &CI = cast<CallInst>(I);
7486 if (CI.isTailCall())
7487 TailCalls.push_back(&CI);
7488 return true;
7489 },
7490 *this, {Instruction::Call}, UsedAssumedInformation))
7491 return ChangeStatus::UNCHANGED;
7492
7493 Argument *Arg = getAssociatedArgument();
7494 // Query AAAlign attribute for alignment of associated argument to
7495 // determine the best alignment of loads.
7496 const auto &AlignAA =
7497 A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
7498
7499 // Callback to repair the associated function. A new alloca is placed at the
7500 // beginning and initialized with the values passed through arguments. The
7501 // new alloca replaces the use of the old pointer argument.
7502 Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB =
7503 [=](const Attributor::ArgumentReplacementInfo &ARI,
7504 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7505 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7506 Instruction *IP = &*EntryBB.getFirstInsertionPt();
7507 const DataLayout &DL = IP->getModule()->getDataLayout();
7508 unsigned AS = DL.getAllocaAddrSpace();
7509 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7510 Arg->getName() + ".priv", IP);
7511 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7512 ArgIt->getArgNo(), *IP);
7513
7514 if (AI->getType() != Arg->getType())
7515 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7516 AI, Arg->getType(), "", IP);
7517 Arg->replaceAllUsesWith(AI);
7518
7519 for (CallInst *CI : TailCalls)
7520 CI->setTailCall(false);
7521 };
7522
7523 // Callback to repair a call site of the associated function. The elements
7524 // of the privatizable type are loaded prior to the call and passed to the
7525 // new function version.
7526 Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB =
7527 [=, &AlignAA](const Attributor::ArgumentReplacementInfo &ARI,
7528 AbstractCallSite ACS,
7529 SmallVectorImpl<Value *> &NewArgOperands) {
7530 // When no alignment is specified for the load instruction,
7531 // natural alignment is assumed.
7532 createReplacementValues(
7533 AlignAA.getAssumedAlign(), *PrivatizableType, ACS,
7534 ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
7535 NewArgOperands);
7536 };
7537
7538 // Collect the types that will replace the privatizable type in the function
7539 // signature.
7540 SmallVector<Type *, 16> ReplacementTypes;
7541 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7542
7543 // Register a rewrite of the argument.
7544 if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7545 std::move(FnRepairCB),
7546 std::move(ACSRepairCB)))
7547 return ChangeStatus::CHANGED;
7548 return ChangeStatus::UNCHANGED;
7549 }
7550
7551 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416295e11::AAPrivatizablePtrArgument7552 void trackStatistics() const override {
7553 STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);
7554 }
7555 };
7556
7557 struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
AAPrivatizablePtrFloating__anon641416295e11::AAPrivatizablePtrFloating7558 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7559 : AAPrivatizablePtrImpl(IRP, A) {}
7560
7561 /// See AbstractAttribute::initialize(...).
initialize__anon641416295e11::AAPrivatizablePtrFloating7562 void initialize(Attributor &A) override {
7563 // TODO: We can privatize more than arguments.
7564 indicatePessimisticFixpoint();
7565 }
7566
updateImpl__anon641416295e11::AAPrivatizablePtrFloating7567 ChangeStatus updateImpl(Attributor &A) override {
7568 llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
7569 "updateImpl will not be called");
7570 }
7571
7572 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
identifyPrivatizableType__anon641416295e11::AAPrivatizablePtrFloating7573 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7574 Value *Obj = getUnderlyingObject(&getAssociatedValue());
7575 if (!Obj) {
7576 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
7577 return nullptr;
7578 }
7579
7580 if (auto *AI = dyn_cast<AllocaInst>(Obj))
7581 if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
7582 if (CI->isOne())
7583 return AI->getAllocatedType();
7584 if (auto *Arg = dyn_cast<Argument>(Obj)) {
7585 auto &PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7586 *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
7587 if (PrivArgAA.isAssumedPrivatizablePtr())
7588 return PrivArgAA.getPrivatizableType();
7589 }
7590
7591 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
7592 "alloca nor privatizable argument: "
7593 << *Obj << "!\n");
7594 return nullptr;
7595 }
7596
7597 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416295e11::AAPrivatizablePtrFloating7598 void trackStatistics() const override {
7599 STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);
7600 }
7601 };
7602
7603 struct AAPrivatizablePtrCallSiteArgument final
7604 : public AAPrivatizablePtrFloating {
AAPrivatizablePtrCallSiteArgument__anon641416295e11::AAPrivatizablePtrCallSiteArgument7605 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7606 : AAPrivatizablePtrFloating(IRP, A) {}
7607
7608 /// See AbstractAttribute::initialize(...).
initialize__anon641416295e11::AAPrivatizablePtrCallSiteArgument7609 void initialize(Attributor &A) override {
7610 if (getIRPosition().hasAttr(Attribute::ByVal))
7611 indicateOptimisticFixpoint();
7612 }
7613
7614 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416295e11::AAPrivatizablePtrCallSiteArgument7615 ChangeStatus updateImpl(Attributor &A) override {
7616 PrivatizableType = identifyPrivatizableType(A);
7617 if (!PrivatizableType)
7618 return ChangeStatus::UNCHANGED;
7619 if (!*PrivatizableType)
7620 return indicatePessimisticFixpoint();
7621
7622 const IRPosition &IRP = getIRPosition();
7623 auto &NoCaptureAA =
7624 A.getAAFor<AANoCapture>(*this, IRP, DepClassTy::REQUIRED);
7625 if (!NoCaptureAA.isAssumedNoCapture()) {
7626 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");
7627 return indicatePessimisticFixpoint();
7628 }
7629
7630 auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, IRP, DepClassTy::REQUIRED);
7631 if (!NoAliasAA.isAssumedNoAlias()) {
7632 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");
7633 return indicatePessimisticFixpoint();
7634 }
7635
7636 bool IsKnown;
7637 if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
7638 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");
7639 return indicatePessimisticFixpoint();
7640 }
7641
7642 return ChangeStatus::UNCHANGED;
7643 }
7644
7645 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416295e11::AAPrivatizablePtrCallSiteArgument7646 void trackStatistics() const override {
7647 STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);
7648 }
7649 };
7650
7651 struct AAPrivatizablePtrCallSiteReturned final
7652 : public AAPrivatizablePtrFloating {
AAPrivatizablePtrCallSiteReturned__anon641416295e11::AAPrivatizablePtrCallSiteReturned7653 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7654 : AAPrivatizablePtrFloating(IRP, A) {}
7655
7656 /// See AbstractAttribute::initialize(...).
initialize__anon641416295e11::AAPrivatizablePtrCallSiteReturned7657 void initialize(Attributor &A) override {
7658 // TODO: We can privatize more than arguments.
7659 indicatePessimisticFixpoint();
7660 }
7661
7662 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416295e11::AAPrivatizablePtrCallSiteReturned7663 void trackStatistics() const override {
7664 STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);
7665 }
7666 };
7667
7668 struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
AAPrivatizablePtrReturned__anon641416295e11::AAPrivatizablePtrReturned7669 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7670 : AAPrivatizablePtrFloating(IRP, A) {}
7671
7672 /// See AbstractAttribute::initialize(...).
initialize__anon641416295e11::AAPrivatizablePtrReturned7673 void initialize(Attributor &A) override {
7674 // TODO: We can privatize more than arguments.
7675 indicatePessimisticFixpoint();
7676 }
7677
7678 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416295e11::AAPrivatizablePtrReturned7679 void trackStatistics() const override {
7680 STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);
7681 }
7682 };
7683 } // namespace
7684
7685 /// -------------------- Memory Behavior Attributes ----------------------------
7686 /// Includes read-none, read-only, and write-only.
7687 /// ----------------------------------------------------------------------------
7688 namespace {
7689 struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
AAMemoryBehaviorImpl__anon641416296911::AAMemoryBehaviorImpl7690 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7691 : AAMemoryBehavior(IRP, A) {}
7692
7693 /// See AbstractAttribute::initialize(...).
initialize__anon641416296911::AAMemoryBehaviorImpl7694 void initialize(Attributor &A) override {
7695 intersectAssumedBits(BEST_STATE);
7696 getKnownStateFromValue(getIRPosition(), getState());
7697 AAMemoryBehavior::initialize(A);
7698 }
7699
7700 /// Return the memory behavior information encoded in the IR for \p IRP.
getKnownStateFromValue__anon641416296911::AAMemoryBehaviorImpl7701 static void getKnownStateFromValue(const IRPosition &IRP,
7702 BitIntegerState &State,
7703 bool IgnoreSubsumingPositions = false) {
7704 SmallVector<Attribute, 2> Attrs;
7705 IRP.getAttrs(AttrKinds, Attrs, IgnoreSubsumingPositions);
7706 for (const Attribute &Attr : Attrs) {
7707 switch (Attr.getKindAsEnum()) {
7708 case Attribute::ReadNone:
7709 State.addKnownBits(NO_ACCESSES);
7710 break;
7711 case Attribute::ReadOnly:
7712 State.addKnownBits(NO_WRITES);
7713 break;
7714 case Attribute::WriteOnly:
7715 State.addKnownBits(NO_READS);
7716 break;
7717 default:
7718 llvm_unreachable("Unexpected attribute!");
7719 }
7720 }
7721
7722 if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
7723 if (!I->mayReadFromMemory())
7724 State.addKnownBits(NO_READS);
7725 if (!I->mayWriteToMemory())
7726 State.addKnownBits(NO_WRITES);
7727 }
7728 }
7729
7730 /// See AbstractAttribute::getDeducedAttributes(...).
getDeducedAttributes__anon641416296911::AAMemoryBehaviorImpl7731 void getDeducedAttributes(LLVMContext &Ctx,
7732 SmallVectorImpl<Attribute> &Attrs) const override {
7733 assert(Attrs.size() == 0);
7734 if (isAssumedReadNone())
7735 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7736 else if (isAssumedReadOnly())
7737 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7738 else if (isAssumedWriteOnly())
7739 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7740 assert(Attrs.size() <= 1);
7741 }
7742
7743 /// See AbstractAttribute::manifest(...).
manifest__anon641416296911::AAMemoryBehaviorImpl7744 ChangeStatus manifest(Attributor &A) override {
7745 if (hasAttr(Attribute::ReadNone, /* IgnoreSubsumingPositions */ true))
7746 return ChangeStatus::UNCHANGED;
7747
7748 const IRPosition &IRP = getIRPosition();
7749
7750 // Check if we would improve the existing attributes first.
7751 SmallVector<Attribute, 4> DeducedAttrs;
7752 getDeducedAttributes(IRP.getAnchorValue().getContext(), DeducedAttrs);
7753 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
7754 return IRP.hasAttr(Attr.getKindAsEnum(),
7755 /* IgnoreSubsumingPositions */ true);
7756 }))
7757 return ChangeStatus::UNCHANGED;
7758
7759 // Clear existing attributes.
7760 IRP.removeAttrs(AttrKinds);
7761
7762 // Use the generic manifest method.
7763 return IRAttribute::manifest(A);
7764 }
7765
7766 /// See AbstractState::getAsStr().
getAsStr__anon641416296911::AAMemoryBehaviorImpl7767 const std::string getAsStr() const override {
7768 if (isAssumedReadNone())
7769 return "readnone";
7770 if (isAssumedReadOnly())
7771 return "readonly";
7772 if (isAssumedWriteOnly())
7773 return "writeonly";
7774 return "may-read/write";
7775 }
7776
7777 /// The set of IR attributes AAMemoryBehavior deals with.
7778 static const Attribute::AttrKind AttrKinds[3];
7779 };
7780
7781 const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7782 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7783
7784 /// Memory behavior attribute for a floating value.
7785 struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
AAMemoryBehaviorFloating__anon641416296911::AAMemoryBehaviorFloating7786 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7787 : AAMemoryBehaviorImpl(IRP, A) {}
7788
7789 /// See AbstractAttribute::updateImpl(...).
7790 ChangeStatus updateImpl(Attributor &A) override;
7791
7792 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296911::AAMemoryBehaviorFloating7793 void trackStatistics() const override {
7794 if (isAssumedReadNone())
7795 STATS_DECLTRACK_FLOATING_ATTR(readnone)
7796 else if (isAssumedReadOnly())
7797 STATS_DECLTRACK_FLOATING_ATTR(readonly)
7798 else if (isAssumedWriteOnly())
7799 STATS_DECLTRACK_FLOATING_ATTR(writeonly)
7800 }
7801
7802 private:
7803 /// Return true if users of \p UserI might access the underlying
7804 /// variable/location described by \p U and should therefore be analyzed.
7805 bool followUsersOfUseIn(Attributor &A, const Use &U,
7806 const Instruction *UserI);
7807
7808 /// Update the state according to the effect of use \p U in \p UserI.
7809 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
7810 };
7811
7812 /// Memory behavior attribute for function argument.
7813 struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
AAMemoryBehaviorArgument__anon641416296911::AAMemoryBehaviorArgument7814 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
7815 : AAMemoryBehaviorFloating(IRP, A) {}
7816
7817 /// See AbstractAttribute::initialize(...).
initialize__anon641416296911::AAMemoryBehaviorArgument7818 void initialize(Attributor &A) override {
7819 intersectAssumedBits(BEST_STATE);
7820 const IRPosition &IRP = getIRPosition();
7821 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
7822 // can query it when we use has/getAttr. That would allow us to reuse the
7823 // initialize of the base class here.
7824 bool HasByVal =
7825 IRP.hasAttr({Attribute::ByVal}, /* IgnoreSubsumingPositions */ true);
7826 getKnownStateFromValue(IRP, getState(),
7827 /* IgnoreSubsumingPositions */ HasByVal);
7828
7829 // Initialize the use vector with all direct uses of the associated value.
7830 Argument *Arg = getAssociatedArgument();
7831 if (!Arg || !A.isFunctionIPOAmendable(*(Arg->getParent())))
7832 indicatePessimisticFixpoint();
7833 }
7834
manifest__anon641416296911::AAMemoryBehaviorArgument7835 ChangeStatus manifest(Attributor &A) override {
7836 // TODO: Pointer arguments are not supported on vectors of pointers yet.
7837 if (!getAssociatedValue().getType()->isPointerTy())
7838 return ChangeStatus::UNCHANGED;
7839
7840 // TODO: From readattrs.ll: "inalloca parameters are always
7841 // considered written"
7842 if (hasAttr({Attribute::InAlloca, Attribute::Preallocated})) {
7843 removeKnownBits(NO_WRITES);
7844 removeAssumedBits(NO_WRITES);
7845 }
7846 return AAMemoryBehaviorFloating::manifest(A);
7847 }
7848
7849 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296911::AAMemoryBehaviorArgument7850 void trackStatistics() const override {
7851 if (isAssumedReadNone())
7852 STATS_DECLTRACK_ARG_ATTR(readnone)
7853 else if (isAssumedReadOnly())
7854 STATS_DECLTRACK_ARG_ATTR(readonly)
7855 else if (isAssumedWriteOnly())
7856 STATS_DECLTRACK_ARG_ATTR(writeonly)
7857 }
7858 };
7859
7860 struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
AAMemoryBehaviorCallSiteArgument__anon641416296911::AAMemoryBehaviorCallSiteArgument7861 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
7862 : AAMemoryBehaviorArgument(IRP, A) {}
7863
7864 /// See AbstractAttribute::initialize(...).
initialize__anon641416296911::AAMemoryBehaviorCallSiteArgument7865 void initialize(Attributor &A) override {
7866 // If we don't have an associated attribute this is either a variadic call
7867 // or an indirect call, either way, nothing to do here.
7868 Argument *Arg = getAssociatedArgument();
7869 if (!Arg) {
7870 indicatePessimisticFixpoint();
7871 return;
7872 }
7873 if (Arg->hasByValAttr()) {
7874 addKnownBits(NO_WRITES);
7875 removeKnownBits(NO_READS);
7876 removeAssumedBits(NO_READS);
7877 }
7878 AAMemoryBehaviorArgument::initialize(A);
7879 if (getAssociatedFunction()->isDeclaration())
7880 indicatePessimisticFixpoint();
7881 }
7882
7883 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416296911::AAMemoryBehaviorCallSiteArgument7884 ChangeStatus updateImpl(Attributor &A) override {
7885 // TODO: Once we have call site specific value information we can provide
7886 // call site specific liveness liveness information and then it makes
7887 // sense to specialize attributes for call sites arguments instead of
7888 // redirecting requests to the callee argument.
7889 Argument *Arg = getAssociatedArgument();
7890 const IRPosition &ArgPos = IRPosition::argument(*Arg);
7891 auto &ArgAA =
7892 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
7893 return clampStateAndIndicateChange(getState(), ArgAA.getState());
7894 }
7895
7896 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296911::AAMemoryBehaviorCallSiteArgument7897 void trackStatistics() const override {
7898 if (isAssumedReadNone())
7899 STATS_DECLTRACK_CSARG_ATTR(readnone)
7900 else if (isAssumedReadOnly())
7901 STATS_DECLTRACK_CSARG_ATTR(readonly)
7902 else if (isAssumedWriteOnly())
7903 STATS_DECLTRACK_CSARG_ATTR(writeonly)
7904 }
7905 };
7906
7907 /// Memory behavior attribute for a call site return position.
7908 struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
AAMemoryBehaviorCallSiteReturned__anon641416296911::AAMemoryBehaviorCallSiteReturned7909 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
7910 : AAMemoryBehaviorFloating(IRP, A) {}
7911
7912 /// See AbstractAttribute::initialize(...).
initialize__anon641416296911::AAMemoryBehaviorCallSiteReturned7913 void initialize(Attributor &A) override {
7914 AAMemoryBehaviorImpl::initialize(A);
7915 Function *F = getAssociatedFunction();
7916 if (!F || F->isDeclaration())
7917 indicatePessimisticFixpoint();
7918 }
7919
7920 /// See AbstractAttribute::manifest(...).
manifest__anon641416296911::AAMemoryBehaviorCallSiteReturned7921 ChangeStatus manifest(Attributor &A) override {
7922 // We do not annotate returned values.
7923 return ChangeStatus::UNCHANGED;
7924 }
7925
7926 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296911::AAMemoryBehaviorCallSiteReturned7927 void trackStatistics() const override {}
7928 };
7929
7930 /// An AA to represent the memory behavior function attributes.
7931 struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
AAMemoryBehaviorFunction__anon641416296911::AAMemoryBehaviorFunction7932 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
7933 : AAMemoryBehaviorImpl(IRP, A) {}
7934
7935 /// See AbstractAttribute::updateImpl(Attributor &A).
7936 ChangeStatus updateImpl(Attributor &A) override;
7937
7938 /// See AbstractAttribute::manifest(...).
manifest__anon641416296911::AAMemoryBehaviorFunction7939 ChangeStatus manifest(Attributor &A) override {
7940 // TODO: It would be better to merge this with AAMemoryLocation, so that
7941 // we could determine read/write per location. This would also have the
7942 // benefit of only one place trying to manifest the memory attribute.
7943 Function &F = cast<Function>(getAnchorValue());
7944 MemoryEffects ME = MemoryEffects::unknown();
7945 if (isAssumedReadNone())
7946 ME = MemoryEffects::none();
7947 else if (isAssumedReadOnly())
7948 ME = MemoryEffects::readOnly();
7949 else if (isAssumedWriteOnly())
7950 ME = MemoryEffects::writeOnly();
7951
7952 // Intersect with existing memory attribute, as we currently deduce the
7953 // location and modref portion separately.
7954 MemoryEffects ExistingME = F.getMemoryEffects();
7955 ME &= ExistingME;
7956 if (ME == ExistingME)
7957 return ChangeStatus::UNCHANGED;
7958
7959 return IRAttributeManifest::manifestAttrs(
7960 A, getIRPosition(), Attribute::getWithMemoryEffects(F.getContext(), ME),
7961 /*ForceReplace*/ true);
7962 }
7963
7964 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296911::AAMemoryBehaviorFunction7965 void trackStatistics() const override {
7966 if (isAssumedReadNone())
7967 STATS_DECLTRACK_FN_ATTR(readnone)
7968 else if (isAssumedReadOnly())
7969 STATS_DECLTRACK_FN_ATTR(readonly)
7970 else if (isAssumedWriteOnly())
7971 STATS_DECLTRACK_FN_ATTR(writeonly)
7972 }
7973 };
7974
7975 /// AAMemoryBehavior attribute for call sites.
7976 struct AAMemoryBehaviorCallSite final : AAMemoryBehaviorImpl {
AAMemoryBehaviorCallSite__anon641416296911::AAMemoryBehaviorCallSite7977 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
7978 : AAMemoryBehaviorImpl(IRP, A) {}
7979
7980 /// See AbstractAttribute::initialize(...).
initialize__anon641416296911::AAMemoryBehaviorCallSite7981 void initialize(Attributor &A) override {
7982 AAMemoryBehaviorImpl::initialize(A);
7983 Function *F = getAssociatedFunction();
7984 if (!F || F->isDeclaration())
7985 indicatePessimisticFixpoint();
7986 }
7987
7988 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416296911::AAMemoryBehaviorCallSite7989 ChangeStatus updateImpl(Attributor &A) override {
7990 // TODO: Once we have call site specific value information we can provide
7991 // call site specific liveness liveness information and then it makes
7992 // sense to specialize attributes for call sites arguments instead of
7993 // redirecting requests to the callee argument.
7994 Function *F = getAssociatedFunction();
7995 const IRPosition &FnPos = IRPosition::function(*F);
7996 auto &FnAA =
7997 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::REQUIRED);
7998 return clampStateAndIndicateChange(getState(), FnAA.getState());
7999 }
8000
8001 /// See AbstractAttribute::manifest(...).
manifest__anon641416296911::AAMemoryBehaviorCallSite8002 ChangeStatus manifest(Attributor &A) override {
8003 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8004 CallBase &CB = cast<CallBase>(getAnchorValue());
8005 MemoryEffects ME = MemoryEffects::unknown();
8006 if (isAssumedReadNone())
8007 ME = MemoryEffects::none();
8008 else if (isAssumedReadOnly())
8009 ME = MemoryEffects::readOnly();
8010 else if (isAssumedWriteOnly())
8011 ME = MemoryEffects::writeOnly();
8012
8013 // Intersect with existing memory attribute, as we currently deduce the
8014 // location and modref portion separately.
8015 MemoryEffects ExistingME = CB.getMemoryEffects();
8016 ME &= ExistingME;
8017 if (ME == ExistingME)
8018 return ChangeStatus::UNCHANGED;
8019
8020 return IRAttributeManifest::manifestAttrs(
8021 A, getIRPosition(),
8022 Attribute::getWithMemoryEffects(CB.getContext(), ME),
8023 /*ForceReplace*/ true);
8024 }
8025
8026 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296911::AAMemoryBehaviorCallSite8027 void trackStatistics() const override {
8028 if (isAssumedReadNone())
8029 STATS_DECLTRACK_CS_ATTR(readnone)
8030 else if (isAssumedReadOnly())
8031 STATS_DECLTRACK_CS_ATTR(readonly)
8032 else if (isAssumedWriteOnly())
8033 STATS_DECLTRACK_CS_ATTR(writeonly)
8034 }
8035 };
8036
updateImpl(Attributor & A)8037 ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8038
8039 // The current assumed state used to determine a change.
8040 auto AssumedState = getAssumed();
8041
8042 auto CheckRWInst = [&](Instruction &I) {
8043 // If the instruction has an own memory behavior state, use it to restrict
8044 // the local state. No further analysis is required as the other memory
8045 // state is as optimistic as it gets.
8046 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8047 const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8048 *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);
8049 intersectAssumedBits(MemBehaviorAA.getAssumed());
8050 return !isAtFixpoint();
8051 }
8052
8053 // Remove access kind modifiers if necessary.
8054 if (I.mayReadFromMemory())
8055 removeAssumedBits(NO_READS);
8056 if (I.mayWriteToMemory())
8057 removeAssumedBits(NO_WRITES);
8058 return !isAtFixpoint();
8059 };
8060
8061 bool UsedAssumedInformation = false;
8062 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8063 UsedAssumedInformation))
8064 return indicatePessimisticFixpoint();
8065
8066 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8067 : ChangeStatus::UNCHANGED;
8068 }
8069
updateImpl(Attributor & A)8070 ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8071
8072 const IRPosition &IRP = getIRPosition();
8073 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8074 AAMemoryBehavior::StateType &S = getState();
8075
8076 // First, check the function scope. We take the known information and we avoid
8077 // work if the assumed information implies the current assumed information for
8078 // this attribute. This is a valid for all but byval arguments.
8079 Argument *Arg = IRP.getAssociatedArgument();
8080 AAMemoryBehavior::base_t FnMemAssumedState =
8081 AAMemoryBehavior::StateType::getWorstState();
8082 if (!Arg || !Arg->hasByValAttr()) {
8083 const auto &FnMemAA =
8084 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8085 FnMemAssumedState = FnMemAA.getAssumed();
8086 S.addKnownBits(FnMemAA.getKnown());
8087 if ((S.getAssumed() & FnMemAA.getAssumed()) == S.getAssumed())
8088 return ChangeStatus::UNCHANGED;
8089 }
8090
8091 // The current assumed state used to determine a change.
8092 auto AssumedState = S.getAssumed();
8093
8094 // Make sure the value is not captured (except through "return"), if
8095 // it is, any information derived would be irrelevant anyway as we cannot
8096 // check the potential aliases introduced by the capture. However, no need
8097 // to fall back to anythign less optimistic than the function state.
8098 const auto &ArgNoCaptureAA =
8099 A.getAAFor<AANoCapture>(*this, IRP, DepClassTy::OPTIONAL);
8100 if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
8101 S.intersectAssumedBits(FnMemAssumedState);
8102 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8103 : ChangeStatus::UNCHANGED;
8104 }
8105
8106 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8107 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8108 Instruction *UserI = cast<Instruction>(U.getUser());
8109 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
8110 << " \n");
8111
8112 // Droppable users, e.g., llvm::assume does not actually perform any action.
8113 if (UserI->isDroppable())
8114 return true;
8115
8116 // Check if the users of UserI should also be visited.
8117 Follow = followUsersOfUseIn(A, U, UserI);
8118
8119 // If UserI might touch memory we analyze the use in detail.
8120 if (UserI->mayReadOrWriteMemory())
8121 analyzeUseIn(A, U, UserI);
8122
8123 return !isAtFixpoint();
8124 };
8125
8126 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8127 return indicatePessimisticFixpoint();
8128
8129 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8130 : ChangeStatus::UNCHANGED;
8131 }
8132
followUsersOfUseIn(Attributor & A,const Use & U,const Instruction * UserI)8133 bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8134 const Instruction *UserI) {
8135 // The loaded value is unrelated to the pointer argument, no need to
8136 // follow the users of the load.
8137 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8138 return false;
8139
8140 // By default we follow all uses assuming UserI might leak information on U,
8141 // we have special handling for call sites operands though.
8142 const auto *CB = dyn_cast<CallBase>(UserI);
8143 if (!CB || !CB->isArgOperand(&U))
8144 return true;
8145
8146 // If the use is a call argument known not to be captured, the users of
8147 // the call do not need to be visited because they have to be unrelated to
8148 // the input. Note that this check is not trivial even though we disallow
8149 // general capturing of the underlying argument. The reason is that the
8150 // call might the argument "through return", which we allow and for which we
8151 // need to check call users.
8152 if (U.get()->getType()->isPointerTy()) {
8153 unsigned ArgNo = CB->getArgOperandNo(&U);
8154 const auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(
8155 *this, IRPosition::callsite_argument(*CB, ArgNo), DepClassTy::OPTIONAL);
8156 return !ArgNoCaptureAA.isAssumedNoCapture();
8157 }
8158
8159 return true;
8160 }
8161
analyzeUseIn(Attributor & A,const Use & U,const Instruction * UserI)8162 void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8163 const Instruction *UserI) {
8164 assert(UserI->mayReadOrWriteMemory());
8165
8166 switch (UserI->getOpcode()) {
8167 default:
8168 // TODO: Handle all atomics and other side-effect operations we know of.
8169 break;
8170 case Instruction::Load:
8171 // Loads cause the NO_READS property to disappear.
8172 removeAssumedBits(NO_READS);
8173 return;
8174
8175 case Instruction::Store:
8176 // Stores cause the NO_WRITES property to disappear if the use is the
8177 // pointer operand. Note that while capturing was taken care of somewhere
8178 // else we need to deal with stores of the value that is not looked through.
8179 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8180 removeAssumedBits(NO_WRITES);
8181 else
8182 indicatePessimisticFixpoint();
8183 return;
8184
8185 case Instruction::Call:
8186 case Instruction::CallBr:
8187 case Instruction::Invoke: {
8188 // For call sites we look at the argument memory behavior attribute (this
8189 // could be recursive!) in order to restrict our own state.
8190 const auto *CB = cast<CallBase>(UserI);
8191
8192 // Give up on operand bundles.
8193 if (CB->isBundleOperand(&U)) {
8194 indicatePessimisticFixpoint();
8195 return;
8196 }
8197
8198 // Calling a function does read the function pointer, maybe write it if the
8199 // function is self-modifying.
8200 if (CB->isCallee(&U)) {
8201 removeAssumedBits(NO_READS);
8202 break;
8203 }
8204
8205 // Adjust the possible access behavior based on the information on the
8206 // argument.
8207 IRPosition Pos;
8208 if (U.get()->getType()->isPointerTy())
8209 Pos = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
8210 else
8211 Pos = IRPosition::callsite_function(*CB);
8212 const auto &MemBehaviorAA =
8213 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8214 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8215 // and at least "known".
8216 intersectAssumedBits(MemBehaviorAA.getAssumed());
8217 return;
8218 }
8219 };
8220
8221 // Generally, look at the "may-properties" and adjust the assumed state if we
8222 // did not trigger special handling before.
8223 if (UserI->mayReadFromMemory())
8224 removeAssumedBits(NO_READS);
8225 if (UserI->mayWriteToMemory())
8226 removeAssumedBits(NO_WRITES);
8227 }
8228 } // namespace
8229
8230 /// -------------------- Memory Locations Attributes ---------------------------
8231 /// Includes read-none, argmemonly, inaccessiblememonly,
8232 /// inaccessiblememorargmemonly
8233 /// ----------------------------------------------------------------------------
8234
getMemoryLocationsAsStr(AAMemoryLocation::MemoryLocationsKind MLK)8235 std::string AAMemoryLocation::getMemoryLocationsAsStr(
8236 AAMemoryLocation::MemoryLocationsKind MLK) {
8237 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8238 return "all memory";
8239 if (MLK == AAMemoryLocation::NO_LOCATIONS)
8240 return "no memory";
8241 std::string S = "memory:";
8242 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8243 S += "stack,";
8244 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8245 S += "constant,";
8246 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_INTERNAL_MEM))
8247 S += "internal global,";
8248 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_EXTERNAL_MEM))
8249 S += "external global,";
8250 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8251 S += "argument,";
8252 if (0 == (MLK & AAMemoryLocation::NO_INACCESSIBLE_MEM))
8253 S += "inaccessible,";
8254 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8255 S += "malloced,";
8256 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8257 S += "unknown,";
8258 S.pop_back();
8259 return S;
8260 }
8261
8262 namespace {
8263 struct AAMemoryLocationImpl : public AAMemoryLocation {
8264
AAMemoryLocationImpl__anon641416296d11::AAMemoryLocationImpl8265 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8266 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8267 AccessKind2Accesses.fill(nullptr);
8268 }
8269
~AAMemoryLocationImpl__anon641416296d11::AAMemoryLocationImpl8270 ~AAMemoryLocationImpl() {
8271 // The AccessSets are allocated via a BumpPtrAllocator, we call
8272 // the destructor manually.
8273 for (AccessSet *AS : AccessKind2Accesses)
8274 if (AS)
8275 AS->~AccessSet();
8276 }
8277
8278 /// See AbstractAttribute::initialize(...).
initialize__anon641416296d11::AAMemoryLocationImpl8279 void initialize(Attributor &A) override {
8280 intersectAssumedBits(BEST_STATE);
8281 getKnownStateFromValue(A, getIRPosition(), getState());
8282 AAMemoryLocation::initialize(A);
8283 }
8284
8285 /// Return the memory behavior information encoded in the IR for \p IRP.
getKnownStateFromValue__anon641416296d11::AAMemoryLocationImpl8286 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8287 BitIntegerState &State,
8288 bool IgnoreSubsumingPositions = false) {
8289 // For internal functions we ignore `argmemonly` and
8290 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8291 // constant propagation. It is unclear if this is the best way but it is
8292 // unlikely this will cause real performance problems. If we are deriving
8293 // attributes for the anchor function we even remove the attribute in
8294 // addition to ignoring it.
8295 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8296 // MemoryEffects::Other as a possible location.
8297 bool UseArgMemOnly = true;
8298 Function *AnchorFn = IRP.getAnchorScope();
8299 if (AnchorFn && A.isRunOn(*AnchorFn))
8300 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8301
8302 SmallVector<Attribute, 2> Attrs;
8303 IRP.getAttrs({Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8304 for (const Attribute &Attr : Attrs) {
8305 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8306 MemoryEffects ME = Attr.getMemoryEffects();
8307 if (ME.doesNotAccessMemory()) {
8308 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8309 continue;
8310 }
8311 if (ME.onlyAccessesInaccessibleMem()) {
8312 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8313 continue;
8314 }
8315 if (ME.onlyAccessesArgPointees()) {
8316 if (UseArgMemOnly)
8317 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8318 else {
8319 // Remove location information, only keep read/write info.
8320 ME = MemoryEffects(ME.getModRef());
8321 IRAttributeManifest::manifestAttrs(
8322 A, IRP,
8323 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(),
8324 ME),
8325 /*ForceReplace*/ true);
8326 }
8327 continue;
8328 }
8329 if (ME.onlyAccessesInaccessibleOrArgMem()) {
8330 if (UseArgMemOnly)
8331 State.addKnownBits(inverseLocation(
8332 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8333 else {
8334 // Remove location information, only keep read/write info.
8335 ME = MemoryEffects(ME.getModRef());
8336 IRAttributeManifest::manifestAttrs(
8337 A, IRP,
8338 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(),
8339 ME),
8340 /*ForceReplace*/ true);
8341 }
8342 continue;
8343 }
8344 }
8345 }
8346
8347 /// See AbstractAttribute::getDeducedAttributes(...).
getDeducedAttributes__anon641416296d11::AAMemoryLocationImpl8348 void getDeducedAttributes(LLVMContext &Ctx,
8349 SmallVectorImpl<Attribute> &Attrs) const override {
8350 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8351 assert(Attrs.size() == 0);
8352 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8353 if (isAssumedReadNone())
8354 Attrs.push_back(
8355 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8356 else if (isAssumedInaccessibleMemOnly())
8357 Attrs.push_back(Attribute::getWithMemoryEffects(
8358 Ctx, MemoryEffects::inaccessibleMemOnly()));
8359 else if (isAssumedArgMemOnly())
8360 Attrs.push_back(
8361 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8362 else if (isAssumedInaccessibleOrArgMemOnly())
8363 Attrs.push_back(Attribute::getWithMemoryEffects(
8364 Ctx, MemoryEffects::inaccessibleOrArgMemOnly()));
8365 }
8366 assert(Attrs.size() <= 1);
8367 }
8368
8369 /// See AbstractAttribute::manifest(...).
manifest__anon641416296d11::AAMemoryLocationImpl8370 ChangeStatus manifest(Attributor &A) override {
8371 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8372 // provide per-location modref information here.
8373 const IRPosition &IRP = getIRPosition();
8374
8375 SmallVector<Attribute, 1> DeducedAttrs;
8376 getDeducedAttributes(IRP.getAnchorValue().getContext(), DeducedAttrs);
8377 if (DeducedAttrs.size() != 1)
8378 return ChangeStatus::UNCHANGED;
8379 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8380
8381 // Intersect with existing memory attribute, as we currently deduce the
8382 // location and modref portion separately.
8383 SmallVector<Attribute, 1> ExistingAttrs;
8384 IRP.getAttrs({Attribute::Memory}, ExistingAttrs,
8385 /* IgnoreSubsumingPositions */ true);
8386 if (ExistingAttrs.size() == 1) {
8387 MemoryEffects ExistingME = ExistingAttrs[0].getMemoryEffects();
8388 ME &= ExistingME;
8389 if (ME == ExistingME)
8390 return ChangeStatus::UNCHANGED;
8391 }
8392
8393 return IRAttributeManifest::manifestAttrs(
8394 A, IRP,
8395 Attribute::getWithMemoryEffects(IRP.getAnchorValue().getContext(), ME),
8396 /*ForceReplace*/ true);
8397 }
8398
8399 /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).
checkForAllAccessesToMemoryKind__anon641416296d11::AAMemoryLocationImpl8400 bool checkForAllAccessesToMemoryKind(
8401 function_ref<bool(const Instruction *, const Value *, AccessKind,
8402 MemoryLocationsKind)>
8403 Pred,
8404 MemoryLocationsKind RequestedMLK) const override {
8405 if (!isValidState())
8406 return false;
8407
8408 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8409 if (AssumedMLK == NO_LOCATIONS)
8410 return true;
8411
8412 unsigned Idx = 0;
8413 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8414 CurMLK *= 2, ++Idx) {
8415 if (CurMLK & RequestedMLK)
8416 continue;
8417
8418 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8419 for (const AccessInfo &AI : *Accesses)
8420 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8421 return false;
8422 }
8423
8424 return true;
8425 }
8426
indicatePessimisticFixpoint__anon641416296d11::AAMemoryLocationImpl8427 ChangeStatus indicatePessimisticFixpoint() override {
8428 // If we give up and indicate a pessimistic fixpoint this instruction will
8429 // become an access for all potential access kinds:
8430 // TODO: Add pointers for argmemonly and globals to improve the results of
8431 // checkForAllAccessesToMemoryKind.
8432 bool Changed = false;
8433 MemoryLocationsKind KnownMLK = getKnown();
8434 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8435 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8436 if (!(CurMLK & KnownMLK))
8437 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8438 getAccessKindFromInst(I));
8439 return AAMemoryLocation::indicatePessimisticFixpoint();
8440 }
8441
8442 protected:
8443 /// Helper struct to tie together an instruction that has a read or write
8444 /// effect with the pointer it accesses (if any).
8445 struct AccessInfo {
8446
8447 /// The instruction that caused the access.
8448 const Instruction *I;
8449
8450 /// The base pointer that is accessed, or null if unknown.
8451 const Value *Ptr;
8452
8453 /// The kind of access (read/write/read+write).
8454 AccessKind Kind;
8455
operator ==__anon641416296d11::AAMemoryLocationImpl::AccessInfo8456 bool operator==(const AccessInfo &RHS) const {
8457 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8458 }
operator ()__anon641416296d11::AAMemoryLocationImpl::AccessInfo8459 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8460 if (LHS.I != RHS.I)
8461 return LHS.I < RHS.I;
8462 if (LHS.Ptr != RHS.Ptr)
8463 return LHS.Ptr < RHS.Ptr;
8464 if (LHS.Kind != RHS.Kind)
8465 return LHS.Kind < RHS.Kind;
8466 return false;
8467 }
8468 };
8469
8470 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8471 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8472 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8473 std::array<AccessSet *, llvm::CTLog2<VALID_STATE>()> AccessKind2Accesses;
8474
8475 /// Categorize the pointer arguments of CB that might access memory in
8476 /// AccessedLoc and update the state and access map accordingly.
8477 void
8478 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8479 AAMemoryLocation::StateType &AccessedLocs,
8480 bool &Changed);
8481
8482 /// Return the kind(s) of location that may be accessed by \p V.
8483 AAMemoryLocation::MemoryLocationsKind
8484 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8485
8486 /// Return the access kind as determined by \p I.
getAccessKindFromInst__anon641416296d11::AAMemoryLocationImpl8487 AccessKind getAccessKindFromInst(const Instruction *I) {
8488 AccessKind AK = READ_WRITE;
8489 if (I) {
8490 AK = I->mayReadFromMemory() ? READ : NONE;
8491 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8492 }
8493 return AK;
8494 }
8495
8496 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8497 /// an access of kind \p AK to a \p MLK memory location with the access
8498 /// pointer \p Ptr.
updateStateAndAccessesMap__anon641416296d11::AAMemoryLocationImpl8499 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8500 MemoryLocationsKind MLK, const Instruction *I,
8501 const Value *Ptr, bool &Changed,
8502 AccessKind AK = READ_WRITE) {
8503
8504 assert(isPowerOf2_32(MLK) && "Expected a single location set!");
8505 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8506 if (!Accesses)
8507 Accesses = new (Allocator) AccessSet();
8508 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8509 State.removeAssumedBits(MLK);
8510 }
8511
8512 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8513 /// arguments, and update the state and access map accordingly.
8514 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8515 AAMemoryLocation::StateType &State, bool &Changed);
8516
8517 /// Used to allocate access sets.
8518 BumpPtrAllocator &Allocator;
8519 };
8520
categorizePtrValue(Attributor & A,const Instruction & I,const Value & Ptr,AAMemoryLocation::StateType & State,bool & Changed)8521 void AAMemoryLocationImpl::categorizePtrValue(
8522 Attributor &A, const Instruction &I, const Value &Ptr,
8523 AAMemoryLocation::StateType &State, bool &Changed) {
8524 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
8525 << Ptr << " ["
8526 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");
8527
8528 auto Pred = [&](Value &Obj) {
8529 // TODO: recognize the TBAA used for constant accesses.
8530 MemoryLocationsKind MLK = NO_LOCATIONS;
8531 if (isa<UndefValue>(&Obj))
8532 return true;
8533 if (isa<Argument>(&Obj)) {
8534 // TODO: For now we do not treat byval arguments as local copies performed
8535 // on the call edge, though, we should. To make that happen we need to
8536 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8537 // would also allow us to mark functions only accessing byval arguments as
8538 // readnone again, arguably their accesses have no effect outside of the
8539 // function, like accesses to allocas.
8540 MLK = NO_ARGUMENT_MEM;
8541 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8542 // Reading constant memory is not treated as a read "effect" by the
8543 // function attr pass so we won't neither. Constants defined by TBAA are
8544 // similar. (We know we do not write it because it is constant.)
8545 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8546 if (GVar->isConstant())
8547 return true;
8548
8549 if (GV->hasLocalLinkage())
8550 MLK = NO_GLOBAL_INTERNAL_MEM;
8551 else
8552 MLK = NO_GLOBAL_EXTERNAL_MEM;
8553 } else if (isa<ConstantPointerNull>(&Obj) &&
8554 !NullPointerIsDefined(getAssociatedFunction(),
8555 Ptr.getType()->getPointerAddressSpace())) {
8556 return true;
8557 } else if (isa<AllocaInst>(&Obj)) {
8558 MLK = NO_LOCAL_MEM;
8559 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8560 const auto &NoAliasAA = A.getAAFor<AANoAlias>(
8561 *this, IRPosition::callsite_returned(*CB), DepClassTy::OPTIONAL);
8562 if (NoAliasAA.isAssumedNoAlias())
8563 MLK = NO_MALLOCED_MEM;
8564 else
8565 MLK = NO_UNKOWN_MEM;
8566 } else {
8567 MLK = NO_UNKOWN_MEM;
8568 }
8569
8570 assert(MLK != NO_LOCATIONS && "No location specified!");
8571 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
8572 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
8573 updateStateAndAccessesMap(getState(), MLK, &I, &Obj, Changed,
8574 getAccessKindFromInst(&I));
8575
8576 return true;
8577 };
8578
8579 const auto &AA = A.getAAFor<AAUnderlyingObjects>(
8580 *this, IRPosition::value(Ptr), DepClassTy::OPTIONAL);
8581 if (!AA.forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8582 LLVM_DEBUG(
8583 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
8584 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8585 getAccessKindFromInst(&I));
8586 return;
8587 }
8588
8589 LLVM_DEBUG(
8590 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
8591 << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
8592 }
8593
categorizeArgumentPointerLocations(Attributor & A,CallBase & CB,AAMemoryLocation::StateType & AccessedLocs,bool & Changed)8594 void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8595 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8596 bool &Changed) {
8597 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8598
8599 // Skip non-pointer arguments.
8600 const Value *ArgOp = CB.getArgOperand(ArgNo);
8601 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8602 continue;
8603
8604 // Skip readnone arguments.
8605 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8606 const auto &ArgOpMemLocationAA =
8607 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8608
8609 if (ArgOpMemLocationAA.isAssumedReadNone())
8610 continue;
8611
8612 // Categorize potentially accessed pointer arguments as if there was an
8613 // access instruction with them as pointer.
8614 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8615 }
8616 }
8617
8618 AAMemoryLocation::MemoryLocationsKind
categorizeAccessedLocations(Attributor & A,Instruction & I,bool & Changed)8619 AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8620 bool &Changed) {
8621 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
8622 << I << "\n");
8623
8624 AAMemoryLocation::StateType AccessedLocs;
8625 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8626
8627 if (auto *CB = dyn_cast<CallBase>(&I)) {
8628
8629 // First check if we assume any memory is access is visible.
8630 const auto &CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8631 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
8632 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
8633 << " [" << CBMemLocationAA << "]\n");
8634
8635 if (CBMemLocationAA.isAssumedReadNone())
8636 return NO_LOCATIONS;
8637
8638 if (CBMemLocationAA.isAssumedInaccessibleMemOnly()) {
8639 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8640 Changed, getAccessKindFromInst(&I));
8641 return AccessedLocs.getAssumed();
8642 }
8643
8644 uint32_t CBAssumedNotAccessedLocs =
8645 CBMemLocationAA.getAssumedNotAccessedLocation();
8646
8647 // Set the argmemonly and global bit as we handle them separately below.
8648 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8649 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8650
8651 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8652 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8653 continue;
8654 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8655 getAccessKindFromInst(&I));
8656 }
8657
8658 // Now handle global memory if it might be accessed. This is slightly tricky
8659 // as NO_GLOBAL_MEM has multiple bits set.
8660 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8661 if (HasGlobalAccesses) {
8662 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8663 AccessKind Kind, MemoryLocationsKind MLK) {
8664 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8665 getAccessKindFromInst(&I));
8666 return true;
8667 };
8668 if (!CBMemLocationAA.checkForAllAccessesToMemoryKind(
8669 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8670 return AccessedLocs.getWorstState();
8671 }
8672
8673 LLVM_DEBUG(
8674 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
8675 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8676
8677 // Now handle argument memory if it might be accessed.
8678 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8679 if (HasArgAccesses)
8680 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8681
8682 LLVM_DEBUG(
8683 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
8684 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8685
8686 return AccessedLocs.getAssumed();
8687 }
8688
8689 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8690 LLVM_DEBUG(
8691 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
8692 << I << " [" << *Ptr << "]\n");
8693 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed);
8694 return AccessedLocs.getAssumed();
8695 }
8696
8697 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
8698 << I << "\n");
8699 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8700 getAccessKindFromInst(&I));
8701 return AccessedLocs.getAssumed();
8702 }
8703
8704 /// An AA to represent the memory behavior function attributes.
8705 struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
AAMemoryLocationFunction__anon641416296d11::AAMemoryLocationFunction8706 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8707 : AAMemoryLocationImpl(IRP, A) {}
8708
8709 /// See AbstractAttribute::updateImpl(Attributor &A).
updateImpl__anon641416296d11::AAMemoryLocationFunction8710 ChangeStatus updateImpl(Attributor &A) override {
8711
8712 const auto &MemBehaviorAA =
8713 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8714 if (MemBehaviorAA.isAssumedReadNone()) {
8715 if (MemBehaviorAA.isKnownReadNone())
8716 return indicateOptimisticFixpoint();
8717 assert(isAssumedReadNone() &&
8718 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8719 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8720 return ChangeStatus::UNCHANGED;
8721 }
8722
8723 // The current assumed state used to determine a change.
8724 auto AssumedState = getAssumed();
8725 bool Changed = false;
8726
8727 auto CheckRWInst = [&](Instruction &I) {
8728 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8729 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
8730 << ": " << getMemoryLocationsAsStr(MLK) << "\n");
8731 removeAssumedBits(inverseLocation(MLK, false, false));
8732 // Stop once only the valid bit set in the *not assumed location*, thus
8733 // once we don't actually exclude any memory locations in the state.
8734 return getAssumedNotAccessedLocation() != VALID_STATE;
8735 };
8736
8737 bool UsedAssumedInformation = false;
8738 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8739 UsedAssumedInformation))
8740 return indicatePessimisticFixpoint();
8741
8742 Changed |= AssumedState != getAssumed();
8743 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8744 }
8745
8746 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296d11::AAMemoryLocationFunction8747 void trackStatistics() const override {
8748 if (isAssumedReadNone())
8749 STATS_DECLTRACK_FN_ATTR(readnone)
8750 else if (isAssumedArgMemOnly())
8751 STATS_DECLTRACK_FN_ATTR(argmemonly)
8752 else if (isAssumedInaccessibleMemOnly())
8753 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
8754 else if (isAssumedInaccessibleOrArgMemOnly())
8755 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
8756 }
8757 };
8758
8759 /// AAMemoryLocation attribute for call sites.
8760 struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
AAMemoryLocationCallSite__anon641416296d11::AAMemoryLocationCallSite8761 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8762 : AAMemoryLocationImpl(IRP, A) {}
8763
8764 /// See AbstractAttribute::initialize(...).
initialize__anon641416296d11::AAMemoryLocationCallSite8765 void initialize(Attributor &A) override {
8766 AAMemoryLocationImpl::initialize(A);
8767 Function *F = getAssociatedFunction();
8768 if (!F || F->isDeclaration())
8769 indicatePessimisticFixpoint();
8770 }
8771
8772 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416296d11::AAMemoryLocationCallSite8773 ChangeStatus updateImpl(Attributor &A) override {
8774 // TODO: Once we have call site specific value information we can provide
8775 // call site specific liveness liveness information and then it makes
8776 // sense to specialize attributes for call sites arguments instead of
8777 // redirecting requests to the callee argument.
8778 Function *F = getAssociatedFunction();
8779 const IRPosition &FnPos = IRPosition::function(*F);
8780 auto &FnAA =
8781 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
8782 bool Changed = false;
8783 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8784 AccessKind Kind, MemoryLocationsKind MLK) {
8785 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
8786 getAccessKindFromInst(I));
8787 return true;
8788 };
8789 if (!FnAA.checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8790 return indicatePessimisticFixpoint();
8791 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8792 }
8793
8794 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416296d11::AAMemoryLocationCallSite8795 void trackStatistics() const override {
8796 if (isAssumedReadNone())
8797 STATS_DECLTRACK_CS_ATTR(readnone)
8798 }
8799 };
8800 } // namespace
8801
8802 /// ------------------ Value Constant Range Attribute -------------------------
8803
8804 namespace {
8805 struct AAValueConstantRangeImpl : AAValueConstantRange {
8806 using StateType = IntegerRangeState;
AAValueConstantRangeImpl__anon641416297211::AAValueConstantRangeImpl8807 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
8808 : AAValueConstantRange(IRP, A) {}
8809
8810 /// See AbstractAttribute::initialize(..).
initialize__anon641416297211::AAValueConstantRangeImpl8811 void initialize(Attributor &A) override {
8812 if (A.hasSimplificationCallback(getIRPosition())) {
8813 indicatePessimisticFixpoint();
8814 return;
8815 }
8816
8817 // Intersect a range given by SCEV.
8818 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
8819
8820 // Intersect a range given by LVI.
8821 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
8822 }
8823
8824 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416297211::AAValueConstantRangeImpl8825 const std::string getAsStr() const override {
8826 std::string Str;
8827 llvm::raw_string_ostream OS(Str);
8828 OS << "range(" << getBitWidth() << ")<";
8829 getKnown().print(OS);
8830 OS << " / ";
8831 getAssumed().print(OS);
8832 OS << ">";
8833 return OS.str();
8834 }
8835
8836 /// Helper function to get a SCEV expr for the associated value at program
8837 /// point \p I.
getSCEV__anon641416297211::AAValueConstantRangeImpl8838 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
8839 if (!getAnchorScope())
8840 return nullptr;
8841
8842 ScalarEvolution *SE =
8843 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8844 *getAnchorScope());
8845
8846 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
8847 *getAnchorScope());
8848
8849 if (!SE || !LI)
8850 return nullptr;
8851
8852 const SCEV *S = SE->getSCEV(&getAssociatedValue());
8853 if (!I)
8854 return S;
8855
8856 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
8857 }
8858
8859 /// Helper function to get a range from SCEV for the associated value at
8860 /// program point \p I.
getConstantRangeFromSCEV__anon641416297211::AAValueConstantRangeImpl8861 ConstantRange getConstantRangeFromSCEV(Attributor &A,
8862 const Instruction *I = nullptr) const {
8863 if (!getAnchorScope())
8864 return getWorstState(getBitWidth());
8865
8866 ScalarEvolution *SE =
8867 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8868 *getAnchorScope());
8869
8870 const SCEV *S = getSCEV(A, I);
8871 if (!SE || !S)
8872 return getWorstState(getBitWidth());
8873
8874 return SE->getUnsignedRange(S);
8875 }
8876
8877 /// Helper function to get a range from LVI for the associated value at
8878 /// program point \p I.
8879 ConstantRange
getConstantRangeFromLVI__anon641416297211::AAValueConstantRangeImpl8880 getConstantRangeFromLVI(Attributor &A,
8881 const Instruction *CtxI = nullptr) const {
8882 if (!getAnchorScope())
8883 return getWorstState(getBitWidth());
8884
8885 LazyValueInfo *LVI =
8886 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
8887 *getAnchorScope());
8888
8889 if (!LVI || !CtxI)
8890 return getWorstState(getBitWidth());
8891 return LVI->getConstantRange(&getAssociatedValue(),
8892 const_cast<Instruction *>(CtxI));
8893 }
8894
8895 /// Return true if \p CtxI is valid for querying outside analyses.
8896 /// This basically makes sure we do not ask intra-procedural analysis
8897 /// about a context in the wrong function or a context that violates
8898 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
8899 /// if the original context of this AA is OK or should be considered invalid.
isValidCtxInstructionForOutsideAnalysis__anon641416297211::AAValueConstantRangeImpl8900 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
8901 const Instruction *CtxI,
8902 bool AllowAACtxI) const {
8903 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
8904 return false;
8905
8906 // Our context might be in a different function, neither intra-procedural
8907 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
8908 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
8909 return false;
8910
8911 // If the context is not dominated by the value there are paths to the
8912 // context that do not define the value. This cannot be handled by
8913 // LazyValueInfo so we need to bail.
8914 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
8915 InformationCache &InfoCache = A.getInfoCache();
8916 const DominatorTree *DT =
8917 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
8918 *I->getFunction());
8919 return DT && DT->dominates(I, CtxI);
8920 }
8921
8922 return true;
8923 }
8924
8925 /// See AAValueConstantRange::getKnownConstantRange(..).
8926 ConstantRange
getKnownConstantRange__anon641416297211::AAValueConstantRangeImpl8927 getKnownConstantRange(Attributor &A,
8928 const Instruction *CtxI = nullptr) const override {
8929 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
8930 /* AllowAACtxI */ false))
8931 return getKnown();
8932
8933 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
8934 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
8935 return getKnown().intersectWith(SCEVR).intersectWith(LVIR);
8936 }
8937
8938 /// See AAValueConstantRange::getAssumedConstantRange(..).
8939 ConstantRange
getAssumedConstantRange__anon641416297211::AAValueConstantRangeImpl8940 getAssumedConstantRange(Attributor &A,
8941 const Instruction *CtxI = nullptr) const override {
8942 // TODO: Make SCEV use Attributor assumption.
8943 // We may be able to bound a variable range via assumptions in
8944 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
8945 // evolve to x^2 + x, then we can say that y is in [2, 12].
8946 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
8947 /* AllowAACtxI */ false))
8948 return getAssumed();
8949
8950 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
8951 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
8952 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
8953 }
8954
8955 /// Helper function to create MDNode for range metadata.
8956 static MDNode *
getMDNodeForConstantRange__anon641416297211::AAValueConstantRangeImpl8957 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
8958 const ConstantRange &AssumedConstantRange) {
8959 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
8960 Ty, AssumedConstantRange.getLower())),
8961 ConstantAsMetadata::get(ConstantInt::get(
8962 Ty, AssumedConstantRange.getUpper()))};
8963 return MDNode::get(Ctx, LowAndHigh);
8964 }
8965
8966 /// Return true if \p Assumed is included in \p KnownRanges.
isBetterRange__anon641416297211::AAValueConstantRangeImpl8967 static bool isBetterRange(const ConstantRange &Assumed, MDNode *KnownRanges) {
8968
8969 if (Assumed.isFullSet())
8970 return false;
8971
8972 if (!KnownRanges)
8973 return true;
8974
8975 // If multiple ranges are annotated in IR, we give up to annotate assumed
8976 // range for now.
8977
8978 // TODO: If there exists a known range which containts assumed range, we
8979 // can say assumed range is better.
8980 if (KnownRanges->getNumOperands() > 2)
8981 return false;
8982
8983 ConstantInt *Lower =
8984 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
8985 ConstantInt *Upper =
8986 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
8987
8988 ConstantRange Known(Lower->getValue(), Upper->getValue());
8989 return Known.contains(Assumed) && Known != Assumed;
8990 }
8991
8992 /// Helper function to set range metadata.
8993 static bool
setRangeMetadataIfisBetterRange__anon641416297211::AAValueConstantRangeImpl8994 setRangeMetadataIfisBetterRange(Instruction *I,
8995 const ConstantRange &AssumedConstantRange) {
8996 auto *OldRangeMD = I->getMetadata(LLVMContext::MD_range);
8997 if (isBetterRange(AssumedConstantRange, OldRangeMD)) {
8998 if (!AssumedConstantRange.isEmptySet()) {
8999 I->setMetadata(LLVMContext::MD_range,
9000 getMDNodeForConstantRange(I->getType(), I->getContext(),
9001 AssumedConstantRange));
9002 return true;
9003 }
9004 }
9005 return false;
9006 }
9007
9008 /// See AbstractAttribute::manifest()
manifest__anon641416297211::AAValueConstantRangeImpl9009 ChangeStatus manifest(Attributor &A) override {
9010 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9011 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9012 assert(!AssumedConstantRange.isFullSet() && "Invalid state");
9013
9014 auto &V = getAssociatedValue();
9015 if (!AssumedConstantRange.isEmptySet() &&
9016 !AssumedConstantRange.isSingleElement()) {
9017 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9018 assert(I == getCtxI() && "Should not annotate an instruction which is "
9019 "not the context instruction");
9020 if (isa<CallInst>(I) || isa<LoadInst>(I))
9021 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9022 Changed = ChangeStatus::CHANGED;
9023 }
9024 }
9025
9026 return Changed;
9027 }
9028 };
9029
9030 struct AAValueConstantRangeArgument final
9031 : AAArgumentFromCallSiteArguments<
9032 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9033 true /* BridgeCallBaseContext */> {
9034 using Base = AAArgumentFromCallSiteArguments<
9035 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9036 true /* BridgeCallBaseContext */>;
AAValueConstantRangeArgument__anon641416297211::AAValueConstantRangeArgument9037 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9038 : Base(IRP, A) {}
9039
9040 /// See AbstractAttribute::initialize(..).
initialize__anon641416297211::AAValueConstantRangeArgument9041 void initialize(Attributor &A) override {
9042 if (!getAnchorScope() || getAnchorScope()->isDeclaration()) {
9043 indicatePessimisticFixpoint();
9044 } else {
9045 Base::initialize(A);
9046 }
9047 }
9048
9049 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297211::AAValueConstantRangeArgument9050 void trackStatistics() const override {
9051 STATS_DECLTRACK_ARG_ATTR(value_range)
9052 }
9053 };
9054
9055 struct AAValueConstantRangeReturned
9056 : AAReturnedFromReturnedValues<AAValueConstantRange,
9057 AAValueConstantRangeImpl,
9058 AAValueConstantRangeImpl::StateType,
9059 /* PropogateCallBaseContext */ true> {
9060 using Base =
9061 AAReturnedFromReturnedValues<AAValueConstantRange,
9062 AAValueConstantRangeImpl,
9063 AAValueConstantRangeImpl::StateType,
9064 /* PropogateCallBaseContext */ true>;
AAValueConstantRangeReturned__anon641416297211::AAValueConstantRangeReturned9065 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9066 : Base(IRP, A) {}
9067
9068 /// See AbstractAttribute::initialize(...).
initialize__anon641416297211::AAValueConstantRangeReturned9069 void initialize(Attributor &A) override {}
9070
9071 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297211::AAValueConstantRangeReturned9072 void trackStatistics() const override {
9073 STATS_DECLTRACK_FNRET_ATTR(value_range)
9074 }
9075 };
9076
9077 struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
AAValueConstantRangeFloating__anon641416297211::AAValueConstantRangeFloating9078 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9079 : AAValueConstantRangeImpl(IRP, A) {}
9080
9081 /// See AbstractAttribute::initialize(...).
initialize__anon641416297211::AAValueConstantRangeFloating9082 void initialize(Attributor &A) override {
9083 AAValueConstantRangeImpl::initialize(A);
9084 if (isAtFixpoint())
9085 return;
9086
9087 Value &V = getAssociatedValue();
9088
9089 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9090 unionAssumed(ConstantRange(C->getValue()));
9091 indicateOptimisticFixpoint();
9092 return;
9093 }
9094
9095 if (isa<UndefValue>(&V)) {
9096 // Collapse the undef state to 0.
9097 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9098 indicateOptimisticFixpoint();
9099 return;
9100 }
9101
9102 if (isa<CallBase>(&V))
9103 return;
9104
9105 if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))
9106 return;
9107
9108 // If it is a load instruction with range metadata, use it.
9109 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9110 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9111 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9112 return;
9113 }
9114
9115 // We can work with PHI and select instruction as we traverse their operands
9116 // during update.
9117 if (isa<SelectInst>(V) || isa<PHINode>(V))
9118 return;
9119
9120 // Otherwise we give up.
9121 indicatePessimisticFixpoint();
9122
9123 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
9124 << getAssociatedValue() << "\n");
9125 }
9126
calculateBinaryOperator__anon641416297211::AAValueConstantRangeFloating9127 bool calculateBinaryOperator(
9128 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9129 const Instruction *CtxI,
9130 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9131 Value *LHS = BinOp->getOperand(0);
9132 Value *RHS = BinOp->getOperand(1);
9133
9134 // Simplify the operands first.
9135 bool UsedAssumedInformation = false;
9136 const auto &SimplifiedLHS = A.getAssumedSimplified(
9137 IRPosition::value(*LHS, getCallBaseContext()), *this,
9138 UsedAssumedInformation, AA::Interprocedural);
9139 if (!SimplifiedLHS.has_value())
9140 return true;
9141 if (!*SimplifiedLHS)
9142 return false;
9143 LHS = *SimplifiedLHS;
9144
9145 const auto &SimplifiedRHS = A.getAssumedSimplified(
9146 IRPosition::value(*RHS, getCallBaseContext()), *this,
9147 UsedAssumedInformation, AA::Interprocedural);
9148 if (!SimplifiedRHS.has_value())
9149 return true;
9150 if (!*SimplifiedRHS)
9151 return false;
9152 RHS = *SimplifiedRHS;
9153
9154 // TODO: Allow non integers as well.
9155 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9156 return false;
9157
9158 auto &LHSAA = A.getAAFor<AAValueConstantRange>(
9159 *this, IRPosition::value(*LHS, getCallBaseContext()),
9160 DepClassTy::REQUIRED);
9161 QuerriedAAs.push_back(&LHSAA);
9162 auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI);
9163
9164 auto &RHSAA = A.getAAFor<AAValueConstantRange>(
9165 *this, IRPosition::value(*RHS, getCallBaseContext()),
9166 DepClassTy::REQUIRED);
9167 QuerriedAAs.push_back(&RHSAA);
9168 auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI);
9169
9170 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9171
9172 T.unionAssumed(AssumedRange);
9173
9174 // TODO: Track a known state too.
9175
9176 return T.isValidState();
9177 }
9178
calculateCastInst__anon641416297211::AAValueConstantRangeFloating9179 bool calculateCastInst(
9180 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9181 const Instruction *CtxI,
9182 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9183 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
9184 // TODO: Allow non integers as well.
9185 Value *OpV = CastI->getOperand(0);
9186
9187 // Simplify the operand first.
9188 bool UsedAssumedInformation = false;
9189 const auto &SimplifiedOpV = A.getAssumedSimplified(
9190 IRPosition::value(*OpV, getCallBaseContext()), *this,
9191 UsedAssumedInformation, AA::Interprocedural);
9192 if (!SimplifiedOpV.has_value())
9193 return true;
9194 if (!*SimplifiedOpV)
9195 return false;
9196 OpV = *SimplifiedOpV;
9197
9198 if (!OpV->getType()->isIntegerTy())
9199 return false;
9200
9201 auto &OpAA = A.getAAFor<AAValueConstantRange>(
9202 *this, IRPosition::value(*OpV, getCallBaseContext()),
9203 DepClassTy::REQUIRED);
9204 QuerriedAAs.push_back(&OpAA);
9205 T.unionAssumed(
9206 OpAA.getAssumed().castOp(CastI->getOpcode(), getState().getBitWidth()));
9207 return T.isValidState();
9208 }
9209
9210 bool
calculateCmpInst__anon641416297211::AAValueConstantRangeFloating9211 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9212 const Instruction *CtxI,
9213 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9214 Value *LHS = CmpI->getOperand(0);
9215 Value *RHS = CmpI->getOperand(1);
9216
9217 // Simplify the operands first.
9218 bool UsedAssumedInformation = false;
9219 const auto &SimplifiedLHS = A.getAssumedSimplified(
9220 IRPosition::value(*LHS, getCallBaseContext()), *this,
9221 UsedAssumedInformation, AA::Interprocedural);
9222 if (!SimplifiedLHS.has_value())
9223 return true;
9224 if (!*SimplifiedLHS)
9225 return false;
9226 LHS = *SimplifiedLHS;
9227
9228 const auto &SimplifiedRHS = A.getAssumedSimplified(
9229 IRPosition::value(*RHS, getCallBaseContext()), *this,
9230 UsedAssumedInformation, AA::Interprocedural);
9231 if (!SimplifiedRHS.has_value())
9232 return true;
9233 if (!*SimplifiedRHS)
9234 return false;
9235 RHS = *SimplifiedRHS;
9236
9237 // TODO: Allow non integers as well.
9238 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9239 return false;
9240
9241 auto &LHSAA = A.getAAFor<AAValueConstantRange>(
9242 *this, IRPosition::value(*LHS, getCallBaseContext()),
9243 DepClassTy::REQUIRED);
9244 QuerriedAAs.push_back(&LHSAA);
9245 auto &RHSAA = A.getAAFor<AAValueConstantRange>(
9246 *this, IRPosition::value(*RHS, getCallBaseContext()),
9247 DepClassTy::REQUIRED);
9248 QuerriedAAs.push_back(&RHSAA);
9249 auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI);
9250 auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI);
9251
9252 // If one of them is empty set, we can't decide.
9253 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9254 return true;
9255
9256 bool MustTrue = false, MustFalse = false;
9257
9258 auto AllowedRegion =
9259 ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange);
9260
9261 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9262 MustFalse = true;
9263
9264 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9265 MustTrue = true;
9266
9267 assert((!MustTrue || !MustFalse) &&
9268 "Either MustTrue or MustFalse should be false!");
9269
9270 if (MustTrue)
9271 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9272 else if (MustFalse)
9273 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9274 else
9275 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9276
9277 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " " << LHSAA
9278 << " " << RHSAA << "\n");
9279
9280 // TODO: Track a known state too.
9281 return T.isValidState();
9282 }
9283
9284 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297211::AAValueConstantRangeFloating9285 ChangeStatus updateImpl(Attributor &A) override {
9286
9287 IntegerRangeState T(getBitWidth());
9288 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9289 Instruction *I = dyn_cast<Instruction>(&V);
9290 if (!I || isa<CallBase>(I)) {
9291
9292 // Simplify the operand first.
9293 bool UsedAssumedInformation = false;
9294 const auto &SimplifiedOpV = A.getAssumedSimplified(
9295 IRPosition::value(V, getCallBaseContext()), *this,
9296 UsedAssumedInformation, AA::Interprocedural);
9297 if (!SimplifiedOpV.has_value())
9298 return true;
9299 if (!*SimplifiedOpV)
9300 return false;
9301 Value *VPtr = *SimplifiedOpV;
9302
9303 // If the value is not instruction, we query AA to Attributor.
9304 const auto &AA = A.getAAFor<AAValueConstantRange>(
9305 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9306 DepClassTy::REQUIRED);
9307
9308 // Clamp operator is not used to utilize a program point CtxI.
9309 T.unionAssumed(AA.getAssumedConstantRange(A, CtxI));
9310
9311 return T.isValidState();
9312 }
9313
9314 SmallVector<const AAValueConstantRange *, 4> QuerriedAAs;
9315 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9316 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9317 return false;
9318 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9319 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9320 return false;
9321 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9322 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9323 return false;
9324 } else {
9325 // Give up with other instructions.
9326 // TODO: Add other instructions
9327
9328 T.indicatePessimisticFixpoint();
9329 return false;
9330 }
9331
9332 // Catch circular reasoning in a pessimistic way for now.
9333 // TODO: Check how the range evolves and if we stripped anything, see also
9334 // AADereferenceable or AAAlign for similar situations.
9335 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9336 if (QueriedAA != this)
9337 continue;
9338 // If we are in a stady state we do not need to worry.
9339 if (T.getAssumed() == getState().getAssumed())
9340 continue;
9341 T.indicatePessimisticFixpoint();
9342 }
9343
9344 return T.isValidState();
9345 };
9346
9347 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9348 return indicatePessimisticFixpoint();
9349
9350 // Ensure that long def-use chains can't cause circular reasoning either by
9351 // introducing a cutoff below.
9352 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9353 return ChangeStatus::UNCHANGED;
9354 if (++NumChanges > MaxNumChanges) {
9355 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
9356 << " but only " << MaxNumChanges
9357 << " are allowed to avoid cyclic reasoning.");
9358 return indicatePessimisticFixpoint();
9359 }
9360 return ChangeStatus::CHANGED;
9361 }
9362
9363 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297211::AAValueConstantRangeFloating9364 void trackStatistics() const override {
9365 STATS_DECLTRACK_FLOATING_ATTR(value_range)
9366 }
9367
9368 /// Tracker to bail after too many widening steps of the constant range.
9369 int NumChanges = 0;
9370
9371 /// Upper bound for the number of allowed changes (=widening steps) for the
9372 /// constant range before we give up.
9373 static constexpr int MaxNumChanges = 5;
9374 };
9375
9376 struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
AAValueConstantRangeFunction__anon641416297211::AAValueConstantRangeFunction9377 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9378 : AAValueConstantRangeImpl(IRP, A) {}
9379
9380 /// See AbstractAttribute::initialize(...).
updateImpl__anon641416297211::AAValueConstantRangeFunction9381 ChangeStatus updateImpl(Attributor &A) override {
9382 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
9383 "not be called");
9384 }
9385
9386 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297211::AAValueConstantRangeFunction9387 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
9388 };
9389
9390 struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
AAValueConstantRangeCallSite__anon641416297211::AAValueConstantRangeCallSite9391 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9392 : AAValueConstantRangeFunction(IRP, A) {}
9393
9394 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297211::AAValueConstantRangeCallSite9395 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
9396 };
9397
9398 struct AAValueConstantRangeCallSiteReturned
9399 : AACallSiteReturnedFromReturned<AAValueConstantRange,
9400 AAValueConstantRangeImpl,
9401 AAValueConstantRangeImpl::StateType,
9402 /* IntroduceCallBaseContext */ true> {
AAValueConstantRangeCallSiteReturned__anon641416297211::AAValueConstantRangeCallSiteReturned9403 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9404 : AACallSiteReturnedFromReturned<AAValueConstantRange,
9405 AAValueConstantRangeImpl,
9406 AAValueConstantRangeImpl::StateType,
9407 /* IntroduceCallBaseContext */ true>(IRP,
9408 A) {
9409 }
9410
9411 /// See AbstractAttribute::initialize(...).
initialize__anon641416297211::AAValueConstantRangeCallSiteReturned9412 void initialize(Attributor &A) override {
9413 // If it is a load instruction with range metadata, use the metadata.
9414 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue()))
9415 if (auto *RangeMD = CI->getMetadata(LLVMContext::MD_range))
9416 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9417
9418 AAValueConstantRangeImpl::initialize(A);
9419 }
9420
9421 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297211::AAValueConstantRangeCallSiteReturned9422 void trackStatistics() const override {
9423 STATS_DECLTRACK_CSRET_ATTR(value_range)
9424 }
9425 };
9426 struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
AAValueConstantRangeCallSiteArgument__anon641416297211::AAValueConstantRangeCallSiteArgument9427 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9428 : AAValueConstantRangeFloating(IRP, A) {}
9429
9430 /// See AbstractAttribute::manifest()
manifest__anon641416297211::AAValueConstantRangeCallSiteArgument9431 ChangeStatus manifest(Attributor &A) override {
9432 return ChangeStatus::UNCHANGED;
9433 }
9434
9435 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297211::AAValueConstantRangeCallSiteArgument9436 void trackStatistics() const override {
9437 STATS_DECLTRACK_CSARG_ATTR(value_range)
9438 }
9439 };
9440 } // namespace
9441
9442 /// ------------------ Potential Values Attribute -------------------------
9443
9444 namespace {
9445 struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9446 using StateType = PotentialConstantIntValuesState;
9447
AAPotentialConstantValuesImpl__anon641416297411::AAPotentialConstantValuesImpl9448 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9449 : AAPotentialConstantValues(IRP, A) {}
9450
9451 /// See AbstractAttribute::initialize(..).
initialize__anon641416297411::AAPotentialConstantValuesImpl9452 void initialize(Attributor &A) override {
9453 if (A.hasSimplificationCallback(getIRPosition()))
9454 indicatePessimisticFixpoint();
9455 else
9456 AAPotentialConstantValues::initialize(A);
9457 }
9458
fillSetWithConstantValues__anon641416297411::AAPotentialConstantValuesImpl9459 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9460 bool &ContainsUndef, bool ForSelf) {
9461 SmallVector<AA::ValueAndContext> Values;
9462 bool UsedAssumedInformation = false;
9463 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9464 UsedAssumedInformation)) {
9465 // Avoid recursion when the caller is computing constant values for this
9466 // IRP itself.
9467 if (ForSelf)
9468 return false;
9469 if (!IRP.getAssociatedType()->isIntegerTy())
9470 return false;
9471 auto &PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9472 *this, IRP, DepClassTy::REQUIRED);
9473 if (!PotentialValuesAA.getState().isValidState())
9474 return false;
9475 ContainsUndef = PotentialValuesAA.getState().undefIsContained();
9476 S = PotentialValuesAA.getState().getAssumedSet();
9477 return true;
9478 }
9479
9480 // Copy all the constant values, except UndefValue. ContainsUndef is true
9481 // iff Values contains only UndefValue instances. If there are other known
9482 // constants, then UndefValue is dropped.
9483 ContainsUndef = false;
9484 for (auto &It : Values) {
9485 if (isa<UndefValue>(It.getValue())) {
9486 ContainsUndef = true;
9487 continue;
9488 }
9489 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9490 if (!CI)
9491 return false;
9492 S.insert(CI->getValue());
9493 }
9494 ContainsUndef &= S.empty();
9495
9496 return true;
9497 }
9498
9499 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416297411::AAPotentialConstantValuesImpl9500 const std::string getAsStr() const override {
9501 std::string Str;
9502 llvm::raw_string_ostream OS(Str);
9503 OS << getState();
9504 return OS.str();
9505 }
9506
9507 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297411::AAPotentialConstantValuesImpl9508 ChangeStatus updateImpl(Attributor &A) override {
9509 return indicatePessimisticFixpoint();
9510 }
9511 };
9512
9513 struct AAPotentialConstantValuesArgument final
9514 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9515 AAPotentialConstantValuesImpl,
9516 PotentialConstantIntValuesState> {
9517 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9518 AAPotentialConstantValuesImpl,
9519 PotentialConstantIntValuesState>;
AAPotentialConstantValuesArgument__anon641416297411::AAPotentialConstantValuesArgument9520 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9521 : Base(IRP, A) {}
9522
9523 /// See AbstractAttribute::initialize(..).
initialize__anon641416297411::AAPotentialConstantValuesArgument9524 void initialize(Attributor &A) override {
9525 if (!getAnchorScope() || getAnchorScope()->isDeclaration()) {
9526 indicatePessimisticFixpoint();
9527 } else {
9528 Base::initialize(A);
9529 }
9530 }
9531
9532 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AAPotentialConstantValuesArgument9533 void trackStatistics() const override {
9534 STATS_DECLTRACK_ARG_ATTR(potential_values)
9535 }
9536 };
9537
9538 struct AAPotentialConstantValuesReturned
9539 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9540 AAPotentialConstantValuesImpl> {
9541 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9542 AAPotentialConstantValuesImpl>;
AAPotentialConstantValuesReturned__anon641416297411::AAPotentialConstantValuesReturned9543 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9544 : Base(IRP, A) {}
9545
9546 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AAPotentialConstantValuesReturned9547 void trackStatistics() const override {
9548 STATS_DECLTRACK_FNRET_ATTR(potential_values)
9549 }
9550 };
9551
9552 struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
AAPotentialConstantValuesFloating__anon641416297411::AAPotentialConstantValuesFloating9553 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9554 : AAPotentialConstantValuesImpl(IRP, A) {}
9555
9556 /// See AbstractAttribute::initialize(..).
initialize__anon641416297411::AAPotentialConstantValuesFloating9557 void initialize(Attributor &A) override {
9558 AAPotentialConstantValuesImpl::initialize(A);
9559 if (isAtFixpoint())
9560 return;
9561
9562 Value &V = getAssociatedValue();
9563
9564 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9565 unionAssumed(C->getValue());
9566 indicateOptimisticFixpoint();
9567 return;
9568 }
9569
9570 if (isa<UndefValue>(&V)) {
9571 unionAssumedWithUndef();
9572 indicateOptimisticFixpoint();
9573 return;
9574 }
9575
9576 if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))
9577 return;
9578
9579 if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))
9580 return;
9581
9582 indicatePessimisticFixpoint();
9583
9584 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
9585 << getAssociatedValue() << "\n");
9586 }
9587
calculateICmpInst__anon641416297411::AAPotentialConstantValuesFloating9588 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9589 const APInt &RHS) {
9590 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9591 }
9592
calculateCastInst__anon641416297411::AAPotentialConstantValuesFloating9593 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9594 uint32_t ResultBitWidth) {
9595 Instruction::CastOps CastOp = CI->getOpcode();
9596 switch (CastOp) {
9597 default:
9598 llvm_unreachable("unsupported or not integer cast");
9599 case Instruction::Trunc:
9600 return Src.trunc(ResultBitWidth);
9601 case Instruction::SExt:
9602 return Src.sext(ResultBitWidth);
9603 case Instruction::ZExt:
9604 return Src.zext(ResultBitWidth);
9605 case Instruction::BitCast:
9606 return Src;
9607 }
9608 }
9609
calculateBinaryOperator__anon641416297411::AAPotentialConstantValuesFloating9610 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9611 const APInt &LHS, const APInt &RHS,
9612 bool &SkipOperation, bool &Unsupported) {
9613 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9614 // Unsupported is set to true when the binary operator is not supported.
9615 // SkipOperation is set to true when UB occur with the given operand pair
9616 // (LHS, RHS).
9617 // TODO: we should look at nsw and nuw keywords to handle operations
9618 // that create poison or undef value.
9619 switch (BinOpcode) {
9620 default:
9621 Unsupported = true;
9622 return LHS;
9623 case Instruction::Add:
9624 return LHS + RHS;
9625 case Instruction::Sub:
9626 return LHS - RHS;
9627 case Instruction::Mul:
9628 return LHS * RHS;
9629 case Instruction::UDiv:
9630 if (RHS.isZero()) {
9631 SkipOperation = true;
9632 return LHS;
9633 }
9634 return LHS.udiv(RHS);
9635 case Instruction::SDiv:
9636 if (RHS.isZero()) {
9637 SkipOperation = true;
9638 return LHS;
9639 }
9640 return LHS.sdiv(RHS);
9641 case Instruction::URem:
9642 if (RHS.isZero()) {
9643 SkipOperation = true;
9644 return LHS;
9645 }
9646 return LHS.urem(RHS);
9647 case Instruction::SRem:
9648 if (RHS.isZero()) {
9649 SkipOperation = true;
9650 return LHS;
9651 }
9652 return LHS.srem(RHS);
9653 case Instruction::Shl:
9654 return LHS.shl(RHS);
9655 case Instruction::LShr:
9656 return LHS.lshr(RHS);
9657 case Instruction::AShr:
9658 return LHS.ashr(RHS);
9659 case Instruction::And:
9660 return LHS & RHS;
9661 case Instruction::Or:
9662 return LHS | RHS;
9663 case Instruction::Xor:
9664 return LHS ^ RHS;
9665 }
9666 }
9667
calculateBinaryOperatorAndTakeUnion__anon641416297411::AAPotentialConstantValuesFloating9668 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9669 const APInt &LHS, const APInt &RHS) {
9670 bool SkipOperation = false;
9671 bool Unsupported = false;
9672 APInt Result =
9673 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9674 if (Unsupported)
9675 return false;
9676 // If SkipOperation is true, we can ignore this operand pair (L, R).
9677 if (!SkipOperation)
9678 unionAssumed(Result);
9679 return isValidState();
9680 }
9681
updateWithICmpInst__anon641416297411::AAPotentialConstantValuesFloating9682 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9683 auto AssumedBefore = getAssumed();
9684 Value *LHS = ICI->getOperand(0);
9685 Value *RHS = ICI->getOperand(1);
9686
9687 bool LHSContainsUndef = false, RHSContainsUndef = false;
9688 SetTy LHSAAPVS, RHSAAPVS;
9689 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9690 LHSContainsUndef, /* ForSelf */ false) ||
9691 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9692 RHSContainsUndef, /* ForSelf */ false))
9693 return indicatePessimisticFixpoint();
9694
9695 // TODO: make use of undef flag to limit potential values aggressively.
9696 bool MaybeTrue = false, MaybeFalse = false;
9697 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
9698 if (LHSContainsUndef && RHSContainsUndef) {
9699 // The result of any comparison between undefs can be soundly replaced
9700 // with undef.
9701 unionAssumedWithUndef();
9702 } else if (LHSContainsUndef) {
9703 for (const APInt &R : RHSAAPVS) {
9704 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9705 MaybeTrue |= CmpResult;
9706 MaybeFalse |= !CmpResult;
9707 if (MaybeTrue & MaybeFalse)
9708 return indicatePessimisticFixpoint();
9709 }
9710 } else if (RHSContainsUndef) {
9711 for (const APInt &L : LHSAAPVS) {
9712 bool CmpResult = calculateICmpInst(ICI, L, Zero);
9713 MaybeTrue |= CmpResult;
9714 MaybeFalse |= !CmpResult;
9715 if (MaybeTrue & MaybeFalse)
9716 return indicatePessimisticFixpoint();
9717 }
9718 } else {
9719 for (const APInt &L : LHSAAPVS) {
9720 for (const APInt &R : RHSAAPVS) {
9721 bool CmpResult = calculateICmpInst(ICI, L, R);
9722 MaybeTrue |= CmpResult;
9723 MaybeFalse |= !CmpResult;
9724 if (MaybeTrue & MaybeFalse)
9725 return indicatePessimisticFixpoint();
9726 }
9727 }
9728 }
9729 if (MaybeTrue)
9730 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
9731 if (MaybeFalse)
9732 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
9733 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9734 : ChangeStatus::CHANGED;
9735 }
9736
updateWithSelectInst__anon641416297411::AAPotentialConstantValuesFloating9737 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
9738 auto AssumedBefore = getAssumed();
9739 Value *LHS = SI->getTrueValue();
9740 Value *RHS = SI->getFalseValue();
9741
9742 bool UsedAssumedInformation = false;
9743 std::optional<Constant *> C = A.getAssumedConstant(
9744 *SI->getCondition(), *this, UsedAssumedInformation);
9745
9746 // Check if we only need one operand.
9747 bool OnlyLeft = false, OnlyRight = false;
9748 if (C && *C && (*C)->isOneValue())
9749 OnlyLeft = true;
9750 else if (C && *C && (*C)->isZeroValue())
9751 OnlyRight = true;
9752
9753 bool LHSContainsUndef = false, RHSContainsUndef = false;
9754 SetTy LHSAAPVS, RHSAAPVS;
9755 if (!OnlyRight &&
9756 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9757 LHSContainsUndef, /* ForSelf */ false))
9758 return indicatePessimisticFixpoint();
9759
9760 if (!OnlyLeft &&
9761 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9762 RHSContainsUndef, /* ForSelf */ false))
9763 return indicatePessimisticFixpoint();
9764
9765 if (OnlyLeft || OnlyRight) {
9766 // select (true/false), lhs, rhs
9767 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9768 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9769
9770 if (Undef)
9771 unionAssumedWithUndef();
9772 else {
9773 for (const auto &It : *OpAA)
9774 unionAssumed(It);
9775 }
9776
9777 } else if (LHSContainsUndef && RHSContainsUndef) {
9778 // select i1 *, undef , undef => undef
9779 unionAssumedWithUndef();
9780 } else {
9781 for (const auto &It : LHSAAPVS)
9782 unionAssumed(It);
9783 for (const auto &It : RHSAAPVS)
9784 unionAssumed(It);
9785 }
9786 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9787 : ChangeStatus::CHANGED;
9788 }
9789
updateWithCastInst__anon641416297411::AAPotentialConstantValuesFloating9790 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
9791 auto AssumedBefore = getAssumed();
9792 if (!CI->isIntegerCast())
9793 return indicatePessimisticFixpoint();
9794 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
9795 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
9796 Value *Src = CI->getOperand(0);
9797
9798 bool SrcContainsUndef = false;
9799 SetTy SrcPVS;
9800 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
9801 SrcContainsUndef, /* ForSelf */ false))
9802 return indicatePessimisticFixpoint();
9803
9804 if (SrcContainsUndef)
9805 unionAssumedWithUndef();
9806 else {
9807 for (const APInt &S : SrcPVS) {
9808 APInt T = calculateCastInst(CI, S, ResultBitWidth);
9809 unionAssumed(T);
9810 }
9811 }
9812 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9813 : ChangeStatus::CHANGED;
9814 }
9815
updateWithBinaryOperator__anon641416297411::AAPotentialConstantValuesFloating9816 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
9817 auto AssumedBefore = getAssumed();
9818 Value *LHS = BinOp->getOperand(0);
9819 Value *RHS = BinOp->getOperand(1);
9820
9821 bool LHSContainsUndef = false, RHSContainsUndef = false;
9822 SetTy LHSAAPVS, RHSAAPVS;
9823 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9824 LHSContainsUndef, /* ForSelf */ false) ||
9825 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9826 RHSContainsUndef, /* ForSelf */ false))
9827 return indicatePessimisticFixpoint();
9828
9829 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
9830
9831 // TODO: make use of undef flag to limit potential values aggressively.
9832 if (LHSContainsUndef && RHSContainsUndef) {
9833 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
9834 return indicatePessimisticFixpoint();
9835 } else if (LHSContainsUndef) {
9836 for (const APInt &R : RHSAAPVS) {
9837 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
9838 return indicatePessimisticFixpoint();
9839 }
9840 } else if (RHSContainsUndef) {
9841 for (const APInt &L : LHSAAPVS) {
9842 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
9843 return indicatePessimisticFixpoint();
9844 }
9845 } else {
9846 for (const APInt &L : LHSAAPVS) {
9847 for (const APInt &R : RHSAAPVS) {
9848 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9849 return indicatePessimisticFixpoint();
9850 }
9851 }
9852 }
9853 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9854 : ChangeStatus::CHANGED;
9855 }
9856
updateWithInstruction__anon641416297411::AAPotentialConstantValuesFloating9857 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
9858 auto AssumedBefore = getAssumed();
9859 SetTy Incoming;
9860 bool ContainsUndef;
9861 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
9862 ContainsUndef, /* ForSelf */ true))
9863 return indicatePessimisticFixpoint();
9864 if (ContainsUndef) {
9865 unionAssumedWithUndef();
9866 } else {
9867 for (const auto &It : Incoming)
9868 unionAssumed(It);
9869 }
9870 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9871 : ChangeStatus::CHANGED;
9872 }
9873
9874 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297411::AAPotentialConstantValuesFloating9875 ChangeStatus updateImpl(Attributor &A) override {
9876 Value &V = getAssociatedValue();
9877 Instruction *I = dyn_cast<Instruction>(&V);
9878
9879 if (auto *ICI = dyn_cast<ICmpInst>(I))
9880 return updateWithICmpInst(A, ICI);
9881
9882 if (auto *SI = dyn_cast<SelectInst>(I))
9883 return updateWithSelectInst(A, SI);
9884
9885 if (auto *CI = dyn_cast<CastInst>(I))
9886 return updateWithCastInst(A, CI);
9887
9888 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
9889 return updateWithBinaryOperator(A, BinOp);
9890
9891 if (isa<PHINode>(I) || isa<LoadInst>(I))
9892 return updateWithInstruction(A, I);
9893
9894 return indicatePessimisticFixpoint();
9895 }
9896
9897 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AAPotentialConstantValuesFloating9898 void trackStatistics() const override {
9899 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
9900 }
9901 };
9902
9903 struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
AAPotentialConstantValuesFunction__anon641416297411::AAPotentialConstantValuesFunction9904 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
9905 : AAPotentialConstantValuesImpl(IRP, A) {}
9906
9907 /// See AbstractAttribute::initialize(...).
updateImpl__anon641416297411::AAPotentialConstantValuesFunction9908 ChangeStatus updateImpl(Attributor &A) override {
9909 llvm_unreachable(
9910 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
9911 "not be called");
9912 }
9913
9914 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AAPotentialConstantValuesFunction9915 void trackStatistics() const override {
9916 STATS_DECLTRACK_FN_ATTR(potential_values)
9917 }
9918 };
9919
9920 struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
AAPotentialConstantValuesCallSite__anon641416297411::AAPotentialConstantValuesCallSite9921 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
9922 : AAPotentialConstantValuesFunction(IRP, A) {}
9923
9924 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AAPotentialConstantValuesCallSite9925 void trackStatistics() const override {
9926 STATS_DECLTRACK_CS_ATTR(potential_values)
9927 }
9928 };
9929
9930 struct AAPotentialConstantValuesCallSiteReturned
9931 : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
9932 AAPotentialConstantValuesImpl> {
AAPotentialConstantValuesCallSiteReturned__anon641416297411::AAPotentialConstantValuesCallSiteReturned9933 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
9934 Attributor &A)
9935 : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
9936 AAPotentialConstantValuesImpl>(IRP, A) {}
9937
9938 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AAPotentialConstantValuesCallSiteReturned9939 void trackStatistics() const override {
9940 STATS_DECLTRACK_CSRET_ATTR(potential_values)
9941 }
9942 };
9943
9944 struct AAPotentialConstantValuesCallSiteArgument
9945 : AAPotentialConstantValuesFloating {
AAPotentialConstantValuesCallSiteArgument__anon641416297411::AAPotentialConstantValuesCallSiteArgument9946 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
9947 Attributor &A)
9948 : AAPotentialConstantValuesFloating(IRP, A) {}
9949
9950 /// See AbstractAttribute::initialize(..).
initialize__anon641416297411::AAPotentialConstantValuesCallSiteArgument9951 void initialize(Attributor &A) override {
9952 AAPotentialConstantValuesImpl::initialize(A);
9953 if (isAtFixpoint())
9954 return;
9955
9956 Value &V = getAssociatedValue();
9957
9958 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9959 unionAssumed(C->getValue());
9960 indicateOptimisticFixpoint();
9961 return;
9962 }
9963
9964 if (isa<UndefValue>(&V)) {
9965 unionAssumedWithUndef();
9966 indicateOptimisticFixpoint();
9967 return;
9968 }
9969 }
9970
9971 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297411::AAPotentialConstantValuesCallSiteArgument9972 ChangeStatus updateImpl(Attributor &A) override {
9973 Value &V = getAssociatedValue();
9974 auto AssumedBefore = getAssumed();
9975 auto &AA = A.getAAFor<AAPotentialConstantValues>(
9976 *this, IRPosition::value(V), DepClassTy::REQUIRED);
9977 const auto &S = AA.getAssumed();
9978 unionAssumed(S);
9979 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9980 : ChangeStatus::CHANGED;
9981 }
9982
9983 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AAPotentialConstantValuesCallSiteArgument9984 void trackStatistics() const override {
9985 STATS_DECLTRACK_CSARG_ATTR(potential_values)
9986 }
9987 };
9988
9989 /// ------------------------ NoUndef Attribute ---------------------------------
9990 struct AANoUndefImpl : AANoUndef {
AANoUndefImpl__anon641416297411::AANoUndefImpl9991 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
9992
9993 /// See AbstractAttribute::initialize(...).
initialize__anon641416297411::AANoUndefImpl9994 void initialize(Attributor &A) override {
9995 if (getIRPosition().hasAttr({Attribute::NoUndef})) {
9996 indicateOptimisticFixpoint();
9997 return;
9998 }
9999 Value &V = getAssociatedValue();
10000 if (isa<UndefValue>(V))
10001 indicatePessimisticFixpoint();
10002 else if (isa<FreezeInst>(V))
10003 indicateOptimisticFixpoint();
10004 else if (getPositionKind() != IRPosition::IRP_RETURNED &&
10005 isGuaranteedNotToBeUndefOrPoison(&V))
10006 indicateOptimisticFixpoint();
10007 else
10008 AANoUndef::initialize(A);
10009 }
10010
10011 /// See followUsesInMBEC
followUseInMBEC__anon641416297411::AANoUndefImpl10012 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10013 AANoUndef::StateType &State) {
10014 const Value *UseV = U->get();
10015 const DominatorTree *DT = nullptr;
10016 AssumptionCache *AC = nullptr;
10017 InformationCache &InfoCache = A.getInfoCache();
10018 if (Function *F = getAnchorScope()) {
10019 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10020 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10021 }
10022 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10023 bool TrackUse = false;
10024 // Track use for instructions which must produce undef or poison bits when
10025 // at least one operand contains such bits.
10026 if (isa<CastInst>(*I) || isa<GetElementPtrInst>(*I))
10027 TrackUse = true;
10028 return TrackUse;
10029 }
10030
10031 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416297411::AANoUndefImpl10032 const std::string getAsStr() const override {
10033 return getAssumed() ? "noundef" : "may-undef-or-poison";
10034 }
10035
manifest__anon641416297411::AANoUndefImpl10036 ChangeStatus manifest(Attributor &A) override {
10037 // We don't manifest noundef attribute for dead positions because the
10038 // associated values with dead positions would be replaced with undef
10039 // values.
10040 bool UsedAssumedInformation = false;
10041 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10042 UsedAssumedInformation))
10043 return ChangeStatus::UNCHANGED;
10044 // A position whose simplified value does not have any value is
10045 // considered to be dead. We don't manifest noundef in such positions for
10046 // the same reason above.
10047 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10048 AA::Interprocedural)
10049 .has_value())
10050 return ChangeStatus::UNCHANGED;
10051 return AANoUndef::manifest(A);
10052 }
10053 };
10054
10055 struct AANoUndefFloating : public AANoUndefImpl {
AANoUndefFloating__anon641416297411::AANoUndefFloating10056 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10057 : AANoUndefImpl(IRP, A) {}
10058
10059 /// See AbstractAttribute::initialize(...).
initialize__anon641416297411::AANoUndefFloating10060 void initialize(Attributor &A) override {
10061 AANoUndefImpl::initialize(A);
10062 if (!getState().isAtFixpoint())
10063 if (Instruction *CtxI = getCtxI())
10064 followUsesInMBEC(*this, A, getState(), *CtxI);
10065 }
10066
10067 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297411::AANoUndefFloating10068 ChangeStatus updateImpl(Attributor &A) override {
10069
10070 SmallVector<AA::ValueAndContext> Values;
10071 bool UsedAssumedInformation = false;
10072 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10073 AA::AnyScope, UsedAssumedInformation)) {
10074 Values.push_back({getAssociatedValue(), getCtxI()});
10075 }
10076
10077 StateType T;
10078 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10079 const auto &AA = A.getAAFor<AANoUndef>(*this, IRPosition::value(V),
10080 DepClassTy::REQUIRED);
10081 if (this == &AA) {
10082 T.indicatePessimisticFixpoint();
10083 } else {
10084 const AANoUndef::StateType &S =
10085 static_cast<const AANoUndef::StateType &>(AA.getState());
10086 T ^= S;
10087 }
10088 return T.isValidState();
10089 };
10090
10091 for (const auto &VAC : Values)
10092 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10093 return indicatePessimisticFixpoint();
10094
10095 return clampStateAndIndicateChange(getState(), T);
10096 }
10097
10098 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AANoUndefFloating10099 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10100 };
10101
10102 struct AANoUndefReturned final
10103 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
AANoUndefReturned__anon641416297411::AANoUndefReturned10104 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10105 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10106
10107 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AANoUndefReturned10108 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10109 };
10110
10111 struct AANoUndefArgument final
10112 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
AANoUndefArgument__anon641416297411::AANoUndefArgument10113 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10114 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10115
10116 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AANoUndefArgument10117 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
10118 };
10119
10120 struct AANoUndefCallSiteArgument final : AANoUndefFloating {
AANoUndefCallSiteArgument__anon641416297411::AANoUndefCallSiteArgument10121 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10122 : AANoUndefFloating(IRP, A) {}
10123
10124 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AANoUndefCallSiteArgument10125 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
10126 };
10127
10128 struct AANoUndefCallSiteReturned final
10129 : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl> {
AANoUndefCallSiteReturned__anon641416297411::AANoUndefCallSiteReturned10130 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10131 : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl>(IRP, A) {}
10132
10133 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297411::AANoUndefCallSiteReturned10134 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
10135 };
10136
10137 struct AACallEdgesImpl : public AACallEdges {
AACallEdgesImpl__anon641416297411::AACallEdgesImpl10138 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10139
getOptimisticEdges__anon641416297411::AACallEdgesImpl10140 const SetVector<Function *> &getOptimisticEdges() const override {
10141 return CalledFunctions;
10142 }
10143
hasUnknownCallee__anon641416297411::AACallEdgesImpl10144 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10145
hasNonAsmUnknownCallee__anon641416297411::AACallEdgesImpl10146 bool hasNonAsmUnknownCallee() const override {
10147 return HasUnknownCalleeNonAsm;
10148 }
10149
getAsStr__anon641416297411::AACallEdgesImpl10150 const std::string getAsStr() const override {
10151 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10152 std::to_string(CalledFunctions.size()) + "]";
10153 }
10154
trackStatistics__anon641416297411::AACallEdgesImpl10155 void trackStatistics() const override {}
10156
10157 protected:
addCalledFunction__anon641416297411::AACallEdgesImpl10158 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10159 if (CalledFunctions.insert(Fn)) {
10160 Change = ChangeStatus::CHANGED;
10161 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
10162 << "\n");
10163 }
10164 }
10165
setHasUnknownCallee__anon641416297411::AACallEdgesImpl10166 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10167 if (!HasUnknownCallee)
10168 Change = ChangeStatus::CHANGED;
10169 if (NonAsm && !HasUnknownCalleeNonAsm)
10170 Change = ChangeStatus::CHANGED;
10171 HasUnknownCalleeNonAsm |= NonAsm;
10172 HasUnknownCallee = true;
10173 }
10174
10175 private:
10176 /// Optimistic set of functions that might be called by this position.
10177 SetVector<Function *> CalledFunctions;
10178
10179 /// Is there any call with a unknown callee.
10180 bool HasUnknownCallee = false;
10181
10182 /// Is there any call with a unknown callee, excluding any inline asm.
10183 bool HasUnknownCalleeNonAsm = false;
10184 };
10185
10186 struct AACallEdgesCallSite : public AACallEdgesImpl {
AACallEdgesCallSite__anon641416297411::AACallEdgesCallSite10187 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10188 : AACallEdgesImpl(IRP, A) {}
10189 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297411::AACallEdgesCallSite10190 ChangeStatus updateImpl(Attributor &A) override {
10191 ChangeStatus Change = ChangeStatus::UNCHANGED;
10192
10193 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10194 if (Function *Fn = dyn_cast<Function>(&V)) {
10195 addCalledFunction(Fn, Change);
10196 } else {
10197 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
10198 setHasUnknownCallee(true, Change);
10199 }
10200
10201 // Explore all values.
10202 return true;
10203 };
10204
10205 SmallVector<AA::ValueAndContext> Values;
10206 // Process any value that we might call.
10207 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10208 bool UsedAssumedInformation = false;
10209 Values.clear();
10210 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10211 AA::AnyScope, UsedAssumedInformation)) {
10212 Values.push_back({*V, CtxI});
10213 }
10214 for (auto &VAC : Values)
10215 VisitValue(*VAC.getValue(), VAC.getCtxI());
10216 };
10217
10218 CallBase *CB = cast<CallBase>(getCtxI());
10219
10220 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10221 if (IA->hasSideEffects() &&
10222 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10223 !hasAssumption(*CB, "ompx_no_call_asm")) {
10224 setHasUnknownCallee(false, Change);
10225 }
10226 return Change;
10227 }
10228
10229 // Process callee metadata if available.
10230 if (auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees)) {
10231 for (const auto &Op : MD->operands()) {
10232 Function *Callee = mdconst::dyn_extract_or_null<Function>(Op);
10233 if (Callee)
10234 addCalledFunction(Callee, Change);
10235 }
10236 return Change;
10237 }
10238
10239 // The most simple case.
10240 ProcessCalledOperand(CB->getCalledOperand(), CB);
10241
10242 // Process callback functions.
10243 SmallVector<const Use *, 4u> CallbackUses;
10244 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10245 for (const Use *U : CallbackUses)
10246 ProcessCalledOperand(U->get(), CB);
10247
10248 return Change;
10249 }
10250 };
10251
10252 struct AACallEdgesFunction : public AACallEdgesImpl {
AACallEdgesFunction__anon641416297411::AACallEdgesFunction10253 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10254 : AACallEdgesImpl(IRP, A) {}
10255
10256 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297411::AACallEdgesFunction10257 ChangeStatus updateImpl(Attributor &A) override {
10258 ChangeStatus Change = ChangeStatus::UNCHANGED;
10259
10260 auto ProcessCallInst = [&](Instruction &Inst) {
10261 CallBase &CB = cast<CallBase>(Inst);
10262
10263 auto &CBEdges = A.getAAFor<AACallEdges>(
10264 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10265 if (CBEdges.hasNonAsmUnknownCallee())
10266 setHasUnknownCallee(true, Change);
10267 if (CBEdges.hasUnknownCallee())
10268 setHasUnknownCallee(false, Change);
10269
10270 for (Function *F : CBEdges.getOptimisticEdges())
10271 addCalledFunction(F, Change);
10272
10273 return true;
10274 };
10275
10276 // Visit all callable instructions.
10277 bool UsedAssumedInformation = false;
10278 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10279 UsedAssumedInformation,
10280 /* CheckBBLivenessOnly */ true)) {
10281 // If we haven't looked at all call like instructions, assume that there
10282 // are unknown callees.
10283 setHasUnknownCallee(true, Change);
10284 }
10285
10286 return Change;
10287 }
10288 };
10289
10290 /// -------------------AAInterFnReachability Attribute--------------------------
10291
10292 struct AAInterFnReachabilityFunction
10293 : public CachedReachabilityAA<AAInterFnReachability, Function> {
AAInterFnReachabilityFunction__anon641416297411::AAInterFnReachabilityFunction10294 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10295 : CachedReachabilityAA<AAInterFnReachability, Function>(IRP, A) {}
10296
instructionCanReach__anon641416297411::AAInterFnReachabilityFunction10297 bool instructionCanReach(
10298 Attributor &A, const Instruction &From, const Function &To,
10299 const AA::InstExclusionSetTy *ExclusionSet,
10300 SmallPtrSet<const Function *, 16> *Visited) const override {
10301 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
10302 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10303
10304 RQITy StackRQI(A, From, To, ExclusionSet);
10305 typename RQITy::Reachable Result;
10306 if (RQITy *RQIPtr = NonConstThis->checkQueryCache(A, StackRQI, Result))
10307 return NonConstThis->isReachableImpl(A, *RQIPtr);
10308 return Result == RQITy::Reachable::Yes;
10309 }
10310
isReachableImpl__anon641416297411::AAInterFnReachabilityFunction10311 bool isReachableImpl(Attributor &A, RQITy &RQI) override {
10312 return isReachableImpl(A, RQI, nullptr);
10313 }
10314
isReachableImpl__anon641416297411::AAInterFnReachabilityFunction10315 bool isReachableImpl(Attributor &A, RQITy &RQI,
10316 SmallPtrSet<const Function *, 16> *Visited) {
10317
10318 SmallPtrSet<const Function *, 16> LocalVisited;
10319 if (!Visited)
10320 Visited = &LocalVisited;
10321
10322 const auto &IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10323 *this, IRPosition::function(*RQI.From->getFunction()),
10324 DepClassTy::OPTIONAL);
10325
10326 // Determine call like instructions that we can reach from the inst.
10327 SmallVector<CallBase *> ReachableCallBases;
10328 auto CheckCallBase = [&](Instruction &CBInst) {
10329 if (IntraFnReachability.isAssumedReachable(A, *RQI.From, CBInst,
10330 RQI.ExclusionSet))
10331 ReachableCallBases.push_back(cast<CallBase>(&CBInst));
10332 return true;
10333 };
10334
10335 bool UsedAssumedInformation = false;
10336 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10337 UsedAssumedInformation,
10338 /* CheckBBLivenessOnly */ true))
10339 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10340
10341 for (CallBase *CB : ReachableCallBases) {
10342 auto &CBEdges = A.getAAFor<AACallEdges>(
10343 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10344 if (!CBEdges.getState().isValidState())
10345 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10346 // TODO Check To backwards in this case.
10347 if (CBEdges.hasUnknownCallee())
10348 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10349
10350 for (Function *Fn : CBEdges.getOptimisticEdges()) {
10351 if (Fn == RQI.To)
10352 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10353 if (!Visited->insert(Fn).second)
10354 continue;
10355 if (Fn->isDeclaration()) {
10356 if (Fn->hasFnAttribute(Attribute::NoCallback))
10357 continue;
10358 // TODO Check To backwards in this case.
10359 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10360 }
10361
10362 const AAInterFnReachability *InterFnReachability = this;
10363 if (Fn != getAnchorScope())
10364 InterFnReachability = &A.getAAFor<AAInterFnReachability>(
10365 *this, IRPosition::function(*Fn), DepClassTy::OPTIONAL);
10366
10367 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10368 if (InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10369 RQI.ExclusionSet, Visited))
10370 return rememberResult(A, RQITy::Reachable::Yes, RQI);
10371 }
10372 }
10373
10374 return rememberResult(A, RQITy::Reachable::No, RQI);
10375 }
10376
trackStatistics__anon641416297411::AAInterFnReachabilityFunction10377 void trackStatistics() const override {}
10378
10379 private:
10380 SmallVector<RQITy *> QueryVector;
10381 DenseSet<RQITy *> QueryCache;
10382 };
10383 } // namespace
10384
10385 template <typename AAType>
10386 static std::optional<Constant *>
askForAssumedConstant(Attributor & A,const AbstractAttribute & QueryingAA,const IRPosition & IRP,Type & Ty)10387 askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA,
10388 const IRPosition &IRP, Type &Ty) {
10389 if (!Ty.isIntegerTy())
10390 return nullptr;
10391
10392 // This will also pass the call base context.
10393 const auto &AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10394
10395 std::optional<Constant *> COpt = AA.getAssumedConstant(A);
10396
10397 if (!COpt.has_value()) {
10398 A.recordDependence(AA, QueryingAA, DepClassTy::OPTIONAL);
10399 return std::nullopt;
10400 }
10401 if (auto *C = *COpt) {
10402 A.recordDependence(AA, QueryingAA, DepClassTy::OPTIONAL);
10403 return C;
10404 }
10405 return nullptr;
10406 }
10407
getSingleValue(Attributor & A,const AbstractAttribute & AA,const IRPosition & IRP,SmallVectorImpl<AA::ValueAndContext> & Values)10408 Value *AAPotentialValues::getSingleValue(
10409 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10410 SmallVectorImpl<AA::ValueAndContext> &Values) {
10411 Type &Ty = *IRP.getAssociatedType();
10412 std::optional<Value *> V;
10413 for (auto &It : Values) {
10414 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10415 if (V.has_value() && !*V)
10416 break;
10417 }
10418 if (!V.has_value())
10419 return UndefValue::get(&Ty);
10420 return *V;
10421 }
10422
10423 namespace {
10424 struct AAPotentialValuesImpl : AAPotentialValues {
10425 using StateType = PotentialLLVMValuesState;
10426
AAPotentialValuesImpl__anon641416297a11::AAPotentialValuesImpl10427 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10428 : AAPotentialValues(IRP, A) {}
10429
10430 /// See AbstractAttribute::initialize(..).
initialize__anon641416297a11::AAPotentialValuesImpl10431 void initialize(Attributor &A) override {
10432 if (A.hasSimplificationCallback(getIRPosition())) {
10433 indicatePessimisticFixpoint();
10434 return;
10435 }
10436 Value *Stripped = getAssociatedValue().stripPointerCasts();
10437 auto *CE = dyn_cast<ConstantExpr>(Stripped);
10438 if (isa<Constant>(Stripped) &&
10439 (!CE || CE->getOpcode() != Instruction::ICmp)) {
10440 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10441 getAnchorScope());
10442 indicateOptimisticFixpoint();
10443 return;
10444 }
10445 AAPotentialValues::initialize(A);
10446 }
10447
10448 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416297a11::AAPotentialValuesImpl10449 const std::string getAsStr() const override {
10450 std::string Str;
10451 llvm::raw_string_ostream OS(Str);
10452 OS << getState();
10453 return OS.str();
10454 }
10455
10456 template <typename AAType>
askOtherAA__anon641416297a11::AAPotentialValuesImpl10457 static std::optional<Value *> askOtherAA(Attributor &A,
10458 const AbstractAttribute &AA,
10459 const IRPosition &IRP, Type &Ty) {
10460 if (isa<Constant>(IRP.getAssociatedValue()))
10461 return &IRP.getAssociatedValue();
10462 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10463 if (!C)
10464 return std::nullopt;
10465 if (*C)
10466 if (auto *CC = AA::getWithType(**C, Ty))
10467 return CC;
10468 return nullptr;
10469 }
10470
addValue__anon641416297a11::AAPotentialValuesImpl10471 void addValue(Attributor &A, StateType &State, Value &V,
10472 const Instruction *CtxI, AA::ValueScope S,
10473 Function *AnchorScope) const {
10474
10475 IRPosition ValIRP = IRPosition::value(V);
10476 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
10477 for (const auto &U : CB->args()) {
10478 if (U.get() != &V)
10479 continue;
10480 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
10481 break;
10482 }
10483 }
10484
10485 Value *VPtr = &V;
10486 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10487 Type &Ty = *getAssociatedType();
10488 std::optional<Value *> SimpleV =
10489 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
10490 if (SimpleV.has_value() && !*SimpleV) {
10491 auto &PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10492 *this, ValIRP, DepClassTy::OPTIONAL);
10493 if (PotentialConstantsAA.isValidState()) {
10494 for (const auto &It : PotentialConstantsAA.getAssumedSet())
10495 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
10496 if (PotentialConstantsAA.undefIsContained())
10497 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
10498 return;
10499 }
10500 }
10501 if (!SimpleV.has_value())
10502 return;
10503
10504 if (*SimpleV)
10505 VPtr = *SimpleV;
10506 }
10507
10508 if (isa<ConstantInt>(VPtr))
10509 CtxI = nullptr;
10510 if (!AA::isValidInScope(*VPtr, AnchorScope))
10511 S = AA::ValueScope(S | AA::Interprocedural);
10512
10513 State.unionAssumed({{*VPtr, CtxI}, S});
10514 }
10515
10516 /// Helper struct to tie a value+context pair together with the scope for
10517 /// which this is the simplified version.
10518 struct ItemInfo {
10519 AA::ValueAndContext I;
10520 AA::ValueScope S;
10521
operator ==__anon641416297a11::AAPotentialValuesImpl::ItemInfo10522 bool operator==(const ItemInfo &II) const {
10523 return II.I == I && II.S == S;
10524 };
operator <__anon641416297a11::AAPotentialValuesImpl::ItemInfo10525 bool operator<(const ItemInfo &II) const {
10526 if (I == II.I)
10527 return S < II.S;
10528 return I < II.I;
10529 };
10530 };
10531
recurseForValue__anon641416297a11::AAPotentialValuesImpl10532 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
10533 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10534 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
10535 if (!(CS & S))
10536 continue;
10537
10538 bool UsedAssumedInformation = false;
10539 SmallVector<AA::ValueAndContext> Values;
10540 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
10541 UsedAssumedInformation))
10542 return false;
10543
10544 for (auto &It : Values)
10545 ValueScopeMap[It] += CS;
10546 }
10547 for (auto &It : ValueScopeMap)
10548 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
10549 AA::ValueScope(It.second), getAnchorScope());
10550
10551 return true;
10552 }
10553
giveUpOnIntraprocedural__anon641416297a11::AAPotentialValuesImpl10554 void giveUpOnIntraprocedural(Attributor &A) {
10555 auto NewS = StateType::getBestState(getState());
10556 for (const auto &It : getAssumedSet()) {
10557 if (It.second == AA::Intraprocedural)
10558 continue;
10559 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
10560 AA::Interprocedural, getAnchorScope());
10561 }
10562 assert(!undefIsContained() && "Undef should be an explicit value!");
10563 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
10564 getAnchorScope());
10565 getState() = NewS;
10566 }
10567
10568 /// See AbstractState::indicatePessimisticFixpoint(...).
indicatePessimisticFixpoint__anon641416297a11::AAPotentialValuesImpl10569 ChangeStatus indicatePessimisticFixpoint() override {
10570 getState() = StateType::getBestState(getState());
10571 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
10572 AAPotentialValues::indicateOptimisticFixpoint();
10573 return ChangeStatus::CHANGED;
10574 }
10575
10576 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297a11::AAPotentialValuesImpl10577 ChangeStatus updateImpl(Attributor &A) override {
10578 return indicatePessimisticFixpoint();
10579 }
10580
10581 /// See AbstractAttribute::manifest(...).
manifest__anon641416297a11::AAPotentialValuesImpl10582 ChangeStatus manifest(Attributor &A) override {
10583 SmallVector<AA::ValueAndContext> Values;
10584 for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {
10585 Values.clear();
10586 if (!getAssumedSimplifiedValues(A, Values, S))
10587 continue;
10588 Value &OldV = getAssociatedValue();
10589 if (isa<UndefValue>(OldV))
10590 continue;
10591 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
10592 if (!NewV || NewV == &OldV)
10593 continue;
10594 if (getCtxI() &&
10595 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
10596 continue;
10597 if (A.changeAfterManifest(getIRPosition(), *NewV))
10598 return ChangeStatus::CHANGED;
10599 }
10600 return ChangeStatus::UNCHANGED;
10601 }
10602
getAssumedSimplifiedValues__anon641416297a11::AAPotentialValuesImpl10603 bool getAssumedSimplifiedValues(Attributor &A,
10604 SmallVectorImpl<AA::ValueAndContext> &Values,
10605 AA::ValueScope S) const override {
10606 if (!isValidState())
10607 return false;
10608 for (const auto &It : getAssumedSet())
10609 if (It.second & S)
10610 Values.push_back(It.first);
10611 assert(!undefIsContained() && "Undef should be an explicit value!");
10612 return true;
10613 }
10614 };
10615
10616 struct AAPotentialValuesFloating : AAPotentialValuesImpl {
AAPotentialValuesFloating__anon641416297a11::AAPotentialValuesFloating10617 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
10618 : AAPotentialValuesImpl(IRP, A) {}
10619
10620 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297a11::AAPotentialValuesFloating10621 ChangeStatus updateImpl(Attributor &A) override {
10622 auto AssumedBefore = getAssumed();
10623
10624 genericValueTraversal(A);
10625
10626 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10627 : ChangeStatus::CHANGED;
10628 }
10629
10630 /// Helper struct to remember which AAIsDead instances we actually used.
10631 struct LivenessInfo {
10632 const AAIsDead *LivenessAA = nullptr;
10633 bool AnyDead = false;
10634 };
10635
10636 /// Check if \p Cmp is a comparison we can simplify.
10637 ///
10638 /// We handle multiple cases, one in which at least one operand is an
10639 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
10640 /// operand. Return true if successful, in that case Worklist will be updated.
handleCmp__anon641416297a11::AAPotentialValuesFloating10641 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
10642 CmpInst::Predicate Pred, ItemInfo II,
10643 SmallVectorImpl<ItemInfo> &Worklist) {
10644
10645 // Simplify the operands first.
10646 bool UsedAssumedInformation = false;
10647 const auto &SimplifiedLHS = A.getAssumedSimplified(
10648 IRPosition::value(*LHS, getCallBaseContext()), *this,
10649 UsedAssumedInformation, AA::Intraprocedural);
10650 if (!SimplifiedLHS.has_value())
10651 return true;
10652 if (!*SimplifiedLHS)
10653 return false;
10654 LHS = *SimplifiedLHS;
10655
10656 const auto &SimplifiedRHS = A.getAssumedSimplified(
10657 IRPosition::value(*RHS, getCallBaseContext()), *this,
10658 UsedAssumedInformation, AA::Intraprocedural);
10659 if (!SimplifiedRHS.has_value())
10660 return true;
10661 if (!*SimplifiedRHS)
10662 return false;
10663 RHS = *SimplifiedRHS;
10664
10665 LLVMContext &Ctx = LHS->getContext();
10666 // Handle the trivial case first in which we don't even need to think about
10667 // null or non-null.
10668 if (LHS == RHS &&
10669 (CmpInst::isTrueWhenEqual(Pred) || CmpInst::isFalseWhenEqual(Pred))) {
10670 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
10671 CmpInst::isTrueWhenEqual(Pred));
10672 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
10673 getAnchorScope());
10674 return true;
10675 }
10676
10677 // From now on we only handle equalities (==, !=).
10678 if (!CmpInst::isEquality(Pred))
10679 return false;
10680
10681 bool LHSIsNull = isa<ConstantPointerNull>(LHS);
10682 bool RHSIsNull = isa<ConstantPointerNull>(RHS);
10683 if (!LHSIsNull && !RHSIsNull)
10684 return false;
10685
10686 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
10687 // non-nullptr operand and if we assume it's non-null we can conclude the
10688 // result of the comparison.
10689 assert((LHSIsNull || RHSIsNull) &&
10690 "Expected nullptr versus non-nullptr comparison at this point");
10691
10692 // The index is the operand that we assume is not null.
10693 unsigned PtrIdx = LHSIsNull;
10694 auto &PtrNonNullAA = A.getAAFor<AANonNull>(
10695 *this, IRPosition::value(*(PtrIdx ? RHS : LHS)), DepClassTy::REQUIRED);
10696 if (!PtrNonNullAA.isAssumedNonNull())
10697 return false;
10698
10699 // The new value depends on the predicate, true for != and false for ==.
10700 Constant *NewV =
10701 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
10702 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S, getAnchorScope());
10703 return true;
10704 }
10705
handleSelectInst__anon641416297a11::AAPotentialValuesFloating10706 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
10707 SmallVectorImpl<ItemInfo> &Worklist) {
10708 const Instruction *CtxI = II.I.getCtxI();
10709 bool UsedAssumedInformation = false;
10710
10711 std::optional<Constant *> C =
10712 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
10713 bool NoValueYet = !C.has_value();
10714 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
10715 return true;
10716 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
10717 if (CI->isZero())
10718 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
10719 else
10720 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
10721 } else if (&SI == &getAssociatedValue()) {
10722 // We could not simplify the condition, assume both values.
10723 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
10724 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
10725 } else {
10726 std::optional<Value *> SimpleV = A.getAssumedSimplified(
10727 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
10728 if (!SimpleV.has_value())
10729 return true;
10730 if (*SimpleV) {
10731 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
10732 return true;
10733 }
10734 return false;
10735 }
10736 return true;
10737 }
10738
handleLoadInst__anon641416297a11::AAPotentialValuesFloating10739 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
10740 SmallVectorImpl<ItemInfo> &Worklist) {
10741 SmallSetVector<Value *, 4> PotentialCopies;
10742 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
10743 bool UsedAssumedInformation = false;
10744 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
10745 PotentialValueOrigins, *this,
10746 UsedAssumedInformation,
10747 /* OnlyExact */ true)) {
10748 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
10749 "loaded values for load instruction "
10750 << LI << "\n");
10751 return false;
10752 }
10753
10754 // Do not simplify loads that are only used in llvm.assume if we cannot also
10755 // remove all stores that may feed into the load. The reason is that the
10756 // assume is probably worth something as long as the stores are around.
10757 InformationCache &InfoCache = A.getInfoCache();
10758 if (InfoCache.isOnlyUsedByAssume(LI)) {
10759 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
10760 if (!I)
10761 return true;
10762 if (auto *SI = dyn_cast<StoreInst>(I))
10763 return A.isAssumedDead(SI->getOperandUse(0), this,
10764 /* LivenessAA */ nullptr,
10765 UsedAssumedInformation,
10766 /* CheckBBLivenessOnly */ false);
10767 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
10768 UsedAssumedInformation,
10769 /* CheckBBLivenessOnly */ false);
10770 })) {
10771 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
10772 "and we cannot delete all the stores: "
10773 << LI << "\n");
10774 return false;
10775 }
10776 }
10777
10778 // Values have to be dynamically unique or we loose the fact that a
10779 // single llvm::Value might represent two runtime values (e.g.,
10780 // stack locations in different recursive calls).
10781 const Instruction *CtxI = II.I.getCtxI();
10782 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
10783 bool AllLocal = ScopeIsLocal;
10784 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
10785 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
10786 return AA::isDynamicallyUnique(A, *this, *PC);
10787 });
10788 if (!DynamicallyUnique) {
10789 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
10790 "values are dynamically unique: "
10791 << LI << "\n");
10792 return false;
10793 }
10794
10795 for (auto *PotentialCopy : PotentialCopies) {
10796 if (AllLocal) {
10797 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
10798 } else {
10799 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
10800 }
10801 }
10802 if (!AllLocal && ScopeIsLocal)
10803 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
10804 return true;
10805 }
10806
handlePHINode__anon641416297a11::AAPotentialValuesFloating10807 bool handlePHINode(
10808 Attributor &A, PHINode &PHI, ItemInfo II,
10809 SmallVectorImpl<ItemInfo> &Worklist,
10810 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
10811 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
10812 LivenessInfo &LI = LivenessAAs[&F];
10813 if (!LI.LivenessAA)
10814 LI.LivenessAA = &A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
10815 DepClassTy::NONE);
10816 return LI;
10817 };
10818
10819 if (&PHI == &getAssociatedValue()) {
10820 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
10821 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
10822 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
10823 if (LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
10824 LI.AnyDead = true;
10825 continue;
10826 }
10827 Worklist.push_back(
10828 {{*PHI.getIncomingValue(u), IncomingBB->getTerminator()}, II.S});
10829 }
10830 return true;
10831 }
10832
10833 bool UsedAssumedInformation = false;
10834 std::optional<Value *> SimpleV = A.getAssumedSimplified(
10835 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
10836 if (!SimpleV.has_value())
10837 return true;
10838 if (!(*SimpleV))
10839 return false;
10840 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
10841 return true;
10842 }
10843
10844 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
10845 /// simplify any operand of the instruction \p I. Return true if successful,
10846 /// in that case Worklist will be updated.
handleGenericInst__anon641416297a11::AAPotentialValuesFloating10847 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
10848 SmallVectorImpl<ItemInfo> &Worklist) {
10849 bool SomeSimplified = false;
10850 bool UsedAssumedInformation = false;
10851
10852 SmallVector<Value *, 8> NewOps(I.getNumOperands());
10853 int Idx = 0;
10854 for (Value *Op : I.operands()) {
10855 const auto &SimplifiedOp = A.getAssumedSimplified(
10856 IRPosition::value(*Op, getCallBaseContext()), *this,
10857 UsedAssumedInformation, AA::Intraprocedural);
10858 // If we are not sure about any operand we are not sure about the entire
10859 // instruction, we'll wait.
10860 if (!SimplifiedOp.has_value())
10861 return true;
10862
10863 if (*SimplifiedOp)
10864 NewOps[Idx] = *SimplifiedOp;
10865 else
10866 NewOps[Idx] = Op;
10867
10868 SomeSimplified |= (NewOps[Idx] != Op);
10869 ++Idx;
10870 }
10871
10872 // We won't bother with the InstSimplify interface if we didn't simplify any
10873 // operand ourselves.
10874 if (!SomeSimplified)
10875 return false;
10876
10877 InformationCache &InfoCache = A.getInfoCache();
10878 Function *F = I.getFunction();
10879 const auto *DT =
10880 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10881 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
10882 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10883 OptimizationRemarkEmitter *ORE = nullptr;
10884
10885 const DataLayout &DL = I.getModule()->getDataLayout();
10886 SimplifyQuery Q(DL, TLI, DT, AC, &I);
10887 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q, ORE);
10888 if (!NewV || NewV == &I)
10889 return false;
10890
10891 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
10892 << *NewV << "\n");
10893 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
10894 return true;
10895 }
10896
simplifyInstruction__anon641416297a11::AAPotentialValuesFloating10897 bool simplifyInstruction(
10898 Attributor &A, Instruction &I, ItemInfo II,
10899 SmallVectorImpl<ItemInfo> &Worklist,
10900 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
10901 if (auto *CI = dyn_cast<CmpInst>(&I))
10902 if (handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
10903 CI->getPredicate(), II, Worklist))
10904 return true;
10905
10906 switch (I.getOpcode()) {
10907 case Instruction::Select:
10908 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
10909 case Instruction::PHI:
10910 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
10911 case Instruction::Load:
10912 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
10913 default:
10914 return handleGenericInst(A, I, II, Worklist);
10915 };
10916 return false;
10917 }
10918
genericValueTraversal__anon641416297a11::AAPotentialValuesFloating10919 void genericValueTraversal(Attributor &A) {
10920 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
10921
10922 Value *InitialV = &getAssociatedValue();
10923 SmallSet<ItemInfo, 16> Visited;
10924 SmallVector<ItemInfo, 16> Worklist;
10925 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
10926
10927 int Iteration = 0;
10928 do {
10929 ItemInfo II = Worklist.pop_back_val();
10930 Value *V = II.I.getValue();
10931 assert(V);
10932 const Instruction *CtxI = II.I.getCtxI();
10933 AA::ValueScope S = II.S;
10934
10935 // Check if we should process the current value. To prevent endless
10936 // recursion keep a record of the values we followed!
10937 if (!Visited.insert(II).second)
10938 continue;
10939
10940 // Make sure we limit the compile time for complex expressions.
10941 if (Iteration++ >= MaxPotentialValuesIterations) {
10942 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
10943 << Iteration << "!\n");
10944 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
10945 continue;
10946 }
10947
10948 // Explicitly look through calls with a "returned" attribute if we do
10949 // not have a pointer as stripPointerCasts only works on them.
10950 Value *NewV = nullptr;
10951 if (V->getType()->isPointerTy()) {
10952 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
10953 } else {
10954 auto *CB = dyn_cast<CallBase>(V);
10955 if (CB && CB->getCalledFunction()) {
10956 for (Argument &Arg : CB->getCalledFunction()->args())
10957 if (Arg.hasReturnedAttr()) {
10958 NewV = CB->getArgOperand(Arg.getArgNo());
10959 break;
10960 }
10961 }
10962 }
10963 if (NewV && NewV != V) {
10964 Worklist.push_back({{*NewV, CtxI}, S});
10965 continue;
10966 }
10967
10968 if (auto *CE = dyn_cast<ConstantExpr>(V)) {
10969 if (CE->getOpcode() == Instruction::ICmp)
10970 if (handleCmp(A, *CE, CE->getOperand(0), CE->getOperand(1),
10971 CmpInst::Predicate(CE->getPredicate()), II, Worklist))
10972 continue;
10973 }
10974
10975 if (auto *I = dyn_cast<Instruction>(V)) {
10976 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
10977 continue;
10978 }
10979
10980 if (V != InitialV || isa<Argument>(V))
10981 if (recurseForValue(A, IRPosition::value(*V), II.S))
10982 continue;
10983
10984 // If we haven't stripped anything we give up.
10985 if (V == InitialV && CtxI == getCtxI()) {
10986 indicatePessimisticFixpoint();
10987 return;
10988 }
10989
10990 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
10991 } while (!Worklist.empty());
10992
10993 // If we actually used liveness information so we have to record a
10994 // dependence.
10995 for (auto &It : LivenessAAs)
10996 if (It.second.AnyDead)
10997 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
10998 }
10999
11000 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297a11::AAPotentialValuesFloating11001 void trackStatistics() const override {
11002 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
11003 }
11004 };
11005
11006 struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11007 using Base = AAPotentialValuesImpl;
AAPotentialValuesArgument__anon641416297a11::AAPotentialValuesArgument11008 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11009 : Base(IRP, A) {}
11010
11011 /// See AbstractAttribute::initialize(..).
initialize__anon641416297a11::AAPotentialValuesArgument11012 void initialize(Attributor &A) override {
11013 auto &Arg = cast<Argument>(getAssociatedValue());
11014 if (Arg.hasPointeeInMemoryValueAttr())
11015 indicatePessimisticFixpoint();
11016 }
11017
11018 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297a11::AAPotentialValuesArgument11019 ChangeStatus updateImpl(Attributor &A) override {
11020 auto AssumedBefore = getAssumed();
11021
11022 unsigned CSArgNo = getCallSiteArgNo();
11023
11024 bool UsedAssumedInformation = false;
11025 SmallVector<AA::ValueAndContext> Values;
11026 auto CallSitePred = [&](AbstractCallSite ACS) {
11027 const auto CSArgIRP = IRPosition::callsite_argument(ACS, CSArgNo);
11028 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11029 return false;
11030
11031 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11032 AA::Interprocedural,
11033 UsedAssumedInformation))
11034 return false;
11035
11036 return isValidState();
11037 };
11038
11039 if (!A.checkForAllCallSites(CallSitePred, *this,
11040 /* RequireAllCallSites */ true,
11041 UsedAssumedInformation))
11042 return indicatePessimisticFixpoint();
11043
11044 Function *Fn = getAssociatedFunction();
11045 bool AnyNonLocal = false;
11046 for (auto &It : Values) {
11047 if (isa<Constant>(It.getValue())) {
11048 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11049 getAnchorScope());
11050 continue;
11051 }
11052 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11053 return indicatePessimisticFixpoint();
11054
11055 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11056 if (Arg->getParent() == Fn) {
11057 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11058 getAnchorScope());
11059 continue;
11060 }
11061 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11062 getAnchorScope());
11063 AnyNonLocal = true;
11064 }
11065 assert(!undefIsContained() && "Undef should be an explicit value!");
11066 if (AnyNonLocal)
11067 giveUpOnIntraprocedural(A);
11068
11069 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11070 : ChangeStatus::CHANGED;
11071 }
11072
11073 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297a11::AAPotentialValuesArgument11074 void trackStatistics() const override {
11075 STATS_DECLTRACK_ARG_ATTR(potential_values)
11076 }
11077 };
11078
11079 struct AAPotentialValuesReturned
11080 : AAReturnedFromReturnedValues<AAPotentialValues, AAPotentialValuesImpl> {
11081 using Base =
11082 AAReturnedFromReturnedValues<AAPotentialValues, AAPotentialValuesImpl>;
AAPotentialValuesReturned__anon641416297a11::AAPotentialValuesReturned11083 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11084 : Base(IRP, A) {}
11085
11086 /// See AbstractAttribute::initialize(..).
initialize__anon641416297a11::AAPotentialValuesReturned11087 void initialize(Attributor &A) override {
11088 if (A.hasSimplificationCallback(getIRPosition()))
11089 indicatePessimisticFixpoint();
11090 else
11091 AAPotentialValues::initialize(A);
11092 }
11093
manifest__anon641416297a11::AAPotentialValuesReturned11094 ChangeStatus manifest(Attributor &A) override {
11095 // We queried AAValueSimplify for the returned values so they will be
11096 // replaced if a simplified form was found. Nothing to do here.
11097 return ChangeStatus::UNCHANGED;
11098 }
11099
indicatePessimisticFixpoint__anon641416297a11::AAPotentialValuesReturned11100 ChangeStatus indicatePessimisticFixpoint() override {
11101 return AAPotentialValues::indicatePessimisticFixpoint();
11102 }
11103
11104 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297a11::AAPotentialValuesReturned11105 void trackStatistics() const override {
11106 STATS_DECLTRACK_FNRET_ATTR(potential_values)
11107 }
11108 };
11109
11110 struct AAPotentialValuesFunction : AAPotentialValuesImpl {
AAPotentialValuesFunction__anon641416297a11::AAPotentialValuesFunction11111 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11112 : AAPotentialValuesImpl(IRP, A) {}
11113
11114 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297a11::AAPotentialValuesFunction11115 ChangeStatus updateImpl(Attributor &A) override {
11116 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
11117 "not be called");
11118 }
11119
11120 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297a11::AAPotentialValuesFunction11121 void trackStatistics() const override {
11122 STATS_DECLTRACK_FN_ATTR(potential_values)
11123 }
11124 };
11125
11126 struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
AAPotentialValuesCallSite__anon641416297a11::AAPotentialValuesCallSite11127 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11128 : AAPotentialValuesFunction(IRP, A) {}
11129
11130 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297a11::AAPotentialValuesCallSite11131 void trackStatistics() const override {
11132 STATS_DECLTRACK_CS_ATTR(potential_values)
11133 }
11134 };
11135
11136 struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
AAPotentialValuesCallSiteReturned__anon641416297a11::AAPotentialValuesCallSiteReturned11137 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11138 : AAPotentialValuesImpl(IRP, A) {}
11139
11140 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297a11::AAPotentialValuesCallSiteReturned11141 ChangeStatus updateImpl(Attributor &A) override {
11142 auto AssumedBefore = getAssumed();
11143
11144 Function *Callee = getAssociatedFunction();
11145 if (!Callee)
11146 return indicatePessimisticFixpoint();
11147
11148 bool UsedAssumedInformation = false;
11149 auto *CB = cast<CallBase>(getCtxI());
11150 if (CB->isMustTailCall() &&
11151 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11152 UsedAssumedInformation))
11153 return indicatePessimisticFixpoint();
11154
11155 SmallVector<AA::ValueAndContext> Values;
11156 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11157 Values, AA::Intraprocedural,
11158 UsedAssumedInformation))
11159 return indicatePessimisticFixpoint();
11160
11161 Function *Caller = CB->getCaller();
11162
11163 bool AnyNonLocal = false;
11164 for (auto &It : Values) {
11165 Value *V = It.getValue();
11166 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11167 V, *CB, *this, UsedAssumedInformation);
11168 if (!CallerV.has_value()) {
11169 // Nothing to do as long as no value was determined.
11170 continue;
11171 }
11172 V = *CallerV ? *CallerV : V;
11173 if (AA::isDynamicallyUnique(A, *this, *V) &&
11174 AA::isValidInScope(*V, Caller)) {
11175 if (*CallerV) {
11176 SmallVector<AA::ValueAndContext> ArgValues;
11177 IRPosition IRP = IRPosition::value(*V);
11178 if (auto *Arg = dyn_cast<Argument>(V))
11179 if (Arg->getParent() == CB->getCalledFunction())
11180 IRP = IRPosition::callsite_argument(*CB, Arg->getArgNo());
11181 if (recurseForValue(A, IRP, AA::AnyScope))
11182 continue;
11183 }
11184 addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
11185 } else {
11186 AnyNonLocal = true;
11187 break;
11188 }
11189 }
11190 if (AnyNonLocal) {
11191 Values.clear();
11192 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11193 Values, AA::Interprocedural,
11194 UsedAssumedInformation))
11195 return indicatePessimisticFixpoint();
11196 AnyNonLocal = false;
11197 getState() = PotentialLLVMValuesState::getBestState();
11198 for (auto &It : Values) {
11199 Value *V = It.getValue();
11200 if (!AA::isDynamicallyUnique(A, *this, *V))
11201 return indicatePessimisticFixpoint();
11202 if (AA::isValidInScope(*V, Caller)) {
11203 addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
11204 } else {
11205 AnyNonLocal = true;
11206 addValue(A, getState(), *V, CB, AA::Interprocedural,
11207 getAnchorScope());
11208 }
11209 }
11210 if (AnyNonLocal)
11211 giveUpOnIntraprocedural(A);
11212 }
11213 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11214 : ChangeStatus::CHANGED;
11215 }
11216
indicatePessimisticFixpoint__anon641416297a11::AAPotentialValuesCallSiteReturned11217 ChangeStatus indicatePessimisticFixpoint() override {
11218 return AAPotentialValues::indicatePessimisticFixpoint();
11219 }
11220
11221 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297a11::AAPotentialValuesCallSiteReturned11222 void trackStatistics() const override {
11223 STATS_DECLTRACK_CSRET_ATTR(potential_values)
11224 }
11225 };
11226
11227 struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
AAPotentialValuesCallSiteArgument__anon641416297a11::AAPotentialValuesCallSiteArgument11228 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11229 : AAPotentialValuesFloating(IRP, A) {}
11230
11231 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297a11::AAPotentialValuesCallSiteArgument11232 void trackStatistics() const override {
11233 STATS_DECLTRACK_CSARG_ATTR(potential_values)
11234 }
11235 };
11236 } // namespace
11237
11238 /// ---------------------- Assumption Propagation ------------------------------
11239 namespace {
11240 struct AAAssumptionInfoImpl : public AAAssumptionInfo {
AAAssumptionInfoImpl__anon641416297f11::AAAssumptionInfoImpl11241 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11242 const DenseSet<StringRef> &Known)
11243 : AAAssumptionInfo(IRP, A, Known) {}
11244
hasAssumption__anon641416297f11::AAAssumptionInfoImpl11245 bool hasAssumption(const StringRef Assumption) const override {
11246 return isValidState() && setContains(Assumption);
11247 }
11248
11249 /// See AbstractAttribute::getAsStr()
getAsStr__anon641416297f11::AAAssumptionInfoImpl11250 const std::string getAsStr() const override {
11251 const SetContents &Known = getKnown();
11252 const SetContents &Assumed = getAssumed();
11253
11254 const std::string KnownStr =
11255 llvm::join(Known.getSet().begin(), Known.getSet().end(), ",");
11256 const std::string AssumedStr =
11257 (Assumed.isUniversal())
11258 ? "Universal"
11259 : llvm::join(Assumed.getSet().begin(), Assumed.getSet().end(), ",");
11260
11261 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11262 }
11263 };
11264
11265 /// Propagates assumption information from parent functions to all of their
11266 /// successors. An assumption can be propagated if the containing function
11267 /// dominates the called function.
11268 ///
11269 /// We start with a "known" set of assumptions already valid for the associated
11270 /// function and an "assumed" set that initially contains all possible
11271 /// assumptions. The assumed set is inter-procedurally updated by narrowing its
11272 /// contents as concrete values are known. The concrete values are seeded by the
11273 /// first nodes that are either entries into the call graph, or contains no
11274 /// assumptions. Each node is updated as the intersection of the assumed state
11275 /// with all of its predecessors.
11276 struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
AAAssumptionInfoFunction__anon641416297f11::AAAssumptionInfoFunction11277 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11278 : AAAssumptionInfoImpl(IRP, A,
11279 getAssumptions(*IRP.getAssociatedFunction())) {}
11280
11281 /// See AbstractAttribute::manifest(...).
manifest__anon641416297f11::AAAssumptionInfoFunction11282 ChangeStatus manifest(Attributor &A) override {
11283 const auto &Assumptions = getKnown();
11284
11285 // Don't manifest a universal set if it somehow made it here.
11286 if (Assumptions.isUniversal())
11287 return ChangeStatus::UNCHANGED;
11288
11289 Function *AssociatedFunction = getAssociatedFunction();
11290
11291 bool Changed = addAssumptions(*AssociatedFunction, Assumptions.getSet());
11292
11293 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11294 }
11295
11296 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297f11::AAAssumptionInfoFunction11297 ChangeStatus updateImpl(Attributor &A) override {
11298 bool Changed = false;
11299
11300 auto CallSitePred = [&](AbstractCallSite ACS) {
11301 const auto &AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11302 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11303 DepClassTy::REQUIRED);
11304 // Get the set of assumptions shared by all of this function's callers.
11305 Changed |= getIntersection(AssumptionAA.getAssumed());
11306 return !getAssumed().empty() || !getKnown().empty();
11307 };
11308
11309 bool UsedAssumedInformation = false;
11310 // Get the intersection of all assumptions held by this node's predecessors.
11311 // If we don't know all the call sites then this is either an entry into the
11312 // call graph or an empty node. This node is known to only contain its own
11313 // assumptions and can be propagated to its successors.
11314 if (!A.checkForAllCallSites(CallSitePred, *this, true,
11315 UsedAssumedInformation))
11316 return indicatePessimisticFixpoint();
11317
11318 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11319 }
11320
trackStatistics__anon641416297f11::AAAssumptionInfoFunction11321 void trackStatistics() const override {}
11322 };
11323
11324 /// Assumption Info defined for call sites.
11325 struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11326
AAAssumptionInfoCallSite__anon641416297f11::AAAssumptionInfoCallSite11327 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11328 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11329
11330 /// See AbstractAttribute::initialize(...).
initialize__anon641416297f11::AAAssumptionInfoCallSite11331 void initialize(Attributor &A) override {
11332 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11333 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11334 }
11335
11336 /// See AbstractAttribute::manifest(...).
manifest__anon641416297f11::AAAssumptionInfoCallSite11337 ChangeStatus manifest(Attributor &A) override {
11338 // Don't manifest a universal set if it somehow made it here.
11339 if (getKnown().isUniversal())
11340 return ChangeStatus::UNCHANGED;
11341
11342 CallBase &AssociatedCall = cast<CallBase>(getAssociatedValue());
11343 bool Changed = addAssumptions(AssociatedCall, getAssumed().getSet());
11344
11345 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11346 }
11347
11348 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416297f11::AAAssumptionInfoCallSite11349 ChangeStatus updateImpl(Attributor &A) override {
11350 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11351 auto &AssumptionAA =
11352 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11353 bool Changed = getIntersection(AssumptionAA.getAssumed());
11354 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11355 }
11356
11357 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416297f11::AAAssumptionInfoCallSite11358 void trackStatistics() const override {}
11359
11360 private:
11361 /// Helper to initialized the known set as all the assumptions this call and
11362 /// the callee contain.
getInitialAssumptions__anon641416297f11::AAAssumptionInfoCallSite11363 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11364 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
11365 auto Assumptions = getAssumptions(CB);
11366 if (const Function *F = CB.getCaller())
11367 set_union(Assumptions, getAssumptions(*F));
11368 if (Function *F = IRP.getAssociatedFunction())
11369 set_union(Assumptions, getAssumptions(*F));
11370 return Assumptions;
11371 }
11372 };
11373 } // namespace
11374
operator *() const11375 AACallGraphNode *AACallEdgeIterator::operator*() const {
11376 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11377 &A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
11378 }
11379
print()11380 void AttributorCallGraph::print() { llvm::WriteGraph(outs(), this); }
11381
11382 /// ------------------------ UnderlyingObjects ---------------------------------
11383
11384 namespace {
11385 struct AAUnderlyingObjectsImpl
11386 : StateWrapper<BooleanState, AAUnderlyingObjects> {
11387 using BaseTy = StateWrapper<BooleanState, AAUnderlyingObjects>;
AAUnderlyingObjectsImpl__anon641416298111::AAUnderlyingObjectsImpl11388 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
11389
11390 /// See AbstractAttribute::getAsStr().
getAsStr__anon641416298111::AAUnderlyingObjectsImpl11391 const std::string getAsStr() const override {
11392 return std::string("UnderlyingObjects ") +
11393 (isValidState()
11394 ? (std::string("inter #") +
11395 std::to_string(InterAssumedUnderlyingObjects.size()) +
11396 " objs" + std::string(", intra #") +
11397 std::to_string(IntraAssumedUnderlyingObjects.size()) +
11398 " objs")
11399 : "<invalid>");
11400 }
11401
11402 /// See AbstractAttribute::trackStatistics()
trackStatistics__anon641416298111::AAUnderlyingObjectsImpl11403 void trackStatistics() const override {}
11404
11405 /// See AbstractAttribute::updateImpl(...).
updateImpl__anon641416298111::AAUnderlyingObjectsImpl11406 ChangeStatus updateImpl(Attributor &A) override {
11407 auto &Ptr = getAssociatedValue();
11408
11409 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11410 AA::ValueScope Scope) {
11411 bool UsedAssumedInformation = false;
11412 SmallPtrSet<Value *, 8> SeenObjects;
11413 SmallVector<AA::ValueAndContext> Values;
11414
11415 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
11416 Scope, UsedAssumedInformation))
11417 return UnderlyingObjects.insert(&Ptr);
11418
11419 bool Changed = false;
11420
11421 for (unsigned I = 0; I < Values.size(); ++I) {
11422 auto &VAC = Values[I];
11423 auto *Obj = VAC.getValue();
11424 Value *UO = getUnderlyingObject(Obj);
11425 if (UO && UO != VAC.getValue() && SeenObjects.insert(UO).second) {
11426 const auto &OtherAA = A.getAAFor<AAUnderlyingObjects>(
11427 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
11428 auto Pred = [&Values](Value &V) {
11429 Values.emplace_back(V, nullptr);
11430 return true;
11431 };
11432
11433 if (!OtherAA.forallUnderlyingObjects(Pred, Scope))
11434 llvm_unreachable(
11435 "The forall call should not return false at this position");
11436
11437 continue;
11438 }
11439
11440 if (isa<SelectInst>(Obj) || isa<PHINode>(Obj)) {
11441 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope);
11442 continue;
11443 }
11444
11445 Changed |= UnderlyingObjects.insert(Obj);
11446 }
11447
11448 return Changed;
11449 };
11450
11451 bool Changed = false;
11452 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
11453 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
11454
11455 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11456 }
11457
forallUnderlyingObjects__anon641416298111::AAUnderlyingObjectsImpl11458 bool forallUnderlyingObjects(
11459 function_ref<bool(Value &)> Pred,
11460 AA::ValueScope Scope = AA::Interprocedural) const override {
11461 if (!isValidState())
11462 return Pred(getAssociatedValue());
11463
11464 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
11465 ? IntraAssumedUnderlyingObjects
11466 : InterAssumedUnderlyingObjects;
11467 for (Value *Obj : AssumedUnderlyingObjects)
11468 if (!Pred(*Obj))
11469 return false;
11470
11471 return true;
11472 }
11473
11474 private:
11475 /// Handle the case where the value is not the actual underlying value, such
11476 /// as a phi node or a select instruction.
handleIndirect__anon641416298111::AAUnderlyingObjectsImpl11477 bool handleIndirect(Attributor &A, Value &V,
11478 SmallSetVector<Value *, 8> &UnderlyingObjects,
11479 AA::ValueScope Scope) {
11480 bool Changed = false;
11481 const auto &AA = A.getAAFor<AAUnderlyingObjects>(
11482 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
11483 auto Pred = [&](Value &V) {
11484 Changed |= UnderlyingObjects.insert(&V);
11485 return true;
11486 };
11487 if (!AA.forallUnderlyingObjects(Pred, Scope))
11488 llvm_unreachable(
11489 "The forall call should not return false at this position");
11490 return Changed;
11491 }
11492
11493 /// All the underlying objects collected so far via intra procedural scope.
11494 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11495 /// All the underlying objects collected so far via inter procedural scope.
11496 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11497 };
11498
11499 struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
AAUnderlyingObjectsFloating__anon641416298111::AAUnderlyingObjectsFloating11500 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
11501 : AAUnderlyingObjectsImpl(IRP, A) {}
11502 };
11503
11504 struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
AAUnderlyingObjectsArgument__anon641416298111::AAUnderlyingObjectsArgument11505 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
11506 : AAUnderlyingObjectsImpl(IRP, A) {}
11507 };
11508
11509 struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
AAUnderlyingObjectsCallSite__anon641416298111::AAUnderlyingObjectsCallSite11510 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
11511 : AAUnderlyingObjectsImpl(IRP, A) {}
11512 };
11513
11514 struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
AAUnderlyingObjectsCallSiteArgument__anon641416298111::AAUnderlyingObjectsCallSiteArgument11515 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
11516 : AAUnderlyingObjectsImpl(IRP, A) {}
11517 };
11518
11519 struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
AAUnderlyingObjectsReturned__anon641416298111::AAUnderlyingObjectsReturned11520 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
11521 : AAUnderlyingObjectsImpl(IRP, A) {}
11522 };
11523
11524 struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
AAUnderlyingObjectsCallSiteReturned__anon641416298111::AAUnderlyingObjectsCallSiteReturned11525 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
11526 : AAUnderlyingObjectsImpl(IRP, A) {}
11527 };
11528
11529 struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
AAUnderlyingObjectsFunction__anon641416298111::AAUnderlyingObjectsFunction11530 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
11531 : AAUnderlyingObjectsImpl(IRP, A) {}
11532 };
11533 }
11534
11535 const char AAReturnedValues::ID = 0;
11536 const char AANoUnwind::ID = 0;
11537 const char AANoSync::ID = 0;
11538 const char AANoFree::ID = 0;
11539 const char AANonNull::ID = 0;
11540 const char AANoRecurse::ID = 0;
11541 const char AAWillReturn::ID = 0;
11542 const char AAUndefinedBehavior::ID = 0;
11543 const char AANoAlias::ID = 0;
11544 const char AAIntraFnReachability::ID = 0;
11545 const char AANoReturn::ID = 0;
11546 const char AAIsDead::ID = 0;
11547 const char AADereferenceable::ID = 0;
11548 const char AAAlign::ID = 0;
11549 const char AAInstanceInfo::ID = 0;
11550 const char AANoCapture::ID = 0;
11551 const char AAValueSimplify::ID = 0;
11552 const char AAHeapToStack::ID = 0;
11553 const char AAPrivatizablePtr::ID = 0;
11554 const char AAMemoryBehavior::ID = 0;
11555 const char AAMemoryLocation::ID = 0;
11556 const char AAValueConstantRange::ID = 0;
11557 const char AAPotentialConstantValues::ID = 0;
11558 const char AAPotentialValues::ID = 0;
11559 const char AANoUndef::ID = 0;
11560 const char AACallEdges::ID = 0;
11561 const char AAInterFnReachability::ID = 0;
11562 const char AAPointerInfo::ID = 0;
11563 const char AAAssumptionInfo::ID = 0;
11564 const char AAUnderlyingObjects::ID = 0;
11565
11566 // Macro magic to create the static generator function for attributes that
11567 // follow the naming scheme.
11568
11569 #define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
11570 case IRPosition::PK: \
11571 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
11572
11573 #define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
11574 case IRPosition::PK: \
11575 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
11576 ++NumAAs; \
11577 break;
11578
11579 #define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11580 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11581 CLASS *AA = nullptr; \
11582 switch (IRP.getPositionKind()) { \
11583 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11584 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
11585 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
11586 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11587 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
11588 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
11589 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11590 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11591 } \
11592 return *AA; \
11593 }
11594
11595 #define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11596 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11597 CLASS *AA = nullptr; \
11598 switch (IRP.getPositionKind()) { \
11599 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11600 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
11601 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
11602 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11603 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11604 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
11605 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11606 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11607 } \
11608 return *AA; \
11609 }
11610
11611 #define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11612 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11613 CLASS *AA = nullptr; \
11614 switch (IRP.getPositionKind()) { \
11615 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11616 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11617 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11618 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11619 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11620 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
11621 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11622 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11623 } \
11624 return *AA; \
11625 }
11626
11627 #define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11628 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11629 CLASS *AA = nullptr; \
11630 switch (IRP.getPositionKind()) { \
11631 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11632 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
11633 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
11634 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11635 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
11636 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
11637 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
11638 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11639 } \
11640 return *AA; \
11641 }
11642
11643 #define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
11644 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
11645 CLASS *AA = nullptr; \
11646 switch (IRP.getPositionKind()) { \
11647 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
11648 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
11649 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
11650 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
11651 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
11652 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
11653 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
11654 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
11655 } \
11656 return *AA; \
11657 }
11658
11659 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
11660 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
11661 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
11662 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
11663 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
11664 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues)
11665 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation)
11666 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges)
11667 CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAssumptionInfo)
11668
11669 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
11670 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
11671 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPrivatizablePtr)
11672 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
11673 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
11674 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInstanceInfo)
11675 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
11676 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange)
11677 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialConstantValues)
11678 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues)
11679 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef)
11680 CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo)
11681
11682 CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)
11683 CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
11684 CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
11685 CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUnderlyingObjects)
11686
11687 CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)
11688 CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior)
11689 CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIntraFnReachability)
11690 CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInterFnReachability)
11691
11692 CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)
11693
11694 #undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
11695 #undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
11696 #undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
11697 #undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
11698 #undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
11699 #undef SWITCH_PK_CREATE
11700 #undef SWITCH_PK_INV
11701