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/ADT/StringExtras.h"
28#include "llvm/Analysis/AliasAnalysis.h"
29#include "llvm/Analysis/AssumeBundleQueries.h"
30#include "llvm/Analysis/AssumptionCache.h"
31#include "llvm/Analysis/CaptureTracking.h"
32#include "llvm/Analysis/CycleAnalysis.h"
33#include "llvm/Analysis/InstructionSimplify.h"
34#include "llvm/Analysis/LazyValueInfo.h"
35#include "llvm/Analysis/MemoryBuiltins.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/Attributes.h"
42#include "llvm/IR/BasicBlock.h"
43#include "llvm/IR/Constant.h"
44#include "llvm/IR/Constants.h"
45#include "llvm/IR/DataLayout.h"
46#include "llvm/IR/DerivedTypes.h"
47#include "llvm/IR/GlobalValue.h"
48#include "llvm/IR/IRBuilder.h"
49#include "llvm/IR/InlineAsm.h"
50#include "llvm/IR/InstrTypes.h"
51#include "llvm/IR/Instruction.h"
52#include "llvm/IR/Instructions.h"
53#include "llvm/IR/IntrinsicInst.h"
54#include "llvm/IR/IntrinsicsAMDGPU.h"
55#include "llvm/IR/IntrinsicsNVPTX.h"
56#include "llvm/IR/LLVMContext.h"
57#include "llvm/IR/MDBuilder.h"
58#include "llvm/IR/NoFolder.h"
59#include "llvm/IR/Value.h"
60#include "llvm/IR/ValueHandle.h"
61#include "llvm/Support/Alignment.h"
62#include "llvm/Support/Casting.h"
63#include "llvm/Support/CommandLine.h"
64#include "llvm/Support/ErrorHandling.h"
65#include "llvm/Support/GraphWriter.h"
66#include "llvm/Support/InterleavedRange.h"
67#include "llvm/Support/KnownFPClass.h"
68#include "llvm/Support/MathExtras.h"
69#include "llvm/Support/TypeSize.h"
70#include "llvm/Support/raw_ostream.h"
71#include "llvm/Transforms/Utils/BasicBlockUtils.h"
72#include "llvm/Transforms/Utils/CallPromotionUtils.h"
73#include "llvm/Transforms/Utils/Local.h"
74#include "llvm/Transforms/Utils/ValueMapper.h"
75#include <cassert>
76#include <numeric>
77#include <optional>
78#include <string>
79
80using namespace llvm;
81
82#define DEBUG_TYPE "attributor"
83
84static cl::opt<bool> ManifestInternal(
85 "attributor-manifest-internal", cl::Hidden,
86 cl::desc("Manifest Attributor internal string attributes."),
87 cl::init(Val: false));
88
89static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(Val: 128),
90 cl::Hidden);
91
92template <>
93unsigned llvm::PotentialConstantIntValuesState::MaxPotentialValues = 0;
94
95template <> unsigned llvm::PotentialLLVMValuesState::MaxPotentialValues = -1;
96
97static cl::opt<unsigned, true> MaxPotentialValues(
98 "attributor-max-potential-values", cl::Hidden,
99 cl::desc("Maximum number of potential values to be "
100 "tracked for each position."),
101 cl::location(L&: llvm::PotentialConstantIntValuesState::MaxPotentialValues),
102 cl::init(Val: 7));
103
104static cl::opt<int> MaxPotentialValuesIterations(
105 "attributor-max-potential-values-iterations", cl::Hidden,
106 cl::desc(
107 "Maximum number of iterations we keep dismantling potential values."),
108 cl::init(Val: 64));
109
110STATISTIC(NumAAs, "Number of abstract attributes created");
111STATISTIC(NumIndirectCallsPromoted, "Number of indirect calls promoted");
112
113// Some helper macros to deal with statistics tracking.
114//
115// Usage:
116// For simple IR attribute tracking overload trackStatistics in the abstract
117// attribute and choose the right STATS_DECLTRACK_********* macro,
118// e.g.,:
119// void trackStatistics() const override {
120// STATS_DECLTRACK_ARG_ATTR(returned)
121// }
122// If there is a single "increment" side one can use the macro
123// STATS_DECLTRACK with a custom message. If there are multiple increment
124// sides, STATS_DECL and STATS_TRACK can also be used separately.
125//
126#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
127 ("Number of " #TYPE " marked '" #NAME "'")
128#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
129#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
130#define STATS_DECL(NAME, TYPE, MSG) \
131 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
132#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
133#define STATS_DECLTRACK(NAME, TYPE, MSG) \
134 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
135#define STATS_DECLTRACK_ARG_ATTR(NAME) \
136 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
137#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
138 STATS_DECLTRACK(NAME, CSArguments, \
139 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
140#define STATS_DECLTRACK_FN_ATTR(NAME) \
141 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
142#define STATS_DECLTRACK_CS_ATTR(NAME) \
143 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
144#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
145 STATS_DECLTRACK(NAME, FunctionReturn, \
146 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
147#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
148 STATS_DECLTRACK(NAME, CSReturn, \
149 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
150#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
151 STATS_DECLTRACK(NAME, Floating, \
152 ("Number of floating values known to be '" #NAME "'"))
153
154// Specialization of the operator<< for abstract attributes subclasses. This
155// disambiguates situations where multiple operators are applicable.
156namespace llvm {
157#define PIPE_OPERATOR(CLASS) \
158 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
159 return OS << static_cast<const AbstractAttribute &>(AA); \
160 }
161
162PIPE_OPERATOR(AAIsDead)
163PIPE_OPERATOR(AANoUnwind)
164PIPE_OPERATOR(AANoSync)
165PIPE_OPERATOR(AANoRecurse)
166PIPE_OPERATOR(AANonConvergent)
167PIPE_OPERATOR(AAWillReturn)
168PIPE_OPERATOR(AANoReturn)
169PIPE_OPERATOR(AANonNull)
170PIPE_OPERATOR(AAMustProgress)
171PIPE_OPERATOR(AANoAlias)
172PIPE_OPERATOR(AADereferenceable)
173PIPE_OPERATOR(AAAlign)
174PIPE_OPERATOR(AAInstanceInfo)
175PIPE_OPERATOR(AANoCapture)
176PIPE_OPERATOR(AAValueSimplify)
177PIPE_OPERATOR(AANoFree)
178PIPE_OPERATOR(AAHeapToStack)
179PIPE_OPERATOR(AAIntraFnReachability)
180PIPE_OPERATOR(AAMemoryBehavior)
181PIPE_OPERATOR(AAMemoryLocation)
182PIPE_OPERATOR(AAValueConstantRange)
183PIPE_OPERATOR(AAPrivatizablePtr)
184PIPE_OPERATOR(AAUndefinedBehavior)
185PIPE_OPERATOR(AAPotentialConstantValues)
186PIPE_OPERATOR(AAPotentialValues)
187PIPE_OPERATOR(AANoUndef)
188PIPE_OPERATOR(AANoFPClass)
189PIPE_OPERATOR(AACallEdges)
190PIPE_OPERATOR(AAInterFnReachability)
191PIPE_OPERATOR(AAPointerInfo)
192PIPE_OPERATOR(AAAssumptionInfo)
193PIPE_OPERATOR(AAUnderlyingObjects)
194PIPE_OPERATOR(AAInvariantLoadPointer)
195PIPE_OPERATOR(AAAddressSpace)
196PIPE_OPERATOR(AANoAliasAddrSpace)
197PIPE_OPERATOR(AAAllocationInfo)
198PIPE_OPERATOR(AAIndirectCallInfo)
199PIPE_OPERATOR(AAGlobalValueInfo)
200PIPE_OPERATOR(AADenormalFPMath)
201
202#undef PIPE_OPERATOR
203
204template <>
205ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
206 const DerefState &R) {
207 ChangeStatus CS0 =
208 clampStateAndIndicateChange(S&: S.DerefBytesState, R: R.DerefBytesState);
209 ChangeStatus CS1 = clampStateAndIndicateChange(S&: S.GlobalState, R: R.GlobalState);
210 return CS0 | CS1;
211}
212
213} // namespace llvm
214
215static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
216 bool HeaderOnly, Cycle **CPtr = nullptr) {
217 if (!CI)
218 return true;
219 auto *BB = I->getParent();
220 auto *C = CI->getCycle(Block: BB);
221 if (!C)
222 return false;
223 if (CPtr)
224 *CPtr = C;
225 return !HeaderOnly || BB == C->getHeader();
226}
227
228/// Checks if a type could have padding bytes.
229static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
230 // There is no size information, so be conservative.
231 if (!Ty->isSized())
232 return false;
233
234 // If the alloc size is not equal to the storage size, then there are padding
235 // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
236 if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
237 return false;
238
239 // FIXME: This isn't the right way to check for padding in vectors with
240 // non-byte-size elements.
241 if (VectorType *SeqTy = dyn_cast<VectorType>(Val: Ty))
242 return isDenselyPacked(Ty: SeqTy->getElementType(), DL);
243
244 // For array types, check for padding within members.
245 if (ArrayType *SeqTy = dyn_cast<ArrayType>(Val: Ty))
246 return isDenselyPacked(Ty: SeqTy->getElementType(), DL);
247
248 if (!isa<StructType>(Val: Ty))
249 return true;
250
251 // Check for padding within and between elements of a struct.
252 StructType *StructTy = cast<StructType>(Val: Ty);
253 const StructLayout *Layout = DL.getStructLayout(Ty: StructTy);
254 uint64_t StartPos = 0;
255 for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
256 Type *ElTy = StructTy->getElementType(N: I);
257 if (!isDenselyPacked(Ty: ElTy, DL))
258 return false;
259 if (StartPos != Layout->getElementOffsetInBits(Idx: I))
260 return false;
261 StartPos += DL.getTypeAllocSizeInBits(Ty: ElTy);
262 }
263
264 return true;
265}
266
267/// Get pointer operand of memory accessing instruction. If \p I is
268/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
269/// is set to false and the instruction is volatile, return nullptr.
270static const Value *getPointerOperand(const Instruction *I,
271 bool AllowVolatile) {
272 if (!AllowVolatile && I->isVolatile())
273 return nullptr;
274
275 if (auto *LI = dyn_cast<LoadInst>(Val: I)) {
276 return LI->getPointerOperand();
277 }
278
279 if (auto *SI = dyn_cast<StoreInst>(Val: I)) {
280 return SI->getPointerOperand();
281 }
282
283 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Val: I)) {
284 return CXI->getPointerOperand();
285 }
286
287 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Val: I)) {
288 return RMWI->getPointerOperand();
289 }
290
291 return nullptr;
292}
293
294/// Helper function to create a pointer based on \p Ptr, and advanced by \p
295/// Offset bytes.
296static Value *constructPointer(Value *Ptr, int64_t Offset,
297 IRBuilder<NoFolder> &IRB) {
298 LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
299 << "-bytes\n");
300
301 if (Offset)
302 Ptr = IRB.CreatePtrAdd(Ptr, Offset: IRB.getInt64(C: Offset),
303 Name: Ptr->getName() + ".b" + Twine(Offset));
304 return Ptr;
305}
306
307static const Value *
308stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA,
309 const Value *Val, const DataLayout &DL, APInt &Offset,
310 bool GetMinOffset, bool AllowNonInbounds,
311 bool UseAssumed = false) {
312
313 auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
314 const IRPosition &Pos = IRPosition::value(V);
315 // Only track dependence if we are going to use the assumed info.
316 const AAValueConstantRange *ValueConstantRangeAA =
317 A.getAAFor<AAValueConstantRange>(QueryingAA, IRP: Pos,
318 DepClass: UseAssumed ? DepClassTy::OPTIONAL
319 : DepClassTy::NONE);
320 if (!ValueConstantRangeAA)
321 return false;
322 ConstantRange Range = UseAssumed ? ValueConstantRangeAA->getAssumed()
323 : ValueConstantRangeAA->getKnown();
324 if (Range.isFullSet())
325 return false;
326
327 // We can only use the lower part of the range because the upper part can
328 // be higher than what the value can really be.
329 if (GetMinOffset)
330 ROffset = Range.getSignedMin();
331 else
332 ROffset = Range.getSignedMax();
333 return true;
334 };
335
336 return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
337 /* AllowInvariant */ AllowInvariantGroup: true,
338 ExternalAnalysis: AttributorAnalysis);
339}
340
341static const Value *
342getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA,
343 const Value *Ptr, int64_t &BytesOffset,
344 const DataLayout &DL, bool AllowNonInbounds = false) {
345 APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ty: Ptr->getType()), 0);
346 const Value *Base =
347 stripAndAccumulateOffsets(A, QueryingAA, Val: Ptr, DL, Offset&: OffsetAPInt,
348 /* GetMinOffset */ true, AllowNonInbounds);
349
350 BytesOffset = OffsetAPInt.getSExtValue();
351 return Base;
352}
353
354/// Clamp the information known for all returned values of a function
355/// (identified by \p QueryingAA) into \p S.
356template <typename AAType, typename StateType = typename AAType::StateType,
357 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
358 bool RecurseForSelectAndPHI = true>
359static void clampReturnedValueStates(
360 Attributor &A, const AAType &QueryingAA, StateType &S,
361 const IRPosition::CallBaseContext *CBContext = nullptr) {
362 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
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(V: RV, CBContext);
379 // If possible, use the hasAssumedIRAttr interface.
380 if (Attribute::isEnumAttrKind(Kind: IRAttributeKind)) {
381 bool IsKnown;
382 return AA::hasAssumedIRAttr<IRAttributeKind>(
383 A, &QueryingAA, RVPos, DepClassTy::REQUIRED, IsKnown);
384 }
385
386 const AAType *AA =
387 A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);
388 if (!AA)
389 return false;
390 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV
391 << " AA: " << AA->getAsStr(&A) << " @ " << RVPos << "\n");
392 const StateType &AAS = AA->getState();
393 if (!T)
394 T = StateType::getBestState(AAS);
395 *T &= AAS;
396 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
397 << "\n");
398 return T->isValidState();
399 };
400
401 if (!A.checkForAllReturnedValues(Pred: CheckReturnValue, QueryingAA,
402 S: AA::ValueScope::Intraprocedural,
403 RecurseForSelectAndPHI))
404 S.indicatePessimisticFixpoint();
405 else if (T)
406 S ^= *T;
407}
408
409namespace {
410/// Helper class for generic deduction: return value -> returned position.
411template <typename AAType, typename BaseType,
412 typename StateType = typename BaseType::StateType,
413 bool PropagateCallBaseContext = false,
414 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
415 bool RecurseForSelectAndPHI = true>
416struct AAReturnedFromReturnedValues : public BaseType {
417 AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
418 : BaseType(IRP, A) {}
419
420 /// See AbstractAttribute::updateImpl(...).
421 ChangeStatus updateImpl(Attributor &A) override {
422 StateType S(StateType::getBestState(this->getState()));
423 clampReturnedValueStates<AAType, StateType, IRAttributeKind,
424 RecurseForSelectAndPHI>(
425 A, *this, S,
426 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
427 // TODO: If we know we visited all returned values, thus no are assumed
428 // dead, we can take the known information from the state T.
429 return clampStateAndIndicateChange<StateType>(this->getState(), S);
430 }
431};
432
433/// Clamp the information known at all call sites for a given argument
434/// (identified by \p QueryingAA) into \p S.
435template <typename AAType, typename StateType = typename AAType::StateType,
436 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
437static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
438 StateType &S) {
439 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
440 << QueryingAA << " into " << S << "\n");
441
442 assert(QueryingAA.getIRPosition().getPositionKind() ==
443 IRPosition::IRP_ARGUMENT &&
444 "Can only clamp call site argument states for an argument position!");
445
446 // Use an optional state as there might not be any return values and we want
447 // to join (IntegerState::operator&) the state of all there are.
448 std::optional<StateType> T;
449
450 // The argument number which is also the call site argument number.
451 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
452
453 auto CallSiteCheck = [&](AbstractCallSite ACS) {
454 const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
455 // Check if a coresponding argument was found or if it is on not associated
456 // (which can happen for callback calls).
457 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
458 return false;
459
460 // If possible, use the hasAssumedIRAttr interface.
461 if (Attribute::isEnumAttrKind(Kind: IRAttributeKind)) {
462 bool IsKnown;
463 return AA::hasAssumedIRAttr<IRAttributeKind>(
464 A, &QueryingAA, ACSArgPos, DepClassTy::REQUIRED, IsKnown);
465 }
466
467 const AAType *AA =
468 A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);
469 if (!AA)
470 return false;
471 LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()
472 << " AA: " << AA->getAsStr(&A) << " @" << ACSArgPos
473 << "\n");
474 const StateType &AAS = AA->getState();
475 if (!T)
476 T = StateType::getBestState(AAS);
477 *T &= AAS;
478 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
479 << "\n");
480 return T->isValidState();
481 };
482
483 bool UsedAssumedInformation = false;
484 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,
485 UsedAssumedInformation))
486 S.indicatePessimisticFixpoint();
487 else if (T)
488 S ^= *T;
489}
490
491/// This function is the bridge between argument position and the call base
492/// context.
493template <typename AAType, typename BaseType,
494 typename StateType = typename AAType::StateType,
495 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
496bool getArgumentStateFromCallBaseContext(Attributor &A,
497 BaseType &QueryingAttribute,
498 IRPosition &Pos, StateType &State) {
499 assert((Pos.getPositionKind() == IRPosition::IRP_ARGUMENT) &&
500 "Expected an 'argument' position !");
501 const CallBase *CBContext = Pos.getCallBaseContext();
502 if (!CBContext)
503 return false;
504
505 int ArgNo = Pos.getCallSiteArgNo();
506 assert(ArgNo >= 0 && "Invalid Arg No!");
507 const IRPosition CBArgPos = IRPosition::callsite_argument(CB: *CBContext, ArgNo);
508
509 // If possible, use the hasAssumedIRAttr interface.
510 if (Attribute::isEnumAttrKind(Kind: IRAttributeKind)) {
511 bool IsKnown;
512 return AA::hasAssumedIRAttr<IRAttributeKind>(
513 A, &QueryingAttribute, CBArgPos, DepClassTy::REQUIRED, IsKnown);
514 }
515
516 const auto *AA =
517 A.getAAFor<AAType>(QueryingAttribute, CBArgPos, DepClassTy::REQUIRED);
518 if (!AA)
519 return false;
520 const StateType &CBArgumentState =
521 static_cast<const StateType &>(AA->getState());
522
523 LLVM_DEBUG(dbgs() << "[Attributor] Briding Call site context to argument"
524 << "Position:" << Pos << "CB Arg state:" << CBArgumentState
525 << "\n");
526
527 // NOTE: If we want to do call site grouping it should happen here.
528 State ^= CBArgumentState;
529 return true;
530}
531
532/// Helper class for generic deduction: call site argument -> argument position.
533template <typename AAType, typename BaseType,
534 typename StateType = typename AAType::StateType,
535 bool BridgeCallBaseContext = false,
536 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
537struct AAArgumentFromCallSiteArguments : public BaseType {
538 AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
539 : BaseType(IRP, A) {}
540
541 /// See AbstractAttribute::updateImpl(...).
542 ChangeStatus updateImpl(Attributor &A) override {
543 StateType S = StateType::getBestState(this->getState());
544
545 if (BridgeCallBaseContext) {
546 bool Success =
547 getArgumentStateFromCallBaseContext<AAType, BaseType, StateType,
548 IRAttributeKind>(
549 A, *this, this->getIRPosition(), S);
550 if (Success)
551 return clampStateAndIndicateChange<StateType>(this->getState(), S);
552 }
553 clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(A, *this,
554 S);
555
556 // TODO: If we know we visited all incoming values, thus no are assumed
557 // dead, we can take the known information from the state T.
558 return clampStateAndIndicateChange<StateType>(this->getState(), S);
559 }
560};
561
562/// Helper class for generic replication: function returned -> cs returned.
563template <typename AAType, typename BaseType,
564 typename StateType = typename BaseType::StateType,
565 bool IntroduceCallBaseContext = false,
566 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
567struct AACalleeToCallSite : public BaseType {
568 AACalleeToCallSite(const IRPosition &IRP, Attributor &A) : BaseType(IRP, A) {}
569
570 /// See AbstractAttribute::updateImpl(...).
571 ChangeStatus updateImpl(Attributor &A) override {
572 auto IRPKind = this->getIRPosition().getPositionKind();
573 assert((IRPKind == IRPosition::IRP_CALL_SITE_RETURNED ||
574 IRPKind == IRPosition::IRP_CALL_SITE) &&
575 "Can only wrap function returned positions for call site "
576 "returned positions!");
577 auto &S = this->getState();
578
579 CallBase &CB = cast<CallBase>(this->getAnchorValue());
580 if (IntroduceCallBaseContext)
581 LLVM_DEBUG(dbgs() << "[Attributor] Introducing call base context:" << CB
582 << "\n");
583
584 ChangeStatus Changed = ChangeStatus::UNCHANGED;
585 auto CalleePred = [&](ArrayRef<const Function *> Callees) {
586 for (const Function *Callee : Callees) {
587 IRPosition FnPos =
588 IRPKind == llvm::IRPosition::IRP_CALL_SITE_RETURNED
589 ? IRPosition::returned(F: *Callee,
590 CBContext: IntroduceCallBaseContext ? &CB : nullptr)
591 : IRPosition::function(
592 F: *Callee, CBContext: IntroduceCallBaseContext ? &CB : nullptr);
593 // If possible, use the hasAssumedIRAttr interface.
594 if (Attribute::isEnumAttrKind(Kind: IRAttributeKind)) {
595 bool IsKnown;
596 if (!AA::hasAssumedIRAttr<IRAttributeKind>(
597 A, this, FnPos, DepClassTy::REQUIRED, IsKnown))
598 return false;
599 continue;
600 }
601
602 const AAType *AA =
603 A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);
604 if (!AA)
605 return false;
606 Changed |= clampStateAndIndicateChange(S, AA->getState());
607 if (S.isAtFixpoint())
608 return S.isValidState();
609 }
610 return true;
611 };
612 if (!A.checkForAllCallees(Pred: CalleePred, QueryingAA: *this, CB))
613 return S.indicatePessimisticFixpoint();
614 return Changed;
615 }
616};
617
618/// Helper function to accumulate uses.
619template <class AAType, typename StateType = typename AAType::StateType>
620static void followUsesInContext(AAType &AA, Attributor &A,
621 MustBeExecutedContextExplorer &Explorer,
622 const Instruction *CtxI,
623 SetVector<const Use *> &Uses,
624 StateType &State) {
625 auto EIt = Explorer.begin(PP: CtxI), EEnd = Explorer.end(CtxI);
626 for (unsigned u = 0; u < Uses.size(); ++u) {
627 const Use *U = Uses[u];
628 if (const Instruction *UserI = dyn_cast<Instruction>(Val: U->getUser())) {
629 bool Found = Explorer.findInContextOf(I: UserI, EIt, EEnd);
630 if (Found && AA.followUseInMBEC(A, U, UserI, State))
631 Uses.insert_range(R: llvm::make_pointer_range(Range: UserI->uses()));
632 }
633 }
634}
635
636/// Use the must-be-executed-context around \p I to add information into \p S.
637/// The AAType class is required to have `followUseInMBEC` method with the
638/// following signature and behaviour:
639///
640/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)
641/// U - Underlying use.
642/// I - The user of the \p U.
643/// Returns true if the value should be tracked transitively.
644///
645template <class AAType, typename StateType = typename AAType::StateType>
646static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,
647 Instruction &CtxI) {
648 const Value &Val = AA.getIRPosition().getAssociatedValue();
649 if (isa<ConstantData>(Val))
650 return;
651
652 MustBeExecutedContextExplorer *Explorer =
653 A.getInfoCache().getMustBeExecutedContextExplorer();
654 if (!Explorer)
655 return;
656
657 // Container for (transitive) uses of the associated value.
658 SetVector<const Use *> Uses;
659 for (const Use &U : Val.uses())
660 Uses.insert(X: &U);
661
662 followUsesInContext<AAType>(AA, A, *Explorer, &CtxI, Uses, S);
663
664 if (S.isAtFixpoint())
665 return;
666
667 SmallVector<const CondBrInst *, 4> BrInsts;
668 auto Pred = [&](const Instruction *I) {
669 if (const CondBrInst *Br = dyn_cast<CondBrInst>(Val: I))
670 BrInsts.push_back(Elt: Br);
671 return true;
672 };
673
674 // Here, accumulate conditional branch instructions in the context. We
675 // explore the child paths and collect the known states. The disjunction of
676 // those states can be merged to its own state. Let ParentState_i be a state
677 // to indicate the known information for an i-th branch instruction in the
678 // context. ChildStates are created for its successors respectively.
679 //
680 // ParentS_1 = ChildS_{1, 1} /\ ChildS_{1, 2} /\ ... /\ ChildS_{1, n_1}
681 // ParentS_2 = ChildS_{2, 1} /\ ChildS_{2, 2} /\ ... /\ ChildS_{2, n_2}
682 // ...
683 // ParentS_m = ChildS_{m, 1} /\ ChildS_{m, 2} /\ ... /\ ChildS_{m, n_m}
684 //
685 // Known State |= ParentS_1 \/ ParentS_2 \/... \/ ParentS_m
686 //
687 // FIXME: Currently, recursive branches are not handled. For example, we
688 // can't deduce that ptr must be dereferenced in below function.
689 //
690 // void f(int a, int c, int *ptr) {
691 // if(a)
692 // if (b) {
693 // *ptr = 0;
694 // } else {
695 // *ptr = 1;
696 // }
697 // else {
698 // if (b) {
699 // *ptr = 0;
700 // } else {
701 // *ptr = 1;
702 // }
703 // }
704 // }
705
706 Explorer->checkForAllContext(PP: &CtxI, Pred);
707 for (const CondBrInst *Br : BrInsts) {
708 StateType ParentState;
709
710 // The known state of the parent state is a conjunction of children's
711 // known states so it is initialized with a best state.
712 ParentState.indicateOptimisticFixpoint();
713
714 for (const BasicBlock *BB : Br->successors()) {
715 StateType ChildState;
716
717 size_t BeforeSize = Uses.size();
718 followUsesInContext(AA, A, *Explorer, &BB->front(), Uses, ChildState);
719
720 // Erase uses which only appear in the child.
721 for (auto It = Uses.begin() + BeforeSize; It != Uses.end();)
722 It = Uses.erase(I: It);
723
724 ParentState &= ChildState;
725 }
726
727 // Use only known state.
728 S += ParentState;
729 }
730}
731} // namespace
732
733/// ------------------------ PointerInfo ---------------------------------------
734
735namespace llvm {
736namespace AA {
737namespace PointerInfo {
738
739struct State;
740
741} // namespace PointerInfo
742} // namespace AA
743
744/// Helper for AA::PointerInfo::Access DenseMap/Set usage.
745template <>
746struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {
747 using Access = AAPointerInfo::Access;
748 static unsigned getHashValue(const Access &A);
749 static bool isEqual(const Access &LHS, const Access &RHS);
750};
751
752/// Helper that allows RangeTy as a key in a DenseMap.
753template <> struct DenseMapInfo<AA::RangeTy> {
754 static unsigned getHashValue(const AA::RangeTy &Range) {
755 return detail::combineHashValue(
756 a: DenseMapInfo<int64_t>::getHashValue(Val: Range.Offset),
757 b: DenseMapInfo<int64_t>::getHashValue(Val: Range.Size));
758 }
759
760 static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {
761 return A == B;
762 }
763};
764
765/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign
766/// but the instruction
767struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {
768 using Base = DenseMapInfo<Instruction *>;
769 using Access = AAPointerInfo::Access;
770 static unsigned getHashValue(const Access &A);
771 static bool isEqual(const Access &LHS, const Access &RHS);
772};
773
774} // namespace llvm
775
776/// A type to track pointer/struct usage and accesses for AAPointerInfo.
777struct AA::PointerInfo::State : public AbstractState {
778 /// Return the best possible representable state.
779 static State getBestState(const State &SIS) { return State(); }
780
781 /// Return the worst possible representable state.
782 static State getWorstState(const State &SIS) {
783 State R;
784 R.indicatePessimisticFixpoint();
785 return R;
786 }
787
788 State() = default;
789 State(State &&SIS) = default;
790
791 const State &getAssumed() const { return *this; }
792
793 /// See AbstractState::isValidState().
794 bool isValidState() const override { return BS.isValidState(); }
795
796 /// See AbstractState::isAtFixpoint().
797 bool isAtFixpoint() const override { return BS.isAtFixpoint(); }
798
799 /// See AbstractState::indicateOptimisticFixpoint().
800 ChangeStatus indicateOptimisticFixpoint() override {
801 BS.indicateOptimisticFixpoint();
802 return ChangeStatus::UNCHANGED;
803 }
804
805 /// See AbstractState::indicatePessimisticFixpoint().
806 ChangeStatus indicatePessimisticFixpoint() override {
807 BS.indicatePessimisticFixpoint();
808 return ChangeStatus::CHANGED;
809 }
810
811 State &operator=(const State &R) {
812 if (this == &R)
813 return *this;
814 BS = R.BS;
815 AccessList = R.AccessList;
816 OffsetBins = R.OffsetBins;
817 RemoteIMap = R.RemoteIMap;
818 ReturnedOffsets = R.ReturnedOffsets;
819 return *this;
820 }
821
822 State &operator=(State &&R) {
823 if (this == &R)
824 return *this;
825 std::swap(a&: BS, b&: R.BS);
826 std::swap(LHS&: AccessList, RHS&: R.AccessList);
827 std::swap(a&: OffsetBins, b&: R.OffsetBins);
828 std::swap(a&: RemoteIMap, b&: R.RemoteIMap);
829 std::swap(a&: ReturnedOffsets, b&: R.ReturnedOffsets);
830 return *this;
831 }
832
833 /// Add a new Access to the state at offset \p Offset and with size \p Size.
834 /// The access is associated with \p I, writes \p Content (if anything), and
835 /// is of kind \p Kind. If an Access already exists for the same \p I and same
836 /// \p RemoteI, the two are combined, potentially losing information about
837 /// offset and size. The resulting access must now be moved from its original
838 /// OffsetBin to the bin for its new offset.
839 ///
840 /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
841 ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges,
842 Instruction &I, std::optional<Value *> Content,
843 AAPointerInfo::AccessKind Kind, Type *Ty,
844 Instruction *RemoteI = nullptr);
845
846 AAPointerInfo::const_bin_iterator begin() const { return OffsetBins.begin(); }
847 AAPointerInfo::const_bin_iterator end() const { return OffsetBins.end(); }
848 int64_t numOffsetBins() const { return OffsetBins.size(); }
849
850 const AAPointerInfo::Access &getAccess(unsigned Index) const {
851 return AccessList[Index];
852 }
853
854protected:
855 // Every memory instruction results in an Access object. We maintain a list of
856 // all Access objects that we own, along with the following maps:
857 //
858 // - OffsetBins: RangeTy -> { Access }
859 // - RemoteIMap: RemoteI x LocalI -> Access
860 //
861 // A RemoteI is any instruction that accesses memory. RemoteI is different
862 // from LocalI if and only if LocalI is a call; then RemoteI is some
863 // instruction in the callgraph starting from LocalI. Multiple paths in the
864 // callgraph from LocalI to RemoteI may produce multiple accesses, but these
865 // are all combined into a single Access object. This may result in loss of
866 // information in RangeTy in the Access object.
867 SmallVector<AAPointerInfo::Access> AccessList;
868 AAPointerInfo::OffsetBinsTy OffsetBins;
869 DenseMap<const Instruction *, SmallVector<unsigned>> RemoteIMap;
870
871 /// Flag to determine if the underlying pointer is reaching a return statement
872 /// in the associated function or not. Returns in other functions cause
873 /// invalidation.
874 AAPointerInfo::OffsetInfo ReturnedOffsets;
875
876 /// See AAPointerInfo::forallInterferingAccesses.
877 template <typename F>
878 bool forallInterferingAccesses(AA::RangeTy Range, F CB) const {
879 if (!isValidState() || !ReturnedOffsets.isUnassigned())
880 return false;
881
882 for (const auto &It : OffsetBins) {
883 AA::RangeTy ItRange = It.getFirst();
884 if (!Range.mayOverlap(Range: ItRange))
885 continue;
886 bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();
887 for (auto Index : It.getSecond()) {
888 auto &Access = AccessList[Index];
889 if (!CB(Access, IsExact))
890 return false;
891 }
892 }
893 return true;
894 }
895
896 /// See AAPointerInfo::forallInterferingAccesses.
897 template <typename F>
898 bool forallInterferingAccesses(Instruction &I, F CB,
899 AA::RangeTy &Range) const {
900 if (!isValidState() || !ReturnedOffsets.isUnassigned())
901 return false;
902
903 auto LocalList = RemoteIMap.find(Val: &I);
904 if (LocalList == RemoteIMap.end()) {
905 return true;
906 }
907
908 for (unsigned Index : LocalList->getSecond()) {
909 for (auto &R : AccessList[Index]) {
910 Range &= R;
911 if (Range.offsetAndSizeAreUnknown())
912 break;
913 }
914 }
915 return forallInterferingAccesses(Range, CB);
916 }
917
918private:
919 /// State to track fixpoint and validity.
920 BooleanState BS;
921};
922
923ChangeStatus AA::PointerInfo::State::addAccess(
924 Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I,
925 std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,
926 Instruction *RemoteI) {
927 RemoteI = RemoteI ? RemoteI : &I;
928
929 // Check if we have an access for this instruction, if not, simply add it.
930 auto &LocalList = RemoteIMap[RemoteI];
931 bool AccExists = false;
932 unsigned AccIndex = AccessList.size();
933 for (auto Index : LocalList) {
934 auto &A = AccessList[Index];
935 if (A.getLocalInst() == &I) {
936 AccExists = true;
937 AccIndex = Index;
938 break;
939 }
940 }
941
942 auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {
943 LLVM_DEBUG(if (ToAdd.size()) dbgs()
944 << "[AAPointerInfo] Inserting access in new offset bins\n";);
945
946 for (auto Key : ToAdd) {
947 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
948 OffsetBins[Key].insert(V: AccIndex);
949 }
950 };
951
952 if (!AccExists) {
953 AccessList.emplace_back(Args: &I, Args&: RemoteI, Args: Ranges, Args&: Content, Args&: Kind, Args&: Ty);
954 assert((AccessList.size() == AccIndex + 1) &&
955 "New Access should have been at AccIndex");
956 LocalList.push_back(Elt: AccIndex);
957 AddToBins(AccessList[AccIndex].getRanges());
958 return ChangeStatus::CHANGED;
959 }
960
961 // Combine the new Access with the existing Access, and then update the
962 // mapping in the offset bins.
963 AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);
964 auto &Current = AccessList[AccIndex];
965 auto Before = Current;
966 Current &= Acc;
967 if (Current == Before)
968 return ChangeStatus::UNCHANGED;
969
970 auto &ExistingRanges = Before.getRanges();
971 auto &NewRanges = Current.getRanges();
972
973 // Ranges that are in the old access but not the new access need to be removed
974 // from the offset bins.
975 AAPointerInfo::RangeList ToRemove;
976 AAPointerInfo::RangeList::set_difference(L: ExistingRanges, R: NewRanges, D&: ToRemove);
977 LLVM_DEBUG(if (ToRemove.size()) dbgs()
978 << "[AAPointerInfo] Removing access from old offset bins\n";);
979
980 for (auto Key : ToRemove) {
981 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
982 assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");
983 auto &Bin = OffsetBins[Key];
984 assert(Bin.count(AccIndex) &&
985 "Expected bin to actually contain the Access.");
986 Bin.erase(V: AccIndex);
987 }
988
989 // Ranges that are in the new access but not the old access need to be added
990 // to the offset bins.
991 AAPointerInfo::RangeList ToAdd;
992 AAPointerInfo::RangeList::set_difference(L: NewRanges, R: ExistingRanges, D&: ToAdd);
993 AddToBins(ToAdd);
994 return ChangeStatus::CHANGED;
995}
996
997namespace {
998
999#ifndef NDEBUG
1000static raw_ostream &operator<<(raw_ostream &OS,
1001 const AAPointerInfo::OffsetInfo &OI) {
1002 OS << llvm::interleaved_array(OI);
1003 return OS;
1004}
1005#endif // NDEBUG
1006
1007struct AAPointerInfoImpl
1008 : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1009 using BaseTy = StateWrapper<AA::PointerInfo::State, AAPointerInfo>;
1010 AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
1011
1012 /// See AbstractAttribute::getAsStr().
1013 const std::string getAsStr(Attributor *A) const override {
1014 return std::string("PointerInfo ") +
1015 (isValidState() ? (std::string("#") +
1016 std::to_string(val: OffsetBins.size()) + " bins")
1017 : "<invalid>") +
1018 (reachesReturn()
1019 ? (" (returned:" +
1020 join(R: map_range(C: ReturnedOffsets,
1021 F: [](int64_t O) { return std::to_string(val: O); }),
1022 Separator: ", ") +
1023 ")")
1024 : "");
1025 }
1026
1027 /// See AbstractAttribute::manifest(...).
1028 ChangeStatus manifest(Attributor &A) override {
1029 return AAPointerInfo::manifest(A);
1030 }
1031
1032 const_bin_iterator begin() const override { return State::begin(); }
1033 const_bin_iterator end() const override { return State::end(); }
1034 int64_t numOffsetBins() const override { return State::numOffsetBins(); }
1035 bool reachesReturn() const override {
1036 return !ReturnedOffsets.isUnassigned();
1037 }
1038 void addReturnedOffsetsTo(OffsetInfo &OI) const override {
1039 if (ReturnedOffsets.isUnknown()) {
1040 OI.setUnknown();
1041 return;
1042 }
1043
1044 OffsetInfo MergedOI;
1045 for (auto Offset : ReturnedOffsets) {
1046 OffsetInfo TmpOI = OI;
1047 TmpOI.addToAll(Inc: Offset);
1048 MergedOI.merge(R: TmpOI);
1049 }
1050 OI = std::move(MergedOI);
1051 }
1052
1053 ChangeStatus setReachesReturn(const OffsetInfo &ReachedReturnedOffsets) {
1054 if (ReturnedOffsets.isUnknown())
1055 return ChangeStatus::UNCHANGED;
1056 if (ReachedReturnedOffsets.isUnknown()) {
1057 ReturnedOffsets.setUnknown();
1058 return ChangeStatus::CHANGED;
1059 }
1060 if (ReturnedOffsets.merge(R: ReachedReturnedOffsets))
1061 return ChangeStatus::CHANGED;
1062 return ChangeStatus::UNCHANGED;
1063 }
1064
1065 bool forallInterferingAccesses(
1066 AA::RangeTy Range,
1067 function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
1068 const override {
1069 return State::forallInterferingAccesses(Range, CB);
1070 }
1071
1072 bool forallInterferingAccesses(
1073 Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
1074 bool FindInterferingWrites, bool FindInterferingReads,
1075 function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
1076 AA::RangeTy &Range,
1077 function_ref<bool(const Access &)> SkipCB) const override {
1078 HasBeenWrittenTo = false;
1079
1080 SmallPtrSet<const Access *, 8> DominatingWrites;
1081 SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;
1082
1083 Function &Scope = *I.getFunction();
1084 bool IsKnownNoSync;
1085 bool IsAssumedNoSync = AA::hasAssumedIRAttr<Attribute::NoSync>(
1086 A, QueryingAA: &QueryingAA, IRP: IRPosition::function(F: Scope), DepClass: DepClassTy::OPTIONAL,
1087 IsKnown&: IsKnownNoSync);
1088 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
1089 IRP: IRPosition::function(F: Scope), QueryingAA: &QueryingAA, DepClass: DepClassTy::NONE);
1090 bool AllInSameNoSyncFn = IsAssumedNoSync;
1091 bool InstIsExecutedByInitialThreadOnly =
1092 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);
1093
1094 // If the function is not ending in aligned barriers, we need the stores to
1095 // be in aligned barriers. The load being in one is not sufficient since the
1096 // store might be executed by a thread that disappears after, causing the
1097 // aligned barrier guarding the load to unblock and the load to read a value
1098 // that has no CFG path to the load.
1099 bool InstIsExecutedInAlignedRegion =
1100 FindInterferingReads && ExecDomainAA &&
1101 ExecDomainAA->isExecutedInAlignedRegion(A, I);
1102
1103 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1104 A.recordDependence(FromAA: *ExecDomainAA, ToAA: QueryingAA, DepClass: DepClassTy::OPTIONAL);
1105
1106 InformationCache &InfoCache = A.getInfoCache();
1107 bool IsThreadLocalObj =
1108 AA::isAssumedThreadLocalObject(A, Obj&: getAssociatedValue(), QueryingAA: *this);
1109
1110 // Helper to determine if we need to consider threading, which we cannot
1111 // right now. However, if the function is (assumed) nosync or the thread
1112 // executing all instructions is the main thread only we can ignore
1113 // threading. Also, thread-local objects do not require threading reasoning.
1114 // Finally, we can ignore threading if either access is executed in an
1115 // aligned region.
1116 auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
1117 if (IsThreadLocalObj || AllInSameNoSyncFn)
1118 return true;
1119 const auto *FnExecDomainAA =
1120 I.getFunction() == &Scope
1121 ? ExecDomainAA
1122 : A.lookupAAFor<AAExecutionDomain>(
1123 IRP: IRPosition::function(F: *I.getFunction()), QueryingAA: &QueryingAA,
1124 DepClass: DepClassTy::NONE);
1125 if (!FnExecDomainAA)
1126 return false;
1127 if (InstIsExecutedInAlignedRegion ||
1128 (FindInterferingWrites &&
1129 FnExecDomainAA->isExecutedInAlignedRegion(A, I))) {
1130 A.recordDependence(FromAA: *FnExecDomainAA, ToAA: QueryingAA, DepClass: DepClassTy::OPTIONAL);
1131 return true;
1132 }
1133 if (InstIsExecutedByInitialThreadOnly &&
1134 FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
1135 A.recordDependence(FromAA: *FnExecDomainAA, ToAA: QueryingAA, DepClass: DepClassTy::OPTIONAL);
1136 return true;
1137 }
1138 return false;
1139 };
1140
1141 // Helper to determine if the access is executed by the same thread as the
1142 // given instruction, for now it is sufficient to avoid any potential
1143 // threading effects as we cannot deal with them anyway.
1144 auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
1145 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1146 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1147 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1148 };
1149
1150 // TODO: Use inter-procedural reachability and dominance.
1151 bool IsKnownNoRecurse;
1152 AA::hasAssumedIRAttr<Attribute::NoRecurse>(
1153 A, QueryingAA: this, IRP: IRPosition::function(F: Scope), DepClass: DepClassTy::OPTIONAL,
1154 IsKnown&: IsKnownNoRecurse);
1155
1156 // TODO: Use reaching kernels from AAKernelInfo (or move it to
1157 // AAExecutionDomain) such that we allow scopes other than kernels as long
1158 // as the reaching kernels are disjoint.
1159 bool InstInKernel = A.getInfoCache().isKernel(F: Scope);
1160 bool ObjHasKernelLifetime = false;
1161 const bool UseDominanceReasoning =
1162 FindInterferingWrites && IsKnownNoRecurse;
1163 const DominatorTree *DT =
1164 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(F: Scope);
1165
1166 // Helper to check if a value has "kernel lifetime", that is it will not
1167 // outlive a GPU kernel. This is true for shared, constant, and local
1168 // globals on AMD and NVIDIA GPUs.
1169 auto HasKernelLifetime = [&](Value *V, Module &M) {
1170 if (!AA::isGPU(M))
1171 return false;
1172 unsigned VAS = V->getType()->getPointerAddressSpace();
1173 return AA::isGPUSharedAddressSpace(M, AS: VAS) ||
1174 AA::isGPUConstantAddressSpace(M, AS: VAS) ||
1175 AA::isGPULocalAddressSpace(M, AS: VAS);
1176 };
1177
1178 // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
1179 // to determine if we should look at reachability from the callee. For
1180 // certain pointers we know the lifetime and we do not have to step into the
1181 // callee to determine reachability as the pointer would be dead in the
1182 // callee. See the conditional initialization below.
1183 std::function<bool(const Function &)> IsLiveInCalleeCB;
1184
1185 if (auto *AI = dyn_cast<AllocaInst>(Val: &getAssociatedValue())) {
1186 // If the alloca containing function is not recursive the alloca
1187 // must be dead in the callee.
1188 const Function *AIFn = AI->getFunction();
1189 ObjHasKernelLifetime = A.getInfoCache().isKernel(F: *AIFn);
1190 bool IsKnownNoRecurse;
1191 if (AA::hasAssumedIRAttr<Attribute::NoRecurse>(
1192 A, QueryingAA: this, IRP: IRPosition::function(F: *AIFn), DepClass: DepClassTy::OPTIONAL,
1193 IsKnown&: IsKnownNoRecurse)) {
1194 IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
1195 }
1196 } else if (auto *GV = dyn_cast<GlobalValue>(Val: &getAssociatedValue())) {
1197 // If the global has kernel lifetime we can stop if we reach a kernel
1198 // as it is "dead" in the (unknown) callees.
1199 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1200 if (ObjHasKernelLifetime)
1201 IsLiveInCalleeCB = [&A](const Function &Fn) {
1202 return !A.getInfoCache().isKernel(F: Fn);
1203 };
1204 }
1205
1206 // Set of accesses/instructions that will overwrite the result and are
1207 // therefore blockers in the reachability traversal.
1208 AA::InstExclusionSetTy ExclusionSet;
1209
1210 auto AccessCB = [&](const Access &Acc, bool Exact) {
1211 Function *AccScope = Acc.getRemoteInst()->getFunction();
1212 bool AccInSameScope = AccScope == &Scope;
1213
1214 // If the object has kernel lifetime we can ignore accesses only reachable
1215 // by other kernels. For now we only skip accesses *in* other kernels.
1216 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1217 A.getInfoCache().isKernel(F: *AccScope))
1218 return true;
1219
1220 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
1221 if (Acc.isWrite() || (isa<LoadInst>(Val: I) && Acc.isWriteOrAssumption()))
1222 ExclusionSet.insert(Ptr: Acc.getRemoteInst());
1223 }
1224
1225 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1226 (!FindInterferingReads || !Acc.isRead()))
1227 return true;
1228
1229 bool Dominates = FindInterferingWrites && DT && Exact &&
1230 Acc.isMustAccess() && AccInSameScope &&
1231 DT->dominates(Def: Acc.getRemoteInst(), User: &I);
1232 if (Dominates)
1233 DominatingWrites.insert(Ptr: &Acc);
1234
1235 // Track if all interesting accesses are in the same `nosync` function as
1236 // the given instruction.
1237 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;
1238
1239 InterferingAccesses.push_back(Elt: {&Acc, Exact});
1240 return true;
1241 };
1242 if (!State::forallInterferingAccesses(I, CB: AccessCB, Range))
1243 return false;
1244
1245 HasBeenWrittenTo = !DominatingWrites.empty();
1246
1247 // Dominating writes form a chain, find the least/lowest member.
1248 Instruction *LeastDominatingWriteInst = nullptr;
1249 for (const Access *Acc : DominatingWrites) {
1250 if (!LeastDominatingWriteInst) {
1251 LeastDominatingWriteInst = Acc->getRemoteInst();
1252 } else if (DT->dominates(Def: LeastDominatingWriteInst,
1253 User: Acc->getRemoteInst())) {
1254 LeastDominatingWriteInst = Acc->getRemoteInst();
1255 }
1256 }
1257
1258 // Helper to determine if we can skip a specific write access.
1259 auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
1260 if (SkipCB && SkipCB(Acc))
1261 return true;
1262 if (!CanIgnoreThreading(Acc))
1263 return false;
1264
1265 // Check read (RAW) dependences and write (WAR) dependences as necessary.
1266 // If we successfully excluded all effects we are interested in, the
1267 // access can be skipped.
1268 bool ReadChecked = !FindInterferingReads;
1269 bool WriteChecked = !FindInterferingWrites;
1270
1271 // If the instruction cannot reach the access, the former does not
1272 // interfere with what the access reads.
1273 if (!ReadChecked) {
1274 if (!AA::isPotentiallyReachable(A, FromI: I, ToI: *Acc.getRemoteInst(), QueryingAA,
1275 ExclusionSet: &ExclusionSet, GoBackwardsCB: IsLiveInCalleeCB))
1276 ReadChecked = true;
1277 }
1278 // If the instruction cannot be reach from the access, the latter does not
1279 // interfere with what the instruction reads.
1280 if (!WriteChecked) {
1281 if (!AA::isPotentiallyReachable(A, FromI: *Acc.getRemoteInst(), ToI: I, QueryingAA,
1282 ExclusionSet: &ExclusionSet, GoBackwardsCB: IsLiveInCalleeCB))
1283 WriteChecked = true;
1284 }
1285
1286 // If we still might be affected by the write of the access but there are
1287 // dominating writes in the function of the instruction
1288 // (HasBeenWrittenTo), we can try to reason that the access is overwritten
1289 // by them. This would have happend above if they are all in the same
1290 // function, so we only check the inter-procedural case. Effectively, we
1291 // want to show that there is no call after the dominting write that might
1292 // reach the access, and when it returns reach the instruction with the
1293 // updated value. To this end, we iterate all call sites, check if they
1294 // might reach the instruction without going through another access
1295 // (ExclusionSet) and at the same time might reach the access. However,
1296 // that is all part of AAInterFnReachability.
1297 if (!WriteChecked && HasBeenWrittenTo &&
1298 Acc.getRemoteInst()->getFunction() != &Scope) {
1299
1300 const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
1301 QueryingAA, IRP: IRPosition::function(F: Scope), DepClass: DepClassTy::OPTIONAL);
1302 if (FnReachabilityAA) {
1303 // Without going backwards in the call tree, can we reach the access
1304 // from the least dominating write. Do not allow to pass the
1305 // instruction itself either.
1306 bool Inserted = ExclusionSet.insert(Ptr: &I).second;
1307
1308 if (!FnReachabilityAA->instructionCanReach(
1309 A, Inst: *LeastDominatingWriteInst,
1310 Fn: *Acc.getRemoteInst()->getFunction(), ExclusionSet: &ExclusionSet))
1311 WriteChecked = true;
1312
1313 if (Inserted)
1314 ExclusionSet.erase(Ptr: &I);
1315 }
1316 }
1317
1318 if (ReadChecked && WriteChecked)
1319 return true;
1320
1321 if (!DT || !UseDominanceReasoning)
1322 return false;
1323 if (!DominatingWrites.count(Ptr: &Acc))
1324 return false;
1325 return LeastDominatingWriteInst != Acc.getRemoteInst();
1326 };
1327
1328 // Run the user callback on all accesses we cannot skip and return if
1329 // that succeeded for all or not.
1330 for (auto &It : InterferingAccesses) {
1331 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1332 !CanSkipAccess(*It.first, It.second)) {
1333 if (!UserCB(*It.first, It.second))
1334 return false;
1335 }
1336 }
1337 return true;
1338 }
1339
1340 ChangeStatus translateAndAddStateFromCallee(Attributor &A,
1341 const AAPointerInfo &OtherAA,
1342 CallBase &CB) {
1343 using namespace AA::PointerInfo;
1344 if (!OtherAA.getState().isValidState() || !isValidState())
1345 return indicatePessimisticFixpoint();
1346
1347 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1348 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1349 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1350 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1351
1352 // Combine the accesses bin by bin.
1353 const auto &State = OtherAAImpl.getState();
1354 for (const auto &It : State) {
1355 for (auto Index : It.getSecond()) {
1356 const auto &RAcc = State.getAccess(Index);
1357 if (IsByval && !RAcc.isRead())
1358 continue;
1359 bool UsedAssumedInformation = false;
1360 AccessKind AK = RAcc.getKind();
1361 auto Content = A.translateArgumentToCallSiteContent(
1362 V: RAcc.getContent(), CB, AA: *this, UsedAssumedInformation);
1363 AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1364 AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1365
1366 Changed |= addAccess(A, Ranges: RAcc.getRanges(), I&: CB, Content, Kind: AK,
1367 Ty: RAcc.getType(), RemoteI: RAcc.getRemoteInst());
1368 }
1369 }
1370 return Changed;
1371 }
1372
1373 ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
1374 const OffsetInfo &Offsets, CallBase &CB,
1375 bool IsMustAcc) {
1376 using namespace AA::PointerInfo;
1377 if (!OtherAA.getState().isValidState() || !isValidState())
1378 return indicatePessimisticFixpoint();
1379
1380 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1381
1382 // Combine the accesses bin by bin.
1383 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1384 const auto &State = OtherAAImpl.getState();
1385 for (const auto &It : State) {
1386 for (auto Index : It.getSecond()) {
1387 const auto &RAcc = State.getAccess(Index);
1388 if (!IsMustAcc && RAcc.isAssumption())
1389 continue;
1390 for (auto Offset : Offsets) {
1391 auto NewRanges = Offset == AA::RangeTy::Unknown
1392 ? AA::RangeTy::getUnknown()
1393 : RAcc.getRanges();
1394 if (!NewRanges.isUnknown()) {
1395 NewRanges.addToAllOffsets(Inc: Offset);
1396 }
1397 AccessKind AK = RAcc.getKind();
1398 if (!IsMustAcc)
1399 AK = AccessKind((AK & ~AK_MUST) | AK_MAY);
1400 Changed |= addAccess(A, Ranges: NewRanges, I&: CB, Content: RAcc.getContent(), Kind: AK,
1401 Ty: RAcc.getType(), RemoteI: RAcc.getRemoteInst());
1402 }
1403 }
1404 }
1405 return Changed;
1406 }
1407
1408 /// Statistic tracking for all AAPointerInfo implementations.
1409 /// See AbstractAttribute::trackStatistics().
1410 void trackPointerInfoStatistics(const IRPosition &IRP) const {}
1411
1412 /// Dump the state into \p O.
1413 void dumpState(raw_ostream &O) {
1414 for (auto &It : OffsetBins) {
1415 O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
1416 << "] : " << It.getSecond().size() << "\n";
1417 for (auto AccIndex : It.getSecond()) {
1418 auto &Acc = AccessList[AccIndex];
1419 O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
1420 if (Acc.getLocalInst() != Acc.getRemoteInst())
1421 O << " --> " << *Acc.getRemoteInst()
1422 << "\n";
1423 if (!Acc.isWrittenValueYetUndetermined()) {
1424 if (isa_and_nonnull<Function>(Val: Acc.getWrittenValue()))
1425 O << " - c: func " << Acc.getWrittenValue()->getName()
1426 << "\n";
1427 else if (Acc.getWrittenValue())
1428 O << " - c: " << *Acc.getWrittenValue() << "\n";
1429 else
1430 O << " - c: <unknown>\n";
1431 }
1432 }
1433 }
1434 }
1435};
1436
1437struct AAPointerInfoFloating : public AAPointerInfoImpl {
1438 using AccessKind = AAPointerInfo::AccessKind;
1439 AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
1440 : AAPointerInfoImpl(IRP, A) {}
1441
1442 /// Deal with an access and signal if it was handled successfully.
1443 bool handleAccess(Attributor &A, Instruction &I,
1444 std::optional<Value *> Content, AccessKind Kind,
1445 OffsetInfo::VecTy &Offsets, ChangeStatus &Changed,
1446 Type &Ty) {
1447 using namespace AA::PointerInfo;
1448 auto Size = AA::RangeTy::Unknown;
1449 const DataLayout &DL = A.getDataLayout();
1450 TypeSize AccessSize = DL.getTypeStoreSize(Ty: &Ty);
1451 if (!AccessSize.isScalable())
1452 Size = AccessSize.getFixedValue();
1453
1454 // Make a strictly ascending list of offsets as required by addAccess()
1455 SmallVector<int64_t> OffsetsSorted(Offsets.begin(), Offsets.end());
1456 llvm::sort(C&: OffsetsSorted);
1457
1458 VectorType *VT = dyn_cast<VectorType>(Val: &Ty);
1459 if (!VT || VT->getElementCount().isScalable() ||
1460 !Content.value_or(u: nullptr) || !isa<Constant>(Val: *Content) ||
1461 (*Content)->getType() != VT ||
1462 DL.getTypeStoreSize(Ty: VT->getElementType()).isScalable()) {
1463 Changed =
1464 Changed | addAccess(A, Ranges: {OffsetsSorted, Size}, I, Content, Kind, Ty: &Ty);
1465 } else {
1466 // Handle vector stores with constant content element-wise.
1467 // TODO: We could look for the elements or create instructions
1468 // representing them.
1469 // TODO: We need to push the Content into the range abstraction
1470 // (AA::RangeTy) to allow different content values for different
1471 // ranges. ranges. Hence, support vectors storing different values.
1472 Type *ElementType = VT->getElementType();
1473 int64_t ElementSize = DL.getTypeStoreSize(Ty: ElementType).getFixedValue();
1474 auto *ConstContent = cast<Constant>(Val: *Content);
1475 Type *Int32Ty = Type::getInt32Ty(C&: ElementType->getContext());
1476 SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());
1477
1478 for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1479 Value *ElementContent = ConstantExpr::getExtractElement(
1480 Vec: ConstContent, Idx: ConstantInt::get(Ty: Int32Ty, V: i));
1481
1482 // Add the element access.
1483 Changed = Changed | addAccess(A, Ranges: {ElementOffsets, ElementSize}, I,
1484 Content: ElementContent, Kind, Ty: ElementType);
1485
1486 // Advance the offsets for the next element.
1487 for (auto &ElementOffset : ElementOffsets)
1488 ElementOffset += ElementSize;
1489 }
1490 }
1491 return true;
1492 };
1493
1494 /// See AbstractAttribute::updateImpl(...).
1495 ChangeStatus updateImpl(Attributor &A) override;
1496
1497 /// If the indices to \p GEP can be traced to constants, incorporate all
1498 /// of these into \p UsrOI.
1499 ///
1500 /// \return true iff \p UsrOI is updated.
1501 bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
1502 OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
1503 const GEPOperator *GEP);
1504
1505 /// See AbstractAttribute::trackStatistics()
1506 void trackStatistics() const override {
1507 AAPointerInfoImpl::trackPointerInfoStatistics(IRP: getIRPosition());
1508 }
1509};
1510
1511bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
1512 const DataLayout &DL,
1513 OffsetInfo &UsrOI,
1514 const OffsetInfo &PtrOI,
1515 const GEPOperator *GEP) {
1516 unsigned BitWidth = DL.getIndexTypeSizeInBits(Ty: GEP->getType());
1517 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1518 APInt ConstantOffset(BitWidth, 0);
1519
1520 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1521 "Don't look for constant values if the offset has already been "
1522 "determined to be unknown.");
1523
1524 if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
1525 UsrOI.setUnknown();
1526 return true;
1527 }
1528
1529 LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "
1530 << (VariableOffsets.empty() ? "" : "not") << " constant "
1531 << *GEP << "\n");
1532
1533 auto Union = PtrOI;
1534 Union.addToAll(Inc: ConstantOffset.getSExtValue());
1535
1536 // Each VI in VariableOffsets has a set of potential constant values. Every
1537 // combination of elements, picked one each from these sets, is separately
1538 // added to the original set of offsets, thus resulting in more offsets.
1539 for (const auto &VI : VariableOffsets) {
1540 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
1541 QueryingAA: *this, IRP: IRPosition::value(V: *VI.first), DepClass: DepClassTy::OPTIONAL);
1542 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1543 UsrOI.setUnknown();
1544 return true;
1545 }
1546
1547 // UndefValue is treated as a zero, which leaves Union as is.
1548 if (PotentialConstantsAA->undefIsContained())
1549 continue;
1550
1551 // We need at least one constant in every set to compute an actual offset.
1552 // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
1553 // don't actually exist. In other words, the absence of constant values
1554 // implies that the operation can be assumed dead for now.
1555 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1556 if (AssumedSet.empty())
1557 return false;
1558
1559 OffsetInfo Product;
1560 for (const auto &ConstOffset : AssumedSet) {
1561 auto CopyPerOffset = Union;
1562 CopyPerOffset.addToAll(Inc: ConstOffset.getSExtValue() *
1563 VI.second.getZExtValue());
1564 Product.merge(R: CopyPerOffset);
1565 }
1566 Union = Product;
1567 }
1568
1569 UsrOI = std::move(Union);
1570 return true;
1571}
1572
1573ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
1574 using namespace AA::PointerInfo;
1575 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1576 const DataLayout &DL = A.getDataLayout();
1577 Value &AssociatedValue = getAssociatedValue();
1578
1579 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1580 OffsetInfoMap[&AssociatedValue].insert(Offset: 0);
1581
1582 auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
1583 // One does not simply walk into a map and assign a reference to a possibly
1584 // new location. That can cause an invalidation before the assignment
1585 // happens, like so:
1586 //
1587 // OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
1588 //
1589 // The RHS is a reference that may be invalidated by an insertion caused by
1590 // the LHS. So we ensure that the side-effect of the LHS happens first.
1591
1592 assert(OffsetInfoMap.contains(CurPtr) &&
1593 "CurPtr does not exist in the map!");
1594
1595 auto &UsrOI = OffsetInfoMap[Usr];
1596 auto &PtrOI = OffsetInfoMap[CurPtr];
1597 assert(!PtrOI.isUnassigned() &&
1598 "Cannot pass through if the input Ptr was not visited!");
1599 UsrOI.merge(R: PtrOI);
1600 Follow = true;
1601 return true;
1602 };
1603
1604 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1605 Value *CurPtr = U.get();
1606 User *Usr = U.getUser();
1607 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usr
1608 << "\n");
1609 assert(OffsetInfoMap.count(CurPtr) &&
1610 "The current pointer offset should have been seeded!");
1611 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1612 "Current pointer should be assigned");
1613
1614 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Val: Usr)) {
1615 if (CE->isCast())
1616 return HandlePassthroughUser(Usr, CurPtr, Follow);
1617 if (!isa<GEPOperator>(Val: CE)) {
1618 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CE
1619 << "\n");
1620 return false;
1621 }
1622 }
1623 if (auto *GEP = dyn_cast<GEPOperator>(Val: Usr)) {
1624 // Note the order here, the Usr access might change the map, CurPtr is
1625 // already in it though.
1626 auto &UsrOI = OffsetInfoMap[Usr];
1627 auto &PtrOI = OffsetInfoMap[CurPtr];
1628
1629 if (UsrOI.isUnknown())
1630 return true;
1631
1632 if (PtrOI.isUnknown()) {
1633 Follow = true;
1634 UsrOI.setUnknown();
1635 return true;
1636 }
1637
1638 Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
1639 return true;
1640 }
1641 if (isa<PtrToIntInst>(Val: Usr))
1642 return false;
1643 if (isa<CastInst>(Val: Usr) || isa<SelectInst>(Val: Usr))
1644 return HandlePassthroughUser(Usr, CurPtr, Follow);
1645 // Returns are allowed if they are in the associated functions. Users can
1646 // then check the call site return. Returns from other functions can't be
1647 // tracked and are cause for invalidation.
1648 if (auto *RI = dyn_cast<ReturnInst>(Val: Usr)) {
1649 if (RI->getFunction() == getAssociatedFunction()) {
1650 auto &PtrOI = OffsetInfoMap[CurPtr];
1651 Changed |= setReachesReturn(PtrOI);
1652 return true;
1653 }
1654 return false;
1655 }
1656
1657 // For PHIs we need to take care of the recurrence explicitly as the value
1658 // might change while we iterate through a loop. For now, we give up if
1659 // the PHI is not invariant.
1660 if (auto *PHI = dyn_cast<PHINode>(Val: Usr)) {
1661 // Note the order here, the Usr access might change the map, CurPtr is
1662 // already in it though.
1663 auto [PhiIt, IsFirstPHIUser] = OffsetInfoMap.try_emplace(Key: PHI);
1664 auto &UsrOI = PhiIt->second;
1665 auto &PtrOI = OffsetInfoMap[CurPtr];
1666
1667 // Check if the PHI operand has already an unknown offset as we can't
1668 // improve on that anymore.
1669 if (PtrOI.isUnknown()) {
1670 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "
1671 << *CurPtr << " in " << *PHI << "\n");
1672 Follow = !UsrOI.isUnknown();
1673 UsrOI.setUnknown();
1674 return true;
1675 }
1676
1677 // Check if the PHI is invariant (so far).
1678 if (UsrOI == PtrOI) {
1679 assert(!PtrOI.isUnassigned() &&
1680 "Cannot assign if the current Ptr was not visited!");
1681 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)");
1682 return true;
1683 }
1684
1685 // Check if the PHI operand can be traced back to AssociatedValue.
1686 APInt Offset(
1687 DL.getIndexSizeInBits(AS: CurPtr->getType()->getPointerAddressSpace()),
1688 0);
1689 Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
1690 DL, Offset, /* AllowNonInbounds */ true);
1691 auto It = OffsetInfoMap.find(Val: CurPtrBase);
1692 if (It == OffsetInfoMap.end()) {
1693 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "
1694 << *CurPtr << " in " << *PHI
1695 << " (base: " << *CurPtrBase << ")\n");
1696 UsrOI.setUnknown();
1697 Follow = true;
1698 return true;
1699 }
1700
1701 // Check if the PHI operand is not dependent on the PHI itself. Every
1702 // recurrence is a cyclic net of PHIs in the data flow, and has an
1703 // equivalent Cycle in the control flow. One of those PHIs must be in the
1704 // header of that control flow Cycle. This is independent of the choice of
1705 // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
1706 // every Cycle header; if such a node is marked unknown, this will
1707 // eventually propagate through the whole net of PHIs in the recurrence.
1708 const auto *CI =
1709 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1710 F: *PHI->getFunction());
1711 if (mayBeInCycle(CI, I: cast<Instruction>(Val: Usr), /* HeaderOnly */ true)) {
1712 auto BaseOI = It->getSecond();
1713 BaseOI.addToAll(Inc: Offset.getZExtValue());
1714 if (IsFirstPHIUser || BaseOI == UsrOI) {
1715 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtr
1716 << " in " << *Usr << "\n");
1717 return HandlePassthroughUser(Usr, CurPtr, Follow);
1718 }
1719
1720 LLVM_DEBUG(
1721 dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
1722 << *CurPtr << " in " << *PHI << "\n");
1723 UsrOI.setUnknown();
1724 Follow = true;
1725 return true;
1726 }
1727
1728 UsrOI.merge(R: PtrOI);
1729 Follow = true;
1730 return true;
1731 }
1732
1733 if (auto *LoadI = dyn_cast<LoadInst>(Val: Usr)) {
1734 // If the access is to a pointer that may or may not be the associated
1735 // value, e.g. due to a PHI, we cannot assume it will be read.
1736 AccessKind AK = AccessKind::AK_R;
1737 if (getUnderlyingObject(V: CurPtr) == &AssociatedValue)
1738 AK = AccessKind(AK | AccessKind::AK_MUST);
1739 else
1740 AK = AccessKind(AK | AccessKind::AK_MAY);
1741 if (!handleAccess(A, I&: *LoadI, /* Content */ nullptr, Kind: AK,
1742 Offsets&: OffsetInfoMap[CurPtr].Offsets, Changed,
1743 Ty&: *LoadI->getType()))
1744 return false;
1745
1746 auto IsAssumption = [](Instruction &I) {
1747 if (auto *II = dyn_cast<IntrinsicInst>(Val: &I))
1748 return II->isAssumeLikeIntrinsic();
1749 return false;
1750 };
1751
1752 auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
1753 // Check if the assumption and the load are executed together without
1754 // memory modification.
1755 do {
1756 if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
1757 return true;
1758 FromI = FromI->getNextNode();
1759 } while (FromI && FromI != ToI);
1760 return false;
1761 };
1762
1763 BasicBlock *BB = LoadI->getParent();
1764 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1765 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1766 return false;
1767 BasicBlock *IntrBB = IntrI.getParent();
1768 if (IntrI.getParent() == BB) {
1769 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1770 return false;
1771 } else {
1772 auto PredIt = pred_begin(BB: IntrBB);
1773 if (PredIt == pred_end(BB: IntrBB))
1774 return false;
1775 if ((*PredIt) != BB)
1776 return false;
1777 if (++PredIt != pred_end(BB: IntrBB))
1778 return false;
1779 for (auto *SuccBB : successors(BB)) {
1780 if (SuccBB == IntrBB)
1781 continue;
1782 if (isa<UnreachableInst>(Val: SuccBB->getTerminator()))
1783 continue;
1784 return false;
1785 }
1786 if (IsImpactedInRange(LoadI->getNextNode(), BB->getTerminator()))
1787 return false;
1788 if (IsImpactedInRange(&IntrBB->front(), &IntrI))
1789 return false;
1790 }
1791 return true;
1792 };
1793
1794 std::pair<Value *, IntrinsicInst *> Assumption;
1795 for (const Use &LoadU : LoadI->uses()) {
1796 if (auto *CmpI = dyn_cast<CmpInst>(Val: LoadU.getUser())) {
1797 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1798 continue;
1799 for (const Use &CmpU : CmpI->uses()) {
1800 if (auto *IntrI = dyn_cast<IntrinsicInst>(Val: CmpU.getUser())) {
1801 if (!IsValidAssume(*IntrI))
1802 continue;
1803 int Idx = CmpI->getOperandUse(i: 0) == LoadU;
1804 Assumption = {CmpI->getOperand(i_nocapture: Idx), IntrI};
1805 break;
1806 }
1807 }
1808 }
1809 if (Assumption.first)
1810 break;
1811 }
1812
1813 // Check if we found an assumption associated with this load.
1814 if (!Assumption.first || !Assumption.second)
1815 return true;
1816
1817 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "
1818 << *Assumption.second << ": " << *LoadI
1819 << " == " << *Assumption.first << "\n");
1820 bool UsedAssumedInformation = false;
1821 std::optional<Value *> Content = nullptr;
1822 if (Assumption.first)
1823 Content =
1824 A.getAssumedSimplified(V: *Assumption.first, AA: *this,
1825 UsedAssumedInformation, S: AA::Interprocedural);
1826 return handleAccess(
1827 A, I&: *Assumption.second, Content, Kind: AccessKind::AK_ASSUMPTION,
1828 Offsets&: OffsetInfoMap[CurPtr].Offsets, Changed, Ty&: *LoadI->getType());
1829 }
1830
1831 auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
1832 ArrayRef<Value *> OtherOps, AccessKind AK) {
1833 for (auto *OtherOp : OtherOps) {
1834 if (OtherOp == CurPtr) {
1835 LLVM_DEBUG(
1836 dbgs()
1837 << "[AAPointerInfo] Escaping use in store like instruction " << I
1838 << "\n");
1839 return false;
1840 }
1841 }
1842
1843 // If the access is to a pointer that may or may not be the associated
1844 // value, e.g. due to a PHI, we cannot assume it will be written.
1845 if (getUnderlyingObject(V: CurPtr) == &AssociatedValue)
1846 AK = AccessKind(AK | AccessKind::AK_MUST);
1847 else
1848 AK = AccessKind(AK | AccessKind::AK_MAY);
1849 bool UsedAssumedInformation = false;
1850 std::optional<Value *> Content = nullptr;
1851 if (ValueOp)
1852 Content = A.getAssumedSimplified(
1853 V: *ValueOp, AA: *this, UsedAssumedInformation, S: AA::Interprocedural);
1854 return handleAccess(A, I, Content, Kind: AK, Offsets&: OffsetInfoMap[CurPtr].Offsets,
1855 Changed, Ty&: ValueTy);
1856 };
1857
1858 if (auto *StoreI = dyn_cast<StoreInst>(Val: Usr))
1859 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1860 *StoreI->getValueOperand()->getType(),
1861 {StoreI->getValueOperand()}, AccessKind::AK_W);
1862 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Val: Usr))
1863 return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
1864 {RMWI->getValOperand()}, AccessKind::AK_RW);
1865 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Val: Usr))
1866 return HandleStoreLike(
1867 *CXI, nullptr, *CXI->getNewValOperand()->getType(),
1868 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1869 AccessKind::AK_RW);
1870
1871 if (auto *CB = dyn_cast<CallBase>(Val: Usr)) {
1872 if (CB->isLifetimeStartOrEnd())
1873 return true;
1874 const auto *TLI =
1875 A.getInfoCache().getTargetLibraryInfoForFunction(F: *CB->getFunction());
1876 if (getFreedOperand(CB, TLI) == U)
1877 return true;
1878 if (CB->isArgOperand(U: &U)) {
1879 unsigned ArgNo = CB->getArgOperandNo(U: &U);
1880 const auto *CSArgPI = A.getAAFor<AAPointerInfo>(
1881 QueryingAA: *this, IRP: IRPosition::callsite_argument(CB: *CB, ArgNo),
1882 DepClass: DepClassTy::REQUIRED);
1883 if (!CSArgPI)
1884 return false;
1885 bool IsArgMustAcc = (getUnderlyingObject(V: CurPtr) == &AssociatedValue);
1886 Changed = translateAndAddState(A, OtherAA: *CSArgPI, Offsets: OffsetInfoMap[CurPtr], CB&: *CB,
1887 IsMustAcc: IsArgMustAcc) |
1888 Changed;
1889 if (!CSArgPI->reachesReturn())
1890 return isValidState();
1891
1892 Function *Callee = CB->getCalledFunction();
1893 if (!Callee || Callee->arg_size() <= ArgNo)
1894 return false;
1895 bool UsedAssumedInformation = false;
1896 auto ReturnedValue = A.getAssumedSimplified(
1897 IRP: IRPosition::returned(F: *Callee), AA: *this, UsedAssumedInformation,
1898 S: AA::ValueScope::Intraprocedural);
1899 auto *ReturnedArg =
1900 dyn_cast_or_null<Argument>(Val: ReturnedValue.value_or(u: nullptr));
1901 auto *Arg = Callee->getArg(i: ArgNo);
1902 if (ReturnedArg && Arg != ReturnedArg)
1903 return true;
1904 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1905 const auto *CSRetPI = A.getAAFor<AAPointerInfo>(
1906 QueryingAA: *this, IRP: IRPosition::callsite_returned(CB: *CB), DepClass: DepClassTy::REQUIRED);
1907 if (!CSRetPI)
1908 return false;
1909 OffsetInfo OI = OffsetInfoMap[CurPtr];
1910 CSArgPI->addReturnedOffsetsTo(OI);
1911 Changed =
1912 translateAndAddState(A, OtherAA: *CSRetPI, Offsets: OI, CB&: *CB, IsMustAcc: IsRetMustAcc) | Changed;
1913 return isValidState();
1914 }
1915 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CB
1916 << "\n");
1917 return false;
1918 }
1919
1920 LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n");
1921 return false;
1922 };
1923 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
1924 assert(OffsetInfoMap.count(OldU) && "Old use should be known already!");
1925 assert(!OffsetInfoMap[OldU].isUnassigned() && "Old use should be assinged");
1926 if (OffsetInfoMap.count(Val: NewU)) {
1927 LLVM_DEBUG({
1928 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1929 dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
1930 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]
1931 << "\n";
1932 }
1933 });
1934 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1935 }
1936 bool Unused;
1937 return HandlePassthroughUser(NewU.get(), OldU.get(), Unused);
1938 };
1939 if (!A.checkForAllUses(Pred: UsePred, QueryingAA: *this, V: AssociatedValue,
1940 /* CheckBBLivenessOnly */ true, LivenessDepClass: DepClassTy::OPTIONAL,
1941 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
1942 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n");
1943 return indicatePessimisticFixpoint();
1944 }
1945
1946 LLVM_DEBUG({
1947 dbgs() << "Accesses by bin after update:\n";
1948 dumpState(dbgs());
1949 });
1950
1951 return Changed;
1952}
1953
1954struct AAPointerInfoReturned final : AAPointerInfoImpl {
1955 AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
1956 : AAPointerInfoImpl(IRP, A) {}
1957
1958 /// See AbstractAttribute::updateImpl(...).
1959 ChangeStatus updateImpl(Attributor &A) override {
1960 return indicatePessimisticFixpoint();
1961 }
1962
1963 /// See AbstractAttribute::trackStatistics()
1964 void trackStatistics() const override {
1965 AAPointerInfoImpl::trackPointerInfoStatistics(IRP: getIRPosition());
1966 }
1967};
1968
1969struct AAPointerInfoArgument final : AAPointerInfoFloating {
1970 AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
1971 : AAPointerInfoFloating(IRP, A) {}
1972
1973 /// See AbstractAttribute::trackStatistics()
1974 void trackStatistics() const override {
1975 AAPointerInfoImpl::trackPointerInfoStatistics(IRP: getIRPosition());
1976 }
1977};
1978
1979struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1980 AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
1981 : AAPointerInfoFloating(IRP, A) {}
1982
1983 /// See AbstractAttribute::updateImpl(...).
1984 ChangeStatus updateImpl(Attributor &A) override {
1985 using namespace AA::PointerInfo;
1986 // We handle memory intrinsics explicitly, at least the first (=
1987 // destination) and second (=source) arguments as we know how they are
1988 // accessed.
1989 if (auto *MI = dyn_cast_or_null<MemIntrinsic>(Val: getCtxI())) {
1990 int64_t LengthVal = AA::RangeTy::Unknown;
1991 if (auto Length = MI->getLengthInBytes())
1992 LengthVal = Length->getSExtValue();
1993 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1994 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1995 if (ArgNo > 1) {
1996 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
1997 << *MI << "\n");
1998 return indicatePessimisticFixpoint();
1999 } else {
2000 auto Kind =
2001 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
2002 Changed =
2003 Changed | addAccess(A, Ranges: {0, LengthVal}, I&: *MI, Content: nullptr, Kind, Ty: nullptr);
2004 }
2005 LLVM_DEBUG({
2006 dbgs() << "Accesses by bin after update:\n";
2007 dumpState(dbgs());
2008 });
2009
2010 return Changed;
2011 }
2012
2013 // TODO: Once we have call site specific value information we can provide
2014 // call site specific liveness information and then it makes
2015 // sense to specialize attributes for call sites arguments instead of
2016 // redirecting requests to the callee argument.
2017 Argument *Arg = getAssociatedArgument();
2018 if (Arg) {
2019 const IRPosition &ArgPos = IRPosition::argument(Arg: *Arg);
2020 auto *ArgAA =
2021 A.getAAFor<AAPointerInfo>(QueryingAA: *this, IRP: ArgPos, DepClass: DepClassTy::REQUIRED);
2022 if (ArgAA && ArgAA->getState().isValidState())
2023 return translateAndAddStateFromCallee(A, OtherAA: *ArgAA,
2024 CB&: *cast<CallBase>(Val: getCtxI()));
2025 if (!Arg->getParent()->isDeclaration())
2026 return indicatePessimisticFixpoint();
2027 }
2028
2029 bool IsKnownNoCapture;
2030 if (!AA::hasAssumedIRAttr<Attribute::Captures>(
2031 A, QueryingAA: this, IRP: getIRPosition(), DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoCapture))
2032 return indicatePessimisticFixpoint();
2033
2034 bool IsKnown = false;
2035 if (AA::isAssumedReadNone(A, IRP: getIRPosition(), QueryingAA: *this, IsKnown))
2036 return ChangeStatus::UNCHANGED;
2037 bool ReadOnly = AA::isAssumedReadOnly(A, IRP: getIRPosition(), QueryingAA: *this, IsKnown);
2038 auto Kind =
2039 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2040 return addAccess(A, Ranges: AA::RangeTy::getUnknown(), I&: *getCtxI(), Content: nullptr, Kind,
2041 Ty: nullptr);
2042 }
2043
2044 /// See AbstractAttribute::trackStatistics()
2045 void trackStatistics() const override {
2046 AAPointerInfoImpl::trackPointerInfoStatistics(IRP: getIRPosition());
2047 }
2048};
2049
2050struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2051 AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
2052 : AAPointerInfoFloating(IRP, A) {}
2053
2054 /// See AbstractAttribute::trackStatistics()
2055 void trackStatistics() const override {
2056 AAPointerInfoImpl::trackPointerInfoStatistics(IRP: getIRPosition());
2057 }
2058};
2059} // namespace
2060
2061/// -----------------------NoUnwind Function Attribute--------------------------
2062
2063namespace {
2064struct AANoUnwindImpl : AANoUnwind {
2065 AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}
2066
2067 /// See AbstractAttribute::initialize(...).
2068 void initialize(Attributor &A) override {
2069 bool IsKnown;
2070 assert(!AA::hasAssumedIRAttr<Attribute::NoUnwind>(
2071 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2072 (void)IsKnown;
2073 }
2074
2075 const std::string getAsStr(Attributor *A) const override {
2076 return getAssumed() ? "nounwind" : "may-unwind";
2077 }
2078
2079 /// See AbstractAttribute::updateImpl(...).
2080 ChangeStatus updateImpl(Attributor &A) override {
2081 auto Opcodes = {
2082 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
2083 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
2084 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
2085
2086 auto CheckForNoUnwind = [&](Instruction &I) {
2087 if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
2088 return true;
2089
2090 if (const auto *CB = dyn_cast<CallBase>(Val: &I)) {
2091 bool IsKnownNoUnwind;
2092 return AA::hasAssumedIRAttr<Attribute::NoUnwind>(
2093 A, QueryingAA: this, IRP: IRPosition::callsite_function(CB: *CB), DepClass: DepClassTy::REQUIRED,
2094 IsKnown&: IsKnownNoUnwind);
2095 }
2096 return false;
2097 };
2098
2099 bool UsedAssumedInformation = false;
2100 if (!A.checkForAllInstructions(Pred: CheckForNoUnwind, QueryingAA: *this, Opcodes,
2101 UsedAssumedInformation))
2102 return indicatePessimisticFixpoint();
2103
2104 return ChangeStatus::UNCHANGED;
2105 }
2106};
2107
2108struct AANoUnwindFunction final : public AANoUnwindImpl {
2109 AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
2110 : AANoUnwindImpl(IRP, A) {}
2111
2112 /// See AbstractAttribute::trackStatistics()
2113 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
2114};
2115
2116/// NoUnwind attribute deduction for a call sites.
2117struct AANoUnwindCallSite final
2118 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2119 AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
2120 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP, A) {}
2121
2122 /// See AbstractAttribute::trackStatistics()
2123 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }
2124};
2125} // namespace
2126
2127/// ------------------------ NoSync Function Attribute -------------------------
2128
2129bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
2130 switch (CB.getIntrinsicID()) {
2131 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2132 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2133 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2134 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2135 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2136 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2137 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2138 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2139 return true;
2140 case Intrinsic::amdgcn_s_barrier:
2141 if (ExecutedAligned)
2142 return true;
2143 break;
2144 default:
2145 break;
2146 }
2147 return hasAssumption(CB, AssumptionStr: KnownAssumptionString("ompx_aligned_barrier"));
2148}
2149
2150bool AANoSync::isNonRelaxedAtomic(const Instruction *I) {
2151 if (!I->isAtomic())
2152 return false;
2153
2154 if (auto *FI = dyn_cast<FenceInst>(Val: I))
2155 // All legal orderings for fence are stronger than monotonic.
2156 return FI->getSyncScopeID() != SyncScope::SingleThread;
2157 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(Val: I)) {
2158 // Unordered is not a legal ordering for cmpxchg.
2159 return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
2160 AI->getFailureOrdering() != AtomicOrdering::Monotonic);
2161 }
2162
2163 AtomicOrdering Ordering;
2164 switch (I->getOpcode()) {
2165 case Instruction::AtomicRMW:
2166 Ordering = cast<AtomicRMWInst>(Val: I)->getOrdering();
2167 break;
2168 case Instruction::Store:
2169 Ordering = cast<StoreInst>(Val: I)->getOrdering();
2170 break;
2171 case Instruction::Load:
2172 Ordering = cast<LoadInst>(Val: I)->getOrdering();
2173 break;
2174 default:
2175 llvm_unreachable(
2176 "New atomic operations need to be known in the attributor.");
2177 }
2178
2179 return (Ordering != AtomicOrdering::Unordered &&
2180 Ordering != AtomicOrdering::Monotonic);
2181}
2182
2183namespace {
2184struct AANoSyncImpl : AANoSync {
2185 AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}
2186
2187 /// See AbstractAttribute::initialize(...).
2188 void initialize(Attributor &A) override {
2189 bool IsKnown;
2190 assert(!AA::hasAssumedIRAttr<Attribute::NoSync>(A, nullptr, getIRPosition(),
2191 DepClassTy::NONE, IsKnown));
2192 (void)IsKnown;
2193 }
2194
2195 const std::string getAsStr(Attributor *A) const override {
2196 return getAssumed() ? "nosync" : "may-sync";
2197 }
2198
2199 /// See AbstractAttribute::updateImpl(...).
2200 ChangeStatus updateImpl(Attributor &A) override;
2201};
2202
2203ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
2204
2205 auto CheckRWInstForNoSync = [&](Instruction &I) {
2206 return AA::isNoSyncInst(A, I, QueryingAA: *this);
2207 };
2208
2209 auto CheckForNoSync = [&](Instruction &I) {
2210 // At this point we handled all read/write effects and they are all
2211 // nosync, so they can be skipped.
2212 if (I.mayReadOrWriteMemory())
2213 return true;
2214
2215 bool IsKnown;
2216 CallBase &CB = cast<CallBase>(Val&: I);
2217 if (AA::hasAssumedIRAttr<Attribute::NoSync>(
2218 A, QueryingAA: this, IRP: IRPosition::callsite_function(CB), DepClass: DepClassTy::OPTIONAL,
2219 IsKnown))
2220 return true;
2221
2222 // non-convergent and readnone imply nosync.
2223 return !CB.isConvergent();
2224 };
2225
2226 bool UsedAssumedInformation = false;
2227 if (!A.checkForAllReadWriteInstructions(Pred: CheckRWInstForNoSync, QueryingAA&: *this,
2228 UsedAssumedInformation) ||
2229 !A.checkForAllCallLikeInstructions(Pred: CheckForNoSync, QueryingAA: *this,
2230 UsedAssumedInformation))
2231 return indicatePessimisticFixpoint();
2232
2233 return ChangeStatus::UNCHANGED;
2234}
2235
2236struct AANoSyncFunction final : public AANoSyncImpl {
2237 AANoSyncFunction(const IRPosition &IRP, Attributor &A)
2238 : AANoSyncImpl(IRP, A) {}
2239
2240 /// See AbstractAttribute::trackStatistics()
2241 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
2242};
2243
2244/// NoSync attribute deduction for a call sites.
2245struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2246 AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
2247 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP, A) {}
2248
2249 /// See AbstractAttribute::trackStatistics()
2250 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }
2251};
2252} // namespace
2253
2254/// ------------------------ No-Free Attributes ----------------------------
2255
2256namespace {
2257struct AANoFreeImpl : public AANoFree {
2258 AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}
2259
2260 /// See AbstractAttribute::initialize(...).
2261 void initialize(Attributor &A) override {
2262 bool IsKnown;
2263 assert(!AA::hasAssumedIRAttr<Attribute::NoFree>(A, nullptr, getIRPosition(),
2264 DepClassTy::NONE, IsKnown));
2265 (void)IsKnown;
2266 }
2267
2268 /// See AbstractAttribute::updateImpl(...).
2269 ChangeStatus updateImpl(Attributor &A) override {
2270 auto CheckForNoFree = [&](Instruction &I) {
2271 if (auto *CB = dyn_cast<CallBase>(Val: &I)) {
2272 bool IsKnown;
2273 return AA::hasAssumedIRAttr<Attribute::NoFree>(
2274 A, QueryingAA: this, IRP: IRPosition::callsite_function(CB: *CB), DepClass: DepClassTy::REQUIRED,
2275 IsKnown);
2276 }
2277 // Make sure that synchronization cannot establish happens-before with a
2278 // free on another thread.
2279 return AA::isNoSyncInst(A, I, QueryingAA: *this);
2280 };
2281
2282 bool UsedAssumedInformation = false;
2283 if (!A.checkForAllReadWriteInstructions(Pred: CheckForNoFree, QueryingAA&: *this,
2284 UsedAssumedInformation) ||
2285 !A.checkForAllCallLikeInstructions(Pred: CheckForNoFree, QueryingAA: *this,
2286 UsedAssumedInformation))
2287 return indicatePessimisticFixpoint();
2288
2289 return ChangeStatus::UNCHANGED;
2290 }
2291
2292 /// See AbstractAttribute::getAsStr().
2293 const std::string getAsStr(Attributor *A) const override {
2294 return getAssumed() ? "nofree" : "may-free";
2295 }
2296};
2297
2298struct AANoFreeFunction final : public AANoFreeImpl {
2299 AANoFreeFunction(const IRPosition &IRP, Attributor &A)
2300 : AANoFreeImpl(IRP, A) {}
2301
2302 /// See AbstractAttribute::trackStatistics()
2303 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
2304};
2305
2306/// NoFree attribute deduction for a call sites.
2307struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2308 AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
2309 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP, A) {}
2310
2311 /// See AbstractAttribute::trackStatistics()
2312 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
2313};
2314
2315/// NoFree attribute for floating values.
2316struct AANoFreeFloating : AANoFreeImpl {
2317 AANoFreeFloating(const IRPosition &IRP, Attributor &A)
2318 : AANoFreeImpl(IRP, A) {}
2319
2320 /// See AbstractAttribute::trackStatistics()
2321 void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}
2322
2323 /// See Abstract Attribute::updateImpl(...).
2324 ChangeStatus updateImpl(Attributor &A) override {
2325 const IRPosition &IRP = getIRPosition();
2326
2327 bool IsKnown;
2328 if (AA::hasAssumedIRAttr<Attribute::NoFree>(A, QueryingAA: this,
2329 IRP: IRPosition::function_scope(IRP),
2330 DepClass: DepClassTy::OPTIONAL, IsKnown))
2331 return ChangeStatus::UNCHANGED;
2332
2333 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2334 auto Pred = [&](const Use &U, bool &Follow) -> bool {
2335 Instruction *UserI = cast<Instruction>(Val: U.getUser());
2336 if (auto *CB = dyn_cast<CallBase>(Val: UserI)) {
2337 if (CB->isBundleOperand(U: &U))
2338 return false;
2339 if (!CB->isArgOperand(U: &U))
2340 return true;
2341 unsigned ArgNo = CB->getArgOperandNo(U: &U);
2342
2343 // Even if the argument is nofree, we still need to check for nocapture,
2344 // as the call may capture the argument without freeing it, and the
2345 // captured argument is freed later.
2346 bool IsKnown;
2347 if (!AA::hasAssumedIRAttr<Attribute::NoFree>(
2348 A, QueryingAA: this, IRP: IRPosition::callsite_argument(CB: *CB, ArgNo),
2349 DepClass: DepClassTy::REQUIRED, IsKnown))
2350 return false;
2351
2352 const AANoCapture *NoCaptureAA = nullptr;
2353 if (!AA::hasAssumedIRAttr<Attribute::Captures>(
2354 A, QueryingAA: this, IRP: IRPosition::callsite_argument(CB: *CB, ArgNo),
2355 DepClass: DepClassTy::REQUIRED, IsKnown,
2356 /*IgnoreSubsumingPositions=*/false, AAPtr: &NoCaptureAA)) {
2357 if (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
2358 Follow = true;
2359 return true;
2360 }
2361 return false;
2362 }
2363
2364 return true;
2365 }
2366
2367 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
2368 if (!capturesAnyProvenance(CC: CI))
2369 return true;
2370 if (capturesAnyProvenance(CC: CI.ResultCC)) {
2371 Follow = true;
2372 return true;
2373 }
2374
2375 if (isa<ReturnInst>(Val: UserI) && getIRPosition().isArgumentPosition())
2376 return true;
2377
2378 // Capturing user.
2379 return false;
2380 };
2381 if (!A.checkForAllUses(Pred, QueryingAA: *this, V: AssociatedValue))
2382 return indicatePessimisticFixpoint();
2383
2384 return ChangeStatus::UNCHANGED;
2385 }
2386};
2387
2388/// NoFree attribute for a call site argument.
2389struct AANoFreeArgument final : AANoFreeFloating {
2390 AANoFreeArgument(const IRPosition &IRP, Attributor &A)
2391 : AANoFreeFloating(IRP, A) {}
2392
2393 /// See AbstractAttribute::trackStatistics()
2394 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }
2395};
2396
2397/// NoFree attribute for call site arguments.
2398struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2399 AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
2400 : AANoFreeFloating(IRP, A) {}
2401
2402 /// See AbstractAttribute::updateImpl(...).
2403 ChangeStatus updateImpl(Attributor &A) override {
2404 // TODO: Once we have call site specific value information we can provide
2405 // call site specific liveness information and then it makes
2406 // sense to specialize attributes for call sites arguments instead of
2407 // redirecting requests to the callee argument.
2408 Argument *Arg = getAssociatedArgument();
2409 if (!Arg)
2410 return indicatePessimisticFixpoint();
2411 const IRPosition &ArgPos = IRPosition::argument(Arg: *Arg);
2412 bool IsKnown;
2413 if (AA::hasAssumedIRAttr<Attribute::NoFree>(A, QueryingAA: this, IRP: ArgPos,
2414 DepClass: DepClassTy::REQUIRED, IsKnown))
2415 return ChangeStatus::UNCHANGED;
2416 return indicatePessimisticFixpoint();
2417 }
2418
2419 /// See AbstractAttribute::trackStatistics()
2420 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nofree) };
2421};
2422
2423/// NoFree attribute for function return value.
2424struct AANoFreeReturned final : AANoFreeFloating {
2425 AANoFreeReturned(const IRPosition &IRP, Attributor &A)
2426 : AANoFreeFloating(IRP, A) {
2427 llvm_unreachable("NoFree is not applicable to function returns!");
2428 }
2429
2430 /// See AbstractAttribute::initialize(...).
2431 void initialize(Attributor &A) override {
2432 llvm_unreachable("NoFree is not applicable to function returns!");
2433 }
2434
2435 /// See AbstractAttribute::updateImpl(...).
2436 ChangeStatus updateImpl(Attributor &A) override {
2437 llvm_unreachable("NoFree is not applicable to function returns!");
2438 }
2439
2440 /// See AbstractAttribute::trackStatistics()
2441 void trackStatistics() const override {}
2442};
2443
2444/// NoFree attribute deduction for a call site return value.
2445struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2446 AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
2447 : AANoFreeFloating(IRP, A) {}
2448
2449 ChangeStatus manifest(Attributor &A) override {
2450 return ChangeStatus::UNCHANGED;
2451 }
2452 /// See AbstractAttribute::trackStatistics()
2453 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }
2454};
2455} // namespace
2456
2457/// ------------------------ NonNull Argument Attribute ------------------------
2458
2459bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP,
2460 Attribute::AttrKind ImpliedAttributeKind,
2461 bool IgnoreSubsumingPositions) {
2462 SmallVector<Attribute::AttrKind, 2> AttrKinds;
2463 AttrKinds.push_back(Elt: Attribute::NonNull);
2464 if (!NullPointerIsDefined(F: IRP.getAnchorScope(),
2465 AS: IRP.getAssociatedType()->getPointerAddressSpace()))
2466 AttrKinds.push_back(Elt: Attribute::Dereferenceable);
2467 if (A.hasAttr(IRP, AKs: AttrKinds, IgnoreSubsumingPositions, ImpliedAttributeKind: Attribute::NonNull))
2468 return true;
2469
2470 DominatorTree *DT = nullptr;
2471 AssumptionCache *AC = nullptr;
2472 InformationCache &InfoCache = A.getInfoCache();
2473 if (const Function *Fn = IRP.getAnchorScope()) {
2474 if (!Fn->isDeclaration()) {
2475 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(F: *Fn);
2476 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(F: *Fn);
2477 }
2478 }
2479
2480 SmallVector<AA::ValueAndContext> Worklist;
2481 if (IRP.getPositionKind() != IRP_RETURNED) {
2482 Worklist.push_back(Elt: {IRP.getAssociatedValue(), IRP.getCtxI()});
2483 } else {
2484 bool UsedAssumedInformation = false;
2485 if (!A.checkForAllInstructions(
2486 Pred: [&](Instruction &I) {
2487 Worklist.push_back(Elt: {*cast<ReturnInst>(Val&: I).getReturnValue(), &I});
2488 return true;
2489 },
2490 Fn: IRP.getAssociatedFunction(), QueryingAA: nullptr, Opcodes: {Instruction::Ret},
2491 UsedAssumedInformation, CheckBBLivenessOnly: false, /*CheckPotentiallyDead=*/true))
2492 return false;
2493 }
2494
2495 if (llvm::any_of(Range&: Worklist, P: [&](AA::ValueAndContext VAC) {
2496 return !isKnownNonZero(
2497 V: VAC.getValue(),
2498 Q: SimplifyQuery(A.getDataLayout(), DT, AC, VAC.getCtxI()));
2499 }))
2500 return false;
2501
2502 A.manifestAttrs(IRP, DeducedAttrs: {Attribute::get(Context&: IRP.getAnchorValue().getContext(),
2503 Kind: Attribute::NonNull)});
2504 return true;
2505}
2506
2507namespace {
2508static int64_t getKnownNonNullAndDerefBytesForUse(
2509 Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
2510 const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
2511 TrackUse = false;
2512
2513 const Value *UseV = U->get();
2514 if (!UseV->getType()->isPointerTy())
2515 return 0;
2516
2517 // We need to follow common pointer manipulation uses to the accesses they
2518 // feed into. We can try to be smart to avoid looking through things we do not
2519 // like for now, e.g., non-inbounds GEPs.
2520 if (isa<CastInst>(Val: I)) {
2521 TrackUse = true;
2522 return 0;
2523 }
2524
2525 if (isa<GetElementPtrInst>(Val: I)) {
2526 TrackUse = true;
2527 return 0;
2528 }
2529
2530 Type *PtrTy = UseV->getType();
2531 const Function *F = I->getFunction();
2532 bool NullPointerIsDefined =
2533 F ? llvm::NullPointerIsDefined(F, AS: PtrTy->getPointerAddressSpace()) : true;
2534 const DataLayout &DL = A.getInfoCache().getDL();
2535 if (const auto *CB = dyn_cast<CallBase>(Val: I)) {
2536 if (CB->isBundleOperand(U)) {
2537 if (RetainedKnowledge RK = getKnowledgeFromUse(
2538 U, AttrKinds: {Attribute::NonNull, Attribute::Dereferenceable})) {
2539 IsNonNull |=
2540 (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);
2541 return RK.ArgValue;
2542 }
2543 return 0;
2544 }
2545
2546 if (CB->isCallee(U)) {
2547 IsNonNull |= !NullPointerIsDefined;
2548 return 0;
2549 }
2550
2551 unsigned ArgNo = CB->getArgOperandNo(U);
2552 IRPosition IRP = IRPosition::callsite_argument(CB: *CB, ArgNo);
2553 // As long as we only use known information there is no need to track
2554 // dependences here.
2555 bool IsKnownNonNull;
2556 AA::hasAssumedIRAttr<Attribute::NonNull>(A, QueryingAA: &QueryingAA, IRP,
2557 DepClass: DepClassTy::NONE, IsKnown&: IsKnownNonNull);
2558 IsNonNull |= IsKnownNonNull;
2559 auto *DerefAA =
2560 A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClass: DepClassTy::NONE);
2561 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2562 }
2563
2564 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(Inst: I);
2565 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2566 Loc->Size.isScalable() || I->isVolatile())
2567 return 0;
2568
2569 int64_t Offset;
2570 const Value *Base =
2571 getMinimalBaseOfPointer(A, QueryingAA, Ptr: Loc->Ptr, BytesOffset&: Offset, DL);
2572 if (Base && Base == &AssociatedValue) {
2573 int64_t DerefBytes = Loc->Size.getValue() + Offset;
2574 IsNonNull |= !NullPointerIsDefined;
2575 return std::max(a: int64_t(0), b: DerefBytes);
2576 }
2577
2578 /// Corner case when an offset is 0.
2579 Base = GetPointerBaseWithConstantOffset(Ptr: Loc->Ptr, Offset, DL,
2580 /*AllowNonInbounds*/ true);
2581 if (Base && Base == &AssociatedValue && Offset == 0) {
2582 int64_t DerefBytes = Loc->Size.getValue();
2583 IsNonNull |= !NullPointerIsDefined;
2584 return std::max(a: int64_t(0), b: DerefBytes);
2585 }
2586
2587 return 0;
2588}
2589
2590struct AANonNullImpl : AANonNull {
2591 AANonNullImpl(const IRPosition &IRP, Attributor &A) : AANonNull(IRP, A) {}
2592
2593 /// See AbstractAttribute::initialize(...).
2594 void initialize(Attributor &A) override {
2595 Value &V = *getAssociatedValue().stripPointerCasts();
2596 if (isa<ConstantPointerNull>(Val: V)) {
2597 indicatePessimisticFixpoint();
2598 return;
2599 }
2600
2601 if (Instruction *CtxI = getCtxI())
2602 followUsesInMBEC(AA&: *this, A, S&: getState(), CtxI&: *CtxI);
2603 }
2604
2605 /// See followUsesInMBEC
2606 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
2607 AANonNull::StateType &State) {
2608 bool IsNonNull = false;
2609 bool TrackUse = false;
2610 getKnownNonNullAndDerefBytesForUse(A, QueryingAA: *this, AssociatedValue&: getAssociatedValue(), U, I,
2611 IsNonNull, TrackUse);
2612 State.setKnown(IsNonNull);
2613 return TrackUse;
2614 }
2615
2616 /// See AbstractAttribute::getAsStr().
2617 const std::string getAsStr(Attributor *A) const override {
2618 return getAssumed() ? "nonnull" : "may-null";
2619 }
2620};
2621
2622/// NonNull attribute for a floating value.
2623struct AANonNullFloating : public AANonNullImpl {
2624 AANonNullFloating(const IRPosition &IRP, Attributor &A)
2625 : AANonNullImpl(IRP, A) {}
2626
2627 /// See AbstractAttribute::updateImpl(...).
2628 ChangeStatus updateImpl(Attributor &A) override {
2629 auto CheckIRP = [&](const IRPosition &IRP) {
2630 bool IsKnownNonNull;
2631 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2632 A, QueryingAA: *this, IRP, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNonNull);
2633 };
2634
2635 bool Stripped;
2636 bool UsedAssumedInformation = false;
2637 Value *AssociatedValue = &getAssociatedValue();
2638 SmallVector<AA::ValueAndContext> Values;
2639 if (!A.getAssumedSimplifiedValues(IRP: getIRPosition(), AA: *this, Values,
2640 S: AA::AnyScope, UsedAssumedInformation))
2641 Stripped = false;
2642 else
2643 Stripped =
2644 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
2645
2646 if (!Stripped) {
2647 bool IsKnown;
2648 if (auto *PHI = dyn_cast<PHINode>(Val: AssociatedValue))
2649 if (llvm::all_of(Range: PHI->incoming_values(), P: [&](Value *Op) {
2650 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2651 A, QueryingAA: this, IRP: IRPosition::value(V: *Op), DepClass: DepClassTy::OPTIONAL,
2652 IsKnown);
2653 }))
2654 return ChangeStatus::UNCHANGED;
2655 if (auto *Select = dyn_cast<SelectInst>(Val: AssociatedValue))
2656 if (AA::hasAssumedIRAttr<Attribute::NonNull>(
2657 A, QueryingAA: this, IRP: IRPosition::value(V: *Select->getFalseValue()),
2658 DepClass: DepClassTy::OPTIONAL, IsKnown) &&
2659 AA::hasAssumedIRAttr<Attribute::NonNull>(
2660 A, QueryingAA: this, IRP: IRPosition::value(V: *Select->getTrueValue()),
2661 DepClass: DepClassTy::OPTIONAL, IsKnown))
2662 return ChangeStatus::UNCHANGED;
2663
2664 // If we haven't stripped anything we might still be able to use a
2665 // different AA, but only if the IRP changes. Effectively when we
2666 // interpret this not as a call site value but as a floating/argument
2667 // value.
2668 const IRPosition AVIRP = IRPosition::value(V: *AssociatedValue);
2669 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2670 return indicatePessimisticFixpoint();
2671 return ChangeStatus::UNCHANGED;
2672 }
2673
2674 for (const auto &VAC : Values)
2675 if (!CheckIRP(IRPosition::value(V: *VAC.getValue())))
2676 return indicatePessimisticFixpoint();
2677
2678 return ChangeStatus::UNCHANGED;
2679 }
2680
2681 /// See AbstractAttribute::trackStatistics()
2682 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2683};
2684
2685/// NonNull attribute for function return value.
2686struct AANonNullReturned final
2687 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2688 false, AANonNull::IRAttributeKind, false> {
2689 AANonNullReturned(const IRPosition &IRP, Attributor &A)
2690 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2691 false, Attribute::NonNull, false>(IRP, A) {
2692 }
2693
2694 /// See AbstractAttribute::getAsStr().
2695 const std::string getAsStr(Attributor *A) const override {
2696 return getAssumed() ? "nonnull" : "may-null";
2697 }
2698
2699 /// See AbstractAttribute::trackStatistics()
2700 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2701};
2702
2703/// NonNull attribute for function argument.
2704struct AANonNullArgument final
2705 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2706 AANonNullArgument(const IRPosition &IRP, Attributor &A)
2707 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}
2708
2709 /// See AbstractAttribute::trackStatistics()
2710 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
2711};
2712
2713struct AANonNullCallSiteArgument final : AANonNullFloating {
2714 AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
2715 : AANonNullFloating(IRP, A) {}
2716
2717 /// See AbstractAttribute::trackStatistics()
2718 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
2719};
2720
2721/// NonNull attribute for a call site return position.
2722struct AANonNullCallSiteReturned final
2723 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2724 AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
2725 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP, A) {}
2726
2727 /// See AbstractAttribute::trackStatistics()
2728 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
2729};
2730} // namespace
2731
2732/// ------------------------ Must-Progress Attributes --------------------------
2733namespace {
2734struct AAMustProgressImpl : public AAMustProgress {
2735 AAMustProgressImpl(const IRPosition &IRP, Attributor &A)
2736 : AAMustProgress(IRP, A) {}
2737
2738 /// See AbstractAttribute::initialize(...).
2739 void initialize(Attributor &A) override {
2740 bool IsKnown;
2741 assert(!AA::hasAssumedIRAttr<Attribute::MustProgress>(
2742 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2743 (void)IsKnown;
2744 }
2745
2746 /// See AbstractAttribute::getAsStr()
2747 const std::string getAsStr(Attributor *A) const override {
2748 return getAssumed() ? "mustprogress" : "may-not-progress";
2749 }
2750};
2751
2752struct AAMustProgressFunction final : AAMustProgressImpl {
2753 AAMustProgressFunction(const IRPosition &IRP, Attributor &A)
2754 : AAMustProgressImpl(IRP, A) {}
2755
2756 /// See AbstractAttribute::updateImpl(...).
2757 ChangeStatus updateImpl(Attributor &A) override {
2758 bool IsKnown;
2759 if (AA::hasAssumedIRAttr<Attribute::WillReturn>(
2760 A, QueryingAA: this, IRP: getIRPosition(), DepClass: DepClassTy::OPTIONAL, IsKnown)) {
2761 if (IsKnown)
2762 return indicateOptimisticFixpoint();
2763 return ChangeStatus::UNCHANGED;
2764 }
2765
2766 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2767 IRPosition IPos = IRPosition::callsite_function(CB: *ACS.getInstruction());
2768 bool IsKnownMustProgress;
2769 return AA::hasAssumedIRAttr<Attribute::MustProgress>(
2770 A, QueryingAA: this, IRP: IPos, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownMustProgress,
2771 /* IgnoreSubsumingPositions */ true);
2772 };
2773
2774 bool AllCallSitesKnown = true;
2775 if (!A.checkForAllCallSites(Pred: CheckForMustProgress, QueryingAA: *this,
2776 /* RequireAllCallSites */ true,
2777 UsedAssumedInformation&: AllCallSitesKnown))
2778 return indicatePessimisticFixpoint();
2779
2780 return ChangeStatus::UNCHANGED;
2781 }
2782
2783 /// See AbstractAttribute::trackStatistics()
2784 void trackStatistics() const override {
2785 STATS_DECLTRACK_FN_ATTR(mustprogress)
2786 }
2787};
2788
2789/// MustProgress attribute deduction for a call sites.
2790struct AAMustProgressCallSite final : AAMustProgressImpl {
2791 AAMustProgressCallSite(const IRPosition &IRP, Attributor &A)
2792 : AAMustProgressImpl(IRP, A) {}
2793
2794 /// See AbstractAttribute::updateImpl(...).
2795 ChangeStatus updateImpl(Attributor &A) override {
2796 // TODO: Once we have call site specific value information we can provide
2797 // call site specific liveness information and then it makes
2798 // sense to specialize attributes for call sites arguments instead of
2799 // redirecting requests to the callee argument.
2800 const IRPosition &FnPos = IRPosition::function(F: *getAnchorScope());
2801 bool IsKnownMustProgress;
2802 if (!AA::hasAssumedIRAttr<Attribute::MustProgress>(
2803 A, QueryingAA: this, IRP: FnPos, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownMustProgress))
2804 return indicatePessimisticFixpoint();
2805 return ChangeStatus::UNCHANGED;
2806 }
2807
2808 /// See AbstractAttribute::trackStatistics()
2809 void trackStatistics() const override {
2810 STATS_DECLTRACK_CS_ATTR(mustprogress);
2811 }
2812};
2813} // namespace
2814
2815/// ------------------------ No-Recurse Attributes ----------------------------
2816
2817namespace {
2818struct AANoRecurseImpl : public AANoRecurse {
2819 AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}
2820
2821 /// See AbstractAttribute::initialize(...).
2822 void initialize(Attributor &A) override {
2823 bool IsKnown;
2824 assert(!AA::hasAssumedIRAttr<Attribute::NoRecurse>(
2825 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2826 (void)IsKnown;
2827 }
2828
2829 /// See AbstractAttribute::getAsStr()
2830 const std::string getAsStr(Attributor *A) const override {
2831 return getAssumed() ? "norecurse" : "may-recurse";
2832 }
2833};
2834
2835struct AANoRecurseFunction final : AANoRecurseImpl {
2836 AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
2837 : AANoRecurseImpl(IRP, A) {}
2838
2839 /// See AbstractAttribute::updateImpl(...).
2840 ChangeStatus updateImpl(Attributor &A) override {
2841
2842 // If all live call sites are known to be no-recurse, we are as well.
2843 auto CallSitePred = [&](AbstractCallSite ACS) {
2844 bool IsKnownNoRecurse;
2845 if (!AA::hasAssumedIRAttr<Attribute::NoRecurse>(
2846 A, QueryingAA: this,
2847 IRP: IRPosition::function(F: *ACS.getInstruction()->getFunction()),
2848 DepClass: DepClassTy::NONE, IsKnown&: IsKnownNoRecurse))
2849 return false;
2850 return IsKnownNoRecurse;
2851 };
2852 bool UsedAssumedInformation = false;
2853 if (A.checkForAllCallSites(Pred: CallSitePred, QueryingAA: *this, RequireAllCallSites: true,
2854 UsedAssumedInformation)) {
2855 // If we know all call sites and all are known no-recurse, we are done.
2856 // If all known call sites, which might not be all that exist, are known
2857 // to be no-recurse, we are not done but we can continue to assume
2858 // no-recurse. If one of the call sites we have not visited will become
2859 // live, another update is triggered.
2860 if (!UsedAssumedInformation)
2861 indicateOptimisticFixpoint();
2862 return ChangeStatus::UNCHANGED;
2863 }
2864
2865 const AAInterFnReachability *EdgeReachability =
2866 A.getAAFor<AAInterFnReachability>(QueryingAA: *this, IRP: getIRPosition(),
2867 DepClass: DepClassTy::REQUIRED);
2868 if (EdgeReachability && EdgeReachability->canReach(A, Fn: *getAnchorScope()))
2869 return indicatePessimisticFixpoint();
2870 return ChangeStatus::UNCHANGED;
2871 }
2872
2873 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
2874};
2875
2876/// NoRecurse attribute deduction for a call sites.
2877struct AANoRecurseCallSite final
2878 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2879 AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
2880 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP, A) {}
2881
2882 /// See AbstractAttribute::trackStatistics()
2883 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }
2884};
2885} // namespace
2886
2887/// ------------------------ No-Convergent Attribute --------------------------
2888
2889namespace {
2890struct AANonConvergentImpl : public AANonConvergent {
2891 AANonConvergentImpl(const IRPosition &IRP, Attributor &A)
2892 : AANonConvergent(IRP, A) {}
2893
2894 /// See AbstractAttribute::getAsStr()
2895 const std::string getAsStr(Attributor *A) const override {
2896 return getAssumed() ? "non-convergent" : "may-be-convergent";
2897 }
2898};
2899
2900struct AANonConvergentFunction final : AANonConvergentImpl {
2901 AANonConvergentFunction(const IRPosition &IRP, Attributor &A)
2902 : AANonConvergentImpl(IRP, A) {}
2903
2904 /// See AbstractAttribute::updateImpl(...).
2905 ChangeStatus updateImpl(Attributor &A) override {
2906 // If all function calls are known to not be convergent, we are not
2907 // convergent.
2908 auto CalleeIsNotConvergent = [&](Instruction &Inst) {
2909 CallBase &CB = cast<CallBase>(Val&: Inst);
2910 auto *Callee = dyn_cast_if_present<Function>(Val: CB.getCalledOperand());
2911 if (!Callee || Callee->isIntrinsic()) {
2912 return false;
2913 }
2914 if (Callee->isDeclaration()) {
2915 return !Callee->hasFnAttribute(Kind: Attribute::Convergent);
2916 }
2917 const auto *ConvergentAA = A.getAAFor<AANonConvergent>(
2918 QueryingAA: *this, IRP: IRPosition::function(F: *Callee), DepClass: DepClassTy::REQUIRED);
2919 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2920 };
2921
2922 bool UsedAssumedInformation = false;
2923 if (!A.checkForAllCallLikeInstructions(Pred: CalleeIsNotConvergent, QueryingAA: *this,
2924 UsedAssumedInformation)) {
2925 return indicatePessimisticFixpoint();
2926 }
2927 return ChangeStatus::UNCHANGED;
2928 }
2929
2930 ChangeStatus manifest(Attributor &A) override {
2931 if (isKnownNotConvergent() &&
2932 A.hasAttr(IRP: getIRPosition(), AKs: Attribute::Convergent)) {
2933 A.removeAttrs(IRP: getIRPosition(), AttrKinds: {Attribute::Convergent});
2934 return ChangeStatus::CHANGED;
2935 }
2936 return ChangeStatus::UNCHANGED;
2937 }
2938
2939 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(convergent) }
2940};
2941} // namespace
2942
2943/// -------------------- Undefined-Behavior Attributes ------------------------
2944
2945namespace {
2946struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
2947 AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
2948 : AAUndefinedBehavior(IRP, A) {}
2949
2950 /// See AbstractAttribute::updateImpl(...).
2951 // through a pointer (i.e. also branches etc.)
2952 ChangeStatus updateImpl(Attributor &A) override {
2953 const size_t UBPrevSize = KnownUBInsts.size();
2954 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2955
2956 auto InspectMemAccessInstForUB = [&](Instruction &I) {
2957 // Volatile accesses on null are not necessarily UB.
2958 if (I.isVolatile())
2959 return true;
2960
2961 // Skip instructions that are already saved.
2962 if (AssumedNoUBInsts.count(Ptr: &I) || KnownUBInsts.count(Ptr: &I))
2963 return true;
2964
2965 // If we reach here, we know we have an instruction
2966 // that accesses memory through a pointer operand,
2967 // for which getPointerOperand() should give it to us.
2968 Value *PtrOp =
2969 const_cast<Value *>(getPointerOperand(I: &I, /* AllowVolatile */ true));
2970 assert(PtrOp &&
2971 "Expected pointer operand of memory accessing instruction");
2972
2973 // Either we stopped and the appropriate action was taken,
2974 // or we got back a simplified value to continue.
2975 std::optional<Value *> SimplifiedPtrOp =
2976 stopOnUndefOrAssumed(A, V: PtrOp, I: &I);
2977 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2978 return true;
2979 const Value *PtrOpVal = *SimplifiedPtrOp;
2980
2981 // A memory access through a pointer is considered UB
2982 // only if the pointer has constant null value.
2983 // TODO: Expand it to not only check constant values.
2984 if (!isa<ConstantPointerNull>(Val: PtrOpVal)) {
2985 AssumedNoUBInsts.insert(Ptr: &I);
2986 return true;
2987 }
2988 const Type *PtrTy = PtrOpVal->getType();
2989
2990 // Because we only consider instructions inside functions,
2991 // assume that a parent function exists.
2992 const Function *F = I.getFunction();
2993
2994 // A memory access using constant null pointer is only considered UB
2995 // if null pointer is _not_ defined for the target platform.
2996 if (llvm::NullPointerIsDefined(F, AS: PtrTy->getPointerAddressSpace()))
2997 AssumedNoUBInsts.insert(Ptr: &I);
2998 else
2999 KnownUBInsts.insert(Ptr: &I);
3000 return true;
3001 };
3002
3003 auto InspectBrInstForUB = [&](Instruction &I) {
3004 // A conditional branch instruction is considered UB if it has `undef`
3005 // condition.
3006
3007 // Skip instructions that are already saved.
3008 if (AssumedNoUBInsts.count(Ptr: &I) || KnownUBInsts.count(Ptr: &I))
3009 return true;
3010
3011 // We know we have a branch instruction.
3012 auto *BrInst = cast<CondBrInst>(Val: &I);
3013
3014 // Either we stopped and the appropriate action was taken,
3015 // or we got back a simplified value to continue.
3016 std::optional<Value *> SimplifiedCond =
3017 stopOnUndefOrAssumed(A, V: BrInst->getCondition(), I: BrInst);
3018 if (!SimplifiedCond || !*SimplifiedCond)
3019 return true;
3020 AssumedNoUBInsts.insert(Ptr: &I);
3021 return true;
3022 };
3023
3024 auto InspectCallSiteForUB = [&](Instruction &I) {
3025 // Check whether a callsite always cause UB or not
3026
3027 // Skip instructions that are already saved.
3028 if (AssumedNoUBInsts.count(Ptr: &I) || KnownUBInsts.count(Ptr: &I))
3029 return true;
3030
3031 // Check nonnull and noundef argument attribute violation for each
3032 // callsite.
3033 CallBase &CB = cast<CallBase>(Val&: I);
3034 auto *Callee = dyn_cast_if_present<Function>(Val: CB.getCalledOperand());
3035 if (!Callee)
3036 return true;
3037 for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
3038 // If current argument is known to be simplified to null pointer and the
3039 // corresponding argument position is known to have nonnull attribute,
3040 // the argument is poison. Furthermore, if the argument is poison and
3041 // the position is known to have noundef attriubte, this callsite is
3042 // considered UB.
3043 if (idx >= Callee->arg_size())
3044 break;
3045 Value *ArgVal = CB.getArgOperand(i: idx);
3046 if (!ArgVal)
3047 continue;
3048 // Here, we handle three cases.
3049 // (1) Not having a value means it is dead. (we can replace the value
3050 // with undef)
3051 // (2) Simplified to undef. The argument violate noundef attriubte.
3052 // (3) Simplified to null pointer where known to be nonnull.
3053 // The argument is a poison value and violate noundef attribute.
3054 IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, ArgNo: idx);
3055 bool IsKnownNoUndef;
3056 AA::hasAssumedIRAttr<Attribute::NoUndef>(
3057 A, QueryingAA: this, IRP: CalleeArgumentIRP, DepClass: DepClassTy::NONE, IsKnown&: IsKnownNoUndef);
3058 if (!IsKnownNoUndef)
3059 continue;
3060 bool UsedAssumedInformation = false;
3061 std::optional<Value *> SimplifiedVal =
3062 A.getAssumedSimplified(IRP: IRPosition::value(V: *ArgVal), AA: *this,
3063 UsedAssumedInformation, S: AA::Interprocedural);
3064 if (UsedAssumedInformation)
3065 continue;
3066 if (SimplifiedVal && !*SimplifiedVal)
3067 return true;
3068 if (!SimplifiedVal || isa<UndefValue>(Val: **SimplifiedVal)) {
3069 KnownUBInsts.insert(Ptr: &I);
3070 continue;
3071 }
3072 if (!ArgVal->getType()->isPointerTy() ||
3073 !isa<ConstantPointerNull>(Val: **SimplifiedVal))
3074 continue;
3075 bool IsKnownNonNull;
3076 AA::hasAssumedIRAttr<Attribute::NonNull>(
3077 A, QueryingAA: this, IRP: CalleeArgumentIRP, DepClass: DepClassTy::NONE, IsKnown&: IsKnownNonNull);
3078 if (IsKnownNonNull)
3079 KnownUBInsts.insert(Ptr: &I);
3080 }
3081 return true;
3082 };
3083
3084 auto InspectReturnInstForUB = [&](Instruction &I) {
3085 auto &RI = cast<ReturnInst>(Val&: I);
3086 // Either we stopped and the appropriate action was taken,
3087 // or we got back a simplified return value to continue.
3088 std::optional<Value *> SimplifiedRetValue =
3089 stopOnUndefOrAssumed(A, V: RI.getReturnValue(), I: &I);
3090 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3091 return true;
3092
3093 // Check if a return instruction always cause UB or not
3094 // Note: It is guaranteed that the returned position of the anchor
3095 // scope has noundef attribute when this is called.
3096 // We also ensure the return position is not "assumed dead"
3097 // because the returned value was then potentially simplified to
3098 // `undef` in AAReturnedValues without removing the `noundef`
3099 // attribute yet.
3100
3101 // When the returned position has noundef attriubte, UB occurs in the
3102 // following cases.
3103 // (1) Returned value is known to be undef.
3104 // (2) The value is known to be a null pointer and the returned
3105 // position has nonnull attribute (because the returned value is
3106 // poison).
3107 if (isa<ConstantPointerNull>(Val: *SimplifiedRetValue)) {
3108 bool IsKnownNonNull;
3109 AA::hasAssumedIRAttr<Attribute::NonNull>(
3110 A, QueryingAA: this, IRP: IRPosition::returned(F: *getAnchorScope()), DepClass: DepClassTy::NONE,
3111 IsKnown&: IsKnownNonNull);
3112 if (IsKnownNonNull)
3113 KnownUBInsts.insert(Ptr: &I);
3114 }
3115
3116 return true;
3117 };
3118
3119 bool UsedAssumedInformation = false;
3120 A.checkForAllInstructions(Pred: InspectMemAccessInstForUB, QueryingAA: *this,
3121 Opcodes: {Instruction::Load, Instruction::Store,
3122 Instruction::AtomicCmpXchg,
3123 Instruction::AtomicRMW},
3124 UsedAssumedInformation,
3125 /* CheckBBLivenessOnly */ true);
3126 A.checkForAllInstructions(Pred: InspectBrInstForUB, QueryingAA: *this, Opcodes: {Instruction::CondBr},
3127 UsedAssumedInformation,
3128 /* CheckBBLivenessOnly */ true);
3129 A.checkForAllCallLikeInstructions(Pred: InspectCallSiteForUB, QueryingAA: *this,
3130 UsedAssumedInformation);
3131
3132 // If the returned position of the anchor scope has noundef attriubte, check
3133 // all returned instructions.
3134 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3135 const IRPosition &ReturnIRP = IRPosition::returned(F: *getAnchorScope());
3136 if (!A.isAssumedDead(IRP: ReturnIRP, QueryingAA: this, FnLivenessAA: nullptr, UsedAssumedInformation)) {
3137 bool IsKnownNoUndef;
3138 AA::hasAssumedIRAttr<Attribute::NoUndef>(
3139 A, QueryingAA: this, IRP: ReturnIRP, DepClass: DepClassTy::NONE, IsKnown&: IsKnownNoUndef);
3140 if (IsKnownNoUndef)
3141 A.checkForAllInstructions(Pred: InspectReturnInstForUB, QueryingAA: *this,
3142 Opcodes: {Instruction::Ret}, UsedAssumedInformation,
3143 /* CheckBBLivenessOnly */ true);
3144 }
3145 }
3146
3147 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3148 UBPrevSize != KnownUBInsts.size())
3149 return ChangeStatus::CHANGED;
3150 return ChangeStatus::UNCHANGED;
3151 }
3152
3153 bool isKnownToCauseUB(Instruction *I) const override {
3154 return KnownUBInsts.count(Ptr: I);
3155 }
3156
3157 bool isAssumedToCauseUB(Instruction *I) const override {
3158 // In simple words, if an instruction is not in the assumed to _not_
3159 // cause UB, then it is assumed UB (that includes those
3160 // in the KnownUBInsts set). The rest is boilerplate
3161 // is to ensure that it is one of the instructions we test
3162 // for UB.
3163
3164 switch (I->getOpcode()) {
3165 case Instruction::Load:
3166 case Instruction::Store:
3167 case Instruction::AtomicCmpXchg:
3168 case Instruction::AtomicRMW:
3169 case Instruction::CondBr:
3170 return !AssumedNoUBInsts.count(Ptr: I);
3171 default:
3172 return false;
3173 }
3174 return false;
3175 }
3176
3177 ChangeStatus manifest(Attributor &A) override {
3178 if (KnownUBInsts.empty())
3179 return ChangeStatus::UNCHANGED;
3180 for (Instruction *I : KnownUBInsts)
3181 A.changeToUnreachableAfterManifest(I);
3182 return ChangeStatus::CHANGED;
3183 }
3184
3185 /// See AbstractAttribute::getAsStr()
3186 const std::string getAsStr(Attributor *A) const override {
3187 return getAssumed() ? "undefined-behavior" : "no-ub";
3188 }
3189
3190 /// Note: The correctness of this analysis depends on the fact that the
3191 /// following 2 sets will stop changing after some point.
3192 /// "Change" here means that their size changes.
3193 /// The size of each set is monotonically increasing
3194 /// (we only add items to them) and it is upper bounded by the number of
3195 /// instructions in the processed function (we can never save more
3196 /// elements in either set than this number). Hence, at some point,
3197 /// they will stop increasing.
3198 /// Consequently, at some point, both sets will have stopped
3199 /// changing, effectively making the analysis reach a fixpoint.
3200
3201 /// Note: These 2 sets are disjoint and an instruction can be considered
3202 /// one of 3 things:
3203 /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
3204 /// the KnownUBInsts set.
3205 /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
3206 /// has a reason to assume it).
3207 /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
3208 /// could not find a reason to assume or prove that it can cause UB,
3209 /// hence it assumes it doesn't. We have a set for these instructions
3210 /// so that we don't reprocess them in every update.
3211 /// Note however that instructions in this set may cause UB.
3212
3213protected:
3214 /// A set of all live instructions _known_ to cause UB.
3215 SmallPtrSet<Instruction *, 8> KnownUBInsts;
3216
3217private:
3218 /// A set of all the (live) instructions that are assumed to _not_ cause UB.
3219 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3220
3221 // Should be called on updates in which if we're processing an instruction
3222 // \p I that depends on a value \p V, one of the following has to happen:
3223 // - If the value is assumed, then stop.
3224 // - If the value is known but undef, then consider it UB.
3225 // - Otherwise, do specific processing with the simplified value.
3226 // We return std::nullopt in the first 2 cases to signify that an appropriate
3227 // action was taken and the caller should stop.
3228 // Otherwise, we return the simplified value that the caller should
3229 // use for specific processing.
3230 std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
3231 Instruction *I) {
3232 bool UsedAssumedInformation = false;
3233 std::optional<Value *> SimplifiedV =
3234 A.getAssumedSimplified(IRP: IRPosition::value(V: *V), AA: *this,
3235 UsedAssumedInformation, S: AA::Interprocedural);
3236 if (!UsedAssumedInformation) {
3237 // Don't depend on assumed values.
3238 if (!SimplifiedV) {
3239 // If it is known (which we tested above) but it doesn't have a value,
3240 // then we can assume `undef` and hence the instruction is UB.
3241 KnownUBInsts.insert(Ptr: I);
3242 return std::nullopt;
3243 }
3244 if (!*SimplifiedV)
3245 return nullptr;
3246 V = *SimplifiedV;
3247 }
3248 if (isa<UndefValue>(Val: V)) {
3249 KnownUBInsts.insert(Ptr: I);
3250 return std::nullopt;
3251 }
3252 return V;
3253 }
3254};
3255
3256struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3257 AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
3258 : AAUndefinedBehaviorImpl(IRP, A) {}
3259
3260 /// See AbstractAttribute::trackStatistics()
3261 void trackStatistics() const override {
3262 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3263 "Number of instructions known to have UB");
3264 BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) +=
3265 KnownUBInsts.size();
3266 }
3267};
3268} // namespace
3269
3270/// ------------------------ Will-Return Attributes ----------------------------
3271
3272namespace {
3273// Helper function that checks whether a function has any cycle which we don't
3274// know if it is bounded or not.
3275// Loops with maximum trip count are considered bounded, any other cycle not.
3276static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
3277 ScalarEvolution *SE =
3278 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
3279 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
3280 // If either SCEV or LoopInfo is not available for the function then we assume
3281 // any cycle to be unbounded cycle.
3282 // We use scc_iterator which uses Tarjan algorithm to find all the maximal
3283 // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
3284 if (!SE || !LI) {
3285 for (scc_iterator<Function *> SCCI = scc_begin(G: &F); !SCCI.isAtEnd(); ++SCCI)
3286 if (SCCI.hasCycle())
3287 return true;
3288 return false;
3289 }
3290
3291 // If there's irreducible control, the function may contain non-loop cycles.
3292 if (mayContainIrreducibleControl(F, LI))
3293 return true;
3294
3295 // Any loop that does not have a max trip count is considered unbounded cycle.
3296 for (auto *L : LI->getLoopsInPreorder()) {
3297 if (!SE->getSmallConstantMaxTripCount(L))
3298 return true;
3299 }
3300 return false;
3301}
3302
3303struct AAWillReturnImpl : public AAWillReturn {
3304 AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
3305 : AAWillReturn(IRP, A) {}
3306
3307 /// See AbstractAttribute::initialize(...).
3308 void initialize(Attributor &A) override {
3309 bool IsKnown;
3310 assert(!AA::hasAssumedIRAttr<Attribute::WillReturn>(
3311 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3312 (void)IsKnown;
3313 }
3314
3315 /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
3316 bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
3317 if (!A.hasAttr(IRP: getIRPosition(), AKs: {Attribute::MustProgress}))
3318 return false;
3319
3320 bool IsKnown;
3321 if (AA::isAssumedReadOnly(A, IRP: getIRPosition(), QueryingAA: *this, IsKnown))
3322 return IsKnown || !KnownOnly;
3323 return false;
3324 }
3325
3326 /// See AbstractAttribute::updateImpl(...).
3327 ChangeStatus updateImpl(Attributor &A) override {
3328 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3329 return ChangeStatus::UNCHANGED;
3330
3331 auto CheckForWillReturn = [&](Instruction &I) {
3332 IRPosition IPos = IRPosition::callsite_function(CB: cast<CallBase>(Val&: I));
3333 bool IsKnown;
3334 if (AA::hasAssumedIRAttr<Attribute::WillReturn>(
3335 A, QueryingAA: this, IRP: IPos, DepClass: DepClassTy::REQUIRED, IsKnown)) {
3336 if (IsKnown)
3337 return true;
3338 } else {
3339 return false;
3340 }
3341 bool IsKnownNoRecurse;
3342 return AA::hasAssumedIRAttr<Attribute::NoRecurse>(
3343 A, QueryingAA: this, IRP: IPos, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoRecurse);
3344 };
3345
3346 bool UsedAssumedInformation = false;
3347 if (!A.checkForAllCallLikeInstructions(Pred: CheckForWillReturn, QueryingAA: *this,
3348 UsedAssumedInformation))
3349 return indicatePessimisticFixpoint();
3350
3351 auto CheckForVolatile = [&](Instruction &I) {
3352 // Volatile operations are not willreturn.
3353 return !I.isVolatile();
3354 };
3355 if (!A.checkForAllInstructions(Pred: CheckForVolatile, QueryingAA: *this,
3356 Opcodes: {Instruction::Load, Instruction::Store,
3357 Instruction::AtomicCmpXchg,
3358 Instruction::AtomicRMW},
3359 UsedAssumedInformation))
3360 return indicatePessimisticFixpoint();
3361
3362 return ChangeStatus::UNCHANGED;
3363 }
3364
3365 /// See AbstractAttribute::getAsStr()
3366 const std::string getAsStr(Attributor *A) const override {
3367 return getAssumed() ? "willreturn" : "may-noreturn";
3368 }
3369};
3370
3371struct AAWillReturnFunction final : AAWillReturnImpl {
3372 AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
3373 : AAWillReturnImpl(IRP, A) {}
3374
3375 /// See AbstractAttribute::initialize(...).
3376 void initialize(Attributor &A) override {
3377 AAWillReturnImpl::initialize(A);
3378
3379 Function *F = getAnchorScope();
3380 assert(F && "Did expect an anchor function");
3381 if (F->isDeclaration() || mayContainUnboundedCycle(F&: *F, A))
3382 indicatePessimisticFixpoint();
3383 }
3384
3385 /// See AbstractAttribute::trackStatistics()
3386 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
3387};
3388
3389/// WillReturn attribute deduction for a call sites.
3390struct AAWillReturnCallSite final
3391 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3392 AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)
3393 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP, A) {}
3394
3395 /// See AbstractAttribute::updateImpl(...).
3396 ChangeStatus updateImpl(Attributor &A) override {
3397 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3398 return ChangeStatus::UNCHANGED;
3399
3400 return AACalleeToCallSite::updateImpl(A);
3401 }
3402
3403 /// See AbstractAttribute::trackStatistics()
3404 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }
3405};
3406} // namespace
3407
3408/// -------------------AAIntraFnReachability Attribute--------------------------
3409
3410/// All information associated with a reachability query. This boilerplate code
3411/// is used by both AAIntraFnReachability and AAInterFnReachability, with
3412/// different \p ToTy values.
3413template <typename ToTy> struct ReachabilityQueryInfo {
3414 enum class Reachable {
3415 No,
3416 Yes,
3417 };
3418
3419 /// Start here,
3420 const Instruction *From = nullptr;
3421 /// reach this place,
3422 const ToTy *To = nullptr;
3423 /// without going through any of these instructions,
3424 const AA::InstExclusionSetTy *ExclusionSet = nullptr;
3425 /// and remember if it worked:
3426 Reachable Result = Reachable::No;
3427
3428 /// Precomputed hash for this RQI.
3429 unsigned Hash = 0;
3430
3431 unsigned computeHashValue() const {
3432 assert(Hash == 0 && "Computed hash twice!");
3433 using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;
3434 using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;
3435 return const_cast<ReachabilityQueryInfo<ToTy> *>(this)->Hash =
3436 detail::combineHashValue(a: PairDMI ::getHashValue({From, To}),
3437 b: InstSetDMI::getHashValue(BES: ExclusionSet));
3438 }
3439
3440 ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
3441 : From(From), To(To) {}
3442
3443 /// Constructor replacement to ensure unique and stable sets are used for the
3444 /// cache.
3445 ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To,
3446 const AA::InstExclusionSetTy *ES, bool MakeUnique)
3447 : From(&From), To(&To), ExclusionSet(ES) {
3448
3449 if (!ES || ES->empty()) {
3450 ExclusionSet = nullptr;
3451 } else if (MakeUnique) {
3452 ExclusionSet = A.getInfoCache().getOrCreateUniqueBlockExecutionSet(BES: ES);
3453 }
3454 }
3455
3456 ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
3457 : From(RQI.From), To(RQI.To), ExclusionSet(RQI.ExclusionSet) {}
3458};
3459
3460namespace llvm {
3461template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
3462 using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;
3463 using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;
3464
3465 static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
3466 return RQI->Hash ? RQI->Hash : RQI->computeHashValue();
3467 }
3468 static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
3469 const ReachabilityQueryInfo<ToTy> *RHS) {
3470 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3471 return false;
3472 return InstSetDMI::isEqual(LHS: LHS->ExclusionSet, RHS: RHS->ExclusionSet);
3473 }
3474};
3475
3476} // namespace llvm
3477
3478namespace {
3479
3480template <typename BaseTy, typename ToTy>
3481struct CachedReachabilityAA : public BaseTy {
3482 using RQITy = ReachabilityQueryInfo<ToTy>;
3483
3484 CachedReachabilityAA(const IRPosition &IRP, Attributor &A) : BaseTy(IRP, A) {}
3485
3486 /// See AbstractAttribute::isQueryAA.
3487 bool isQueryAA() const override { return true; }
3488
3489 /// See AbstractAttribute::updateImpl(...).
3490 ChangeStatus updateImpl(Attributor &A) override {
3491 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3492 for (unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3493 RQITy *RQI = QueryVector[u];
3494 if (RQI->Result == RQITy::Reachable::No &&
3495 isReachableImpl(A, RQI&: *RQI, /*IsTemporaryRQI=*/false))
3496 Changed = ChangeStatus::CHANGED;
3497 }
3498 return Changed;
3499 }
3500
3501 virtual bool isReachableImpl(Attributor &A, RQITy &RQI,
3502 bool IsTemporaryRQI) = 0;
3503
3504 bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
3505 RQITy &RQI, bool UsedExclusionSet, bool IsTemporaryRQI) {
3506 RQI.Result = Result;
3507
3508 // Remove the temporary RQI from the cache.
3509 if (IsTemporaryRQI)
3510 QueryCache.erase(&RQI);
3511
3512 // Insert a plain RQI (w/o exclusion set) if that makes sense. Two options:
3513 // 1) If it is reachable, it doesn't matter if we have an exclusion set for
3514 // this query. 2) We did not use the exclusion set, potentially because
3515 // there is none.
3516 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3517 RQITy PlainRQI(RQI.From, RQI.To);
3518 if (!QueryCache.count(&PlainRQI)) {
3519 RQITy *RQIPtr = new (A.Allocator) RQITy(RQI.From, RQI.To);
3520 RQIPtr->Result = Result;
3521 QueryVector.push_back(RQIPtr);
3522 QueryCache.insert(RQIPtr);
3523 }
3524 }
3525
3526 // Check if we need to insert a new permanent RQI with the exclusion set.
3527 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3528 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3529 "Did not expect empty set!");
3530 RQITy *RQIPtr = new (A.Allocator)
3531 RQITy(A, *RQI.From, *RQI.To, RQI.ExclusionSet, true);
3532 assert(RQIPtr->Result == RQITy::Reachable::No && "Already reachable?");
3533 RQIPtr->Result = Result;
3534 assert(!QueryCache.count(RQIPtr));
3535 QueryVector.push_back(RQIPtr);
3536 QueryCache.insert(RQIPtr);
3537 }
3538
3539 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3540 A.registerForUpdate(AA&: *this);
3541 return Result == RQITy::Reachable::Yes;
3542 }
3543
3544 const std::string getAsStr(Attributor *A) const override {
3545 // TODO: Return the number of reachable queries.
3546 return "#queries(" + std::to_string(QueryVector.size()) + ")";
3547 }
3548
3549 bool checkQueryCache(Attributor &A, RQITy &StackRQI,
3550 typename RQITy::Reachable &Result) {
3551 if (!this->getState().isValidState()) {
3552 Result = RQITy::Reachable::Yes;
3553 return true;
3554 }
3555
3556 // If we have an exclusion set we might be able to find our answer by
3557 // ignoring it first.
3558 if (StackRQI.ExclusionSet) {
3559 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3560 auto It = QueryCache.find(&PlainRQI);
3561 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3562 Result = RQITy::Reachable::No;
3563 return true;
3564 }
3565 }
3566
3567 auto It = QueryCache.find(&StackRQI);
3568 if (It != QueryCache.end()) {
3569 Result = (*It)->Result;
3570 return true;
3571 }
3572
3573 // Insert a temporary for recursive queries. We will replace it with a
3574 // permanent entry later.
3575 QueryCache.insert(&StackRQI);
3576 return false;
3577 }
3578
3579private:
3580 SmallVector<RQITy *> QueryVector;
3581 DenseSet<RQITy *> QueryCache;
3582};
3583
3584struct AAIntraFnReachabilityFunction final
3585 : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3586 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3587 AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
3588 : Base(IRP, A) {
3589 DT = A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3590 F: *IRP.getAssociatedFunction());
3591 }
3592
3593 bool isAssumedReachable(
3594 Attributor &A, const Instruction &From, const Instruction &To,
3595 const AA::InstExclusionSetTy *ExclusionSet) const override {
3596 auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
3597 if (&From == &To)
3598 return true;
3599
3600 RQITy StackRQI(A, From, To, ExclusionSet, false);
3601 RQITy::Reachable Result;
3602 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
3603 return NonConstThis->isReachableImpl(A, RQI&: StackRQI,
3604 /*IsTemporaryRQI=*/true);
3605 return Result == RQITy::Reachable::Yes;
3606 }
3607
3608 ChangeStatus updateImpl(Attributor &A) override {
3609 // We only depend on liveness. DeadEdges is all we care about, check if any
3610 // of them changed.
3611 auto *LivenessAA =
3612 A.getAAFor<AAIsDead>(QueryingAA: *this, IRP: getIRPosition(), DepClass: DepClassTy::OPTIONAL);
3613 if (LivenessAA &&
3614 llvm::all_of(Range&: DeadEdges,
3615 P: [&](const auto &DeadEdge) {
3616 return LivenessAA->isEdgeDead(From: DeadEdge.first,
3617 To: DeadEdge.second);
3618 }) &&
3619 llvm::all_of(Range&: DeadBlocks, P: [&](const BasicBlock *BB) {
3620 return LivenessAA->isAssumedDead(BB);
3621 })) {
3622 return ChangeStatus::UNCHANGED;
3623 }
3624 DeadEdges.clear();
3625 DeadBlocks.clear();
3626 return Base::updateImpl(A);
3627 }
3628
3629 bool isReachableImpl(Attributor &A, RQITy &RQI,
3630 bool IsTemporaryRQI) override {
3631 const Instruction *Origin = RQI.From;
3632 bool UsedExclusionSet = false;
3633
3634 auto WillReachInBlock = [&](const Instruction &From, const Instruction &To,
3635 const AA::InstExclusionSetTy *ExclusionSet) {
3636 const Instruction *IP = &From;
3637 while (IP && IP != &To) {
3638 if (ExclusionSet && IP != Origin && ExclusionSet->count(Ptr: IP)) {
3639 UsedExclusionSet = true;
3640 break;
3641 }
3642 IP = IP->getNextNode();
3643 }
3644 return IP == &To;
3645 };
3646
3647 const BasicBlock *FromBB = RQI.From->getParent();
3648 const BasicBlock *ToBB = RQI.To->getParent();
3649 assert(FromBB->getParent() == ToBB->getParent() &&
3650 "Not an intra-procedural query!");
3651
3652 // Check intra-block reachability, however, other reaching paths are still
3653 // possible.
3654 if (FromBB == ToBB &&
3655 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3656 return rememberResult(A, Result: RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3657 IsTemporaryRQI);
3658
3659 // Check if reaching the ToBB block is sufficient or if even that would not
3660 // ensure reaching the target. In the latter case we are done.
3661 if (!WillReachInBlock(ToBB->front(), *RQI.To, RQI.ExclusionSet))
3662 return rememberResult(A, Result: RQITy::Reachable::No, RQI, UsedExclusionSet,
3663 IsTemporaryRQI);
3664
3665 const Function *Fn = FromBB->getParent();
3666 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3667 if (RQI.ExclusionSet)
3668 for (auto *I : *RQI.ExclusionSet)
3669 if (I->getFunction() == Fn)
3670 ExclusionBlocks.insert(Ptr: I->getParent());
3671
3672 // Check if we make it out of the FromBB block at all.
3673 if (ExclusionBlocks.count(Ptr: FromBB) &&
3674 !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
3675 RQI.ExclusionSet))
3676 return rememberResult(A, Result: RQITy::Reachable::No, RQI, UsedExclusionSet: true, IsTemporaryRQI);
3677
3678 auto *LivenessAA =
3679 A.getAAFor<AAIsDead>(QueryingAA: *this, IRP: getIRPosition(), DepClass: DepClassTy::OPTIONAL);
3680 if (LivenessAA && LivenessAA->isAssumedDead(BB: ToBB)) {
3681 DeadBlocks.insert(V: ToBB);
3682 return rememberResult(A, Result: RQITy::Reachable::No, RQI, UsedExclusionSet,
3683 IsTemporaryRQI);
3684 }
3685
3686 SmallPtrSet<const BasicBlock *, 16> Visited;
3687 SmallVector<const BasicBlock *, 16> Worklist;
3688 Worklist.push_back(Elt: FromBB);
3689
3690 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3691 while (!Worklist.empty()) {
3692 const BasicBlock *BB = Worklist.pop_back_val();
3693 if (!Visited.insert(Ptr: BB).second)
3694 continue;
3695 for (const BasicBlock *SuccBB : successors(BB)) {
3696 if (LivenessAA && LivenessAA->isEdgeDead(From: BB, To: SuccBB)) {
3697 LocalDeadEdges.insert(V: {BB, SuccBB});
3698 continue;
3699 }
3700 // We checked before if we just need to reach the ToBB block.
3701 if (SuccBB == ToBB)
3702 return rememberResult(A, Result: RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3703 IsTemporaryRQI);
3704 if (DT && ExclusionBlocks.empty() && DT->dominates(A: BB, B: ToBB))
3705 return rememberResult(A, Result: RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3706 IsTemporaryRQI);
3707
3708 if (ExclusionBlocks.count(Ptr: SuccBB)) {
3709 UsedExclusionSet = true;
3710 continue;
3711 }
3712 Worklist.push_back(Elt: SuccBB);
3713 }
3714 }
3715
3716 DeadEdges.insert_range(R&: LocalDeadEdges);
3717 return rememberResult(A, Result: RQITy::Reachable::No, RQI, UsedExclusionSet,
3718 IsTemporaryRQI);
3719 }
3720
3721 /// See AbstractAttribute::trackStatistics()
3722 void trackStatistics() const override {}
3723
3724private:
3725 // Set of assumed dead blocks we used in the last query. If any changes we
3726 // update the state.
3727 DenseSet<const BasicBlock *> DeadBlocks;
3728
3729 // Set of assumed dead edges we used in the last query. If any changes we
3730 // update the state.
3731 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3732
3733 /// The dominator tree of the function to short-circuit reasoning.
3734 const DominatorTree *DT = nullptr;
3735};
3736} // namespace
3737
3738/// ------------------------ NoAlias Argument Attribute ------------------------
3739
3740bool AANoAlias::isImpliedByIR(Attributor &A, const IRPosition &IRP,
3741 Attribute::AttrKind ImpliedAttributeKind,
3742 bool IgnoreSubsumingPositions) {
3743 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3744 "Unexpected attribute kind");
3745 Value *Val = &IRP.getAssociatedValue();
3746 if (IRP.getPositionKind() != IRP_CALL_SITE_ARGUMENT) {
3747 if (isa<AllocaInst>(Val))
3748 return true;
3749 } else {
3750 IgnoreSubsumingPositions = true;
3751 }
3752
3753 if (isa<UndefValue>(Val))
3754 return true;
3755
3756 if (isa<ConstantPointerNull>(Val) &&
3757 !NullPointerIsDefined(F: IRP.getAnchorScope(),
3758 AS: Val->getType()->getPointerAddressSpace()))
3759 return true;
3760
3761 if (A.hasAttr(IRP, AKs: {Attribute::ByVal, Attribute::NoAlias},
3762 IgnoreSubsumingPositions, ImpliedAttributeKind: Attribute::NoAlias))
3763 return true;
3764
3765 return false;
3766}
3767
3768namespace {
3769struct AANoAliasImpl : AANoAlias {
3770 AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
3771 assert(getAssociatedType()->isPointerTy() &&
3772 "Noalias is a pointer attribute");
3773 }
3774
3775 const std::string getAsStr(Attributor *A) const override {
3776 return getAssumed() ? "noalias" : "may-alias";
3777 }
3778};
3779
3780/// NoAlias attribute for a floating value.
3781struct AANoAliasFloating final : AANoAliasImpl {
3782 AANoAliasFloating(const IRPosition &IRP, Attributor &A)
3783 : AANoAliasImpl(IRP, A) {}
3784
3785 /// See AbstractAttribute::updateImpl(...).
3786 ChangeStatus updateImpl(Attributor &A) override {
3787 // TODO: Implement this.
3788 return indicatePessimisticFixpoint();
3789 }
3790
3791 /// See AbstractAttribute::trackStatistics()
3792 void trackStatistics() const override {
3793 STATS_DECLTRACK_FLOATING_ATTR(noalias)
3794 }
3795};
3796
3797/// NoAlias attribute for an argument.
3798struct AANoAliasArgument final
3799 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3800 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3801 AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
3802
3803 /// See AbstractAttribute::update(...).
3804 ChangeStatus updateImpl(Attributor &A) override {
3805 // We have to make sure no-alias on the argument does not break
3806 // synchronization when this is a callback argument, see also [1] below.
3807 // If synchronization cannot be affected, we delegate to the base updateImpl
3808 // function, otherwise we give up for now.
3809
3810 // If the function is no-sync, no-alias cannot break synchronization.
3811 bool IsKnownNoSycn;
3812 if (AA::hasAssumedIRAttr<Attribute::NoSync>(
3813 A, QueryingAA: this, IRP: IRPosition::function_scope(IRP: getIRPosition()),
3814 DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoSycn))
3815 return Base::updateImpl(A);
3816
3817 // If the argument is read-only, no-alias cannot break synchronization.
3818 bool IsKnown;
3819 if (AA::isAssumedReadOnly(A, IRP: getIRPosition(), QueryingAA: *this, IsKnown))
3820 return Base::updateImpl(A);
3821
3822 // If the argument is never passed through callbacks, no-alias cannot break
3823 // synchronization.
3824 bool UsedAssumedInformation = false;
3825 if (A.checkForAllCallSites(
3826 Pred: [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, QueryingAA: *this,
3827 RequireAllCallSites: true, UsedAssumedInformation))
3828 return Base::updateImpl(A);
3829
3830 // TODO: add no-alias but make sure it doesn't break synchronization by
3831 // introducing fake uses. See:
3832 // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
3833 // International Workshop on OpenMP 2018,
3834 // http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf
3835
3836 return indicatePessimisticFixpoint();
3837 }
3838
3839 /// See AbstractAttribute::trackStatistics()
3840 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
3841};
3842
3843struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3844 AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
3845 : AANoAliasImpl(IRP, A) {}
3846
3847 /// Determine if the underlying value may alias with the call site argument
3848 /// \p OtherArgNo of \p ICS (= the underlying call site).
3849 bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
3850 const AAMemoryBehavior &MemBehaviorAA,
3851 const CallBase &CB, unsigned OtherArgNo) {
3852 // We do not need to worry about aliasing with the underlying IRP.
3853 if (this->getCalleeArgNo() == (int)OtherArgNo)
3854 return false;
3855
3856 // If it is not a pointer or pointer vector we do not alias.
3857 const Value *ArgOp = CB.getArgOperand(i: OtherArgNo);
3858 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
3859 return false;
3860
3861 auto *CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
3862 QueryingAA: *this, IRP: IRPosition::callsite_argument(CB, ArgNo: OtherArgNo), DepClass: DepClassTy::NONE);
3863
3864 // If the argument is readnone, there is no read-write aliasing.
3865 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3866 A.recordDependence(FromAA: *CBArgMemBehaviorAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
3867 return false;
3868 }
3869
3870 // If the argument is readonly and the underlying value is readonly, there
3871 // is no read-write aliasing.
3872 bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
3873 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3874 IsReadOnly) {
3875 A.recordDependence(FromAA: MemBehaviorAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
3876 A.recordDependence(FromAA: *CBArgMemBehaviorAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
3877 return false;
3878 }
3879
3880 // We have to utilize actual alias analysis queries so we need the object.
3881 if (!AAR)
3882 AAR = A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3883 F: *getAnchorScope());
3884
3885 // Try to rule it out at the call site.
3886 bool IsAliasing = !AAR || !AAR->isNoAlias(V1: &getAssociatedValue(), V2: ArgOp);
3887 LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "
3888 "callsite arguments: "
3889 << getAssociatedValue() << " " << *ArgOp << " => "
3890 << (IsAliasing ? "" : "no-") << "alias \n");
3891
3892 return IsAliasing;
3893 }
3894
3895 bool isKnownNoAliasDueToNoAliasPreservation(
3896 Attributor &A, AAResults *&AAR, const AAMemoryBehavior &MemBehaviorAA) {
3897 // We can deduce "noalias" if the following conditions hold.
3898 // (i) Associated value is assumed to be noalias in the definition.
3899 // (ii) Associated value is assumed to be no-capture in all the uses
3900 // possibly executed before this callsite.
3901 // (iii) There is no other pointer argument which could alias with the
3902 // value.
3903
3904 const IRPosition &VIRP = IRPosition::value(V: getAssociatedValue());
3905 const Function *ScopeFn = VIRP.getAnchorScope();
3906 // Check whether the value is captured in the scope using AANoCapture.
3907 // Look at CFG and check only uses possibly executed before this
3908 // callsite.
3909 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
3910 Instruction *UserI = cast<Instruction>(Val: U.getUser());
3911
3912 // If UserI is the curr instruction and there is a single potential use of
3913 // the value in UserI we allow the use.
3914 // TODO: We should inspect the operands and allow those that cannot alias
3915 // with the value.
3916 if (UserI == getCtxI() && UserI->getNumOperands() == 1)
3917 return true;
3918
3919 if (ScopeFn) {
3920 if (auto *CB = dyn_cast<CallBase>(Val: UserI)) {
3921 if (CB->isArgOperand(U: &U)) {
3922
3923 unsigned ArgNo = CB->getArgOperandNo(U: &U);
3924
3925 bool IsKnownNoCapture;
3926 if (AA::hasAssumedIRAttr<Attribute::Captures>(
3927 A, QueryingAA: this, IRP: IRPosition::callsite_argument(CB: *CB, ArgNo),
3928 DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoCapture))
3929 return true;
3930 }
3931 }
3932
3933 if (!AA::isPotentiallyReachable(
3934 A, FromI: *UserI, ToI: *getCtxI(), QueryingAA: *this, /* ExclusionSet */ nullptr,
3935 GoBackwardsCB: [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
3936 return true;
3937 }
3938
3939 // TODO: We should track the capturing uses in AANoCapture but the problem
3940 // is CGSCC runs. For those we would need to "allow" AANoCapture for
3941 // a value in the module slice.
3942 // TODO(captures): Make this more precise.
3943 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
3944 if (capturesNothing(CC: CI))
3945 return true;
3946 if (CI.isPassthrough()) {
3947 Follow = true;
3948 return true;
3949 }
3950 LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserI << "\n");
3951 return false;
3952 };
3953
3954 bool IsKnownNoCapture;
3955 const AANoCapture *NoCaptureAA = nullptr;
3956 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
3957 A, QueryingAA: this, IRP: VIRP, DepClass: DepClassTy::NONE, IsKnown&: IsKnownNoCapture, IgnoreSubsumingPositions: false, AAPtr: &NoCaptureAA);
3958 if (!IsAssumedNoCapture &&
3959 (!NoCaptureAA || !NoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
3960 if (!A.checkForAllUses(Pred: UsePred, QueryingAA: *this, V: getAssociatedValue())) {
3961 LLVM_DEBUG(
3962 dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
3963 << " cannot be noalias as it is potentially captured\n");
3964 return false;
3965 }
3966 }
3967 if (NoCaptureAA)
3968 A.recordDependence(FromAA: *NoCaptureAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
3969
3970 // Check there is no other pointer argument which could alias with the
3971 // value passed at this call site.
3972 // TODO: AbstractCallSite
3973 const auto &CB = cast<CallBase>(Val&: getAnchorValue());
3974 for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
3975 if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
3976 return false;
3977
3978 return true;
3979 }
3980
3981 /// See AbstractAttribute::updateImpl(...).
3982 ChangeStatus updateImpl(Attributor &A) override {
3983 // If the argument is readnone we are done as there are no accesses via the
3984 // argument.
3985 auto *MemBehaviorAA =
3986 A.getAAFor<AAMemoryBehavior>(QueryingAA: *this, IRP: getIRPosition(), DepClass: DepClassTy::NONE);
3987 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
3988 A.recordDependence(FromAA: *MemBehaviorAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
3989 return ChangeStatus::UNCHANGED;
3990 }
3991
3992 bool IsKnownNoAlias;
3993 const IRPosition &VIRP = IRPosition::value(V: getAssociatedValue());
3994 if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(
3995 A, QueryingAA: this, IRP: VIRP, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoAlias)) {
3996 LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()
3997 << " is not no-alias at the definition\n");
3998 return indicatePessimisticFixpoint();
3999 }
4000
4001 AAResults *AAR = nullptr;
4002 if (MemBehaviorAA &&
4003 isKnownNoAliasDueToNoAliasPreservation(A, AAR, MemBehaviorAA: *MemBehaviorAA)) {
4004 LLVM_DEBUG(
4005 dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n");
4006 return ChangeStatus::UNCHANGED;
4007 }
4008
4009 return indicatePessimisticFixpoint();
4010 }
4011
4012 /// See AbstractAttribute::trackStatistics()
4013 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }
4014};
4015
4016/// NoAlias attribute for function return value.
4017struct AANoAliasReturned final : AANoAliasImpl {
4018 AANoAliasReturned(const IRPosition &IRP, Attributor &A)
4019 : AANoAliasImpl(IRP, A) {}
4020
4021 /// See AbstractAttribute::updateImpl(...).
4022 ChangeStatus updateImpl(Attributor &A) override {
4023
4024 auto CheckReturnValue = [&](Value &RV) -> bool {
4025 if (Constant *C = dyn_cast<Constant>(Val: &RV))
4026 if (C->isNullValue() || isa<UndefValue>(Val: C))
4027 return true;
4028
4029 /// For now, we can only deduce noalias if we have call sites.
4030 /// FIXME: add more support.
4031 if (!isa<CallBase>(Val: &RV))
4032 return false;
4033
4034 const IRPosition &RVPos = IRPosition::value(V: RV);
4035 bool IsKnownNoAlias;
4036 if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(
4037 A, QueryingAA: this, IRP: RVPos, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoAlias))
4038 return false;
4039
4040 bool IsKnownNoCapture;
4041 const AANoCapture *NoCaptureAA = nullptr;
4042 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
4043 A, QueryingAA: this, IRP: RVPos, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoCapture, IgnoreSubsumingPositions: false,
4044 AAPtr: &NoCaptureAA);
4045 return IsAssumedNoCapture ||
4046 (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned());
4047 };
4048
4049 if (!A.checkForAllReturnedValues(Pred: CheckReturnValue, QueryingAA: *this))
4050 return indicatePessimisticFixpoint();
4051
4052 return ChangeStatus::UNCHANGED;
4053 }
4054
4055 /// See AbstractAttribute::trackStatistics()
4056 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
4057};
4058
4059/// NoAlias attribute deduction for a call site return value.
4060struct AANoAliasCallSiteReturned final
4061 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4062 AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
4063 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP, A) {}
4064
4065 /// See AbstractAttribute::trackStatistics()
4066 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }
4067};
4068} // namespace
4069
4070/// -------------------AAIsDead Function Attribute-----------------------
4071
4072namespace {
4073struct AAIsDeadValueImpl : public AAIsDead {
4074 AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4075
4076 /// See AAIsDead::isAssumedDead().
4077 bool isAssumedDead() const override { return isAssumed(BitsEncoding: IS_DEAD); }
4078
4079 /// See AAIsDead::isKnownDead().
4080 bool isKnownDead() const override { return isKnown(BitsEncoding: IS_DEAD); }
4081
4082 /// See AAIsDead::isAssumedDead(BasicBlock *).
4083 bool isAssumedDead(const BasicBlock *BB) const override { return false; }
4084
4085 /// See AAIsDead::isKnownDead(BasicBlock *).
4086 bool isKnownDead(const BasicBlock *BB) const override { return false; }
4087
4088 /// See AAIsDead::isAssumedDead(Instruction *I).
4089 bool isAssumedDead(const Instruction *I) const override {
4090 return I == getCtxI() && isAssumedDead();
4091 }
4092
4093 /// See AAIsDead::isKnownDead(Instruction *I).
4094 bool isKnownDead(const Instruction *I) const override {
4095 return isAssumedDead(I) && isKnownDead();
4096 }
4097
4098 /// See AbstractAttribute::getAsStr().
4099 const std::string getAsStr(Attributor *A) const override {
4100 return isAssumedDead() ? "assumed-dead" : "assumed-live";
4101 }
4102
4103 /// Check if all uses are assumed dead.
4104 bool areAllUsesAssumedDead(Attributor &A, Value &V) {
4105 // Callers might not check the type, void has no uses.
4106 if (V.getType()->isVoidTy() || V.use_empty())
4107 return true;
4108
4109 // If we replace a value with a constant there are no uses left afterwards.
4110 if (!isa<Constant>(Val: V)) {
4111 if (auto *I = dyn_cast<Instruction>(Val: &V))
4112 if (!A.isRunOn(Fn&: *I->getFunction()))
4113 return false;
4114 bool UsedAssumedInformation = false;
4115 std::optional<Constant *> C =
4116 A.getAssumedConstant(V, AA: *this, UsedAssumedInformation);
4117 if (!C || *C)
4118 return true;
4119 }
4120
4121 auto UsePred = [&](const Use &U, bool &Follow) { return false; };
4122 // Explicitly set the dependence class to required because we want a long
4123 // chain of N dependent instructions to be considered live as soon as one is
4124 // without going through N update cycles. This is not required for
4125 // correctness.
4126 return A.checkForAllUses(Pred: UsePred, QueryingAA: *this, V, /* CheckBBLivenessOnly */ false,
4127 LivenessDepClass: DepClassTy::REQUIRED,
4128 /* IgnoreDroppableUses */ false);
4129 }
4130
4131 /// Determine if \p I is assumed to be side-effect free.
4132 bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
4133 if (!I || wouldInstructionBeTriviallyDead(I))
4134 return true;
4135
4136 if (!I->isTerminator() && !I->mayHaveSideEffects())
4137 return true;
4138
4139 auto *CB = dyn_cast<CallBase>(Val: I);
4140 if (!CB || isa<IntrinsicInst>(Val: CB))
4141 return false;
4142
4143 const IRPosition &CallIRP = IRPosition::callsite_function(CB: *CB);
4144
4145 bool IsKnownNoUnwind;
4146 if (!AA::hasAssumedIRAttr<Attribute::NoUnwind>(
4147 A, QueryingAA: this, IRP: CallIRP, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoUnwind))
4148 return false;
4149
4150 bool IsKnown;
4151 return AA::isAssumedReadOnly(A, IRP: CallIRP, QueryingAA: *this, IsKnown);
4152 }
4153};
4154
4155struct AAIsDeadFloating : public AAIsDeadValueImpl {
4156 AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
4157 : AAIsDeadValueImpl(IRP, A) {}
4158
4159 /// See AbstractAttribute::initialize(...).
4160 void initialize(Attributor &A) override {
4161 AAIsDeadValueImpl::initialize(A);
4162
4163 if (isa<UndefValue>(Val: getAssociatedValue())) {
4164 indicatePessimisticFixpoint();
4165 return;
4166 }
4167
4168 Instruction *I = dyn_cast<Instruction>(Val: &getAssociatedValue());
4169 if (!isAssumedSideEffectFree(A, I)) {
4170 if (!isa_and_nonnull<StoreInst>(Val: I) && !isa_and_nonnull<FenceInst>(Val: I))
4171 indicatePessimisticFixpoint();
4172 else
4173 removeAssumedBits(BitsEncoding: HAS_NO_EFFECT);
4174 }
4175 }
4176
4177 bool isDeadFence(Attributor &A, FenceInst &FI) {
4178 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
4179 IRP: IRPosition::function(F: *FI.getFunction()), QueryingAA: *this, DepClass: DepClassTy::NONE);
4180 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4181 return false;
4182 A.recordDependence(FromAA: *ExecDomainAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
4183 return true;
4184 }
4185
4186 bool isDeadStore(Attributor &A, StoreInst &SI,
4187 SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
4188 // Lang ref now states volatile store is not UB/dead, let's skip them.
4189 if (SI.isVolatile())
4190 return false;
4191
4192 // If we are collecting assumes to be deleted we are in the manifest stage.
4193 // It's problematic to collect the potential copies again now so we use the
4194 // cached ones.
4195 bool UsedAssumedInformation = false;
4196 if (!AssumeOnlyInst) {
4197 PotentialCopies.clear();
4198 if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, QueryingAA: *this,
4199 UsedAssumedInformation)) {
4200 LLVM_DEBUG(
4201 dbgs()
4202 << "[AAIsDead] Could not determine potential copies of store!\n");
4203 return false;
4204 }
4205 }
4206 LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()
4207 << " potential copies.\n");
4208
4209 InformationCache &InfoCache = A.getInfoCache();
4210 return llvm::all_of(Range&: PotentialCopies, P: [&](Value *V) {
4211 if (A.isAssumedDead(IRP: IRPosition::value(V: *V), QueryingAA: this, FnLivenessAA: nullptr,
4212 UsedAssumedInformation))
4213 return true;
4214 if (auto *LI = dyn_cast<LoadInst>(Val: V)) {
4215 if (llvm::all_of(Range: LI->uses(), P: [&](const Use &U) {
4216 auto &UserI = cast<Instruction>(Val&: *U.getUser());
4217 if (InfoCache.isOnlyUsedByAssume(I: UserI)) {
4218 if (AssumeOnlyInst)
4219 AssumeOnlyInst->insert(X: &UserI);
4220 return true;
4221 }
4222 return A.isAssumedDead(U, QueryingAA: this, FnLivenessAA: nullptr, UsedAssumedInformation);
4223 })) {
4224 return true;
4225 }
4226 }
4227 LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *V
4228 << " is assumed live!\n");
4229 return false;
4230 });
4231 }
4232
4233 /// See AbstractAttribute::getAsStr().
4234 const std::string getAsStr(Attributor *A) const override {
4235 Instruction *I = dyn_cast<Instruction>(Val: &getAssociatedValue());
4236 if (isa_and_nonnull<StoreInst>(Val: I))
4237 if (isValidState())
4238 return "assumed-dead-store";
4239 if (isa_and_nonnull<FenceInst>(Val: I))
4240 if (isValidState())
4241 return "assumed-dead-fence";
4242 return AAIsDeadValueImpl::getAsStr(A);
4243 }
4244
4245 /// See AbstractAttribute::updateImpl(...).
4246 ChangeStatus updateImpl(Attributor &A) override {
4247 Instruction *I = dyn_cast<Instruction>(Val: &getAssociatedValue());
4248 if (auto *SI = dyn_cast_or_null<StoreInst>(Val: I)) {
4249 if (!isDeadStore(A, SI&: *SI))
4250 return indicatePessimisticFixpoint();
4251 } else if (auto *FI = dyn_cast_or_null<FenceInst>(Val: I)) {
4252 if (!isDeadFence(A, FI&: *FI))
4253 return indicatePessimisticFixpoint();
4254 } else {
4255 if (!isAssumedSideEffectFree(A, I))
4256 return indicatePessimisticFixpoint();
4257 if (!areAllUsesAssumedDead(A, V&: getAssociatedValue()))
4258 return indicatePessimisticFixpoint();
4259 }
4260 return ChangeStatus::UNCHANGED;
4261 }
4262
4263 bool isRemovableStore() const override {
4264 return isAssumed(BitsEncoding: IS_REMOVABLE) && isa<StoreInst>(Val: &getAssociatedValue());
4265 }
4266
4267 /// See AbstractAttribute::manifest(...).
4268 ChangeStatus manifest(Attributor &A) override {
4269 Value &V = getAssociatedValue();
4270 if (auto *I = dyn_cast<Instruction>(Val: &V)) {
4271 // If we get here we basically know the users are all dead. We check if
4272 // isAssumedSideEffectFree returns true here again because it might not be
4273 // the case and only the users are dead but the instruction (=call) is
4274 // still needed.
4275 if (auto *SI = dyn_cast<StoreInst>(Val: I)) {
4276 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4277 bool IsDead = isDeadStore(A, SI&: *SI, AssumeOnlyInst: &AssumeOnlyInst);
4278 (void)IsDead;
4279 assert(IsDead && "Store was assumed to be dead!");
4280 A.deleteAfterManifest(I&: *I);
4281 for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
4282 Instruction *AOI = AssumeOnlyInst[i];
4283 for (auto *Usr : AOI->users())
4284 AssumeOnlyInst.insert(X: cast<Instruction>(Val: Usr));
4285 A.deleteAfterManifest(I&: *AOI);
4286 }
4287 return ChangeStatus::CHANGED;
4288 }
4289 if (auto *FI = dyn_cast<FenceInst>(Val: I)) {
4290 assert(isDeadFence(A, *FI));
4291 A.deleteAfterManifest(I&: *FI);
4292 return ChangeStatus::CHANGED;
4293 }
4294 if (isAssumedSideEffectFree(A, I) && !I->isTerminator()) {
4295 A.deleteAfterManifest(I&: *I);
4296 return ChangeStatus::CHANGED;
4297 }
4298 }
4299 return ChangeStatus::UNCHANGED;
4300 }
4301
4302 /// See AbstractAttribute::trackStatistics()
4303 void trackStatistics() const override {
4304 STATS_DECLTRACK_FLOATING_ATTR(IsDead)
4305 }
4306
4307private:
4308 // The potential copies of a dead store, used for deletion during manifest.
4309 SmallSetVector<Value *, 4> PotentialCopies;
4310};
4311
4312struct AAIsDeadArgument : public AAIsDeadFloating {
4313 AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
4314 : AAIsDeadFloating(IRP, A) {}
4315
4316 /// See AbstractAttribute::manifest(...).
4317 ChangeStatus manifest(Attributor &A) override {
4318 Argument &Arg = *getAssociatedArgument();
4319 if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
4320 if (A.registerFunctionSignatureRewrite(
4321 Arg, /* ReplacementTypes */ {},
4322 CalleeRepairCB: Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{},
4323 ACSRepairCB: Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) {
4324 return ChangeStatus::CHANGED;
4325 }
4326 return ChangeStatus::UNCHANGED;
4327 }
4328
4329 /// See AbstractAttribute::trackStatistics()
4330 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) }
4331};
4332
4333struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
4334 AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
4335 : AAIsDeadValueImpl(IRP, A) {}
4336
4337 /// See AbstractAttribute::initialize(...).
4338 void initialize(Attributor &A) override {
4339 AAIsDeadValueImpl::initialize(A);
4340 if (isa<UndefValue>(Val: getAssociatedValue()))
4341 indicatePessimisticFixpoint();
4342 }
4343
4344 /// See AbstractAttribute::updateImpl(...).
4345 ChangeStatus updateImpl(Attributor &A) override {
4346 // TODO: Once we have call site specific value information we can provide
4347 // call site specific liveness information and then it makes
4348 // sense to specialize attributes for call sites arguments instead of
4349 // redirecting requests to the callee argument.
4350 Argument *Arg = getAssociatedArgument();
4351 if (!Arg)
4352 return indicatePessimisticFixpoint();
4353 const IRPosition &ArgPos = IRPosition::argument(Arg: *Arg);
4354 auto *ArgAA = A.getAAFor<AAIsDead>(QueryingAA: *this, IRP: ArgPos, DepClass: DepClassTy::REQUIRED);
4355 if (!ArgAA)
4356 return indicatePessimisticFixpoint();
4357 return clampStateAndIndicateChange(S&: getState(), R: ArgAA->getState());
4358 }
4359
4360 /// See AbstractAttribute::manifest(...).
4361 ChangeStatus manifest(Attributor &A) override {
4362 CallBase &CB = cast<CallBase>(Val&: getAnchorValue());
4363 Use &U = CB.getArgOperandUse(i: getCallSiteArgNo());
4364 assert(!isa<UndefValue>(U.get()) &&
4365 "Expected undef values to be filtered out!");
4366 UndefValue &UV = *UndefValue::get(T: U->getType());
4367 if (A.changeUseAfterManifest(U, NV&: UV))
4368 return ChangeStatus::CHANGED;
4369 return ChangeStatus::UNCHANGED;
4370 }
4371
4372 /// See AbstractAttribute::trackStatistics()
4373 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) }
4374};
4375
4376struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
4377 AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
4378 : AAIsDeadFloating(IRP, A) {}
4379
4380 /// See AAIsDead::isAssumedDead().
4381 bool isAssumedDead() const override {
4382 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4383 }
4384
4385 /// See AbstractAttribute::initialize(...).
4386 void initialize(Attributor &A) override {
4387 AAIsDeadFloating::initialize(A);
4388 if (isa<UndefValue>(Val: getAssociatedValue())) {
4389 indicatePessimisticFixpoint();
4390 return;
4391 }
4392
4393 // We track this separately as a secondary state.
4394 IsAssumedSideEffectFree = isAssumedSideEffectFree(A, I: getCtxI());
4395 }
4396
4397 /// See AbstractAttribute::updateImpl(...).
4398 ChangeStatus updateImpl(Attributor &A) override {
4399 ChangeStatus Changed = ChangeStatus::UNCHANGED;
4400 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, I: getCtxI())) {
4401 IsAssumedSideEffectFree = false;
4402 Changed = ChangeStatus::CHANGED;
4403 }
4404 if (!areAllUsesAssumedDead(A, V&: getAssociatedValue()))
4405 return indicatePessimisticFixpoint();
4406 return Changed;
4407 }
4408
4409 /// See AbstractAttribute::trackStatistics()
4410 void trackStatistics() const override {
4411 if (IsAssumedSideEffectFree)
4412 STATS_DECLTRACK_CSRET_ATTR(IsDead)
4413 else
4414 STATS_DECLTRACK_CSRET_ATTR(UnusedResult)
4415 }
4416
4417 /// See AbstractAttribute::getAsStr().
4418 const std::string getAsStr(Attributor *A) const override {
4419 return isAssumedDead()
4420 ? "assumed-dead"
4421 : (getAssumed() ? "assumed-dead-users" : "assumed-live");
4422 }
4423
4424private:
4425 bool IsAssumedSideEffectFree = true;
4426};
4427
4428struct AAIsDeadReturned : public AAIsDeadValueImpl {
4429 AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
4430 : AAIsDeadValueImpl(IRP, A) {}
4431
4432 /// See AbstractAttribute::updateImpl(...).
4433 ChangeStatus updateImpl(Attributor &A) override {
4434
4435 bool UsedAssumedInformation = false;
4436 A.checkForAllInstructions(Pred: [](Instruction &) { return true; }, QueryingAA: *this,
4437 Opcodes: {Instruction::Ret}, UsedAssumedInformation);
4438
4439 auto PredForCallSite = [&](AbstractCallSite ACS) {
4440 if (ACS.isCallbackCall() || !ACS.getInstruction())
4441 return false;
4442 return areAllUsesAssumedDead(A, V&: *ACS.getInstruction());
4443 };
4444
4445 if (!A.checkForAllCallSites(Pred: PredForCallSite, QueryingAA: *this, RequireAllCallSites: true,
4446 UsedAssumedInformation))
4447 return indicatePessimisticFixpoint();
4448
4449 return ChangeStatus::UNCHANGED;
4450 }
4451
4452 /// See AbstractAttribute::manifest(...).
4453 ChangeStatus manifest(Attributor &A) override {
4454 // TODO: Rewrite the signature to return void?
4455 bool AnyChange = false;
4456 UndefValue &UV = *UndefValue::get(T: getAssociatedFunction()->getReturnType());
4457 auto RetInstPred = [&](Instruction &I) {
4458 ReturnInst &RI = cast<ReturnInst>(Val&: I);
4459 if (!isa<UndefValue>(Val: RI.getReturnValue()))
4460 AnyChange |= A.changeUseAfterManifest(U&: RI.getOperandUse(i: 0), NV&: UV);
4461 return true;
4462 };
4463 bool UsedAssumedInformation = false;
4464 A.checkForAllInstructions(Pred: RetInstPred, QueryingAA: *this, Opcodes: {Instruction::Ret},
4465 UsedAssumedInformation);
4466 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4467 }
4468
4469 /// See AbstractAttribute::trackStatistics()
4470 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) }
4471};
4472
4473struct AAIsDeadFunction : public AAIsDead {
4474 AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4475
4476 /// See AbstractAttribute::initialize(...).
4477 void initialize(Attributor &A) override {
4478 Function *F = getAnchorScope();
4479 assert(F && "Did expect an anchor function");
4480 if (!isAssumedDeadInternalFunction(A)) {
4481 ToBeExploredFrom.insert(X: &F->getEntryBlock().front());
4482 assumeLive(A, BB: F->getEntryBlock());
4483 }
4484 }
4485
4486 bool isAssumedDeadInternalFunction(Attributor &A) {
4487 if (!getAnchorScope()->hasLocalLinkage())
4488 return false;
4489 bool UsedAssumedInformation = false;
4490 return A.checkForAllCallSites(Pred: [](AbstractCallSite) { return false; }, QueryingAA: *this,
4491 RequireAllCallSites: true, UsedAssumedInformation);
4492 }
4493
4494 /// See AbstractAttribute::getAsStr().
4495 const std::string getAsStr(Attributor *A) const override {
4496 return "Live[#BB " + std::to_string(val: AssumedLiveBlocks.size()) + "/" +
4497 std::to_string(val: getAnchorScope()->size()) + "][#TBEP " +
4498 std::to_string(val: ToBeExploredFrom.size()) + "][#KDE " +
4499 std::to_string(val: KnownDeadEnds.size()) + "]";
4500 }
4501
4502 /// See AbstractAttribute::manifest(...).
4503 ChangeStatus manifest(Attributor &A) override {
4504 assert(getState().isValidState() &&
4505 "Attempted to manifest an invalid state!");
4506
4507 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
4508 Function &F = *getAnchorScope();
4509
4510 if (AssumedLiveBlocks.empty()) {
4511 A.deleteAfterManifest(F);
4512 return ChangeStatus::CHANGED;
4513 }
4514
4515 // Flag to determine if we can change an invoke to a call assuming the
4516 // callee is nounwind. This is not possible if the personality of the
4517 // function allows to catch asynchronous exceptions.
4518 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
4519
4520 KnownDeadEnds.set_union(ToBeExploredFrom);
4521 for (const Instruction *DeadEndI : KnownDeadEnds) {
4522 auto *CB = dyn_cast<CallBase>(Val: DeadEndI);
4523 if (!CB)
4524 continue;
4525 bool IsKnownNoReturn;
4526 bool MayReturn = !AA::hasAssumedIRAttr<Attribute::NoReturn>(
4527 A, QueryingAA: this, IRP: IRPosition::callsite_function(CB: *CB), DepClass: DepClassTy::OPTIONAL,
4528 IsKnown&: IsKnownNoReturn);
4529 if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(Val: CB)))
4530 continue;
4531
4532 if (auto *II = dyn_cast<InvokeInst>(Val: DeadEndI))
4533 A.registerInvokeWithDeadSuccessor(II&: const_cast<InvokeInst &>(*II));
4534 else
4535 A.changeToUnreachableAfterManifest(
4536 I: const_cast<Instruction *>(DeadEndI->getNextNode()));
4537 HasChanged = ChangeStatus::CHANGED;
4538 }
4539
4540 STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.");
4541 for (BasicBlock &BB : F)
4542 if (!AssumedLiveBlocks.count(V: &BB)) {
4543 A.deleteAfterManifest(BB);
4544 ++BUILD_STAT_NAME(AAIsDead, BasicBlock);
4545 HasChanged = ChangeStatus::CHANGED;
4546 }
4547
4548 return HasChanged;
4549 }
4550
4551 /// See AbstractAttribute::updateImpl(...).
4552 ChangeStatus updateImpl(Attributor &A) override;
4553
4554 bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
4555 assert(From->getParent() == getAnchorScope() &&
4556 To->getParent() == getAnchorScope() &&
4557 "Used AAIsDead of the wrong function");
4558 return isValidState() && !AssumedLiveEdges.count(V: std::make_pair(x&: From, y&: To));
4559 }
4560
4561 /// See AbstractAttribute::trackStatistics()
4562 void trackStatistics() const override {}
4563
4564 /// Returns true if the function is assumed dead.
4565 bool isAssumedDead() const override { return false; }
4566
4567 /// See AAIsDead::isKnownDead().
4568 bool isKnownDead() const override { return false; }
4569
4570 /// See AAIsDead::isAssumedDead(BasicBlock *).
4571 bool isAssumedDead(const BasicBlock *BB) const override {
4572 assert(BB->getParent() == getAnchorScope() &&
4573 "BB must be in the same anchor scope function.");
4574
4575 if (!getAssumed())
4576 return false;
4577 return !AssumedLiveBlocks.count(V: BB);
4578 }
4579
4580 /// See AAIsDead::isKnownDead(BasicBlock *).
4581 bool isKnownDead(const BasicBlock *BB) const override {
4582 return getKnown() && isAssumedDead(BB);
4583 }
4584
4585 /// See AAIsDead::isAssumed(Instruction *I).
4586 bool isAssumedDead(const Instruction *I) const override {
4587 assert(I->getParent()->getParent() == getAnchorScope() &&
4588 "Instruction must be in the same anchor scope function.");
4589
4590 if (!getAssumed())
4591 return false;
4592
4593 // If it is not in AssumedLiveBlocks then it for sure dead.
4594 // Otherwise, it can still be after noreturn call in a live block.
4595 if (!AssumedLiveBlocks.count(V: I->getParent()))
4596 return true;
4597
4598 // If it is not after a liveness barrier it is live.
4599 const Instruction *PrevI = I->getPrevNode();
4600 while (PrevI) {
4601 if (KnownDeadEnds.count(key: PrevI) || ToBeExploredFrom.count(key: PrevI))
4602 return true;
4603 PrevI = PrevI->getPrevNode();
4604 }
4605 return false;
4606 }
4607
4608 /// See AAIsDead::isKnownDead(Instruction *I).
4609 bool isKnownDead(const Instruction *I) const override {
4610 return getKnown() && isAssumedDead(I);
4611 }
4612
4613 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
4614 /// that internal function called from \p BB should now be looked at.
4615 bool assumeLive(Attributor &A, const BasicBlock &BB) {
4616 if (!AssumedLiveBlocks.insert(V: &BB).second)
4617 return false;
4618
4619 // We assume that all of BB is (probably) live now and if there are calls to
4620 // internal functions we will assume that those are now live as well. This
4621 // is a performance optimization for blocks with calls to a lot of internal
4622 // functions. It can however cause dead functions to be treated as live.
4623 for (const Instruction &I : BB)
4624 if (const auto *CB = dyn_cast<CallBase>(Val: &I))
4625 if (auto *F = dyn_cast_if_present<Function>(Val: CB->getCalledOperand()))
4626 if (F->hasLocalLinkage())
4627 A.markLiveInternalFunction(F: *F);
4628 return true;
4629 }
4630
4631 /// Collection of instructions that need to be explored again, e.g., we
4632 /// did assume they do not transfer control to (one of their) successors.
4633 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4634
4635 /// Collection of instructions that are known to not transfer control.
4636 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4637
4638 /// Collection of all assumed live edges
4639 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4640
4641 /// Collection of all assumed live BasicBlocks.
4642 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4643};
4644
4645static bool
4646identifyAliveSuccessors(Attributor &A, const CallBase &CB,
4647 AbstractAttribute &AA,
4648 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4649 const IRPosition &IPos = IRPosition::callsite_function(CB);
4650
4651 bool IsKnownNoReturn;
4652 if (AA::hasAssumedIRAttr<Attribute::NoReturn>(
4653 A, QueryingAA: &AA, IRP: IPos, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoReturn))
4654 return !IsKnownNoReturn;
4655 if (CB.isTerminator())
4656 AliveSuccessors.push_back(Elt: &CB.getSuccessor(Idx: 0)->front());
4657 else
4658 AliveSuccessors.push_back(Elt: CB.getNextNode());
4659 return false;
4660}
4661
4662static bool
4663identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
4664 AbstractAttribute &AA,
4665 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4666 bool UsedAssumedInformation =
4667 identifyAliveSuccessors(A, CB: cast<CallBase>(Val: II), AA, AliveSuccessors);
4668
4669 // First, determine if we can change an invoke to a call assuming the
4670 // callee is nounwind. This is not possible if the personality of the
4671 // function allows to catch asynchronous exceptions.
4672 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(F: *II.getFunction())) {
4673 AliveSuccessors.push_back(Elt: &II.getUnwindDest()->front());
4674 } else {
4675 const IRPosition &IPos = IRPosition::callsite_function(CB: II);
4676
4677 bool IsKnownNoUnwind;
4678 if (AA::hasAssumedIRAttr<Attribute::NoUnwind>(
4679 A, QueryingAA: &AA, IRP: IPos, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoUnwind)) {
4680 UsedAssumedInformation |= !IsKnownNoUnwind;
4681 } else {
4682 AliveSuccessors.push_back(Elt: &II.getUnwindDest()->front());
4683 }
4684 }
4685 return UsedAssumedInformation;
4686}
4687
4688static bool
4689identifyAliveSuccessors(Attributor &, const UncondBrInst &BI,
4690 AbstractAttribute &,
4691 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4692 AliveSuccessors.push_back(Elt: &BI.getSuccessor()->front());
4693 return false;
4694}
4695
4696static bool
4697identifyAliveSuccessors(Attributor &A, const CondBrInst &BI,
4698 AbstractAttribute &AA,
4699 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4700 bool UsedAssumedInformation = false;
4701 std::optional<Constant *> C =
4702 A.getAssumedConstant(V: *BI.getCondition(), AA, UsedAssumedInformation);
4703 if (!C || isa_and_nonnull<UndefValue>(Val: *C)) {
4704 // No value yet, assume both edges are dead.
4705 } else if (isa_and_nonnull<ConstantInt>(Val: *C)) {
4706 const BasicBlock *SuccBB =
4707 BI.getSuccessor(i: 1 - cast<ConstantInt>(Val: *C)->getValue().getZExtValue());
4708 AliveSuccessors.push_back(Elt: &SuccBB->front());
4709 } else {
4710 AliveSuccessors.push_back(Elt: &BI.getSuccessor(i: 0)->front());
4711 AliveSuccessors.push_back(Elt: &BI.getSuccessor(i: 1)->front());
4712 UsedAssumedInformation = false;
4713 }
4714 return UsedAssumedInformation;
4715}
4716
4717static bool
4718identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
4719 AbstractAttribute &AA,
4720 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4721 bool UsedAssumedInformation = false;
4722 SmallVector<AA::ValueAndContext> Values;
4723 if (!A.getAssumedSimplifiedValues(IRP: IRPosition::value(V: *SI.getCondition()), AA: &AA,
4724 Values, S: AA::AnyScope,
4725 UsedAssumedInformation)) {
4726 // Something went wrong, assume all successors are live.
4727 for (const BasicBlock *SuccBB : successors(BB: SI.getParent()))
4728 AliveSuccessors.push_back(Elt: &SuccBB->front());
4729 return false;
4730 }
4731
4732 if (Values.empty() ||
4733 (Values.size() == 1 &&
4734 isa_and_nonnull<UndefValue>(Val: Values.front().getValue()))) {
4735 // No valid value yet, assume all edges are dead.
4736 return UsedAssumedInformation;
4737 }
4738
4739 Type &Ty = *SI.getCondition()->getType();
4740 SmallPtrSet<ConstantInt *, 8> Constants;
4741 auto CheckForConstantInt = [&](Value *V) {
4742 if (auto *CI = dyn_cast_if_present<ConstantInt>(Val: AA::getWithType(V&: *V, Ty))) {
4743 Constants.insert(Ptr: CI);
4744 return true;
4745 }
4746 return false;
4747 };
4748
4749 if (!all_of(Range&: Values, P: [&](AA::ValueAndContext &VAC) {
4750 return CheckForConstantInt(VAC.getValue());
4751 })) {
4752 for (const BasicBlock *SuccBB : successors(BB: SI.getParent()))
4753 AliveSuccessors.push_back(Elt: &SuccBB->front());
4754 return UsedAssumedInformation;
4755 }
4756
4757 unsigned MatchedCases = 0;
4758 for (const auto &CaseIt : SI.cases()) {
4759 if (Constants.count(Ptr: CaseIt.getCaseValue())) {
4760 ++MatchedCases;
4761 AliveSuccessors.push_back(Elt: &CaseIt.getCaseSuccessor()->front());
4762 }
4763 }
4764
4765 // If all potential values have been matched, we will not visit the default
4766 // case.
4767 if (MatchedCases < Constants.size())
4768 AliveSuccessors.push_back(Elt: &SI.getDefaultDest()->front());
4769 return UsedAssumedInformation;
4770}
4771
4772ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
4773 ChangeStatus Change = ChangeStatus::UNCHANGED;
4774
4775 if (AssumedLiveBlocks.empty()) {
4776 if (isAssumedDeadInternalFunction(A))
4777 return ChangeStatus::UNCHANGED;
4778
4779 Function *F = getAnchorScope();
4780 ToBeExploredFrom.insert(X: &F->getEntryBlock().front());
4781 assumeLive(A, BB: F->getEntryBlock());
4782 Change = ChangeStatus::CHANGED;
4783 }
4784
4785 LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"
4786 << getAnchorScope()->size() << "] BBs and "
4787 << ToBeExploredFrom.size() << " exploration points and "
4788 << KnownDeadEnds.size() << " known dead ends\n");
4789
4790 // Copy and clear the list of instructions we need to explore from. It is
4791 // refilled with instructions the next update has to look at.
4792 SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
4793 ToBeExploredFrom.end());
4794 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4795
4796 SmallVector<const Instruction *, 8> AliveSuccessors;
4797 while (!Worklist.empty()) {
4798 const Instruction *I = Worklist.pop_back_val();
4799 LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n");
4800
4801 // Fast forward for uninteresting instructions. We could look for UB here
4802 // though.
4803 while (!I->isTerminator() && !isa<CallBase>(Val: I))
4804 I = I->getNextNode();
4805
4806 AliveSuccessors.clear();
4807
4808 bool UsedAssumedInformation = false;
4809 switch (I->getOpcode()) {
4810 // TODO: look for (assumed) UB to backwards propagate "deadness".
4811 default:
4812 assert(I->isTerminator() &&
4813 "Expected non-terminators to be handled already!");
4814 for (const BasicBlock *SuccBB : successors(BB: I->getParent()))
4815 AliveSuccessors.push_back(Elt: &SuccBB->front());
4816 break;
4817 case Instruction::Call:
4818 UsedAssumedInformation = identifyAliveSuccessors(A, CB: cast<CallInst>(Val: *I),
4819 AA&: *this, AliveSuccessors);
4820 break;
4821 case Instruction::Invoke:
4822 UsedAssumedInformation = identifyAliveSuccessors(A, II: cast<InvokeInst>(Val: *I),
4823 AA&: *this, AliveSuccessors);
4824 break;
4825 case Instruction::UncondBr:
4826 UsedAssumedInformation = identifyAliveSuccessors(
4827 A, BI: cast<UncondBrInst>(Val: *I), *this, AliveSuccessors);
4828 break;
4829 case Instruction::CondBr:
4830 UsedAssumedInformation = identifyAliveSuccessors(A, BI: cast<CondBrInst>(Val: *I),
4831 AA&: *this, AliveSuccessors);
4832 break;
4833 case Instruction::Switch:
4834 UsedAssumedInformation = identifyAliveSuccessors(A, SI: cast<SwitchInst>(Val: *I),
4835 AA&: *this, AliveSuccessors);
4836 break;
4837 }
4838
4839 if (UsedAssumedInformation) {
4840 NewToBeExploredFrom.insert(X: I);
4841 } else if (AliveSuccessors.empty() ||
4842 (I->isTerminator() &&
4843 AliveSuccessors.size() < I->getNumSuccessors())) {
4844 if (KnownDeadEnds.insert(X: I))
4845 Change = ChangeStatus::CHANGED;
4846 }
4847
4848 LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "
4849 << AliveSuccessors.size() << " UsedAssumedInformation: "
4850 << UsedAssumedInformation << "\n");
4851
4852 for (const Instruction *AliveSuccessor : AliveSuccessors) {
4853 if (!I->isTerminator()) {
4854 assert(AliveSuccessors.size() == 1 &&
4855 "Non-terminator expected to have a single successor!");
4856 Worklist.push_back(Elt: AliveSuccessor);
4857 } else {
4858 // record the assumed live edge
4859 auto Edge = std::make_pair(x: I->getParent(), y: AliveSuccessor->getParent());
4860 if (AssumedLiveEdges.insert(V: Edge).second)
4861 Change = ChangeStatus::CHANGED;
4862 if (assumeLive(A, BB: *AliveSuccessor->getParent()))
4863 Worklist.push_back(Elt: AliveSuccessor);
4864 }
4865 }
4866 }
4867
4868 // Check if the content of ToBeExploredFrom changed, ignore the order.
4869 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4870 llvm::any_of(Range&: NewToBeExploredFrom, P: [&](const Instruction *I) {
4871 return !ToBeExploredFrom.count(key: I);
4872 })) {
4873 Change = ChangeStatus::CHANGED;
4874 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4875 }
4876
4877 // If we know everything is live there is no need to query for liveness.
4878 // Instead, indicating a pessimistic fixpoint will cause the state to be
4879 // "invalid" and all queries to be answered conservatively without lookups.
4880 // To be in this state we have to (1) finished the exploration and (3) not
4881 // discovered any non-trivial dead end and (2) not ruled unreachable code
4882 // dead.
4883 if (ToBeExploredFrom.empty() &&
4884 getAnchorScope()->size() == AssumedLiveBlocks.size() &&
4885 llvm::all_of(Range&: KnownDeadEnds, P: [](const Instruction *DeadEndI) {
4886 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4887 }))
4888 return indicatePessimisticFixpoint();
4889 return Change;
4890}
4891
4892/// Liveness information for a call sites.
4893struct AAIsDeadCallSite final : AAIsDeadFunction {
4894 AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
4895 : AAIsDeadFunction(IRP, A) {}
4896
4897 /// See AbstractAttribute::initialize(...).
4898 void initialize(Attributor &A) override {
4899 // TODO: Once we have call site specific value information we can provide
4900 // call site specific liveness information and then it makes
4901 // sense to specialize attributes for call sites instead of
4902 // redirecting requests to the callee.
4903 llvm_unreachable("Abstract attributes for liveness are not "
4904 "supported for call sites yet!");
4905 }
4906
4907 /// See AbstractAttribute::updateImpl(...).
4908 ChangeStatus updateImpl(Attributor &A) override {
4909 return indicatePessimisticFixpoint();
4910 }
4911
4912 /// See AbstractAttribute::trackStatistics()
4913 void trackStatistics() const override {}
4914};
4915} // namespace
4916
4917/// -------------------- Dereferenceable Argument Attribute --------------------
4918
4919namespace {
4920struct AADereferenceableImpl : AADereferenceable {
4921 AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
4922 : AADereferenceable(IRP, A) {}
4923 using StateType = DerefState;
4924
4925 /// See AbstractAttribute::initialize(...).
4926 void initialize(Attributor &A) override {
4927 Value &V = *getAssociatedValue().stripPointerCasts();
4928 SmallVector<Attribute, 4> Attrs;
4929 A.getAttrs(IRP: getIRPosition(),
4930 AKs: {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4931 Attrs, /* IgnoreSubsumingPositions */ false);
4932 for (const Attribute &Attr : Attrs)
4933 takeKnownDerefBytesMaximum(Bytes: Attr.getValueAsInt());
4934
4935 // Ensure we initialize the non-null AA (if necessary).
4936 bool IsKnownNonNull;
4937 AA::hasAssumedIRAttr<Attribute::NonNull>(
4938 A, QueryingAA: this, IRP: getIRPosition(), DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNonNull);
4939
4940 bool CanBeNull;
4941 takeKnownDerefBytesMaximum(Bytes: V.getPointerDereferenceableBytes(
4942 DL: A.getDataLayout(), CanBeNull, /*CanBeFreed=*/nullptr));
4943
4944 if (Instruction *CtxI = getCtxI())
4945 followUsesInMBEC(AA&: *this, A, S&: getState(), CtxI&: *CtxI);
4946 }
4947
4948 /// See AbstractAttribute::getState()
4949 /// {
4950 StateType &getState() override { return *this; }
4951 const StateType &getState() const override { return *this; }
4952 /// }
4953
4954 /// Helper function for collecting accessed bytes in must-be-executed-context
4955 void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
4956 DerefState &State) {
4957 const Value *UseV = U->get();
4958 if (!UseV->getType()->isPointerTy())
4959 return;
4960
4961 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(Inst: I);
4962 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
4963 return;
4964
4965 int64_t Offset;
4966 const Value *Base = GetPointerBaseWithConstantOffset(
4967 Ptr: Loc->Ptr, Offset, DL: A.getDataLayout(), /*AllowNonInbounds*/ true);
4968 if (Base && Base == &getAssociatedValue())
4969 State.addAccessedBytes(Offset, Size: Loc->Size.getValue());
4970 }
4971
4972 /// See followUsesInMBEC
4973 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
4974 AADereferenceable::StateType &State) {
4975 bool IsNonNull = false;
4976 bool TrackUse = false;
4977 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4978 A, QueryingAA: *this, AssociatedValue&: getAssociatedValue(), U, I, IsNonNull, TrackUse);
4979 LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytes
4980 << " for instruction " << *I << "\n");
4981
4982 addAccessedBytesForUse(A, U, I, State);
4983 State.takeKnownDerefBytesMaximum(Bytes: DerefBytes);
4984 return TrackUse;
4985 }
4986
4987 /// See AbstractAttribute::manifest(...).
4988 ChangeStatus manifest(Attributor &A) override {
4989 ChangeStatus Change = AADereferenceable::manifest(A);
4990 bool IsKnownNonNull;
4991 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
4992 A, QueryingAA: this, IRP: getIRPosition(), DepClass: DepClassTy::NONE, IsKnown&: IsKnownNonNull);
4993 if (IsAssumedNonNull &&
4994 A.hasAttr(IRP: getIRPosition(), AKs: Attribute::DereferenceableOrNull)) {
4995 A.removeAttrs(IRP: getIRPosition(), AttrKinds: {Attribute::DereferenceableOrNull});
4996 return ChangeStatus::CHANGED;
4997 }
4998 return Change;
4999 }
5000
5001 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5002 SmallVectorImpl<Attribute> &Attrs) const override {
5003 // TODO: Add *_globally support
5004 bool IsKnownNonNull;
5005 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
5006 A, QueryingAA: this, IRP: getIRPosition(), DepClass: DepClassTy::NONE, IsKnown&: IsKnownNonNull);
5007 if (IsAssumedNonNull)
5008 Attrs.emplace_back(Args: Attribute::getWithDereferenceableBytes(
5009 Context&: Ctx, Bytes: getAssumedDereferenceableBytes()));
5010 else
5011 Attrs.emplace_back(Args: Attribute::getWithDereferenceableOrNullBytes(
5012 Context&: Ctx, Bytes: getAssumedDereferenceableBytes()));
5013 }
5014
5015 /// See AbstractAttribute::getAsStr().
5016 const std::string getAsStr(Attributor *A) const override {
5017 if (!getAssumedDereferenceableBytes())
5018 return "unknown-dereferenceable";
5019 bool IsKnownNonNull;
5020 bool IsAssumedNonNull = false;
5021 if (A)
5022 IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
5023 A&: *A, QueryingAA: this, IRP: getIRPosition(), DepClass: DepClassTy::NONE, IsKnown&: IsKnownNonNull);
5024 return std::string("dereferenceable") +
5025 (IsAssumedNonNull ? "" : "_or_null") +
5026 (isAssumedGlobal() ? "_globally" : "") + "<" +
5027 std::to_string(val: getKnownDereferenceableBytes()) + "-" +
5028 std::to_string(val: getAssumedDereferenceableBytes()) + ">" +
5029 (!A ? " [non-null is unknown]" : "");
5030 }
5031};
5032
5033/// Dereferenceable attribute for a floating value.
5034struct AADereferenceableFloating : AADereferenceableImpl {
5035 AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
5036 : AADereferenceableImpl(IRP, A) {}
5037
5038 /// See AbstractAttribute::updateImpl(...).
5039 ChangeStatus updateImpl(Attributor &A) override {
5040 bool Stripped;
5041 bool UsedAssumedInformation = false;
5042 SmallVector<AA::ValueAndContext> Values;
5043 if (!A.getAssumedSimplifiedValues(IRP: getIRPosition(), AA: *this, Values,
5044 S: AA::AnyScope, UsedAssumedInformation)) {
5045 Values.push_back(Elt: {getAssociatedValue(), getCtxI()});
5046 Stripped = false;
5047 } else {
5048 Stripped = Values.size() != 1 ||
5049 Values.front().getValue() != &getAssociatedValue();
5050 }
5051
5052 const DataLayout &DL = A.getDataLayout();
5053 DerefState T;
5054
5055 auto VisitValueCB = [&](const Value &V) -> bool {
5056 unsigned IdxWidth =
5057 DL.getIndexSizeInBits(AS: V.getType()->getPointerAddressSpace());
5058 APInt Offset(IdxWidth, 0);
5059 const Value *Base = stripAndAccumulateOffsets(
5060 A, QueryingAA: *this, Val: &V, DL, Offset, /* GetMinOffset */ false,
5061 /* AllowNonInbounds */ true);
5062
5063 const auto *AA = A.getAAFor<AADereferenceable>(
5064 QueryingAA: *this, IRP: IRPosition::value(V: *Base), DepClass: DepClassTy::REQUIRED);
5065 int64_t DerefBytes = 0;
5066 if (!AA || (!Stripped && this == AA)) {
5067 // Use IR information if we did not strip anything.
5068 // TODO: track globally.
5069 bool CanBeNull;
5070 DerefBytes = Base->getPointerDereferenceableBytes(
5071 DL, CanBeNull, /*CanBeFreed=*/nullptr);
5072 T.GlobalState.indicatePessimisticFixpoint();
5073 } else {
5074 const DerefState &DS = AA->getState();
5075 DerefBytes = DS.DerefBytesState.getAssumed();
5076 T.GlobalState &= DS.GlobalState;
5077 }
5078
5079 // For now we do not try to "increase" dereferenceability due to negative
5080 // indices as we first have to come up with code to deal with loops and
5081 // for overflows of the dereferenceable bytes.
5082 int64_t OffsetSExt = Offset.getSExtValue();
5083 if (OffsetSExt < 0)
5084 OffsetSExt = 0;
5085
5086 T.takeAssumedDerefBytesMinimum(
5087 Bytes: std::max(a: int64_t(0), b: DerefBytes - OffsetSExt));
5088
5089 if (this == AA) {
5090 if (!Stripped) {
5091 // If nothing was stripped IR information is all we got.
5092 T.takeKnownDerefBytesMaximum(
5093 Bytes: std::max(a: int64_t(0), b: DerefBytes - OffsetSExt));
5094 T.indicatePessimisticFixpoint();
5095 } else if (OffsetSExt > 0) {
5096 // If something was stripped but there is circular reasoning we look
5097 // for the offset. If it is positive we basically decrease the
5098 // dereferenceable bytes in a circular loop now, which will simply
5099 // drive them down to the known value in a very slow way which we
5100 // can accelerate.
5101 T.indicatePessimisticFixpoint();
5102 }
5103 }
5104
5105 return T.isValidState();
5106 };
5107
5108 for (const auto &VAC : Values)
5109 if (!VisitValueCB(*VAC.getValue()))
5110 return indicatePessimisticFixpoint();
5111
5112 return clampStateAndIndicateChange(S&: getState(), R: T);
5113 }
5114
5115 /// See AbstractAttribute::trackStatistics()
5116 void trackStatistics() const override {
5117 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
5118 }
5119};
5120
5121/// Dereferenceable attribute for a return value.
5122struct AADereferenceableReturned final
5123 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5124 using Base =
5125 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5126 AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
5127 : Base(IRP, A) {}
5128
5129 /// See AbstractAttribute::trackStatistics()
5130 void trackStatistics() const override {
5131 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
5132 }
5133};
5134
5135/// Dereferenceable attribute for an argument
5136struct AADereferenceableArgument final
5137 : AAArgumentFromCallSiteArguments<AADereferenceable,
5138 AADereferenceableImpl> {
5139 using Base =
5140 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5141 AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
5142 : Base(IRP, A) {}
5143
5144 /// See AbstractAttribute::trackStatistics()
5145 void trackStatistics() const override {
5146 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
5147 }
5148};
5149
5150/// Dereferenceable attribute for a call site argument.
5151struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5152 AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
5153 : AADereferenceableFloating(IRP, A) {}
5154
5155 /// See AbstractAttribute::trackStatistics()
5156 void trackStatistics() const override {
5157 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
5158 }
5159};
5160
5161/// Dereferenceable attribute deduction for a call site return value.
5162struct AADereferenceableCallSiteReturned final
5163 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5164 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5165 AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
5166 : Base(IRP, A) {}
5167
5168 /// See AbstractAttribute::trackStatistics()
5169 void trackStatistics() const override {
5170 STATS_DECLTRACK_CS_ATTR(dereferenceable);
5171 }
5172};
5173} // namespace
5174
5175// ------------------------ Align Argument Attribute ------------------------
5176
5177namespace {
5178
5179static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
5180 Value &AssociatedValue, const Use *U,
5181 const Instruction *I, bool &TrackUse) {
5182 // We need to follow common pointer manipulation uses to the accesses they
5183 // feed into.
5184 if (isa<CastInst>(Val: I)) {
5185 // Follow all but ptr2int casts.
5186 TrackUse = !isa<PtrToIntInst>(Val: I);
5187 return 0;
5188 }
5189 if (auto *GEP = dyn_cast<GetElementPtrInst>(Val: I)) {
5190 if (GEP->hasAllConstantIndices())
5191 TrackUse = true;
5192 return 0;
5193 }
5194 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Val: I))
5195 switch (II->getIntrinsicID()) {
5196 case Intrinsic::ptrmask: {
5197 // Is it appropriate to pull attribute in initialization?
5198 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5199 QueryingAA, IRP: IRPosition::value(V: *II->getOperand(i_nocapture: 1)), DepClass: DepClassTy::NONE);
5200 const auto *AlignAA = A.getAAFor<AAAlign>(
5201 QueryingAA, IRP: IRPosition::value(V: *II), DepClass: DepClassTy::NONE);
5202 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5203 unsigned ShiftValue = std::min(a: ConstVals->getAssumedMinTrailingZeros(),
5204 b: Value::MaxAlignmentExponent);
5205 Align ConstAlign(UINT64_C(1) << ShiftValue);
5206 if (ConstAlign >= AlignAA->getKnownAlign())
5207 return Align(1).value();
5208 }
5209 if (AlignAA)
5210 return AlignAA->getKnownAlign().value();
5211 break;
5212 }
5213 case Intrinsic::amdgcn_make_buffer_rsrc: {
5214 const auto *AlignAA = A.getAAFor<AAAlign>(
5215 QueryingAA, IRP: IRPosition::value(V: *II), DepClass: DepClassTy::NONE);
5216 if (AlignAA)
5217 return AlignAA->getKnownAlign().value();
5218 break;
5219 }
5220 default:
5221 break;
5222 }
5223
5224 MaybeAlign MA;
5225 if (const auto *CB = dyn_cast<CallBase>(Val: I)) {
5226 if (CB->isBundleOperand(U) || CB->isCallee(U))
5227 return 0;
5228
5229 unsigned ArgNo = CB->getArgOperandNo(U);
5230 IRPosition IRP = IRPosition::callsite_argument(CB: *CB, ArgNo);
5231 // As long as we only use known information there is no need to track
5232 // dependences here.
5233 auto *AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClass: DepClassTy::NONE);
5234 if (AlignAA)
5235 MA = MaybeAlign(AlignAA->getKnownAlign());
5236 }
5237
5238 const DataLayout &DL = A.getDataLayout();
5239 const Value *UseV = U->get();
5240 if (auto *SI = dyn_cast<StoreInst>(Val: I)) {
5241 if (SI->getPointerOperand() == UseV)
5242 MA = SI->getAlign();
5243 } else if (auto *LI = dyn_cast<LoadInst>(Val: I)) {
5244 if (LI->getPointerOperand() == UseV)
5245 MA = LI->getAlign();
5246 } else if (auto *AI = dyn_cast<AtomicRMWInst>(Val: I)) {
5247 if (AI->getPointerOperand() == UseV)
5248 MA = AI->getAlign();
5249 } else if (auto *AI = dyn_cast<AtomicCmpXchgInst>(Val: I)) {
5250 if (AI->getPointerOperand() == UseV)
5251 MA = AI->getAlign();
5252 }
5253
5254 if (!MA || *MA <= QueryingAA.getKnownAlign())
5255 return 0;
5256
5257 unsigned Alignment = MA->value();
5258 int64_t Offset;
5259
5260 if (const Value *Base = GetPointerBaseWithConstantOffset(Ptr: UseV, Offset, DL)) {
5261 if (Base == &AssociatedValue) {
5262 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5263 // So we can say that the maximum power of two which is a divisor of
5264 // gcd(Offset, Alignment) is an alignment.
5265
5266 uint32_t gcd = std::gcd(m: uint32_t(abs(x: (int32_t)Offset)), n: Alignment);
5267 Alignment = llvm::bit_floor(Value: gcd);
5268 }
5269 }
5270
5271 return Alignment;
5272}
5273
5274struct AAAlignImpl : AAAlign {
5275 AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}
5276
5277 /// See AbstractAttribute::initialize(...).
5278 void initialize(Attributor &A) override {
5279 SmallVector<Attribute, 4> Attrs;
5280 A.getAttrs(IRP: getIRPosition(), AKs: {Attribute::Alignment}, Attrs);
5281 for (const Attribute &Attr : Attrs)
5282 takeKnownMaximum(Value: Attr.getValueAsInt());
5283
5284 Value &V = *getAssociatedValue().stripPointerCasts();
5285 takeKnownMaximum(Value: V.getPointerAlignment(DL: A.getDataLayout()).value());
5286
5287 if (Instruction *CtxI = getCtxI())
5288 followUsesInMBEC(AA&: *this, A, S&: getState(), CtxI&: *CtxI);
5289 }
5290
5291 /// See AbstractAttribute::manifest(...).
5292 ChangeStatus manifest(Attributor &A) override {
5293 ChangeStatus InstrChanged = ChangeStatus::UNCHANGED;
5294
5295 // Check for users that allow alignment annotations.
5296 Value &AssociatedValue = getAssociatedValue();
5297 if (isa<ConstantData>(Val: AssociatedValue))
5298 return ChangeStatus::UNCHANGED;
5299
5300 for (const Use &U : AssociatedValue.uses()) {
5301 if (auto *SI = dyn_cast<StoreInst>(Val: U.getUser())) {
5302 if (SI->getPointerOperand() == &AssociatedValue)
5303 if (SI->getAlign() < getAssumedAlign()) {
5304 STATS_DECLTRACK(AAAlign, Store,
5305 "Number of times alignment added to a store");
5306 SI->setAlignment(getAssumedAlign());
5307 InstrChanged = ChangeStatus::CHANGED;
5308 }
5309 } else if (auto *LI = dyn_cast<LoadInst>(Val: U.getUser())) {
5310 if (LI->getPointerOperand() == &AssociatedValue)
5311 if (LI->getAlign() < getAssumedAlign()) {
5312 LI->setAlignment(getAssumedAlign());
5313 STATS_DECLTRACK(AAAlign, Load,
5314 "Number of times alignment added to a load");
5315 InstrChanged = ChangeStatus::CHANGED;
5316 }
5317 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Val: U.getUser())) {
5318 if (RMW->getPointerOperand() == &AssociatedValue) {
5319 if (RMW->getAlign() < getAssumedAlign()) {
5320 STATS_DECLTRACK(AAAlign, AtomicRMW,
5321 "Number of times alignment added to atomicrmw");
5322
5323 RMW->setAlignment(getAssumedAlign());
5324 InstrChanged = ChangeStatus::CHANGED;
5325 }
5326 }
5327 } else if (auto *CAS = dyn_cast<AtomicCmpXchgInst>(Val: U.getUser())) {
5328 if (CAS->getPointerOperand() == &AssociatedValue) {
5329 if (CAS->getAlign() < getAssumedAlign()) {
5330 STATS_DECLTRACK(AAAlign, AtomicCmpXchg,
5331 "Number of times alignment added to cmpxchg");
5332 CAS->setAlignment(getAssumedAlign());
5333 InstrChanged = ChangeStatus::CHANGED;
5334 }
5335 }
5336 }
5337 }
5338
5339 ChangeStatus Changed = AAAlign::manifest(A);
5340
5341 Align InheritAlign =
5342 getAssociatedValue().getPointerAlignment(DL: A.getDataLayout());
5343 if (InheritAlign >= getAssumedAlign())
5344 return InstrChanged;
5345 return Changed | InstrChanged;
5346 }
5347
5348 // TODO: Provide a helper to determine the implied ABI alignment and check in
5349 // the existing manifest method and a new one for AAAlignImpl that value
5350 // to avoid making the alignment explicit if it did not improve.
5351
5352 /// See AbstractAttribute::getDeducedAttributes
5353 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5354 SmallVectorImpl<Attribute> &Attrs) const override {
5355 if (getAssumedAlign() > 1)
5356 Attrs.emplace_back(
5357 Args: Attribute::getWithAlignment(Context&: Ctx, Alignment: Align(getAssumedAlign())));
5358 }
5359
5360 /// See followUsesInMBEC
5361 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5362 AAAlign::StateType &State) {
5363 bool TrackUse = false;
5364
5365 unsigned int KnownAlign =
5366 getKnownAlignForUse(A, QueryingAA&: *this, AssociatedValue&: getAssociatedValue(), U, I, TrackUse);
5367 State.takeKnownMaximum(Value: KnownAlign);
5368
5369 return TrackUse;
5370 }
5371
5372 /// See AbstractAttribute::getAsStr().
5373 const std::string getAsStr(Attributor *A) const override {
5374 return "align<" + std::to_string(val: getKnownAlign().value()) + "-" +
5375 std::to_string(val: getAssumedAlign().value()) + ">";
5376 }
5377};
5378
5379/// Align attribute for a floating value.
5380struct AAAlignFloating : AAAlignImpl {
5381 AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}
5382
5383 /// See AbstractAttribute::updateImpl(...).
5384 ChangeStatus updateImpl(Attributor &A) override {
5385 const DataLayout &DL = A.getDataLayout();
5386
5387 bool Stripped;
5388 bool UsedAssumedInformation = false;
5389 SmallVector<AA::ValueAndContext> Values;
5390 if (!A.getAssumedSimplifiedValues(IRP: getIRPosition(), AA: *this, Values,
5391 S: AA::AnyScope, UsedAssumedInformation)) {
5392 Values.push_back(Elt: {getAssociatedValue(), getCtxI()});
5393 Stripped = false;
5394 } else {
5395 Stripped = Values.size() != 1 ||
5396 Values.front().getValue() != &getAssociatedValue();
5397 }
5398
5399 StateType T;
5400 auto VisitValueCB = [&](Value &V) -> bool {
5401 if (isa<UndefValue>(Val: V) || isa<ConstantPointerNull>(Val: V))
5402 return true;
5403 const auto *AA = A.getAAFor<AAAlign>(QueryingAA: *this, IRP: IRPosition::value(V),
5404 DepClass: DepClassTy::REQUIRED);
5405 if (!AA || (!Stripped && this == AA)) {
5406 int64_t Offset;
5407 unsigned Alignment = 1;
5408 if (const Value *Base =
5409 GetPointerBaseWithConstantOffset(Ptr: &V, Offset, DL)) {
5410 // TODO: Use AAAlign for the base too.
5411 Align PA = Base->getPointerAlignment(DL);
5412 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5413 // So we can say that the maximum power of two which is a divisor of
5414 // gcd(Offset, Alignment) is an alignment.
5415
5416 uint32_t gcd =
5417 std::gcd(m: uint32_t(abs(x: (int32_t)Offset)), n: uint32_t(PA.value()));
5418 Alignment = llvm::bit_floor(Value: gcd);
5419 } else {
5420 Alignment = V.getPointerAlignment(DL).value();
5421 }
5422 // Use only IR information if we did not strip anything.
5423 T.takeKnownMaximum(Value: Alignment);
5424 T.indicatePessimisticFixpoint();
5425 } else {
5426 // Use abstract attribute information.
5427 const AAAlign::StateType &DS = AA->getState();
5428 T ^= DS;
5429 }
5430 return T.isValidState();
5431 };
5432
5433 for (const auto &VAC : Values) {
5434 if (!VisitValueCB(*VAC.getValue()))
5435 return indicatePessimisticFixpoint();
5436 }
5437
5438 // TODO: If we know we visited all incoming values, thus no are assumed
5439 // dead, we can take the known information from the state T.
5440 return clampStateAndIndicateChange(S&: getState(), R: T);
5441 }
5442
5443 /// See AbstractAttribute::trackStatistics()
5444 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
5445};
5446
5447/// Align attribute for function return value.
5448struct AAAlignReturned final
5449 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5450 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5451 AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5452
5453 /// See AbstractAttribute::trackStatistics()
5454 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
5455};
5456
5457/// Align attribute for function argument.
5458struct AAAlignArgument final
5459 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5460 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5461 AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5462
5463 /// See AbstractAttribute::manifest(...).
5464 ChangeStatus manifest(Attributor &A) override {
5465 // If the associated argument is involved in a must-tail call we give up
5466 // because we would need to keep the argument alignments of caller and
5467 // callee in-sync. Just does not seem worth the trouble right now.
5468 if (A.getInfoCache().isInvolvedInMustTailCall(Arg: *getAssociatedArgument()))
5469 return ChangeStatus::UNCHANGED;
5470 return Base::manifest(A);
5471 }
5472
5473 /// See AbstractAttribute::trackStatistics()
5474 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
5475};
5476
5477struct AAAlignCallSiteArgument final : AAAlignFloating {
5478 AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
5479 : AAAlignFloating(IRP, A) {}
5480
5481 /// See AbstractAttribute::manifest(...).
5482 ChangeStatus manifest(Attributor &A) override {
5483 // If the associated argument is involved in a must-tail call we give up
5484 // because we would need to keep the argument alignments of caller and
5485 // callee in-sync. Just does not seem worth the trouble right now.
5486 if (Argument *Arg = getAssociatedArgument())
5487 if (A.getInfoCache().isInvolvedInMustTailCall(Arg: *Arg))
5488 return ChangeStatus::UNCHANGED;
5489 ChangeStatus Changed = AAAlignImpl::manifest(A);
5490 Align InheritAlign =
5491 getAssociatedValue().getPointerAlignment(DL: A.getDataLayout());
5492 if (InheritAlign >= getAssumedAlign())
5493 Changed = ChangeStatus::UNCHANGED;
5494 return Changed;
5495 }
5496
5497 /// See AbstractAttribute::updateImpl(Attributor &A).
5498 ChangeStatus updateImpl(Attributor &A) override {
5499 ChangeStatus Changed = AAAlignFloating::updateImpl(A);
5500 if (Argument *Arg = getAssociatedArgument()) {
5501 // We only take known information from the argument
5502 // so we do not need to track a dependence.
5503 const auto *ArgAlignAA = A.getAAFor<AAAlign>(
5504 QueryingAA: *this, IRP: IRPosition::argument(Arg: *Arg), DepClass: DepClassTy::NONE);
5505 if (ArgAlignAA)
5506 takeKnownMaximum(Value: ArgAlignAA->getKnownAlign().value());
5507 }
5508 return Changed;
5509 }
5510
5511 /// See AbstractAttribute::trackStatistics()
5512 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
5513};
5514
5515/// Align attribute deduction for a call site return value.
5516struct AAAlignCallSiteReturned final
5517 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5518 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5519 AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
5520 : Base(IRP, A) {}
5521
5522 ChangeStatus updateImpl(Attributor &A) override {
5523 Instruction *I = getIRPosition().getCtxI();
5524 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Val: I)) {
5525 switch (II->getIntrinsicID()) {
5526 case Intrinsic::ptrmask: {
5527 Align Alignment;
5528 bool Valid = false;
5529
5530 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5531 QueryingAA: *this, IRP: IRPosition::value(V: *II->getOperand(i_nocapture: 1)), DepClass: DepClassTy::REQUIRED);
5532 if (ConstVals && ConstVals->isValidState()) {
5533 unsigned ShiftValue =
5534 std::min(a: ConstVals->getAssumedMinTrailingZeros(),
5535 b: Value::MaxAlignmentExponent);
5536 Alignment = Align(UINT64_C(1) << ShiftValue);
5537 Valid = true;
5538 }
5539
5540 const auto *AlignAA =
5541 A.getAAFor<AAAlign>(QueryingAA: *this, IRP: IRPosition::value(V: *(II->getOperand(i_nocapture: 0))),
5542 DepClass: DepClassTy::REQUIRED);
5543 if (AlignAA) {
5544 Alignment = std::max(a: AlignAA->getAssumedAlign(), b: Alignment);
5545 Valid = true;
5546 }
5547
5548 if (Valid)
5549 return clampStateAndIndicateChange<StateType>(
5550 S&: this->getState(),
5551 R: std::min(a: this->getAssumedAlign(), b: Alignment).value());
5552 break;
5553 }
5554 // FIXME: Should introduce target specific sub-attributes and letting
5555 // getAAfor<AAAlign> lead to create sub-attribute to handle target
5556 // specific intrinsics.
5557 case Intrinsic::amdgcn_make_buffer_rsrc: {
5558 const auto *AlignAA =
5559 A.getAAFor<AAAlign>(QueryingAA: *this, IRP: IRPosition::value(V: *(II->getOperand(i_nocapture: 0))),
5560 DepClass: DepClassTy::REQUIRED);
5561 if (AlignAA)
5562 return clampStateAndIndicateChange<StateType>(
5563 S&: this->getState(), R: AlignAA->getAssumedAlign().value());
5564 break;
5565 }
5566 default:
5567 break;
5568 }
5569 }
5570 return Base::updateImpl(A);
5571 };
5572 /// See AbstractAttribute::trackStatistics()
5573 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
5574};
5575} // namespace
5576
5577/// ------------------ Function No-Return Attribute ----------------------------
5578namespace {
5579struct AANoReturnImpl : public AANoReturn {
5580 AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}
5581
5582 /// See AbstractAttribute::initialize(...).
5583 void initialize(Attributor &A) override {
5584 bool IsKnown;
5585 assert(!AA::hasAssumedIRAttr<Attribute::NoReturn>(
5586 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5587 (void)IsKnown;
5588 }
5589
5590 /// See AbstractAttribute::getAsStr().
5591 const std::string getAsStr(Attributor *A) const override {
5592 return getAssumed() ? "noreturn" : "may-return";
5593 }
5594
5595 /// See AbstractAttribute::updateImpl(Attributor &A).
5596 ChangeStatus updateImpl(Attributor &A) override {
5597 auto CheckForNoReturn = [](Instruction &) { return false; };
5598 bool UsedAssumedInformation = false;
5599 if (!A.checkForAllInstructions(Pred: CheckForNoReturn, QueryingAA: *this,
5600 Opcodes: {(unsigned)Instruction::Ret},
5601 UsedAssumedInformation))
5602 return indicatePessimisticFixpoint();
5603 return ChangeStatus::UNCHANGED;
5604 }
5605};
5606
5607struct AANoReturnFunction final : AANoReturnImpl {
5608 AANoReturnFunction(const IRPosition &IRP, Attributor &A)
5609 : AANoReturnImpl(IRP, A) {}
5610
5611 /// See AbstractAttribute::trackStatistics()
5612 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
5613};
5614
5615/// NoReturn attribute deduction for a call sites.
5616struct AANoReturnCallSite final
5617 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5618 AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
5619 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP, A) {}
5620
5621 /// See AbstractAttribute::trackStatistics()
5622 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
5623};
5624} // namespace
5625
5626/// ----------------------- Instance Info ---------------------------------
5627
5628namespace {
5629/// A class to hold the state of for no-capture attributes.
5630struct AAInstanceInfoImpl : public AAInstanceInfo {
5631 AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
5632 : AAInstanceInfo(IRP, A) {}
5633
5634 /// See AbstractAttribute::initialize(...).
5635 void initialize(Attributor &A) override {
5636 Value &V = getAssociatedValue();
5637 if (auto *C = dyn_cast<Constant>(Val: &V)) {
5638 if (C->isThreadDependent())
5639 indicatePessimisticFixpoint();
5640 else
5641 indicateOptimisticFixpoint();
5642 return;
5643 }
5644 if (auto *CB = dyn_cast<CallBase>(Val: &V))
5645 if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
5646 !CB->mayReadFromMemory()) {
5647 indicateOptimisticFixpoint();
5648 return;
5649 }
5650 if (auto *I = dyn_cast<Instruction>(Val: &V)) {
5651 const auto *CI =
5652 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5653 F: *I->getFunction());
5654 if (mayBeInCycle(CI, I, /* HeaderOnly */ false)) {
5655 indicatePessimisticFixpoint();
5656 return;
5657 }
5658 }
5659 }
5660
5661 /// See AbstractAttribute::updateImpl(...).
5662 ChangeStatus updateImpl(Attributor &A) override {
5663 ChangeStatus Changed = ChangeStatus::UNCHANGED;
5664
5665 Value &V = getAssociatedValue();
5666 const Function *Scope = nullptr;
5667 if (auto *I = dyn_cast<Instruction>(Val: &V))
5668 Scope = I->getFunction();
5669 if (auto *A = dyn_cast<Argument>(Val: &V)) {
5670 Scope = A->getParent();
5671 if (!Scope->hasLocalLinkage())
5672 return Changed;
5673 }
5674 if (!Scope)
5675 return indicateOptimisticFixpoint();
5676
5677 bool IsKnownNoRecurse;
5678 if (AA::hasAssumedIRAttr<Attribute::NoRecurse>(
5679 A, QueryingAA: this, IRP: IRPosition::function(F: *Scope), DepClass: DepClassTy::OPTIONAL,
5680 IsKnown&: IsKnownNoRecurse))
5681 return Changed;
5682
5683 auto UsePred = [&](const Use &U, bool &Follow) {
5684 const Instruction *UserI = dyn_cast<Instruction>(Val: U.getUser());
5685 if (!UserI || isa<GetElementPtrInst>(Val: UserI) || isa<CastInst>(Val: UserI) ||
5686 isa<PHINode>(Val: UserI) || isa<SelectInst>(Val: UserI)) {
5687 Follow = true;
5688 return true;
5689 }
5690 if (isa<LoadInst>(Val: UserI) || isa<CmpInst>(Val: UserI) ||
5691 (isa<StoreInst>(Val: UserI) &&
5692 cast<StoreInst>(Val: UserI)->getValueOperand() != U.get()))
5693 return true;
5694 if (auto *CB = dyn_cast<CallBase>(Val: UserI)) {
5695 // This check is not guaranteeing uniqueness but for now that we cannot
5696 // end up with two versions of \p U thinking it was one.
5697 auto *Callee = dyn_cast_if_present<Function>(Val: CB->getCalledOperand());
5698 if (!Callee || !Callee->hasLocalLinkage())
5699 return true;
5700 if (!CB->isArgOperand(U: &U))
5701 return false;
5702 const auto *ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
5703 QueryingAA: *this, IRP: IRPosition::callsite_argument(CB: *CB, ArgNo: CB->getArgOperandNo(U: &U)),
5704 DepClass: DepClassTy::OPTIONAL);
5705 if (!ArgInstanceInfoAA ||
5706 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5707 return false;
5708 // If this call base might reach the scope again we might forward the
5709 // argument back here. This is very conservative.
5710 if (AA::isPotentiallyReachable(
5711 A, FromI: *CB, ToFn: *Scope, QueryingAA: *this, /* ExclusionSet */ nullptr,
5712 GoBackwardsCB: [Scope](const Function &Fn) { return &Fn != Scope; }))
5713 return false;
5714 return true;
5715 }
5716 return false;
5717 };
5718
5719 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
5720 if (auto *SI = dyn_cast<StoreInst>(Val: OldU.getUser())) {
5721 auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
5722 if ((isa<AllocaInst>(Val: Ptr) || isNoAliasCall(V: Ptr)) &&
5723 AA::isDynamicallyUnique(A, QueryingAA: *this, V: *Ptr))
5724 return true;
5725 }
5726 return false;
5727 };
5728
5729 if (!A.checkForAllUses(Pred: UsePred, QueryingAA: *this, V, /* CheckBBLivenessOnly */ true,
5730 LivenessDepClass: DepClassTy::OPTIONAL,
5731 /* IgnoreDroppableUses */ true, EquivalentUseCB))
5732 return indicatePessimisticFixpoint();
5733
5734 return Changed;
5735 }
5736
5737 /// See AbstractState::getAsStr().
5738 const std::string getAsStr(Attributor *A) const override {
5739 return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
5740 }
5741
5742 /// See AbstractAttribute::trackStatistics()
5743 void trackStatistics() const override {}
5744};
5745
5746/// InstanceInfo attribute for floating values.
5747struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5748 AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
5749 : AAInstanceInfoImpl(IRP, A) {}
5750};
5751
5752/// NoCapture attribute for function arguments.
5753struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5754 AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
5755 : AAInstanceInfoFloating(IRP, A) {}
5756};
5757
5758/// InstanceInfo attribute for call site arguments.
5759struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5760 AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
5761 : AAInstanceInfoImpl(IRP, A) {}
5762
5763 /// See AbstractAttribute::updateImpl(...).
5764 ChangeStatus updateImpl(Attributor &A) override {
5765 // TODO: Once we have call site specific value information we can provide
5766 // call site specific liveness information and then it makes
5767 // sense to specialize attributes for call sites arguments instead of
5768 // redirecting requests to the callee argument.
5769 Argument *Arg = getAssociatedArgument();
5770 if (!Arg)
5771 return indicatePessimisticFixpoint();
5772 const IRPosition &ArgPos = IRPosition::argument(Arg: *Arg);
5773 auto *ArgAA =
5774 A.getAAFor<AAInstanceInfo>(QueryingAA: *this, IRP: ArgPos, DepClass: DepClassTy::REQUIRED);
5775 if (!ArgAA)
5776 return indicatePessimisticFixpoint();
5777 return clampStateAndIndicateChange(S&: getState(), R: ArgAA->getState());
5778 }
5779};
5780
5781/// InstanceInfo attribute for function return value.
5782struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5783 AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
5784 : AAInstanceInfoImpl(IRP, A) {
5785 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5786 }
5787
5788 /// See AbstractAttribute::initialize(...).
5789 void initialize(Attributor &A) override {
5790 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5791 }
5792
5793 /// See AbstractAttribute::updateImpl(...).
5794 ChangeStatus updateImpl(Attributor &A) override {
5795 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5796 }
5797};
5798
5799/// InstanceInfo attribute deduction for a call site return value.
5800struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5801 AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
5802 : AAInstanceInfoFloating(IRP, A) {}
5803};
5804} // namespace
5805
5806/// ----------------------- Variable Capturing ---------------------------------
5807bool AANoCapture::isImpliedByIR(Attributor &A, const IRPosition &IRP,
5808 Attribute::AttrKind ImpliedAttributeKind,
5809 bool IgnoreSubsumingPositions) {
5810 assert(ImpliedAttributeKind == Attribute::Captures &&
5811 "Unexpected attribute kind");
5812 Value &V = IRP.getAssociatedValue();
5813 if (!isa<Constant>(Val: V) && !IRP.isArgumentPosition())
5814 return V.use_empty();
5815
5816 // You cannot "capture" null in the default address space.
5817 //
5818 // FIXME: This should use NullPointerIsDefined to account for the function
5819 // attribute.
5820 if (isa<UndefValue>(Val: V) || (isa<ConstantPointerNull>(Val: V) &&
5821 V.getType()->getPointerAddressSpace() == 0)) {
5822 return true;
5823 }
5824
5825 SmallVector<Attribute, 1> Attrs;
5826 A.getAttrs(IRP, AKs: {Attribute::Captures}, Attrs,
5827 /* IgnoreSubsumingPositions */ true);
5828 for (const Attribute &Attr : Attrs)
5829 if (capturesNothing(CC: Attr.getCaptureInfo()))
5830 return true;
5831
5832 if (IRP.getPositionKind() == IRP_CALL_SITE_ARGUMENT)
5833 if (Argument *Arg = IRP.getAssociatedArgument()) {
5834 SmallVector<Attribute, 1> Attrs;
5835 A.getAttrs(IRP: IRPosition::argument(Arg: *Arg),
5836 AKs: {Attribute::Captures, Attribute::ByVal}, Attrs,
5837 /* IgnoreSubsumingPositions */ true);
5838 bool ArgNoCapture = any_of(Range&: Attrs, P: [](Attribute Attr) {
5839 return Attr.getKindAsEnum() == Attribute::ByVal ||
5840 capturesNothing(CC: Attr.getCaptureInfo());
5841 });
5842 if (ArgNoCapture) {
5843 A.manifestAttrs(IRP, DeducedAttrs: Attribute::getWithCaptureInfo(
5844 Context&: V.getContext(), CI: CaptureInfo::none()));
5845 return true;
5846 }
5847 }
5848
5849 if (const Function *F = IRP.getAssociatedFunction()) {
5850 // Check what state the associated function can actually capture.
5851 AANoCapture::StateType State;
5852 determineFunctionCaptureCapabilities(IRP, F: *F, State);
5853 if (State.isKnown(BitsEncoding: NO_CAPTURE)) {
5854 A.manifestAttrs(IRP, DeducedAttrs: Attribute::getWithCaptureInfo(Context&: V.getContext(),
5855 CI: CaptureInfo::none()));
5856 return true;
5857 }
5858 }
5859
5860 return false;
5861}
5862
5863/// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
5864/// depending on the ability of the function associated with \p IRP to capture
5865/// state in memory and through "returning/throwing", respectively.
5866void AANoCapture::determineFunctionCaptureCapabilities(const IRPosition &IRP,
5867 const Function &F,
5868 BitIntegerState &State) {
5869 // TODO: Once we have memory behavior attributes we should use them here.
5870
5871 // If we know we cannot communicate or write to memory, we do not care about
5872 // ptr2int anymore.
5873 bool ReadOnly = F.onlyReadsMemory();
5874 bool NoThrow = F.doesNotThrow();
5875 bool IsVoidReturn = F.getReturnType()->isVoidTy();
5876 if (ReadOnly && NoThrow && IsVoidReturn) {
5877 State.addKnownBits(Bits: NO_CAPTURE);
5878 return;
5879 }
5880
5881 // A function cannot capture state in memory if it only reads memory, it can
5882 // however return/throw state and the state might be influenced by the
5883 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5884 if (ReadOnly)
5885 State.addKnownBits(Bits: NOT_CAPTURED_IN_MEM);
5886
5887 // A function cannot communicate state back if it does not through
5888 // exceptions and doesn not return values.
5889 if (NoThrow && IsVoidReturn)
5890 State.addKnownBits(Bits: NOT_CAPTURED_IN_RET);
5891
5892 // Check existing "returned" attributes.
5893 int ArgNo = IRP.getCalleeArgNo();
5894 if (!NoThrow || ArgNo < 0 ||
5895 !F.getAttributes().hasAttrSomewhere(Kind: Attribute::Returned))
5896 return;
5897
5898 for (unsigned U = 0, E = F.arg_size(); U < E; ++U)
5899 if (F.hasParamAttribute(ArgNo: U, Kind: Attribute::Returned)) {
5900 if (U == unsigned(ArgNo))
5901 State.removeAssumedBits(BitsEncoding: NOT_CAPTURED_IN_RET);
5902 else if (ReadOnly)
5903 State.addKnownBits(Bits: NO_CAPTURE);
5904 else
5905 State.addKnownBits(Bits: NOT_CAPTURED_IN_RET);
5906 break;
5907 }
5908}
5909
5910namespace {
5911/// A class to hold the state of for no-capture attributes.
5912struct AANoCaptureImpl : public AANoCapture {
5913 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5914
5915 /// See AbstractAttribute::initialize(...).
5916 void initialize(Attributor &A) override {
5917 bool IsKnown;
5918 assert(!AA::hasAssumedIRAttr<Attribute::Captures>(
5919 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5920 (void)IsKnown;
5921 }
5922
5923 /// See AbstractAttribute::updateImpl(...).
5924 ChangeStatus updateImpl(Attributor &A) override;
5925
5926 /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
5927 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5928 SmallVectorImpl<Attribute> &Attrs) const override {
5929 if (!isAssumedNoCaptureMaybeReturned())
5930 return;
5931
5932 if (isArgumentPosition()) {
5933 if (isAssumedNoCapture())
5934 Attrs.emplace_back(Args: Attribute::get(Context&: Ctx, Kind: Attribute::Captures));
5935 else if (ManifestInternal)
5936 Attrs.emplace_back(Args: Attribute::get(Context&: Ctx, Kind: "no-capture-maybe-returned"));
5937 }
5938 }
5939
5940 /// See AbstractState::getAsStr().
5941 const std::string getAsStr(Attributor *A) const override {
5942 if (isKnownNoCapture())
5943 return "known not-captured";
5944 if (isAssumedNoCapture())
5945 return "assumed not-captured";
5946 if (isKnownNoCaptureMaybeReturned())
5947 return "known not-captured-maybe-returned";
5948 if (isAssumedNoCaptureMaybeReturned())
5949 return "assumed not-captured-maybe-returned";
5950 return "assumed-captured";
5951 }
5952
5953 /// Check the use \p U and update \p State accordingly. Return true if we
5954 /// should continue to update the state.
5955 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
5956 bool &Follow) {
5957 Instruction *UInst = cast<Instruction>(Val: U.getUser());
5958 LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "
5959 << *UInst << "\n");
5960
5961 // Deal with ptr2int by following uses.
5962 if (isa<PtrToIntInst>(Val: UInst)) {
5963 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
5964 return isCapturedIn(State, /* Memory */ CapturedInMem: true, /* Integer */ CapturedInInt: true,
5965 /* Return */ CapturedInRet: true);
5966 }
5967
5968 // For stores we already checked if we can follow them, if they make it
5969 // here we give up.
5970 if (isa<StoreInst>(Val: UInst))
5971 return isCapturedIn(State, /* Memory */ CapturedInMem: true, /* Integer */ CapturedInInt: true,
5972 /* Return */ CapturedInRet: true);
5973
5974 // Explicitly catch return instructions.
5975 if (isa<ReturnInst>(Val: UInst)) {
5976 if (UInst->getFunction() == getAnchorScope())
5977 return isCapturedIn(State, /* Memory */ CapturedInMem: false, /* Integer */ CapturedInInt: false,
5978 /* Return */ CapturedInRet: true);
5979 return isCapturedIn(State, /* Memory */ CapturedInMem: true, /* Integer */ CapturedInInt: true,
5980 /* Return */ CapturedInRet: true);
5981 }
5982
5983 // For now we only use special logic for call sites. However, the tracker
5984 // itself knows about a lot of other non-capturing cases already.
5985 auto *CB = dyn_cast<CallBase>(Val: UInst);
5986 if (!CB || !CB->isArgOperand(U: &U))
5987 return isCapturedIn(State, /* Memory */ CapturedInMem: true, /* Integer */ CapturedInInt: true,
5988 /* Return */ CapturedInRet: true);
5989
5990 unsigned ArgNo = CB->getArgOperandNo(U: &U);
5991 const IRPosition &CSArgPos = IRPosition::callsite_argument(CB: *CB, ArgNo);
5992 // If we have a abstract no-capture attribute for the argument we can use
5993 // it to justify a non-capture attribute here. This allows recursion!
5994 bool IsKnownNoCapture;
5995 const AANoCapture *ArgNoCaptureAA = nullptr;
5996 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
5997 A, QueryingAA: this, IRP: CSArgPos, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoCapture, IgnoreSubsumingPositions: false,
5998 AAPtr: &ArgNoCaptureAA);
5999 if (IsAssumedNoCapture)
6000 return isCapturedIn(State, /* Memory */ CapturedInMem: false, /* Integer */ CapturedInInt: false,
6001 /* Return */ CapturedInRet: false);
6002 if (ArgNoCaptureAA && ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
6003 Follow = true;
6004 return isCapturedIn(State, /* Memory */ CapturedInMem: false, /* Integer */ CapturedInInt: false,
6005 /* Return */ CapturedInRet: false);
6006 }
6007
6008 // Lastly, we could not find a reason no-capture can be assumed so we don't.
6009 return isCapturedIn(State, /* Memory */ CapturedInMem: true, /* Integer */ CapturedInInt: true,
6010 /* Return */ CapturedInRet: true);
6011 }
6012
6013 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
6014 /// \p CapturedInRet, then return true if we should continue updating the
6015 /// state.
6016 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
6017 bool CapturedInInt, bool CapturedInRet) {
6018 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
6019 << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
6020 if (CapturedInMem)
6021 State.removeAssumedBits(BitsEncoding: AANoCapture::NOT_CAPTURED_IN_MEM);
6022 if (CapturedInInt)
6023 State.removeAssumedBits(BitsEncoding: AANoCapture::NOT_CAPTURED_IN_INT);
6024 if (CapturedInRet)
6025 State.removeAssumedBits(BitsEncoding: AANoCapture::NOT_CAPTURED_IN_RET);
6026 return State.isAssumed(BitsEncoding: AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
6027 }
6028};
6029
6030ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
6031 const IRPosition &IRP = getIRPosition();
6032 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
6033 : &IRP.getAssociatedValue();
6034 if (!V)
6035 return indicatePessimisticFixpoint();
6036
6037 const Function *F =
6038 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
6039
6040 // TODO: Is the checkForAllUses below useful for constants?
6041 if (!F)
6042 return indicatePessimisticFixpoint();
6043
6044 AANoCapture::StateType T;
6045 const IRPosition &FnPos = IRPosition::function(F: *F);
6046
6047 // Readonly means we cannot capture through memory.
6048 bool IsKnown;
6049 if (AA::isAssumedReadOnly(A, IRP: FnPos, QueryingAA: *this, IsKnown)) {
6050 T.addKnownBits(Bits: NOT_CAPTURED_IN_MEM);
6051 if (IsKnown)
6052 addKnownBits(Bits: NOT_CAPTURED_IN_MEM);
6053 }
6054
6055 // Make sure all returned values are different than the underlying value.
6056 // TODO: we could do this in a more sophisticated way inside
6057 // AAReturnedValues, e.g., track all values that escape through returns
6058 // directly somehow.
6059 auto CheckReturnedArgs = [&](bool &UsedAssumedInformation) {
6060 SmallVector<AA::ValueAndContext> Values;
6061 if (!A.getAssumedSimplifiedValues(IRP: IRPosition::returned(F: *F), AA: this, Values,
6062 S: AA::ValueScope::Intraprocedural,
6063 UsedAssumedInformation))
6064 return false;
6065 bool SeenConstant = false;
6066 for (const AA::ValueAndContext &VAC : Values) {
6067 if (isa<Constant>(Val: VAC.getValue())) {
6068 if (SeenConstant)
6069 return false;
6070 SeenConstant = true;
6071 } else if (!isa<Argument>(Val: VAC.getValue()) ||
6072 VAC.getValue() == getAssociatedArgument())
6073 return false;
6074 }
6075 return true;
6076 };
6077
6078 bool IsKnownNoUnwind;
6079 if (AA::hasAssumedIRAttr<Attribute::NoUnwind>(
6080 A, QueryingAA: this, IRP: FnPos, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoUnwind)) {
6081 bool IsVoidTy = F->getReturnType()->isVoidTy();
6082 bool UsedAssumedInformation = false;
6083 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6084 T.addKnownBits(Bits: NOT_CAPTURED_IN_RET);
6085 if (T.isKnown(BitsEncoding: NOT_CAPTURED_IN_MEM))
6086 return ChangeStatus::UNCHANGED;
6087 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6088 addKnownBits(Bits: NOT_CAPTURED_IN_RET);
6089 if (isKnown(BitsEncoding: NOT_CAPTURED_IN_MEM))
6090 return indicateOptimisticFixpoint();
6091 }
6092 }
6093 }
6094
6095 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
6096 // TODO(captures): Make this more precise.
6097 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
6098 if (capturesNothing(CC: CI))
6099 return true;
6100 if (CI.isPassthrough()) {
6101 Follow = true;
6102 return true;
6103 }
6104 return checkUse(A, State&: T, U, Follow);
6105 };
6106
6107 if (!A.checkForAllUses(Pred: UseCheck, QueryingAA: *this, V: *V))
6108 return indicatePessimisticFixpoint();
6109
6110 AANoCapture::StateType &S = getState();
6111 auto Assumed = S.getAssumed();
6112 S.intersectAssumedBits(BitsEncoding: T.getAssumed());
6113 if (!isAssumedNoCaptureMaybeReturned())
6114 return indicatePessimisticFixpoint();
6115 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
6116 : ChangeStatus::CHANGED;
6117}
6118
6119/// NoCapture attribute for function arguments.
6120struct AANoCaptureArgument final : AANoCaptureImpl {
6121 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
6122 : AANoCaptureImpl(IRP, A) {}
6123
6124 /// See AbstractAttribute::trackStatistics()
6125 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
6126};
6127
6128/// NoCapture attribute for call site arguments.
6129struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6130 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
6131 : AANoCaptureImpl(IRP, A) {}
6132
6133 /// See AbstractAttribute::updateImpl(...).
6134 ChangeStatus updateImpl(Attributor &A) override {
6135 // TODO: Once we have call site specific value information we can provide
6136 // call site specific liveness information and then it makes
6137 // sense to specialize attributes for call sites arguments instead of
6138 // redirecting requests to the callee argument.
6139 Argument *Arg = getAssociatedArgument();
6140 if (!Arg)
6141 return indicatePessimisticFixpoint();
6142 const IRPosition &ArgPos = IRPosition::argument(Arg: *Arg);
6143 bool IsKnownNoCapture;
6144 const AANoCapture *ArgAA = nullptr;
6145 if (AA::hasAssumedIRAttr<Attribute::Captures>(
6146 A, QueryingAA: this, IRP: ArgPos, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoCapture, IgnoreSubsumingPositions: false,
6147 AAPtr: &ArgAA))
6148 return ChangeStatus::UNCHANGED;
6149 if (!ArgAA || !ArgAA->isAssumedNoCaptureMaybeReturned())
6150 return indicatePessimisticFixpoint();
6151 return clampStateAndIndicateChange(S&: getState(), R: ArgAA->getState());
6152 }
6153
6154 /// See AbstractAttribute::trackStatistics()
6155 void trackStatistics() const override {
6156 STATS_DECLTRACK_CSARG_ATTR(nocapture)
6157 };
6158};
6159
6160/// NoCapture attribute for floating values.
6161struct AANoCaptureFloating final : AANoCaptureImpl {
6162 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
6163 : AANoCaptureImpl(IRP, A) {}
6164
6165 /// See AbstractAttribute::trackStatistics()
6166 void trackStatistics() const override {
6167 STATS_DECLTRACK_FLOATING_ATTR(nocapture)
6168 }
6169};
6170
6171/// NoCapture attribute for function return value.
6172struct AANoCaptureReturned final : AANoCaptureImpl {
6173 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
6174 : AANoCaptureImpl(IRP, A) {
6175 llvm_unreachable("NoCapture is not applicable to function returns!");
6176 }
6177
6178 /// See AbstractAttribute::initialize(...).
6179 void initialize(Attributor &A) override {
6180 llvm_unreachable("NoCapture is not applicable to function returns!");
6181 }
6182
6183 /// See AbstractAttribute::updateImpl(...).
6184 ChangeStatus updateImpl(Attributor &A) override {
6185 llvm_unreachable("NoCapture is not applicable to function returns!");
6186 }
6187
6188 /// See AbstractAttribute::trackStatistics()
6189 void trackStatistics() const override {}
6190};
6191
6192/// NoCapture attribute deduction for a call site return value.
6193struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6194 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
6195 : AANoCaptureImpl(IRP, A) {}
6196
6197 /// See AbstractAttribute::initialize(...).
6198 void initialize(Attributor &A) override {
6199 const Function *F = getAnchorScope();
6200 // Check what state the associated function can actually capture.
6201 determineFunctionCaptureCapabilities(IRP: getIRPosition(), F: *F, State&: *this);
6202 }
6203
6204 /// See AbstractAttribute::trackStatistics()
6205 void trackStatistics() const override {
6206 STATS_DECLTRACK_CSRET_ATTR(nocapture)
6207 }
6208};
6209} // namespace
6210
6211/// ------------------ Value Simplify Attribute ----------------------------
6212
6213bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6214 // FIXME: Add a typecast support.
6215 SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
6216 A: SimplifiedAssociatedValue, B: Other, Ty);
6217 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6218 return false;
6219
6220 LLVM_DEBUG({
6221 if (SimplifiedAssociatedValue)
6222 dbgs() << "[ValueSimplify] is assumed to be "
6223 << **SimplifiedAssociatedValue << "\n";
6224 else
6225 dbgs() << "[ValueSimplify] is assumed to be <none>\n";
6226 });
6227 return true;
6228}
6229
6230namespace {
6231struct AAValueSimplifyImpl : AAValueSimplify {
6232 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6233 : AAValueSimplify(IRP, A) {}
6234
6235 /// See AbstractAttribute::initialize(...).
6236 void initialize(Attributor &A) override {
6237 if (getAssociatedValue().getType()->isVoidTy())
6238 indicatePessimisticFixpoint();
6239 if (A.hasSimplificationCallback(IRP: getIRPosition()))
6240 indicatePessimisticFixpoint();
6241 }
6242
6243 /// See AbstractAttribute::getAsStr().
6244 const std::string getAsStr(Attributor *A) const override {
6245 LLVM_DEBUG({
6246 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";
6247 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6248 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";
6249 });
6250 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6251 : "not-simple";
6252 }
6253
6254 /// See AbstractAttribute::trackStatistics()
6255 void trackStatistics() const override {}
6256
6257 /// See AAValueSimplify::getAssumedSimplifiedValue()
6258 std::optional<Value *>
6259 getAssumedSimplifiedValue(Attributor &A) const override {
6260 return SimplifiedAssociatedValue;
6261 }
6262
6263 /// Ensure the return value is \p V with type \p Ty, if not possible return
6264 /// nullptr. If \p Check is true we will only verify such an operation would
6265 /// suceed and return a non-nullptr value if that is the case. No IR is
6266 /// generated or modified.
6267 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6268 bool Check) {
6269 if (auto *TypedV = AA::getWithType(V, Ty))
6270 return TypedV;
6271 if (CtxI && V.getType()->canLosslesslyBitCastTo(Ty: &Ty))
6272 return Check ? &V
6273 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6274 S: &V, Ty: &Ty, Name: "", InsertBefore: CtxI->getIterator());
6275 return nullptr;
6276 }
6277
6278 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6279 /// If \p Check is true we will only verify such an operation would suceed and
6280 /// return a non-nullptr value if that is the case. No IR is generated or
6281 /// modified.
6282 static Value *reproduceInst(Attributor &A,
6283 const AbstractAttribute &QueryingAA,
6284 Instruction &I, Type &Ty, Instruction *CtxI,
6285 bool Check, ValueToValueMapTy &VMap) {
6286 assert(CtxI && "Cannot reproduce an instruction without context!");
6287 if (Check && (I.mayReadFromMemory() ||
6288 !isSafeToSpeculativelyExecute(I: &I, CtxI, /* DT */ AC: nullptr,
6289 /* TLI */ DT: nullptr)))
6290 return nullptr;
6291 for (Value *Op : I.operands()) {
6292 Value *NewOp = reproduceValue(A, QueryingAA, V&: *Op, Ty, CtxI, Check, VMap);
6293 if (!NewOp) {
6294 assert(Check && "Manifest of new value unexpectedly failed!");
6295 return nullptr;
6296 }
6297 if (!Check)
6298 VMap[Op] = NewOp;
6299 }
6300 if (Check)
6301 return &I;
6302
6303 Instruction *CloneI = I.clone();
6304 // TODO: Try to salvage debug information here.
6305 CloneI->setDebugLoc(DebugLoc());
6306 VMap[&I] = CloneI;
6307 CloneI->insertBefore(InsertPos: CtxI->getIterator());
6308 RemapInstruction(I: CloneI, VM&: VMap);
6309 return CloneI;
6310 }
6311
6312 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6313 /// If \p Check is true we will only verify such an operation would suceed and
6314 /// return a non-nullptr value if that is the case. No IR is generated or
6315 /// modified.
6316 static Value *reproduceValue(Attributor &A,
6317 const AbstractAttribute &QueryingAA, Value &V,
6318 Type &Ty, Instruction *CtxI, bool Check,
6319 ValueToValueMapTy &VMap) {
6320 if (const auto &NewV = VMap.lookup(Val: &V))
6321 return NewV;
6322 bool UsedAssumedInformation = false;
6323 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6324 V, AA: QueryingAA, UsedAssumedInformation, S: AA::Interprocedural);
6325 if (!SimpleV.has_value())
6326 return PoisonValue::get(T: &Ty);
6327 Value *EffectiveV = &V;
6328 if (*SimpleV)
6329 EffectiveV = *SimpleV;
6330 if (auto *C = dyn_cast<Constant>(Val: EffectiveV))
6331 return C;
6332 if (CtxI && AA::isValidAtPosition(VAC: AA::ValueAndContext(*EffectiveV, *CtxI),
6333 InfoCache&: A.getInfoCache()))
6334 return ensureType(A, V&: *EffectiveV, Ty, CtxI, Check);
6335 if (auto *I = dyn_cast<Instruction>(Val: EffectiveV))
6336 if (Value *NewV = reproduceInst(A, QueryingAA, I&: *I, Ty, CtxI, Check, VMap))
6337 return ensureType(A, V&: *NewV, Ty, CtxI, Check);
6338 return nullptr;
6339 }
6340
6341 /// Return a value we can use as replacement for the associated one, or
6342 /// nullptr if we don't have one that makes sense.
6343 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6344 Value *NewV = SimplifiedAssociatedValue
6345 ? *SimplifiedAssociatedValue
6346 : UndefValue::get(T: getAssociatedType());
6347 if (NewV && NewV != &getAssociatedValue()) {
6348 ValueToValueMapTy VMap;
6349 // First verify we can reprduce the value with the required type at the
6350 // context location before we actually start modifying the IR.
6351 if (reproduceValue(A, QueryingAA: *this, V&: *NewV, Ty&: *getAssociatedType(), CtxI,
6352 /* CheckOnly */ Check: true, VMap))
6353 return reproduceValue(A, QueryingAA: *this, V&: *NewV, Ty&: *getAssociatedType(), CtxI,
6354 /* CheckOnly */ Check: false, VMap);
6355 }
6356 return nullptr;
6357 }
6358
6359 /// Helper function for querying AAValueSimplify and updating candidate.
6360 /// \param IRP The value position we are trying to unify with SimplifiedValue
6361 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6362 const IRPosition &IRP, bool Simplify = true) {
6363 bool UsedAssumedInformation = false;
6364 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6365 if (Simplify)
6366 QueryingValueSimplified = A.getAssumedSimplified(
6367 IRP, AA: QueryingAA, UsedAssumedInformation, S: AA::Interprocedural);
6368 return unionAssumed(Other: QueryingValueSimplified);
6369 }
6370
6371 /// Returns a candidate is found or not
6372 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6373 if (!getAssociatedValue().getType()->isIntegerTy())
6374 return false;
6375
6376 // This will also pass the call base context.
6377 const auto *AA =
6378 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6379 if (!AA)
6380 return false;
6381
6382 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
6383
6384 if (!COpt) {
6385 SimplifiedAssociatedValue = std::nullopt;
6386 A.recordDependence(FromAA: *AA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
6387 return true;
6388 }
6389 if (auto *C = *COpt) {
6390 SimplifiedAssociatedValue = C;
6391 A.recordDependence(FromAA: *AA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
6392 return true;
6393 }
6394 return false;
6395 }
6396
6397 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6398 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6399 return true;
6400 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6401 return true;
6402 return false;
6403 }
6404
6405 /// See AbstractAttribute::manifest(...).
6406 ChangeStatus manifest(Attributor &A) override {
6407 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6408 for (auto &U : getAssociatedValue().uses()) {
6409 // Check if we need to adjust the insertion point to make sure the IR is
6410 // valid.
6411 Instruction *IP = dyn_cast<Instruction>(Val: U.getUser());
6412 if (auto *PHI = dyn_cast_or_null<PHINode>(Val: IP))
6413 IP = PHI->getIncomingBlock(U)->getTerminator();
6414 if (auto *NewV = manifestReplacementValue(A, CtxI: IP)) {
6415 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()
6416 << " -> " << *NewV << " :: " << *this << "\n");
6417 if (A.changeUseAfterManifest(U, NV&: *NewV))
6418 Changed = ChangeStatus::CHANGED;
6419 }
6420 }
6421
6422 return Changed | AAValueSimplify::manifest(A);
6423 }
6424
6425 /// See AbstractState::indicatePessimisticFixpoint(...).
6426 ChangeStatus indicatePessimisticFixpoint() override {
6427 SimplifiedAssociatedValue = &getAssociatedValue();
6428 return AAValueSimplify::indicatePessimisticFixpoint();
6429 }
6430};
6431
6432struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6433 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6434 : AAValueSimplifyImpl(IRP, A) {}
6435
6436 void initialize(Attributor &A) override {
6437 AAValueSimplifyImpl::initialize(A);
6438 if (A.hasAttr(IRP: getIRPosition(),
6439 AKs: {Attribute::InAlloca, Attribute::Preallocated,
6440 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6441 /* IgnoreSubsumingPositions */ true))
6442 indicatePessimisticFixpoint();
6443 }
6444
6445 /// See AbstractAttribute::updateImpl(...).
6446 ChangeStatus updateImpl(Attributor &A) override {
6447 // Byval is only replacable if it is readonly otherwise we would write into
6448 // the replaced value and not the copy that byval creates implicitly.
6449 Argument *Arg = getAssociatedArgument();
6450 if (Arg->hasByValAttr()) {
6451 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6452 // there is no race by not copying a constant byval.
6453 bool IsKnown;
6454 if (!AA::isAssumedReadOnly(A, IRP: getIRPosition(), QueryingAA: *this, IsKnown))
6455 return indicatePessimisticFixpoint();
6456 }
6457
6458 auto Before = SimplifiedAssociatedValue;
6459
6460 auto PredForCallSite = [&](AbstractCallSite ACS) {
6461 const IRPosition &ACSArgPos =
6462 IRPosition::callsite_argument(ACS, ArgNo: getCallSiteArgNo());
6463 // Check if a coresponding argument was found or if it is on not
6464 // associated (which can happen for callback calls).
6465 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6466 return false;
6467
6468 // Simplify the argument operand explicitly and check if the result is
6469 // valid in the current scope. This avoids refering to simplified values
6470 // in other functions, e.g., we don't want to say a an argument in a
6471 // static function is actually an argument in a different function.
6472 bool UsedAssumedInformation = false;
6473 std::optional<Constant *> SimpleArgOp =
6474 A.getAssumedConstant(IRP: ACSArgPos, AA: *this, UsedAssumedInformation);
6475 if (!SimpleArgOp)
6476 return true;
6477 if (!*SimpleArgOp)
6478 return false;
6479 if (!AA::isDynamicallyUnique(A, QueryingAA: *this, V: **SimpleArgOp))
6480 return false;
6481 return unionAssumed(Other: *SimpleArgOp);
6482 };
6483
6484 // Generate a answer specific to a call site context.
6485 bool Success;
6486 bool UsedAssumedInformation = false;
6487 if (hasCallBaseContext() &&
6488 getCallBaseContext()->getCalledOperand() == Arg->getParent())
6489 Success = PredForCallSite(
6490 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6491 else
6492 Success = A.checkForAllCallSites(Pred: PredForCallSite, QueryingAA: *this, RequireAllCallSites: true,
6493 UsedAssumedInformation);
6494
6495 if (!Success)
6496 if (!askSimplifiedValueForOtherAAs(A))
6497 return indicatePessimisticFixpoint();
6498
6499 // If a candidate was found in this update, return CHANGED.
6500 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6501 : ChangeStatus ::CHANGED;
6502 }
6503
6504 /// See AbstractAttribute::trackStatistics()
6505 void trackStatistics() const override {
6506 STATS_DECLTRACK_ARG_ATTR(value_simplify)
6507 }
6508};
6509
6510struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6511 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6512 : AAValueSimplifyImpl(IRP, A) {}
6513
6514 /// See AAValueSimplify::getAssumedSimplifiedValue()
6515 std::optional<Value *>
6516 getAssumedSimplifiedValue(Attributor &A) const override {
6517 if (!isValidState())
6518 return nullptr;
6519 return SimplifiedAssociatedValue;
6520 }
6521
6522 /// See AbstractAttribute::updateImpl(...).
6523 ChangeStatus updateImpl(Attributor &A) override {
6524 auto Before = SimplifiedAssociatedValue;
6525
6526 auto ReturnInstCB = [&](Instruction &I) {
6527 auto &RI = cast<ReturnInst>(Val&: I);
6528 return checkAndUpdate(
6529 A, QueryingAA: *this,
6530 IRP: IRPosition::value(V: *RI.getReturnValue(), CBContext: getCallBaseContext()));
6531 };
6532
6533 bool UsedAssumedInformation = false;
6534 if (!A.checkForAllInstructions(Pred: ReturnInstCB, QueryingAA: *this, Opcodes: {Instruction::Ret},
6535 UsedAssumedInformation))
6536 if (!askSimplifiedValueForOtherAAs(A))
6537 return indicatePessimisticFixpoint();
6538
6539 // If a candidate was found in this update, return CHANGED.
6540 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6541 : ChangeStatus ::CHANGED;
6542 }
6543
6544 ChangeStatus manifest(Attributor &A) override {
6545 // We queried AAValueSimplify for the returned values so they will be
6546 // replaced if a simplified form was found. Nothing to do here.
6547 return ChangeStatus::UNCHANGED;
6548 }
6549
6550 /// See AbstractAttribute::trackStatistics()
6551 void trackStatistics() const override {
6552 STATS_DECLTRACK_FNRET_ATTR(value_simplify)
6553 }
6554};
6555
6556struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6557 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6558 : AAValueSimplifyImpl(IRP, A) {}
6559
6560 /// See AbstractAttribute::initialize(...).
6561 void initialize(Attributor &A) override {
6562 AAValueSimplifyImpl::initialize(A);
6563 Value &V = getAnchorValue();
6564
6565 // TODO: add other stuffs
6566 if (isa<Constant>(Val: V))
6567 indicatePessimisticFixpoint();
6568 }
6569
6570 /// See AbstractAttribute::updateImpl(...).
6571 ChangeStatus updateImpl(Attributor &A) override {
6572 auto Before = SimplifiedAssociatedValue;
6573 if (!askSimplifiedValueForOtherAAs(A))
6574 return indicatePessimisticFixpoint();
6575
6576 // If a candidate was found in this update, return CHANGED.
6577 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6578 : ChangeStatus ::CHANGED;
6579 }
6580
6581 /// See AbstractAttribute::trackStatistics()
6582 void trackStatistics() const override {
6583 STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
6584 }
6585};
6586
6587struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6588 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6589 : AAValueSimplifyImpl(IRP, A) {}
6590
6591 /// See AbstractAttribute::initialize(...).
6592 void initialize(Attributor &A) override {
6593 SimplifiedAssociatedValue = nullptr;
6594 indicateOptimisticFixpoint();
6595 }
6596 /// See AbstractAttribute::initialize(...).
6597 ChangeStatus updateImpl(Attributor &A) override {
6598 llvm_unreachable(
6599 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6600 }
6601 /// See AbstractAttribute::trackStatistics()
6602 void trackStatistics() const override {
6603 STATS_DECLTRACK_FN_ATTR(value_simplify)
6604 }
6605};
6606
6607struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6608 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6609 : AAValueSimplifyFunction(IRP, A) {}
6610 /// See AbstractAttribute::trackStatistics()
6611 void trackStatistics() const override {
6612 STATS_DECLTRACK_CS_ATTR(value_simplify)
6613 }
6614};
6615
6616struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6617 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6618 : AAValueSimplifyImpl(IRP, A) {}
6619
6620 void initialize(Attributor &A) override {
6621 AAValueSimplifyImpl::initialize(A);
6622 Function *Fn = getAssociatedFunction();
6623 assert(Fn && "Did expect an associted function");
6624 for (Argument &Arg : Fn->args()) {
6625 if (Arg.hasReturnedAttr()) {
6626 auto IRP = IRPosition::callsite_argument(CB: *cast<CallBase>(Val: getCtxI()),
6627 ArgNo: Arg.getArgNo());
6628 if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_ARGUMENT &&
6629 checkAndUpdate(A, QueryingAA: *this, IRP))
6630 indicateOptimisticFixpoint();
6631 else
6632 indicatePessimisticFixpoint();
6633 return;
6634 }
6635 }
6636 }
6637
6638 /// See AbstractAttribute::updateImpl(...).
6639 ChangeStatus updateImpl(Attributor &A) override {
6640 return indicatePessimisticFixpoint();
6641 }
6642
6643 void trackStatistics() const override {
6644 STATS_DECLTRACK_CSRET_ATTR(value_simplify)
6645 }
6646};
6647
6648struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6649 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6650 : AAValueSimplifyFloating(IRP, A) {}
6651
6652 /// See AbstractAttribute::manifest(...).
6653 ChangeStatus manifest(Attributor &A) override {
6654 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6655 // TODO: We should avoid simplification duplication to begin with.
6656 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6657 IRP: IRPosition::value(V: getAssociatedValue()), QueryingAA: this, DepClass: DepClassTy::NONE);
6658 if (FloatAA && FloatAA->getState().isValidState())
6659 return Changed;
6660
6661 if (auto *NewV = manifestReplacementValue(A, CtxI: getCtxI())) {
6662 Use &U = cast<CallBase>(Val: &getAnchorValue())
6663 ->getArgOperandUse(i: getCallSiteArgNo());
6664 if (A.changeUseAfterManifest(U, NV&: *NewV))
6665 Changed = ChangeStatus::CHANGED;
6666 }
6667
6668 return Changed | AAValueSimplify::manifest(A);
6669 }
6670
6671 void trackStatistics() const override {
6672 STATS_DECLTRACK_CSARG_ATTR(value_simplify)
6673 }
6674};
6675} // namespace
6676
6677/// ----------------------- Heap-To-Stack Conversion ---------------------------
6678namespace {
6679struct AAHeapToStackFunction final : public AAHeapToStack {
6680
6681 static bool isGlobalizedLocal(const CallBase &CB) {
6682 Attribute A = CB.getFnAttr(Kind: "alloc-family");
6683 return A.isValid() && A.getValueAsString() == "__kmpc_alloc_shared";
6684 }
6685
6686 struct AllocationInfo {
6687 /// The call that allocates the memory.
6688 CallBase *const CB;
6689
6690 /// Whether this allocation is an OpenMP globalized local variable.
6691 bool IsGlobalizedLocal = false;
6692
6693 /// The status wrt. a rewrite.
6694 enum {
6695 STACK_DUE_TO_USE,
6696 STACK_DUE_TO_FREE,
6697 INVALID,
6698 } Status = STACK_DUE_TO_USE;
6699
6700 /// Flag to indicate if we encountered a use that might free this allocation
6701 /// but which is not in the deallocation infos.
6702 bool HasPotentiallyFreeingUnknownUses = false;
6703
6704 /// Flag to indicate that we should place the new alloca in the function
6705 /// entry block rather than where the call site (CB) is.
6706 bool MoveAllocaIntoEntry = true;
6707
6708 /// The set of free calls that use this allocation.
6709 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6710 };
6711
6712 struct DeallocationInfo {
6713 /// The call that deallocates the memory.
6714 CallBase *const CB;
6715 /// The value freed by the call.
6716 Value *FreedOp;
6717
6718 /// Flag to indicate if we don't know all objects this deallocation might
6719 /// free.
6720 bool MightFreeUnknownObjects = false;
6721
6722 /// The set of allocation calls that are potentially freed.
6723 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6724 };
6725
6726 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6727 : AAHeapToStack(IRP, A) {}
6728
6729 ~AAHeapToStackFunction() override {
6730 // Ensure we call the destructor so we release any memory allocated in the
6731 // sets.
6732 for (auto &It : AllocationInfos)
6733 It.second->~AllocationInfo();
6734 for (auto &It : DeallocationInfos)
6735 It.second->~DeallocationInfo();
6736 }
6737
6738 void initialize(Attributor &A) override {
6739 AAHeapToStack::initialize(A);
6740
6741 const Function *F = getAnchorScope();
6742 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(F: *F);
6743
6744 auto AllocationIdentifierCB = [&](Instruction &I) {
6745 CallBase *CB = dyn_cast<CallBase>(Val: &I);
6746 if (!CB)
6747 return true;
6748 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6749 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{.CB: CB, .FreedOp: FreedOp};
6750 return true;
6751 }
6752 // To do heap to stack, we need to know that the allocation itself is
6753 // removable once uses are rewritten, and that we can initialize the
6754 // alloca to the same pattern as the original allocation result.
6755 if (isRemovableAlloc(V: CB, TLI)) {
6756 auto *I8Ty = Type::getInt8Ty(C&: CB->getParent()->getContext());
6757 if (nullptr != getInitialValueOfAllocation(V: CB, TLI, Ty: I8Ty)) {
6758 AllocationInfo *AI = new (A.Allocator) AllocationInfo{.CB: CB};
6759 AllocationInfos[CB] = AI;
6760 AI->IsGlobalizedLocal = isGlobalizedLocal(CB: *CB);
6761 }
6762 }
6763 return true;
6764 };
6765
6766 bool UsedAssumedInformation = false;
6767 bool Success = A.checkForAllCallLikeInstructions(
6768 Pred: AllocationIdentifierCB, QueryingAA: *this, UsedAssumedInformation,
6769 /* CheckBBLivenessOnly */ false,
6770 /* CheckPotentiallyDead */ true);
6771 (void)Success;
6772 assert(Success && "Did not expect the call base visit callback to fail!");
6773
6774 Attributor::SimplifictionCallbackTy SCB =
6775 [](const IRPosition &, const AbstractAttribute *,
6776 bool &) -> std::optional<Value *> { return nullptr; };
6777 for (const auto &It : AllocationInfos)
6778 A.registerSimplificationCallback(IRP: IRPosition::callsite_returned(CB: *It.first),
6779 CB: SCB);
6780 for (const auto &It : DeallocationInfos)
6781 A.registerSimplificationCallback(IRP: IRPosition::callsite_returned(CB: *It.first),
6782 CB: SCB);
6783 }
6784
6785 const std::string getAsStr(Attributor *A) const override {
6786 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6787 for (const auto &It : AllocationInfos) {
6788 if (It.second->Status == AllocationInfo::INVALID)
6789 ++NumInvalidMallocs;
6790 else
6791 ++NumH2SMallocs;
6792 }
6793 return "[H2S] Mallocs Good/Bad: " + std::to_string(val: NumH2SMallocs) + "/" +
6794 std::to_string(val: NumInvalidMallocs);
6795 }
6796
6797 /// See AbstractAttribute::trackStatistics().
6798 void trackStatistics() const override {
6799 STATS_DECL(
6800 MallocCalls, Function,
6801 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6802 for (const auto &It : AllocationInfos)
6803 if (It.second->Status != AllocationInfo::INVALID)
6804 ++BUILD_STAT_NAME(MallocCalls, Function);
6805 }
6806
6807 bool isAssumedHeapToStack(const CallBase &CB) const override {
6808 if (isValidState())
6809 if (AllocationInfo *AI =
6810 AllocationInfos.lookup(Key: const_cast<CallBase *>(&CB)))
6811 return AI->Status != AllocationInfo::INVALID;
6812 return false;
6813 }
6814
6815 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6816 if (!isValidState())
6817 return false;
6818
6819 for (const auto &It : AllocationInfos) {
6820 AllocationInfo &AI = *It.second;
6821 if (AI.Status == AllocationInfo::INVALID)
6822 continue;
6823
6824 if (AI.PotentialFreeCalls.count(key: &CB))
6825 return true;
6826 }
6827
6828 return false;
6829 }
6830
6831 ChangeStatus manifest(Attributor &A) override {
6832 assert(getState().isValidState() &&
6833 "Attempted to manifest an invalid state!");
6834
6835 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6836 Function *F = getAnchorScope();
6837 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(F: *F);
6838
6839 for (auto &It : AllocationInfos) {
6840 AllocationInfo &AI = *It.second;
6841 if (AI.Status == AllocationInfo::INVALID)
6842 continue;
6843
6844 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6845 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
6846 A.deleteAfterManifest(I&: *FreeCall);
6847 HasChanged = ChangeStatus::CHANGED;
6848 }
6849
6850 LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB
6851 << "\n");
6852
6853 auto Remark = [&](OptimizationRemark OR) {
6854 if (AI.IsGlobalizedLocal)
6855 return OR << "Moving globalized variable to the stack.";
6856 return OR << "Moving memory allocation from the heap to the stack.";
6857 };
6858 if (AI.IsGlobalizedLocal)
6859 A.emitRemark<OptimizationRemark>(I: AI.CB, RemarkName: "OMP110", RemarkCB&: Remark);
6860 else
6861 A.emitRemark<OptimizationRemark>(I: AI.CB, RemarkName: "HeapToStack", RemarkCB&: Remark);
6862
6863 const DataLayout &DL = A.getInfoCache().getDL();
6864 Value *Size;
6865 std::optional<APInt> SizeAPI = getSize(A, AA: *this, AI);
6866 if (SizeAPI) {
6867 Size = ConstantInt::get(Context&: AI.CB->getContext(), V: *SizeAPI);
6868 } else {
6869 LLVMContext &Ctx = AI.CB->getContext();
6870 ObjectSizeOpts Opts;
6871 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts);
6872 SizeOffsetValue SizeOffsetPair = Eval.compute(V: AI.CB);
6873 assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&
6874 cast<ConstantInt>(SizeOffsetPair.Offset)->isZero());
6875 Size = SizeOffsetPair.Size;
6876 }
6877
6878 BasicBlock::iterator IP = AI.MoveAllocaIntoEntry
6879 ? F->getEntryBlock().begin()
6880 : AI.CB->getIterator();
6881
6882 Align Alignment(1);
6883 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6884 Alignment = std::max(a: Alignment, b: *RetAlign);
6885 if (Value *Align = getAllocAlignment(V: AI.CB, TLI)) {
6886 std::optional<APInt> AlignmentAPI = getAPInt(A, AA: *this, V&: *Align);
6887 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6888 "Expected an alignment during manifest!");
6889 Alignment =
6890 std::max(a: Alignment, b: assumeAligned(Value: AlignmentAPI->getZExtValue()));
6891 }
6892
6893 // TODO: Hoist the alloca towards the function entry.
6894 unsigned AS = DL.getAllocaAddrSpace();
6895 Instruction *Alloca =
6896 new AllocaInst(Type::getInt8Ty(C&: F->getContext()), AS, Size, Alignment,
6897 AI.CB->getName() + ".h2s", IP);
6898
6899 if (Alloca->getType() != AI.CB->getType())
6900 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6901 S: Alloca, Ty: AI.CB->getType(), Name: "malloc_cast", InsertBefore: AI.CB->getIterator());
6902
6903 auto *I8Ty = Type::getInt8Ty(C&: F->getContext());
6904 auto *InitVal = getInitialValueOfAllocation(V: AI.CB, TLI, Ty: I8Ty);
6905 assert(InitVal &&
6906 "Must be able to materialize initial memory state of allocation");
6907
6908 A.changeAfterManifest(IRP: IRPosition::inst(I: *AI.CB), NV&: *Alloca);
6909
6910 if (auto *II = dyn_cast<InvokeInst>(Val: AI.CB)) {
6911 auto *NBB = II->getNormalDest();
6912 UncondBrInst::Create(Target: NBB, InsertBefore: AI.CB->getParent());
6913 A.deleteAfterManifest(I&: *AI.CB);
6914 } else {
6915 A.deleteAfterManifest(I&: *AI.CB);
6916 }
6917
6918 // Initialize the alloca with the same value as used by the allocation
6919 // function. We can skip undef as the initial value of an alloc is
6920 // undef, and the memset would simply end up being DSEd.
6921 if (!isa<UndefValue>(Val: InitVal)) {
6922 IRBuilder<> Builder(Alloca->getNextNode());
6923 // TODO: Use alignment above if align!=1
6924 Builder.CreateMemSet(Ptr: Alloca, Val: InitVal, Size, Align: std::nullopt);
6925 }
6926 HasChanged = ChangeStatus::CHANGED;
6927 }
6928
6929 return HasChanged;
6930 }
6931
6932 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
6933 Value &V) {
6934 bool UsedAssumedInformation = false;
6935 std::optional<Constant *> SimpleV =
6936 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6937 if (!SimpleV)
6938 return APInt(64, 0);
6939 if (auto *CI = dyn_cast_or_null<ConstantInt>(Val: *SimpleV))
6940 return CI->getValue();
6941 return std::nullopt;
6942 }
6943
6944 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
6945 AllocationInfo &AI) {
6946 auto Mapper = [&](const Value *V) -> const Value * {
6947 bool UsedAssumedInformation = false;
6948 if (std::optional<Constant *> SimpleV =
6949 A.getAssumedConstant(V: *V, AA, UsedAssumedInformation))
6950 if (*SimpleV)
6951 return *SimpleV;
6952 return V;
6953 };
6954
6955 const Function *F = getAnchorScope();
6956 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(F: *F);
6957 return getAllocSize(CB: AI.CB, TLI, Mapper);
6958 }
6959
6960 /// Collection of all malloc-like calls in a function with associated
6961 /// information.
6962 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6963
6964 /// Collection of all free-like calls in a function with associated
6965 /// information.
6966 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6967
6968 ChangeStatus updateImpl(Attributor &A) override;
6969};
6970
6971ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
6972 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6973 const Function *F = getAnchorScope();
6974 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(F: *F);
6975
6976 const auto *LivenessAA =
6977 A.getAAFor<AAIsDead>(QueryingAA: *this, IRP: IRPosition::function(F: *F), DepClass: DepClassTy::NONE);
6978
6979 MustBeExecutedContextExplorer *Explorer =
6980 A.getInfoCache().getMustBeExecutedContextExplorer();
6981
6982 bool StackIsAccessibleByOtherThreads =
6983 A.getInfoCache().stackIsAccessibleByOtherThreads();
6984
6985 LoopInfo *LI =
6986 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F: *F);
6987 std::optional<bool> MayContainIrreducibleControl;
6988 auto IsInLoop = [&](BasicBlock &BB) {
6989 if (&F->getEntryBlock() == &BB)
6990 return false;
6991 if (!MayContainIrreducibleControl.has_value())
6992 MayContainIrreducibleControl = mayContainIrreducibleControl(F: *F, LI);
6993 if (*MayContainIrreducibleControl)
6994 return true;
6995 if (!LI)
6996 return true;
6997 return LI->getLoopFor(BB: &BB) != nullptr;
6998 };
6999
7000 // Flag to ensure we update our deallocation information at most once per
7001 // updateImpl call and only if we use the free check reasoning.
7002 bool HasUpdatedFrees = false;
7003
7004 auto UpdateFrees = [&]() {
7005 HasUpdatedFrees = true;
7006
7007 for (auto &It : DeallocationInfos) {
7008 DeallocationInfo &DI = *It.second;
7009 // For now we cannot use deallocations that have unknown inputs, skip
7010 // them.
7011 if (DI.MightFreeUnknownObjects)
7012 continue;
7013
7014 // No need to analyze dead calls, ignore them instead.
7015 bool UsedAssumedInformation = false;
7016 if (A.isAssumedDead(I: *DI.CB, QueryingAA: this, LivenessAA, UsedAssumedInformation,
7017 /* CheckBBLivenessOnly */ true))
7018 continue;
7019
7020 // Use the non-optimistic version to get the freed object.
7021 Value *Obj = getUnderlyingObject(V: DI.FreedOp);
7022 if (!Obj) {
7023 LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");
7024 DI.MightFreeUnknownObjects = true;
7025 continue;
7026 }
7027
7028 // Free of null and undef can be ignored as no-ops (or UB in the latter
7029 // case).
7030 if (isa<ConstantPointerNull>(Val: Obj) || isa<UndefValue>(Val: Obj))
7031 continue;
7032
7033 CallBase *ObjCB = dyn_cast<CallBase>(Val: Obj);
7034 if (!ObjCB) {
7035 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj
7036 << "\n");
7037 DI.MightFreeUnknownObjects = true;
7038 continue;
7039 }
7040
7041 AllocationInfo *AI = AllocationInfos.lookup(Key: ObjCB);
7042 if (!AI) {
7043 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj
7044 << "\n");
7045 DI.MightFreeUnknownObjects = true;
7046 continue;
7047 }
7048
7049 DI.PotentialAllocationCalls.insert(X: ObjCB);
7050 }
7051 };
7052
7053 auto FreeCheck = [&](AllocationInfo &AI) {
7054 // If the stack is not accessible by other threads, the "must-free" logic
7055 // doesn't apply as the pointer could be shared and needs to be places in
7056 // "shareable" memory.
7057 if (!StackIsAccessibleByOtherThreads) {
7058 bool IsKnownNoSycn;
7059 if (!AA::hasAssumedIRAttr<Attribute::NoSync>(
7060 A, QueryingAA: this, IRP: getIRPosition(), DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoSycn)) {
7061 LLVM_DEBUG(
7062 dbgs() << "[H2S] found an escaping use, stack is not accessible by "
7063 "other threads and function is not nosync:\n");
7064 return false;
7065 }
7066 }
7067 if (!HasUpdatedFrees)
7068 UpdateFrees();
7069
7070 // TODO: Allow multi exit functions that have different free calls.
7071 if (AI.PotentialFreeCalls.size() != 1) {
7072 LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "
7073 << AI.PotentialFreeCalls.size() << "\n");
7074 return false;
7075 }
7076 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7077 DeallocationInfo *DI = DeallocationInfos.lookup(Key: UniqueFree);
7078 if (!DI) {
7079 LLVM_DEBUG(
7080 dbgs() << "[H2S] unique free call was not known as deallocation call "
7081 << *UniqueFree << "\n");
7082 return false;
7083 }
7084 if (DI->MightFreeUnknownObjects) {
7085 LLVM_DEBUG(
7086 dbgs() << "[H2S] unique free call might free unknown allocations\n");
7087 return false;
7088 }
7089 if (DI->PotentialAllocationCalls.empty())
7090 return true;
7091 if (DI->PotentialAllocationCalls.size() > 1) {
7092 LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "
7093 << DI->PotentialAllocationCalls.size()
7094 << " different allocations\n");
7095 return false;
7096 }
7097 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7098 LLVM_DEBUG(
7099 dbgs()
7100 << "[H2S] unique free call not known to free this allocation but "
7101 << **DI->PotentialAllocationCalls.begin() << "\n");
7102 return false;
7103 }
7104
7105 // __kmpc_alloc_shared and __kmpc_free_shared are by construction matched.
7106 if (!AI.IsGlobalizedLocal) {
7107 Instruction *CtxI = isa<InvokeInst>(Val: AI.CB) ? AI.CB : AI.CB->getNextNode();
7108 if (!Explorer || !Explorer->findInContextOf(I: UniqueFree, PP: CtxI)) {
7109 LLVM_DEBUG(dbgs() << "[H2S] unique free call might not be executed "
7110 "with the allocation "
7111 << *UniqueFree << "\n");
7112 return false;
7113 }
7114 }
7115 return true;
7116 };
7117
7118 auto UsesCheck = [&](AllocationInfo &AI) {
7119 bool ValidUsesOnly = true;
7120
7121 auto Pred = [&](const Use &U, bool &Follow) -> bool {
7122 Instruction *UserI = cast<Instruction>(Val: U.getUser());
7123 if (isa<LoadInst>(Val: UserI))
7124 return true;
7125 if (auto *SI = dyn_cast<StoreInst>(Val: UserI)) {
7126 if (SI->getValueOperand() == U.get()) {
7127 LLVM_DEBUG(dbgs()
7128 << "[H2S] escaping store to memory: " << *UserI << "\n");
7129 ValidUsesOnly = false;
7130 } else {
7131 // A store into the malloc'ed memory is fine.
7132 }
7133 return true;
7134 }
7135 if (auto *CB = dyn_cast<CallBase>(Val: UserI)) {
7136 if (!CB->isArgOperand(U: &U) || CB->isLifetimeStartOrEnd())
7137 return true;
7138 if (DeallocationInfos.count(Key: CB)) {
7139 AI.PotentialFreeCalls.insert(X: CB);
7140 return true;
7141 }
7142
7143 unsigned ArgNo = CB->getArgOperandNo(U: &U);
7144 auto CBIRP = IRPosition::callsite_argument(CB: *CB, ArgNo);
7145
7146 bool IsKnownNoCapture;
7147 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7148 A, QueryingAA: this, IRP: CBIRP, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoCapture);
7149
7150 // If a call site argument use is nofree, we are fine.
7151 bool IsKnownNoFree;
7152 bool IsAssumedNoFree = AA::hasAssumedIRAttr<Attribute::NoFree>(
7153 A, QueryingAA: this, IRP: CBIRP, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoFree);
7154
7155 if (!IsAssumedNoCapture ||
7156 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7157 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7158
7159 // Emit a missed remark if this is missed OpenMP globalization.
7160 auto Remark = [&](OptimizationRemarkMissed ORM) {
7161 return ORM
7162 << "Could not move globalized variable to the stack. "
7163 "Variable is potentially captured in call. Mark "
7164 "parameter as `__attribute__((noescape))` to override.";
7165 };
7166
7167 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7168 A.emitRemark<OptimizationRemarkMissed>(I: CB, RemarkName: "OMP113", RemarkCB&: Remark);
7169
7170 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
7171 ValidUsesOnly = false;
7172 }
7173 return true;
7174 }
7175
7176 if (isa<GetElementPtrInst>(Val: UserI) || isa<BitCastInst>(Val: UserI) ||
7177 isa<PHINode>(Val: UserI) || isa<SelectInst>(Val: UserI)) {
7178 Follow = true;
7179 return true;
7180 }
7181 // Unknown user for which we can not track uses further (in a way that
7182 // makes sense).
7183 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
7184 ValidUsesOnly = false;
7185 return true;
7186 };
7187 if (!A.checkForAllUses(Pred, QueryingAA: *this, V: *AI.CB, /* CheckBBLivenessOnly */ false,
7188 LivenessDepClass: DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,
7189 EquivalentUseCB: [&](const Use &OldU, const Use &NewU) {
7190 auto *SI = dyn_cast<StoreInst>(Val: OldU.getUser());
7191 return !SI || StackIsAccessibleByOtherThreads ||
7192 AA::isAssumedThreadLocalObject(
7193 A, Obj&: *SI->getPointerOperand(), QueryingAA: *this);
7194 }))
7195 return false;
7196 return ValidUsesOnly;
7197 };
7198
7199 // The actual update starts here. We look at all allocations and depending on
7200 // their status perform the appropriate check(s).
7201 for (auto &It : AllocationInfos) {
7202 AllocationInfo &AI = *It.second;
7203 if (AI.Status == AllocationInfo::INVALID)
7204 continue;
7205
7206 if (Value *Align = getAllocAlignment(V: AI.CB, TLI)) {
7207 std::optional<APInt> APAlign = getAPInt(A, AA: *this, V&: *Align);
7208 if (!APAlign) {
7209 // Can't generate an alloca which respects the required alignment
7210 // on the allocation.
7211 LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB
7212 << "\n");
7213 AI.Status = AllocationInfo::INVALID;
7214 Changed = ChangeStatus::CHANGED;
7215 continue;
7216 }
7217 if (APAlign->ugt(RHS: llvm::Value::MaximumAlignment) ||
7218 !APAlign->isPowerOf2()) {
7219 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign
7220 << "\n");
7221 AI.Status = AllocationInfo::INVALID;
7222 Changed = ChangeStatus::CHANGED;
7223 continue;
7224 }
7225 }
7226
7227 std::optional<APInt> Size = getSize(A, AA: *this, AI);
7228 if (!AI.IsGlobalizedLocal && MaxHeapToStackSize != -1) {
7229 if (!Size || Size->ugt(RHS: MaxHeapToStackSize)) {
7230 LLVM_DEBUG({
7231 if (!Size)
7232 dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";
7233 else
7234 dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "
7235 << MaxHeapToStackSize << "\n";
7236 });
7237
7238 AI.Status = AllocationInfo::INVALID;
7239 Changed = ChangeStatus::CHANGED;
7240 continue;
7241 }
7242 }
7243
7244 switch (AI.Status) {
7245 case AllocationInfo::STACK_DUE_TO_USE:
7246 if (UsesCheck(AI))
7247 break;
7248 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7249 [[fallthrough]];
7250 case AllocationInfo::STACK_DUE_TO_FREE:
7251 if (FreeCheck(AI))
7252 break;
7253 AI.Status = AllocationInfo::INVALID;
7254 Changed = ChangeStatus::CHANGED;
7255 break;
7256 case AllocationInfo::INVALID:
7257 llvm_unreachable("Invalid allocations should never reach this point!");
7258 };
7259
7260 // Check if we still think we can move it into the entry block. If the
7261 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7262 // ignore the potential complications associated with loops.
7263 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7264 if (AI.MoveAllocaIntoEntry &&
7265 (!Size.has_value() ||
7266 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7267 AI.MoveAllocaIntoEntry = false;
7268 }
7269
7270 return Changed;
7271}
7272} // namespace
7273
7274/// ----------------------- Privatizable Pointers ------------------------------
7275namespace {
7276struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
7277 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7278 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7279
7280 ChangeStatus indicatePessimisticFixpoint() override {
7281 AAPrivatizablePtr::indicatePessimisticFixpoint();
7282 PrivatizableType = nullptr;
7283 return ChangeStatus::CHANGED;
7284 }
7285
7286 /// Identify the type we can chose for a private copy of the underlying
7287 /// argument. std::nullopt means it is not clear yet, nullptr means there is
7288 /// none.
7289 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7290
7291 /// Return a privatizable type that encloses both T0 and T1.
7292 /// TODO: This is merely a stub for now as we should manage a mapping as well.
7293 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7294 std::optional<Type *> T1) {
7295 if (!T0)
7296 return T1;
7297 if (!T1)
7298 return T0;
7299 if (T0 == T1)
7300 return T0;
7301 return nullptr;
7302 }
7303
7304 std::optional<Type *> getPrivatizableType() const override {
7305 return PrivatizableType;
7306 }
7307
7308 const std::string getAsStr(Attributor *A) const override {
7309 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7310 }
7311
7312protected:
7313 std::optional<Type *> PrivatizableType;
7314};
7315
7316// TODO: Do this for call site arguments (probably also other values) as well.
7317
7318struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
7319 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7320 : AAPrivatizablePtrImpl(IRP, A) {}
7321
7322 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7323 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7324 // If this is a byval argument and we know all the call sites (so we can
7325 // rewrite them), there is no need to check them explicitly.
7326 bool UsedAssumedInformation = false;
7327 SmallVector<Attribute, 1> Attrs;
7328 A.getAttrs(IRP: getIRPosition(), AKs: {Attribute::ByVal}, Attrs,
7329 /* IgnoreSubsumingPositions */ true);
7330 if (!Attrs.empty() &&
7331 A.checkForAllCallSites(Pred: [](AbstractCallSite ACS) { return true; }, QueryingAA: *this,
7332 RequireAllCallSites: true, UsedAssumedInformation))
7333 return Attrs[0].getValueAsType();
7334
7335 std::optional<Type *> Ty;
7336 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7337
7338 // Make sure the associated call site argument has the same type at all call
7339 // sites and it is an allocation we know is safe to privatize, for now that
7340 // means we only allow alloca instructions.
7341 // TODO: We can additionally analyze the accesses in the callee to create
7342 // the type from that information instead. That is a little more
7343 // involved and will be done in a follow up patch.
7344 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7345 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7346 // Check if a coresponding argument was found or if it is one not
7347 // associated (which can happen for callback calls).
7348 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7349 return false;
7350
7351 // Check that all call sites agree on a type.
7352 auto *PrivCSArgAA =
7353 A.getAAFor<AAPrivatizablePtr>(QueryingAA: *this, IRP: ACSArgPos, DepClass: DepClassTy::REQUIRED);
7354 if (!PrivCSArgAA)
7355 return false;
7356 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7357
7358 LLVM_DEBUG({
7359 dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
7360 if (CSTy && *CSTy)
7361 (*CSTy)->print(dbgs());
7362 else if (CSTy)
7363 dbgs() << "<nullptr>";
7364 else
7365 dbgs() << "<none>";
7366 });
7367
7368 Ty = combineTypes(T0: Ty, T1: CSTy);
7369
7370 LLVM_DEBUG({
7371 dbgs() << " : New Type: ";
7372 if (Ty && *Ty)
7373 (*Ty)->print(dbgs());
7374 else if (Ty)
7375 dbgs() << "<nullptr>";
7376 else
7377 dbgs() << "<none>";
7378 dbgs() << "\n";
7379 });
7380
7381 return !Ty || *Ty;
7382 };
7383
7384 if (!A.checkForAllCallSites(Pred: CallSiteCheck, QueryingAA: *this, RequireAllCallSites: true,
7385 UsedAssumedInformation))
7386 return nullptr;
7387 return Ty;
7388 }
7389
7390 /// See AbstractAttribute::updateImpl(...).
7391 ChangeStatus updateImpl(Attributor &A) override {
7392 PrivatizableType = identifyPrivatizableType(A);
7393 if (!PrivatizableType)
7394 return ChangeStatus::UNCHANGED;
7395 if (!*PrivatizableType)
7396 return indicatePessimisticFixpoint();
7397
7398 // The dependence is optional so we don't give up once we give up on the
7399 // alignment.
7400 A.getAAFor<AAAlign>(QueryingAA: *this, IRP: IRPosition::value(V: getAssociatedValue()),
7401 DepClass: DepClassTy::OPTIONAL);
7402
7403 // Avoid arguments with padding for now.
7404 if (!A.hasAttr(IRP: getIRPosition(), AKs: Attribute::ByVal) &&
7405 !isDenselyPacked(Ty: *PrivatizableType, DL: A.getInfoCache().getDL())) {
7406 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
7407 return indicatePessimisticFixpoint();
7408 }
7409
7410 // Collect the types that will replace the privatizable type in the function
7411 // signature.
7412 SmallVector<Type *, 16> ReplacementTypes;
7413 identifyReplacementTypes(PrivType: *PrivatizableType, ReplacementTypes);
7414
7415 // Verify callee and caller agree on how the promoted argument would be
7416 // passed.
7417 Function &Fn = *getIRPosition().getAnchorScope();
7418 const auto *TTI =
7419 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(F: Fn);
7420 if (!TTI) {
7421 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
7422 << Fn.getName() << "\n");
7423 return indicatePessimisticFixpoint();
7424 }
7425
7426 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7427 CallBase *CB = ACS.getInstruction();
7428 return TTI->areTypesABICompatible(
7429 Caller: CB->getCaller(),
7430 Callee: dyn_cast_if_present<Function>(Val: CB->getCalledOperand()),
7431 Types: ReplacementTypes);
7432 };
7433 bool UsedAssumedInformation = false;
7434 if (!A.checkForAllCallSites(Pred: CallSiteCheck, QueryingAA: *this, RequireAllCallSites: true,
7435 UsedAssumedInformation)) {
7436 LLVM_DEBUG(
7437 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
7438 << Fn.getName() << "\n");
7439 return indicatePessimisticFixpoint();
7440 }
7441
7442 // Register a rewrite of the argument.
7443 Argument *Arg = getAssociatedArgument();
7444 if (!A.isValidFunctionSignatureRewrite(Arg&: *Arg, ReplacementTypes)) {
7445 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");
7446 return indicatePessimisticFixpoint();
7447 }
7448
7449 unsigned ArgNo = Arg->getArgNo();
7450
7451 // Helper to check if for the given call site the associated argument is
7452 // passed to a callback where the privatization would be different.
7453 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7454 SmallVector<const Use *, 4> CallbackUses;
7455 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7456 for (const Use *U : CallbackUses) {
7457 AbstractCallSite CBACS(U);
7458 assert(CBACS && CBACS.isCallbackCall());
7459 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7460 int CBArgNo = CBACS.getCallArgOperandNo(Arg&: CBArg);
7461
7462 LLVM_DEBUG({
7463 dbgs()
7464 << "[AAPrivatizablePtr] Argument " << *Arg
7465 << "check if can be privatized in the context of its parent ("
7466 << Arg->getParent()->getName()
7467 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7468 "callback ("
7469 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7470 << ")\n[AAPrivatizablePtr] " << CBArg << " : "
7471 << CBACS.getCallArgOperand(CBArg) << " vs "
7472 << CB.getArgOperand(ArgNo) << "\n"
7473 << "[AAPrivatizablePtr] " << CBArg << " : "
7474 << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";
7475 });
7476
7477 if (CBArgNo != int(ArgNo))
7478 continue;
7479 const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7480 QueryingAA: *this, IRP: IRPosition::argument(Arg: CBArg), DepClass: DepClassTy::REQUIRED);
7481 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7482 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7483 if (!CBArgPrivTy)
7484 continue;
7485 if (*CBArgPrivTy == PrivatizableType)
7486 continue;
7487 }
7488
7489 LLVM_DEBUG({
7490 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7491 << " cannot be privatized in the context of its parent ("
7492 << Arg->getParent()->getName()
7493 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7494 "callback ("
7495 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7496 << ").\n[AAPrivatizablePtr] for which the argument "
7497 "privatization is not compatible.\n";
7498 });
7499 return false;
7500 }
7501 }
7502 return true;
7503 };
7504
7505 // Helper to check if for the given call site the associated argument is
7506 // passed to a direct call where the privatization would be different.
7507 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7508 CallBase *DC = cast<CallBase>(Val: ACS.getInstruction());
7509 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7510 assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&
7511 "Expected a direct call operand for callback call operand");
7512
7513 Function *DCCallee =
7514 dyn_cast_if_present<Function>(Val: DC->getCalledOperand());
7515 LLVM_DEBUG({
7516 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7517 << " check if be privatized in the context of its parent ("
7518 << Arg->getParent()->getName()
7519 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7520 "direct call of ("
7521 << DCArgNo << "@" << DCCallee->getName() << ").\n";
7522 });
7523
7524 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7525 const auto *DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7526 QueryingAA: *this, IRP: IRPosition::argument(Arg: *DCCallee->getArg(i: DCArgNo)),
7527 DepClass: DepClassTy::REQUIRED);
7528 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7529 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7530 if (!DCArgPrivTy)
7531 return true;
7532 if (*DCArgPrivTy == PrivatizableType)
7533 return true;
7534 }
7535 }
7536
7537 LLVM_DEBUG({
7538 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7539 << " cannot be privatized in the context of its parent ("
7540 << Arg->getParent()->getName()
7541 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7542 "direct call of ("
7543 << ACS.getInstruction()->getCalledOperand()->getName()
7544 << ").\n[AAPrivatizablePtr] for which the argument "
7545 "privatization is not compatible.\n";
7546 });
7547 return false;
7548 };
7549
7550 // Helper to check if the associated argument is used at the given abstract
7551 // call site in a way that is incompatible with the privatization assumed
7552 // here.
7553 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7554 if (ACS.isDirectCall())
7555 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7556 if (ACS.isCallbackCall())
7557 return IsCompatiblePrivArgOfDirectCS(ACS);
7558 return false;
7559 };
7560
7561 if (!A.checkForAllCallSites(Pred: IsCompatiblePrivArgOfOtherCallSite, QueryingAA: *this, RequireAllCallSites: true,
7562 UsedAssumedInformation))
7563 return indicatePessimisticFixpoint();
7564
7565 return ChangeStatus::UNCHANGED;
7566 }
7567
7568 /// Given a type to private \p PrivType, collect the constituates (which are
7569 /// used) in \p ReplacementTypes.
7570 static void
7571 identifyReplacementTypes(Type *PrivType,
7572 SmallVectorImpl<Type *> &ReplacementTypes) {
7573 // TODO: For now we expand the privatization type to the fullest which can
7574 // lead to dead arguments that need to be removed later.
7575 assert(PrivType && "Expected privatizable type!");
7576
7577 // Traverse the type, extract constituate types on the outermost level.
7578 if (auto *PrivStructType = dyn_cast<StructType>(Val: PrivType)) {
7579 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7580 ReplacementTypes.push_back(Elt: PrivStructType->getElementType(N: u));
7581 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(Val: PrivType)) {
7582 ReplacementTypes.append(NumInputs: PrivArrayType->getNumElements(),
7583 Elt: PrivArrayType->getElementType());
7584 } else {
7585 ReplacementTypes.push_back(Elt: PrivType);
7586 }
7587 }
7588
7589 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7590 /// The values needed are taken from the arguments of \p F starting at
7591 /// position \p ArgNo.
7592 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7593 unsigned ArgNo, BasicBlock::iterator IP) {
7594 assert(PrivType && "Expected privatizable type!");
7595
7596 IRBuilder<NoFolder> IRB(IP->getParent(), IP);
7597 const DataLayout &DL = F.getDataLayout();
7598
7599 // Traverse the type, build GEPs and stores.
7600 if (auto *PrivStructType = dyn_cast<StructType>(Val: PrivType)) {
7601 const StructLayout *PrivStructLayout = DL.getStructLayout(Ty: PrivStructType);
7602 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7603 Value *Ptr =
7604 constructPointer(Ptr: &Base, Offset: PrivStructLayout->getElementOffset(Idx: u), IRB);
7605 new StoreInst(F.getArg(i: ArgNo + u), Ptr, IP);
7606 }
7607 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(Val: PrivType)) {
7608 Type *PointeeTy = PrivArrayType->getElementType();
7609 uint64_t PointeeTySize = DL.getTypeStoreSize(Ty: PointeeTy);
7610 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7611 Value *Ptr = constructPointer(Ptr: &Base, Offset: u * PointeeTySize, IRB);
7612 new StoreInst(F.getArg(i: ArgNo + u), Ptr, IP);
7613 }
7614 } else {
7615 new StoreInst(F.getArg(i: ArgNo), &Base, IP);
7616 }
7617 }
7618
7619 /// Extract values from \p Base according to the type \p PrivType at the
7620 /// call position \p ACS. The values are appended to \p ReplacementValues.
7621 void createReplacementValues(Align Alignment, Type *PrivType,
7622 AbstractCallSite ACS, Value *Base,
7623 SmallVectorImpl<Value *> &ReplacementValues) {
7624 assert(Base && "Expected base value!");
7625 assert(PrivType && "Expected privatizable type!");
7626 Instruction *IP = ACS.getInstruction();
7627
7628 IRBuilder<NoFolder> IRB(IP);
7629 const DataLayout &DL = IP->getDataLayout();
7630
7631 // Traverse the type, build GEPs and loads.
7632 if (auto *PrivStructType = dyn_cast<StructType>(Val: PrivType)) {
7633 const StructLayout *PrivStructLayout = DL.getStructLayout(Ty: PrivStructType);
7634 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7635 Type *PointeeTy = PrivStructType->getElementType(N: u);
7636 Value *Ptr =
7637 constructPointer(Ptr: Base, Offset: PrivStructLayout->getElementOffset(Idx: u), IRB);
7638 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7639 L->setAlignment(Alignment);
7640 ReplacementValues.push_back(Elt: L);
7641 }
7642 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(Val: PrivType)) {
7643 Type *PointeeTy = PrivArrayType->getElementType();
7644 uint64_t PointeeTySize = DL.getTypeStoreSize(Ty: PointeeTy);
7645 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7646 Value *Ptr = constructPointer(Ptr: Base, Offset: u * PointeeTySize, IRB);
7647 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7648 L->setAlignment(Alignment);
7649 ReplacementValues.push_back(Elt: L);
7650 }
7651 } else {
7652 LoadInst *L = new LoadInst(PrivType, Base, "", IP->getIterator());
7653 L->setAlignment(Alignment);
7654 ReplacementValues.push_back(Elt: L);
7655 }
7656 }
7657
7658 /// See AbstractAttribute::manifest(...)
7659 ChangeStatus manifest(Attributor &A) override {
7660 if (!PrivatizableType)
7661 return ChangeStatus::UNCHANGED;
7662 assert(*PrivatizableType && "Expected privatizable type!");
7663
7664 // Collect all tail calls in the function as we cannot allow new allocas to
7665 // escape into tail recursion.
7666 // TODO: Be smarter about new allocas escaping into tail calls.
7667 SmallVector<CallInst *, 16> TailCalls;
7668 bool UsedAssumedInformation = false;
7669 if (!A.checkForAllInstructions(
7670 Pred: [&](Instruction &I) {
7671 CallInst &CI = cast<CallInst>(Val&: I);
7672 if (CI.isTailCall())
7673 TailCalls.push_back(Elt: &CI);
7674 return true;
7675 },
7676 QueryingAA: *this, Opcodes: {Instruction::Call}, UsedAssumedInformation))
7677 return ChangeStatus::UNCHANGED;
7678
7679 Argument *Arg = getAssociatedArgument();
7680 // Query AAAlign attribute for alignment of associated argument to
7681 // determine the best alignment of loads.
7682 const auto *AlignAA =
7683 A.getAAFor<AAAlign>(QueryingAA: *this, IRP: IRPosition::value(V: *Arg), DepClass: DepClassTy::NONE);
7684
7685 // Callback to repair the associated function. A new alloca is placed at the
7686 // beginning and initialized with the values passed through arguments. The
7687 // new alloca replaces the use of the old pointer argument.
7688 Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB =
7689 [=](const Attributor::ArgumentReplacementInfo &ARI,
7690 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7691 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7692 BasicBlock::iterator IP = EntryBB.getFirstInsertionPt();
7693 const DataLayout &DL = IP->getDataLayout();
7694 unsigned AS = DL.getAllocaAddrSpace();
7695 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7696 Arg->getName() + ".priv", IP);
7697 createInitialization(PrivType: *PrivatizableType, Base&: *AI, F&: ReplacementFn,
7698 ArgNo: ArgIt->getArgNo(), IP);
7699
7700 if (AI->getType() != Arg->getType())
7701 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7702 S: AI, Ty: Arg->getType(), Name: "", InsertBefore: IP);
7703 Arg->replaceAllUsesWith(V: AI);
7704
7705 for (CallInst *CI : TailCalls)
7706 CI->setTailCall(false);
7707 };
7708
7709 // Callback to repair a call site of the associated function. The elements
7710 // of the privatizable type are loaded prior to the call and passed to the
7711 // new function version.
7712 Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB =
7713 [=](const Attributor::ArgumentReplacementInfo &ARI,
7714 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7715 // When no alignment is specified for the load instruction,
7716 // natural alignment is assumed.
7717 createReplacementValues(
7718 Alignment: AlignAA ? AlignAA->getAssumedAlign() : Align(0),
7719 PrivType: *PrivatizableType, ACS,
7720 Base: ACS.getCallArgOperand(ArgNo: ARI.getReplacedArg().getArgNo()),
7721 ReplacementValues&: NewArgOperands);
7722 };
7723
7724 // Collect the types that will replace the privatizable type in the function
7725 // signature.
7726 SmallVector<Type *, 16> ReplacementTypes;
7727 identifyReplacementTypes(PrivType: *PrivatizableType, ReplacementTypes);
7728
7729 // Register a rewrite of the argument.
7730 if (A.registerFunctionSignatureRewrite(Arg&: *Arg, ReplacementTypes,
7731 CalleeRepairCB: std::move(FnRepairCB),
7732 ACSRepairCB: std::move(ACSRepairCB)))
7733 return ChangeStatus::CHANGED;
7734 return ChangeStatus::UNCHANGED;
7735 }
7736
7737 /// See AbstractAttribute::trackStatistics()
7738 void trackStatistics() const override {
7739 STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);
7740 }
7741};
7742
7743struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
7744 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7745 : AAPrivatizablePtrImpl(IRP, A) {}
7746
7747 /// See AbstractAttribute::initialize(...).
7748 void initialize(Attributor &A) override {
7749 // TODO: We can privatize more than arguments.
7750 indicatePessimisticFixpoint();
7751 }
7752
7753 ChangeStatus updateImpl(Attributor &A) override {
7754 llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
7755 "updateImpl will not be called");
7756 }
7757
7758 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7759 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7760 Value *Obj = getUnderlyingObject(V: &getAssociatedValue());
7761 if (!Obj) {
7762 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
7763 return nullptr;
7764 }
7765
7766 if (auto *AI = dyn_cast<AllocaInst>(Val: Obj))
7767 if (auto *CI = dyn_cast<ConstantInt>(Val: AI->getArraySize()))
7768 if (CI->isOne())
7769 return AI->getAllocatedType();
7770 if (auto *Arg = dyn_cast<Argument>(Val: Obj)) {
7771 auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7772 QueryingAA: *this, IRP: IRPosition::argument(Arg: *Arg), DepClass: DepClassTy::REQUIRED);
7773 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7774 return PrivArgAA->getPrivatizableType();
7775 }
7776
7777 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
7778 "alloca nor privatizable argument: "
7779 << *Obj << "!\n");
7780 return nullptr;
7781 }
7782
7783 /// See AbstractAttribute::trackStatistics()
7784 void trackStatistics() const override {
7785 STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);
7786 }
7787};
7788
7789struct AAPrivatizablePtrCallSiteArgument final
7790 : public AAPrivatizablePtrFloating {
7791 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7792 : AAPrivatizablePtrFloating(IRP, A) {}
7793
7794 /// See AbstractAttribute::initialize(...).
7795 void initialize(Attributor &A) override {
7796 if (A.hasAttr(IRP: getIRPosition(), AKs: Attribute::ByVal))
7797 indicateOptimisticFixpoint();
7798 }
7799
7800 /// See AbstractAttribute::updateImpl(...).
7801 ChangeStatus updateImpl(Attributor &A) override {
7802 PrivatizableType = identifyPrivatizableType(A);
7803 if (!PrivatizableType)
7804 return ChangeStatus::UNCHANGED;
7805 if (!*PrivatizableType)
7806 return indicatePessimisticFixpoint();
7807
7808 const IRPosition &IRP = getIRPosition();
7809 bool IsKnownNoCapture;
7810 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7811 A, QueryingAA: this, IRP, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoCapture);
7812 if (!IsAssumedNoCapture) {
7813 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");
7814 return indicatePessimisticFixpoint();
7815 }
7816
7817 bool IsKnownNoAlias;
7818 if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(
7819 A, QueryingAA: this, IRP, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoAlias)) {
7820 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");
7821 return indicatePessimisticFixpoint();
7822 }
7823
7824 bool IsKnown;
7825 if (!AA::isAssumedReadOnly(A, IRP, QueryingAA: *this, IsKnown)) {
7826 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");
7827 return indicatePessimisticFixpoint();
7828 }
7829
7830 return ChangeStatus::UNCHANGED;
7831 }
7832
7833 /// See AbstractAttribute::trackStatistics()
7834 void trackStatistics() const override {
7835 STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);
7836 }
7837};
7838
7839struct AAPrivatizablePtrCallSiteReturned final
7840 : public AAPrivatizablePtrFloating {
7841 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7842 : AAPrivatizablePtrFloating(IRP, A) {}
7843
7844 /// See AbstractAttribute::initialize(...).
7845 void initialize(Attributor &A) override {
7846 // TODO: We can privatize more than arguments.
7847 indicatePessimisticFixpoint();
7848 }
7849
7850 /// See AbstractAttribute::trackStatistics()
7851 void trackStatistics() const override {
7852 STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);
7853 }
7854};
7855
7856struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
7857 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7858 : AAPrivatizablePtrFloating(IRP, A) {}
7859
7860 /// See AbstractAttribute::initialize(...).
7861 void initialize(Attributor &A) override {
7862 // TODO: We can privatize more than arguments.
7863 indicatePessimisticFixpoint();
7864 }
7865
7866 /// See AbstractAttribute::trackStatistics()
7867 void trackStatistics() const override {
7868 STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);
7869 }
7870};
7871} // namespace
7872
7873/// -------------------- Memory Behavior Attributes ----------------------------
7874/// Includes read-none, read-only, and write-only.
7875/// ----------------------------------------------------------------------------
7876namespace {
7877struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
7878 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7879 : AAMemoryBehavior(IRP, A) {}
7880
7881 /// See AbstractAttribute::initialize(...).
7882 void initialize(Attributor &A) override {
7883 intersectAssumedBits(BitsEncoding: BEST_STATE);
7884 getKnownStateFromValue(A, IRP: getIRPosition(), State&: getState());
7885 AAMemoryBehavior::initialize(A);
7886 }
7887
7888 /// Return the memory behavior information encoded in the IR for \p IRP.
7889 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
7890 BitIntegerState &State,
7891 bool IgnoreSubsumingPositions = false) {
7892 SmallVector<Attribute, 2> Attrs;
7893 A.getAttrs(IRP, AKs: AttrKinds, Attrs, IgnoreSubsumingPositions);
7894 for (const Attribute &Attr : Attrs) {
7895 switch (Attr.getKindAsEnum()) {
7896 case Attribute::ReadNone:
7897 State.addKnownBits(Bits: NO_ACCESSES);
7898 break;
7899 case Attribute::ReadOnly:
7900 State.addKnownBits(Bits: NO_WRITES);
7901 break;
7902 case Attribute::WriteOnly:
7903 State.addKnownBits(Bits: NO_READS);
7904 break;
7905 default:
7906 llvm_unreachable("Unexpected attribute!");
7907 }
7908 }
7909
7910 if (auto *I = dyn_cast<Instruction>(Val: &IRP.getAnchorValue())) {
7911 if (!I->mayReadFromMemory())
7912 State.addKnownBits(Bits: NO_READS);
7913 if (!I->mayWriteToMemory())
7914 State.addKnownBits(Bits: NO_WRITES);
7915 }
7916 }
7917
7918 /// See AbstractAttribute::getDeducedAttributes(...).
7919 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
7920 SmallVectorImpl<Attribute> &Attrs) const override {
7921 assert(Attrs.size() == 0);
7922 if (isAssumedReadNone())
7923 Attrs.push_back(Elt: Attribute::get(Context&: Ctx, Kind: Attribute::ReadNone));
7924 else if (isAssumedReadOnly())
7925 Attrs.push_back(Elt: Attribute::get(Context&: Ctx, Kind: Attribute::ReadOnly));
7926 else if (isAssumedWriteOnly())
7927 Attrs.push_back(Elt: Attribute::get(Context&: Ctx, Kind: Attribute::WriteOnly));
7928 assert(Attrs.size() <= 1);
7929 }
7930
7931 /// See AbstractAttribute::manifest(...).
7932 ChangeStatus manifest(Attributor &A) override {
7933 const IRPosition &IRP = getIRPosition();
7934
7935 if (A.hasAttr(IRP, AKs: Attribute::ReadNone,
7936 /* IgnoreSubsumingPositions */ true))
7937 return ChangeStatus::UNCHANGED;
7938
7939 // Check if we would improve the existing attributes first.
7940 SmallVector<Attribute, 4> DeducedAttrs;
7941 getDeducedAttributes(A, Ctx&: IRP.getAnchorValue().getContext(), Attrs&: DeducedAttrs);
7942 if (llvm::all_of(Range&: DeducedAttrs, P: [&](const Attribute &Attr) {
7943 return A.hasAttr(IRP, AKs: Attr.getKindAsEnum(),
7944 /* IgnoreSubsumingPositions */ true);
7945 }))
7946 return ChangeStatus::UNCHANGED;
7947
7948 // Clear existing attributes.
7949 A.removeAttrs(IRP, AttrKinds);
7950 // Clear conflicting writable attribute.
7951 if (isAssumedReadOnly())
7952 A.removeAttrs(IRP, AttrKinds: Attribute::Writable);
7953
7954 // Use the generic manifest method.
7955 return IRAttribute::manifest(A);
7956 }
7957
7958 /// See AbstractState::getAsStr().
7959 const std::string getAsStr(Attributor *A) const override {
7960 if (isAssumedReadNone())
7961 return "readnone";
7962 if (isAssumedReadOnly())
7963 return "readonly";
7964 if (isAssumedWriteOnly())
7965 return "writeonly";
7966 return "may-read/write";
7967 }
7968
7969 /// The set of IR attributes AAMemoryBehavior deals with.
7970 static const Attribute::AttrKind AttrKinds[3];
7971};
7972
7973const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7974 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7975
7976/// Memory behavior attribute for a floating value.
7977struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7978 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7979 : AAMemoryBehaviorImpl(IRP, A) {}
7980
7981 /// See AbstractAttribute::updateImpl(...).
7982 ChangeStatus updateImpl(Attributor &A) override;
7983
7984 /// See AbstractAttribute::trackStatistics()
7985 void trackStatistics() const override {
7986 if (isAssumedReadNone())
7987 STATS_DECLTRACK_FLOATING_ATTR(readnone)
7988 else if (isAssumedReadOnly())
7989 STATS_DECLTRACK_FLOATING_ATTR(readonly)
7990 else if (isAssumedWriteOnly())
7991 STATS_DECLTRACK_FLOATING_ATTR(writeonly)
7992 }
7993
7994private:
7995 /// Return true if users of \p UserI might access the underlying
7996 /// variable/location described by \p U and should therefore be analyzed.
7997 bool followUsersOfUseIn(Attributor &A, const Use &U,
7998 const Instruction *UserI);
7999
8000 /// Update the state according to the effect of use \p U in \p UserI.
8001 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
8002};
8003
8004/// Memory behavior attribute for function argument.
8005struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8006 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
8007 : AAMemoryBehaviorFloating(IRP, A) {}
8008
8009 /// See AbstractAttribute::initialize(...).
8010 void initialize(Attributor &A) override {
8011 intersectAssumedBits(BitsEncoding: BEST_STATE);
8012 const IRPosition &IRP = getIRPosition();
8013 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
8014 // can query it when we use has/getAttr. That would allow us to reuse the
8015 // initialize of the base class here.
8016 bool HasByVal = A.hasAttr(IRP, AKs: {Attribute::ByVal},
8017 /* IgnoreSubsumingPositions */ true);
8018 getKnownStateFromValue(A, IRP, State&: getState(),
8019 /* IgnoreSubsumingPositions */ HasByVal);
8020 }
8021
8022 ChangeStatus manifest(Attributor &A) override {
8023 // TODO: Pointer arguments are not supported on vectors of pointers yet.
8024 if (!getAssociatedValue().getType()->isPointerTy())
8025 return ChangeStatus::UNCHANGED;
8026
8027 // TODO: From readattrs.ll: "inalloca parameters are always
8028 // considered written"
8029 if (A.hasAttr(IRP: getIRPosition(),
8030 AKs: {Attribute::InAlloca, Attribute::Preallocated})) {
8031 removeKnownBits(BitsEncoding: NO_WRITES);
8032 removeAssumedBits(BitsEncoding: NO_WRITES);
8033 }
8034 A.removeAttrs(IRP: getIRPosition(), AttrKinds);
8035 return AAMemoryBehaviorFloating::manifest(A);
8036 }
8037
8038 /// See AbstractAttribute::trackStatistics()
8039 void trackStatistics() const override {
8040 if (isAssumedReadNone())
8041 STATS_DECLTRACK_ARG_ATTR(readnone)
8042 else if (isAssumedReadOnly())
8043 STATS_DECLTRACK_ARG_ATTR(readonly)
8044 else if (isAssumedWriteOnly())
8045 STATS_DECLTRACK_ARG_ATTR(writeonly)
8046 }
8047};
8048
8049struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8050 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
8051 : AAMemoryBehaviorArgument(IRP, A) {}
8052
8053 /// See AbstractAttribute::initialize(...).
8054 void initialize(Attributor &A) override {
8055 // If we don't have an associated attribute this is either a variadic call
8056 // or an indirect call, either way, nothing to do here.
8057 Argument *Arg = getAssociatedArgument();
8058 if (!Arg) {
8059 indicatePessimisticFixpoint();
8060 return;
8061 }
8062 if (Arg->hasByValAttr()) {
8063 addKnownBits(Bits: NO_WRITES);
8064 removeKnownBits(BitsEncoding: NO_READS);
8065 removeAssumedBits(BitsEncoding: NO_READS);
8066 }
8067 AAMemoryBehaviorArgument::initialize(A);
8068 if (getAssociatedFunction()->isDeclaration())
8069 indicatePessimisticFixpoint();
8070 }
8071
8072 /// See AbstractAttribute::updateImpl(...).
8073 ChangeStatus updateImpl(Attributor &A) override {
8074 // TODO: Once we have call site specific value information we can provide
8075 // call site specific liveness liveness information and then it makes
8076 // sense to specialize attributes for call sites arguments instead of
8077 // redirecting requests to the callee argument.
8078 Argument *Arg = getAssociatedArgument();
8079 const IRPosition &ArgPos = IRPosition::argument(Arg: *Arg);
8080 auto *ArgAA =
8081 A.getAAFor<AAMemoryBehavior>(QueryingAA: *this, IRP: ArgPos, DepClass: DepClassTy::REQUIRED);
8082 if (!ArgAA)
8083 return indicatePessimisticFixpoint();
8084 return clampStateAndIndicateChange(S&: getState(), R: ArgAA->getState());
8085 }
8086
8087 /// See AbstractAttribute::trackStatistics()
8088 void trackStatistics() const override {
8089 if (isAssumedReadNone())
8090 STATS_DECLTRACK_CSARG_ATTR(readnone)
8091 else if (isAssumedReadOnly())
8092 STATS_DECLTRACK_CSARG_ATTR(readonly)
8093 else if (isAssumedWriteOnly())
8094 STATS_DECLTRACK_CSARG_ATTR(writeonly)
8095 }
8096};
8097
8098/// Memory behavior attribute for a call site return position.
8099struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8100 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
8101 : AAMemoryBehaviorFloating(IRP, A) {}
8102
8103 /// See AbstractAttribute::initialize(...).
8104 void initialize(Attributor &A) override {
8105 AAMemoryBehaviorImpl::initialize(A);
8106 }
8107 /// See AbstractAttribute::manifest(...).
8108 ChangeStatus manifest(Attributor &A) override {
8109 // We do not annotate returned values.
8110 return ChangeStatus::UNCHANGED;
8111 }
8112
8113 /// See AbstractAttribute::trackStatistics()
8114 void trackStatistics() const override {}
8115};
8116
8117/// An AA to represent the memory behavior function attributes.
8118struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
8119 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
8120 : AAMemoryBehaviorImpl(IRP, A) {}
8121
8122 /// See AbstractAttribute::updateImpl(Attributor &A).
8123 ChangeStatus updateImpl(Attributor &A) override;
8124
8125 /// See AbstractAttribute::manifest(...).
8126 ChangeStatus manifest(Attributor &A) override {
8127 // TODO: It would be better to merge this with AAMemoryLocation, so that
8128 // we could determine read/write per location. This would also have the
8129 // benefit of only one place trying to manifest the memory attribute.
8130 Function &F = cast<Function>(Val&: getAnchorValue());
8131 MemoryEffects ME = MemoryEffects::unknown();
8132 if (isAssumedReadNone())
8133 ME = MemoryEffects::none();
8134 else if (isAssumedReadOnly())
8135 ME = MemoryEffects::readOnly();
8136 else if (isAssumedWriteOnly())
8137 ME = MemoryEffects::writeOnly();
8138
8139 A.removeAttrs(IRP: getIRPosition(), AttrKinds);
8140 // Clear conflicting writable attribute.
8141 if (ME.onlyReadsMemory())
8142 for (Argument &Arg : F.args())
8143 A.removeAttrs(IRP: IRPosition::argument(Arg), AttrKinds: Attribute::Writable);
8144 return A.manifestAttrs(IRP: getIRPosition(),
8145 DeducedAttrs: Attribute::getWithMemoryEffects(Context&: F.getContext(), ME));
8146 }
8147
8148 /// See AbstractAttribute::trackStatistics()
8149 void trackStatistics() const override {
8150 if (isAssumedReadNone())
8151 STATS_DECLTRACK_FN_ATTR(readnone)
8152 else if (isAssumedReadOnly())
8153 STATS_DECLTRACK_FN_ATTR(readonly)
8154 else if (isAssumedWriteOnly())
8155 STATS_DECLTRACK_FN_ATTR(writeonly)
8156 }
8157};
8158
8159/// AAMemoryBehavior attribute for call sites.
8160struct AAMemoryBehaviorCallSite final
8161 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8162 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
8163 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP, A) {}
8164
8165 /// See AbstractAttribute::manifest(...).
8166 ChangeStatus manifest(Attributor &A) override {
8167 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8168 CallBase &CB = cast<CallBase>(Val&: getAnchorValue());
8169 MemoryEffects ME = MemoryEffects::unknown();
8170 if (isAssumedReadNone())
8171 ME = MemoryEffects::none();
8172 else if (isAssumedReadOnly())
8173 ME = MemoryEffects::readOnly();
8174 else if (isAssumedWriteOnly())
8175 ME = MemoryEffects::writeOnly();
8176
8177 A.removeAttrs(IRP: getIRPosition(), AttrKinds);
8178 // Clear conflicting writable attribute.
8179 if (ME.onlyReadsMemory())
8180 for (Use &U : CB.args())
8181 A.removeAttrs(IRP: IRPosition::callsite_argument(CB, ArgNo: U.getOperandNo()),
8182 AttrKinds: Attribute::Writable);
8183 return A.manifestAttrs(
8184 IRP: getIRPosition(), DeducedAttrs: Attribute::getWithMemoryEffects(Context&: CB.getContext(), ME));
8185 }
8186
8187 /// See AbstractAttribute::trackStatistics()
8188 void trackStatistics() const override {
8189 if (isAssumedReadNone())
8190 STATS_DECLTRACK_CS_ATTR(readnone)
8191 else if (isAssumedReadOnly())
8192 STATS_DECLTRACK_CS_ATTR(readonly)
8193 else if (isAssumedWriteOnly())
8194 STATS_DECLTRACK_CS_ATTR(writeonly)
8195 }
8196};
8197
8198ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8199
8200 // The current assumed state used to determine a change.
8201 auto AssumedState = getAssumed();
8202
8203 auto CheckRWInst = [&](Instruction &I) {
8204 // If the instruction has an own memory behavior state, use it to restrict
8205 // the local state. No further analysis is required as the other memory
8206 // state is as optimistic as it gets.
8207 if (const auto *CB = dyn_cast<CallBase>(Val: &I)) {
8208 const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8209 QueryingAA: *this, IRP: IRPosition::callsite_function(CB: *CB), DepClass: DepClassTy::REQUIRED);
8210 if (MemBehaviorAA) {
8211 intersectAssumedBits(BitsEncoding: MemBehaviorAA->getAssumed());
8212 return !isAtFixpoint();
8213 }
8214 }
8215
8216 // Remove access kind modifiers if necessary.
8217 if (I.mayReadFromMemory())
8218 removeAssumedBits(BitsEncoding: NO_READS);
8219 if (I.mayWriteToMemory())
8220 removeAssumedBits(BitsEncoding: NO_WRITES);
8221 return !isAtFixpoint();
8222 };
8223
8224 bool UsedAssumedInformation = false;
8225 if (!A.checkForAllReadWriteInstructions(Pred: CheckRWInst, QueryingAA&: *this,
8226 UsedAssumedInformation))
8227 return indicatePessimisticFixpoint();
8228
8229 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8230 : ChangeStatus::UNCHANGED;
8231}
8232
8233ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8234
8235 const IRPosition &IRP = getIRPosition();
8236 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8237 AAMemoryBehavior::StateType &S = getState();
8238
8239 // First, check the function scope. We take the known information and we avoid
8240 // work if the assumed information implies the current assumed information for
8241 // this attribute. This is a valid for all but byval arguments.
8242 Argument *Arg = IRP.getAssociatedArgument();
8243 AAMemoryBehavior::base_t FnMemAssumedState =
8244 AAMemoryBehavior::StateType::getWorstState();
8245 if (!Arg || !Arg->hasByValAttr()) {
8246 const auto *FnMemAA =
8247 A.getAAFor<AAMemoryBehavior>(QueryingAA: *this, IRP: FnPos, DepClass: DepClassTy::OPTIONAL);
8248 if (FnMemAA) {
8249 FnMemAssumedState = FnMemAA->getAssumed();
8250 S.addKnownBits(Bits: FnMemAA->getKnown());
8251 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8252 return ChangeStatus::UNCHANGED;
8253 }
8254 }
8255
8256 // The current assumed state used to determine a change.
8257 auto AssumedState = S.getAssumed();
8258
8259 // Make sure the value is not captured (except through "return"), if
8260 // it is, any information derived would be irrelevant anyway as we cannot
8261 // check the potential aliases introduced by the capture. However, no need
8262 // to fall back to anythign less optimistic than the function state.
8263 bool IsKnownNoCapture;
8264 const AANoCapture *ArgNoCaptureAA = nullptr;
8265 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
8266 A, QueryingAA: this, IRP, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoCapture, IgnoreSubsumingPositions: false,
8267 AAPtr: &ArgNoCaptureAA);
8268
8269 if (!IsAssumedNoCapture &&
8270 (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
8271 S.intersectAssumedBits(BitsEncoding: FnMemAssumedState);
8272 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8273 : ChangeStatus::UNCHANGED;
8274 }
8275
8276 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8277 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8278 Instruction *UserI = cast<Instruction>(Val: U.getUser());
8279 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
8280 << " \n");
8281
8282 // Droppable users, e.g., llvm::assume does not actually perform any action.
8283 if (UserI->isDroppable())
8284 return true;
8285
8286 // Check if the users of UserI should also be visited.
8287 Follow = followUsersOfUseIn(A, U, UserI);
8288
8289 // If UserI might touch memory we analyze the use in detail.
8290 if (UserI->mayReadOrWriteMemory())
8291 analyzeUseIn(A, U, UserI);
8292
8293 return !isAtFixpoint();
8294 };
8295
8296 if (!A.checkForAllUses(Pred: UsePred, QueryingAA: *this, V: getAssociatedValue()))
8297 return indicatePessimisticFixpoint();
8298
8299 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8300 : ChangeStatus::UNCHANGED;
8301}
8302
8303bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8304 const Instruction *UserI) {
8305 // The loaded value is unrelated to the pointer argument, no need to
8306 // follow the users of the load.
8307 if (isa<LoadInst>(Val: UserI) || isa<ReturnInst>(Val: UserI))
8308 return false;
8309
8310 // By default we follow all uses assuming UserI might leak information on U,
8311 // we have special handling for call sites operands though.
8312 const auto *CB = dyn_cast<CallBase>(Val: UserI);
8313 if (!CB || !CB->isArgOperand(U: &U))
8314 return true;
8315
8316 // If the use is a call argument known not to be captured, the users of
8317 // the call do not need to be visited because they have to be unrelated to
8318 // the input. Note that this check is not trivial even though we disallow
8319 // general capturing of the underlying argument. The reason is that the
8320 // call might the argument "through return", which we allow and for which we
8321 // need to check call users.
8322 if (U.get()->getType()->isPointerTy()) {
8323 unsigned ArgNo = CB->getArgOperandNo(U: &U);
8324 bool IsKnownNoCapture;
8325 return !AA::hasAssumedIRAttr<Attribute::Captures>(
8326 A, QueryingAA: this, IRP: IRPosition::callsite_argument(CB: *CB, ArgNo),
8327 DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoCapture);
8328 }
8329
8330 return true;
8331}
8332
8333void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8334 const Instruction *UserI) {
8335 assert(UserI->mayReadOrWriteMemory());
8336
8337 switch (UserI->getOpcode()) {
8338 default:
8339 // TODO: Handle all atomics and other side-effect operations we know of.
8340 break;
8341 case Instruction::Load:
8342 // Loads cause the NO_READS property to disappear.
8343 removeAssumedBits(BitsEncoding: NO_READS);
8344 return;
8345
8346 case Instruction::Store:
8347 // Stores cause the NO_WRITES property to disappear if the use is the
8348 // pointer operand. Note that while capturing was taken care of somewhere
8349 // else we need to deal with stores of the value that is not looked through.
8350 if (cast<StoreInst>(Val: UserI)->getPointerOperand() == U.get())
8351 removeAssumedBits(BitsEncoding: NO_WRITES);
8352 else
8353 indicatePessimisticFixpoint();
8354 return;
8355
8356 case Instruction::Call:
8357 case Instruction::CallBr:
8358 case Instruction::Invoke: {
8359 // For call sites we look at the argument memory behavior attribute (this
8360 // could be recursive!) in order to restrict our own state.
8361 const auto *CB = cast<CallBase>(Val: UserI);
8362
8363 // Give up on operand bundles.
8364 if (CB->isBundleOperand(U: &U)) {
8365 indicatePessimisticFixpoint();
8366 return;
8367 }
8368
8369 // Calling a function does read the function pointer, maybe write it if the
8370 // function is self-modifying.
8371 if (CB->isCallee(U: &U)) {
8372 removeAssumedBits(BitsEncoding: NO_READS);
8373 break;
8374 }
8375
8376 // Adjust the possible access behavior based on the information on the
8377 // argument.
8378 IRPosition Pos;
8379 if (U.get()->getType()->isPointerTy())
8380 Pos = IRPosition::callsite_argument(CB: *CB, ArgNo: CB->getArgOperandNo(U: &U));
8381 else
8382 Pos = IRPosition::callsite_function(CB: *CB);
8383 const auto *MemBehaviorAA =
8384 A.getAAFor<AAMemoryBehavior>(QueryingAA: *this, IRP: Pos, DepClass: DepClassTy::OPTIONAL);
8385 if (!MemBehaviorAA)
8386 break;
8387 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8388 // and at least "known".
8389 intersectAssumedBits(BitsEncoding: MemBehaviorAA->getAssumed());
8390 return;
8391 }
8392 };
8393
8394 // Generally, look at the "may-properties" and adjust the assumed state if we
8395 // did not trigger special handling before.
8396 if (UserI->mayReadFromMemory())
8397 removeAssumedBits(BitsEncoding: NO_READS);
8398 if (UserI->mayWriteToMemory())
8399 removeAssumedBits(BitsEncoding: NO_WRITES);
8400}
8401} // namespace
8402
8403/// -------------------- Memory Locations Attributes ---------------------------
8404/// Includes read-none, argmemonly, inaccessiblememonly,
8405/// inaccessiblememorargmemonly
8406/// ----------------------------------------------------------------------------
8407
8408std::string AAMemoryLocation::getMemoryLocationsAsStr(
8409 AAMemoryLocation::MemoryLocationsKind MLK) {
8410 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8411 return "all memory";
8412 if (MLK == AAMemoryLocation::NO_LOCATIONS)
8413 return "no memory";
8414 std::string S = "memory:";
8415 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8416 S += "stack,";
8417 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8418 S += "constant,";
8419 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_INTERNAL_MEM))
8420 S += "internal global,";
8421 if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_EXTERNAL_MEM))
8422 S += "external global,";
8423 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8424 S += "argument,";
8425 if (0 == (MLK & AAMemoryLocation::NO_INACCESSIBLE_MEM))
8426 S += "inaccessible,";
8427 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8428 S += "malloced,";
8429 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8430 S += "unknown,";
8431 S.pop_back();
8432 return S;
8433}
8434
8435namespace {
8436struct AAMemoryLocationImpl : public AAMemoryLocation {
8437
8438 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8439 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8440 AccessKind2Accesses.fill(u: nullptr);
8441 }
8442
8443 ~AAMemoryLocationImpl() override {
8444 // The AccessSets are allocated via a BumpPtrAllocator, we call
8445 // the destructor manually.
8446 for (AccessSet *AS : AccessKind2Accesses)
8447 if (AS)
8448 AS->~AccessSet();
8449 }
8450
8451 /// See AbstractAttribute::initialize(...).
8452 void initialize(Attributor &A) override {
8453 intersectAssumedBits(BitsEncoding: BEST_STATE);
8454 getKnownStateFromValue(A, IRP: getIRPosition(), State&: getState());
8455 AAMemoryLocation::initialize(A);
8456 }
8457
8458 /// Return the memory behavior information encoded in the IR for \p IRP.
8459 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8460 BitIntegerState &State,
8461 bool IgnoreSubsumingPositions = false) {
8462 // For internal functions we ignore `argmemonly` and
8463 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8464 // constant propagation. It is unclear if this is the best way but it is
8465 // unlikely this will cause real performance problems. If we are deriving
8466 // attributes for the anchor function we even remove the attribute in
8467 // addition to ignoring it.
8468 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8469 // MemoryEffects::Other as a possible location.
8470 bool UseArgMemOnly = true;
8471 Function *AnchorFn = IRP.getAnchorScope();
8472 if (AnchorFn && A.isRunOn(Fn&: *AnchorFn))
8473 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8474
8475 SmallVector<Attribute, 2> Attrs;
8476 A.getAttrs(IRP, AKs: {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8477 for (const Attribute &Attr : Attrs) {
8478 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8479 MemoryEffects ME = Attr.getMemoryEffects();
8480 if (ME.doesNotAccessMemory()) {
8481 State.addKnownBits(Bits: NO_LOCAL_MEM | NO_CONST_MEM);
8482 continue;
8483 }
8484 if (ME.onlyAccessesInaccessibleMem()) {
8485 State.addKnownBits(Bits: inverseLocation(Loc: NO_INACCESSIBLE_MEM, AndLocalMem: true, AndConstMem: true));
8486 continue;
8487 }
8488 if (ME.onlyAccessesArgPointees()) {
8489 if (UseArgMemOnly)
8490 State.addKnownBits(Bits: inverseLocation(Loc: NO_ARGUMENT_MEM, AndLocalMem: true, AndConstMem: true));
8491 else {
8492 // Remove location information, only keep read/write info.
8493 ME = MemoryEffects(ME.getModRef());
8494 A.manifestAttrs(IRP,
8495 DeducedAttrs: Attribute::getWithMemoryEffects(
8496 Context&: IRP.getAnchorValue().getContext(), ME),
8497 /*ForceReplace*/ true);
8498 }
8499 continue;
8500 }
8501 if (ME.onlyAccessesInaccessibleOrArgMem()) {
8502 if (UseArgMemOnly)
8503 State.addKnownBits(Bits: inverseLocation(
8504 Loc: NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, AndLocalMem: true, AndConstMem: true));
8505 else {
8506 // Remove location information, only keep read/write info.
8507 ME = MemoryEffects(ME.getModRef());
8508 A.manifestAttrs(IRP,
8509 DeducedAttrs: Attribute::getWithMemoryEffects(
8510 Context&: IRP.getAnchorValue().getContext(), ME),
8511 /*ForceReplace*/ true);
8512 }
8513 continue;
8514 }
8515 }
8516 }
8517
8518 /// See AbstractAttribute::getDeducedAttributes(...).
8519 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
8520 SmallVectorImpl<Attribute> &Attrs) const override {
8521 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8522 assert(Attrs.size() == 0);
8523 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8524 if (isAssumedReadNone())
8525 Attrs.push_back(
8526 Elt: Attribute::getWithMemoryEffects(Context&: Ctx, ME: MemoryEffects::none()));
8527 else if (isAssumedInaccessibleMemOnly())
8528 Attrs.push_back(Elt: Attribute::getWithMemoryEffects(
8529 Context&: Ctx, ME: MemoryEffects::inaccessibleMemOnly()));
8530 else if (isAssumedArgMemOnly())
8531 Attrs.push_back(
8532 Elt: Attribute::getWithMemoryEffects(Context&: Ctx, ME: MemoryEffects::argMemOnly()));
8533 else if (isAssumedInaccessibleOrArgMemOnly())
8534 Attrs.push_back(Elt: Attribute::getWithMemoryEffects(
8535 Context&: Ctx, ME: MemoryEffects::inaccessibleOrArgMemOnly()));
8536 }
8537 assert(Attrs.size() <= 1);
8538 }
8539
8540 /// See AbstractAttribute::manifest(...).
8541 ChangeStatus manifest(Attributor &A) override {
8542 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8543 // provide per-location modref information here.
8544 const IRPosition &IRP = getIRPosition();
8545
8546 SmallVector<Attribute, 1> DeducedAttrs;
8547 getDeducedAttributes(A, Ctx&: IRP.getAnchorValue().getContext(), Attrs&: DeducedAttrs);
8548 if (DeducedAttrs.size() != 1)
8549 return ChangeStatus::UNCHANGED;
8550 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8551
8552 return A.manifestAttrs(IRP, DeducedAttrs: Attribute::getWithMemoryEffects(
8553 Context&: IRP.getAnchorValue().getContext(), ME));
8554 }
8555
8556 /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).
8557 bool checkForAllAccessesToMemoryKind(
8558 function_ref<bool(const Instruction *, const Value *, AccessKind,
8559 MemoryLocationsKind)>
8560 Pred,
8561 MemoryLocationsKind RequestedMLK) const override {
8562 if (!isValidState())
8563 return false;
8564
8565 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8566 if (AssumedMLK == NO_LOCATIONS)
8567 return true;
8568
8569 unsigned Idx = 0;
8570 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8571 CurMLK *= 2, ++Idx) {
8572 if (CurMLK & RequestedMLK)
8573 continue;
8574
8575 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8576 for (const AccessInfo &AI : *Accesses)
8577 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8578 return false;
8579 }
8580
8581 return true;
8582 }
8583
8584 ChangeStatus indicatePessimisticFixpoint() override {
8585 // If we give up and indicate a pessimistic fixpoint this instruction will
8586 // become an access for all potential access kinds:
8587 // TODO: Add pointers for argmemonly and globals to improve the results of
8588 // checkForAllAccessesToMemoryKind.
8589 bool Changed = false;
8590 MemoryLocationsKind KnownMLK = getKnown();
8591 Instruction *I = dyn_cast<Instruction>(Val: &getAssociatedValue());
8592 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8593 if (!(CurMLK & KnownMLK))
8594 updateStateAndAccessesMap(State&: getState(), MLK: CurMLK, I, Ptr: nullptr, Changed,
8595 AK: getAccessKindFromInst(I));
8596 return AAMemoryLocation::indicatePessimisticFixpoint();
8597 }
8598
8599protected:
8600 /// Helper struct to tie together an instruction that has a read or write
8601 /// effect with the pointer it accesses (if any).
8602 struct AccessInfo {
8603
8604 /// The instruction that caused the access.
8605 const Instruction *I;
8606
8607 /// The base pointer that is accessed, or null if unknown.
8608 const Value *Ptr;
8609
8610 /// The kind of access (read/write/read+write).
8611 AccessKind Kind;
8612
8613 bool operator==(const AccessInfo &RHS) const {
8614 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8615 }
8616 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8617 if (LHS.I != RHS.I)
8618 return LHS.I < RHS.I;
8619 if (LHS.Ptr != RHS.Ptr)
8620 return LHS.Ptr < RHS.Ptr;
8621 if (LHS.Kind != RHS.Kind)
8622 return LHS.Kind < RHS.Kind;
8623 return false;
8624 }
8625 };
8626
8627 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8628 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8629 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8630 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8631 AccessKind2Accesses;
8632
8633 /// Categorize the pointer arguments of CB that might access memory in
8634 /// AccessedLoc and update the state and access map accordingly.
8635 void
8636 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8637 AAMemoryLocation::StateType &AccessedLocs,
8638 bool &Changed);
8639
8640 /// Return the kind(s) of location that may be accessed by \p V.
8641 AAMemoryLocation::MemoryLocationsKind
8642 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8643
8644 /// Return the access kind as determined by \p I.
8645 AccessKind getAccessKindFromInst(const Instruction *I) {
8646 AccessKind AK = READ_WRITE;
8647 if (I) {
8648 AK = I->mayReadFromMemory() ? READ : NONE;
8649 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8650 }
8651 return AK;
8652 }
8653
8654 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8655 /// an access of kind \p AK to a \p MLK memory location with the access
8656 /// pointer \p Ptr.
8657 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8658 MemoryLocationsKind MLK, const Instruction *I,
8659 const Value *Ptr, bool &Changed,
8660 AccessKind AK = READ_WRITE) {
8661
8662 assert(isPowerOf2_32(MLK) && "Expected a single location set!");
8663 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(Value: MLK)];
8664 if (!Accesses)
8665 Accesses = new (Allocator) AccessSet();
8666 Changed |= Accesses->insert(V: AccessInfo{.I: I, .Ptr: Ptr, .Kind: AK}).second;
8667 if (MLK == NO_UNKOWN_MEM)
8668 MLK = NO_LOCATIONS;
8669 State.removeAssumedBits(BitsEncoding: MLK);
8670 }
8671
8672 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8673 /// arguments, and update the state and access map accordingly.
8674 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8675 AAMemoryLocation::StateType &State, bool &Changed,
8676 unsigned AccessAS = 0);
8677
8678 /// Used to allocate access sets.
8679 BumpPtrAllocator &Allocator;
8680};
8681
8682void AAMemoryLocationImpl::categorizePtrValue(
8683 Attributor &A, const Instruction &I, const Value &Ptr,
8684 AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {
8685 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
8686 << Ptr << " ["
8687 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");
8688
8689 auto Pred = [&](Value &Obj) {
8690 unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();
8691 // TODO: recognize the TBAA used for constant accesses.
8692 MemoryLocationsKind MLK = NO_LOCATIONS;
8693
8694 // Filter accesses to constant (GPU) memory if we have an AS at the access
8695 // site or the object is known to actually have the associated AS.
8696 if (AA::isGPU(M: A.getModule())) {
8697 if (AA::isGPUConstantAddressSpace(M: A.getModule(), AS: AccessAS) ||
8698 (AA::isGPUConstantAddressSpace(M: A.getModule(), AS: ObjectAS) &&
8699 isIdentifiedObject(V: &Obj)))
8700 return true;
8701 }
8702
8703 if (isa<UndefValue>(Val: &Obj))
8704 return true;
8705 if (isa<Argument>(Val: &Obj)) {
8706 // TODO: For now we do not treat byval arguments as local copies performed
8707 // on the call edge, though, we should. To make that happen we need to
8708 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8709 // would also allow us to mark functions only accessing byval arguments as
8710 // readnone again, arguably their accesses have no effect outside of the
8711 // function, like accesses to allocas.
8712 MLK = NO_ARGUMENT_MEM;
8713 } else if (auto *GV = dyn_cast<GlobalValue>(Val: &Obj)) {
8714 // Reading constant memory is not treated as a read "effect" by the
8715 // function attr pass so we won't neither. Constants defined by TBAA are
8716 // similar. (We know we do not write it because it is constant.)
8717 if (auto *GVar = dyn_cast<GlobalVariable>(Val: GV))
8718 if (GVar->isConstant())
8719 return true;
8720
8721 if (GV->hasLocalLinkage())
8722 MLK = NO_GLOBAL_INTERNAL_MEM;
8723 else
8724 MLK = NO_GLOBAL_EXTERNAL_MEM;
8725 } else if (isa<ConstantPointerNull>(Val: &Obj) &&
8726 (!NullPointerIsDefined(F: getAssociatedFunction(), AS: AccessAS) ||
8727 !NullPointerIsDefined(F: getAssociatedFunction(), AS: ObjectAS))) {
8728 return true;
8729 } else if (isa<AllocaInst>(Val: &Obj)) {
8730 MLK = NO_LOCAL_MEM;
8731 } else if (const auto *CB = dyn_cast<CallBase>(Val: &Obj)) {
8732 bool IsKnownNoAlias;
8733 if (AA::hasAssumedIRAttr<Attribute::NoAlias>(
8734 A, QueryingAA: this, IRP: IRPosition::callsite_returned(CB: *CB), DepClass: DepClassTy::OPTIONAL,
8735 IsKnown&: IsKnownNoAlias))
8736 MLK = NO_MALLOCED_MEM;
8737 else
8738 MLK = NO_UNKOWN_MEM;
8739 } else {
8740 MLK = NO_UNKOWN_MEM;
8741 }
8742
8743 assert(MLK != NO_LOCATIONS && "No location specified!");
8744 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
8745 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
8746 updateStateAndAccessesMap(State, MLK, I: &I, Ptr: &Obj, Changed,
8747 AK: getAccessKindFromInst(I: &I));
8748
8749 return true;
8750 };
8751
8752 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
8753 QueryingAA: *this, IRP: IRPosition::value(V: Ptr), DepClass: DepClassTy::OPTIONAL);
8754 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope: AA::Intraprocedural)) {
8755 LLVM_DEBUG(
8756 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
8757 updateStateAndAccessesMap(State, MLK: NO_UNKOWN_MEM, I: &I, Ptr: nullptr, Changed,
8758 AK: getAccessKindFromInst(I: &I));
8759 return;
8760 }
8761
8762 LLVM_DEBUG(
8763 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
8764 << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
8765}
8766
8767void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8768 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8769 bool &Changed) {
8770 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8771
8772 // Skip non-pointer arguments.
8773 const Value *ArgOp = CB.getArgOperand(i: ArgNo);
8774 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8775 continue;
8776
8777 // Skip readnone arguments.
8778 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8779 const auto *ArgOpMemLocationAA =
8780 A.getAAFor<AAMemoryBehavior>(QueryingAA: *this, IRP: ArgOpIRP, DepClass: DepClassTy::OPTIONAL);
8781
8782 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8783 continue;
8784
8785 // Categorize potentially accessed pointer arguments as if there was an
8786 // access instruction with them as pointer.
8787 categorizePtrValue(A, I: CB, Ptr: *ArgOp, State&: AccessedLocs, Changed);
8788 }
8789}
8790
8791AAMemoryLocation::MemoryLocationsKind
8792AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8793 bool &Changed) {
8794 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
8795 << I << "\n");
8796
8797 AAMemoryLocation::StateType AccessedLocs;
8798 AccessedLocs.intersectAssumedBits(BitsEncoding: NO_LOCATIONS);
8799
8800 if (auto *CB = dyn_cast<CallBase>(Val: &I)) {
8801
8802 // First check if we assume any memory is access is visible.
8803 const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8804 QueryingAA: *this, IRP: IRPosition::callsite_function(CB: *CB), DepClass: DepClassTy::OPTIONAL);
8805 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
8806 << " [" << CBMemLocationAA << "]\n");
8807 if (!CBMemLocationAA) {
8808 updateStateAndAccessesMap(State&: AccessedLocs, MLK: NO_UNKOWN_MEM, I: &I, Ptr: nullptr,
8809 Changed, AK: getAccessKindFromInst(I: &I));
8810 return NO_UNKOWN_MEM;
8811 }
8812
8813 if (CBMemLocationAA->isAssumedReadNone())
8814 return NO_LOCATIONS;
8815
8816 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8817 updateStateAndAccessesMap(State&: AccessedLocs, MLK: NO_INACCESSIBLE_MEM, I: &I, Ptr: nullptr,
8818 Changed, AK: getAccessKindFromInst(I: &I));
8819 return AccessedLocs.getAssumed();
8820 }
8821
8822 uint32_t CBAssumedNotAccessedLocs =
8823 CBMemLocationAA->getAssumedNotAccessedLocation();
8824
8825 // Set the argmemonly and global bit as we handle them separately below.
8826 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8827 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8828
8829 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8830 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8831 continue;
8832 updateStateAndAccessesMap(State&: AccessedLocs, MLK: CurMLK, I: &I, Ptr: nullptr, Changed,
8833 AK: getAccessKindFromInst(I: &I));
8834 }
8835
8836 // Now handle global memory if it might be accessed. This is slightly tricky
8837 // as NO_GLOBAL_MEM has multiple bits set.
8838 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8839 if (HasGlobalAccesses) {
8840 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8841 AccessKind Kind, MemoryLocationsKind MLK) {
8842 updateStateAndAccessesMap(State&: AccessedLocs, MLK, I: &I, Ptr, Changed,
8843 AK: getAccessKindFromInst(I: &I));
8844 return true;
8845 };
8846 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8847 Pred: AccessPred, MLK: inverseLocation(Loc: NO_GLOBAL_MEM, AndLocalMem: false, AndConstMem: false)))
8848 return AccessedLocs.getWorstState();
8849 }
8850
8851 LLVM_DEBUG(
8852 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
8853 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8854
8855 // Now handle argument memory if it might be accessed.
8856 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8857 if (HasArgAccesses)
8858 categorizeArgumentPointerLocations(A, CB&: *CB, AccessedLocs, Changed);
8859
8860 LLVM_DEBUG(
8861 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
8862 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8863
8864 return AccessedLocs.getAssumed();
8865 }
8866
8867 if (const Value *Ptr = getPointerOperand(I: &I, /* AllowVolatile */ true)) {
8868 LLVM_DEBUG(
8869 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
8870 << I << " [" << *Ptr << "]\n");
8871 categorizePtrValue(A, I, Ptr: *Ptr, State&: AccessedLocs, Changed,
8872 AccessAS: Ptr->getType()->getPointerAddressSpace());
8873 return AccessedLocs.getAssumed();
8874 }
8875
8876 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
8877 << I << "\n");
8878 updateStateAndAccessesMap(State&: AccessedLocs, MLK: NO_UNKOWN_MEM, I: &I, Ptr: nullptr, Changed,
8879 AK: getAccessKindFromInst(I: &I));
8880 return AccessedLocs.getAssumed();
8881}
8882
8883/// An AA to represent the memory behavior function attributes.
8884struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8885 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8886 : AAMemoryLocationImpl(IRP, A) {}
8887
8888 /// See AbstractAttribute::updateImpl(Attributor &A).
8889 ChangeStatus updateImpl(Attributor &A) override {
8890
8891 const auto *MemBehaviorAA =
8892 A.getAAFor<AAMemoryBehavior>(QueryingAA: *this, IRP: getIRPosition(), DepClass: DepClassTy::NONE);
8893 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
8894 if (MemBehaviorAA->isKnownReadNone())
8895 return indicateOptimisticFixpoint();
8896 assert(isAssumedReadNone() &&
8897 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8898 A.recordDependence(FromAA: *MemBehaviorAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
8899 return ChangeStatus::UNCHANGED;
8900 }
8901
8902 // The current assumed state used to determine a change.
8903 auto AssumedState = getAssumed();
8904 bool Changed = false;
8905
8906 auto CheckRWInst = [&](Instruction &I) {
8907 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8908 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
8909 << ": " << getMemoryLocationsAsStr(MLK) << "\n");
8910 removeAssumedBits(BitsEncoding: inverseLocation(Loc: MLK, AndLocalMem: false, AndConstMem: false));
8911 // Stop once only the valid bit set in the *not assumed location*, thus
8912 // once we don't actually exclude any memory locations in the state.
8913 return getAssumedNotAccessedLocation() != VALID_STATE;
8914 };
8915
8916 bool UsedAssumedInformation = false;
8917 if (!A.checkForAllReadWriteInstructions(Pred: CheckRWInst, QueryingAA&: *this,
8918 UsedAssumedInformation))
8919 return indicatePessimisticFixpoint();
8920
8921 Changed |= AssumedState != getAssumed();
8922 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8923 }
8924
8925 /// See AbstractAttribute::trackStatistics()
8926 void trackStatistics() const override {
8927 if (isAssumedReadNone())
8928 STATS_DECLTRACK_FN_ATTR(readnone)
8929 else if (isAssumedArgMemOnly())
8930 STATS_DECLTRACK_FN_ATTR(argmemonly)
8931 else if (isAssumedInaccessibleMemOnly())
8932 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
8933 else if (isAssumedInaccessibleOrArgMemOnly())
8934 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
8935 }
8936};
8937
8938/// AAMemoryLocation attribute for call sites.
8939struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8940 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8941 : AAMemoryLocationImpl(IRP, A) {}
8942
8943 /// See AbstractAttribute::updateImpl(...).
8944 ChangeStatus updateImpl(Attributor &A) override {
8945 // TODO: Once we have call site specific value information we can provide
8946 // call site specific liveness liveness information and then it makes
8947 // sense to specialize attributes for call sites arguments instead of
8948 // redirecting requests to the callee argument.
8949 Function *F = getAssociatedFunction();
8950 const IRPosition &FnPos = IRPosition::function(F: *F);
8951 auto *FnAA =
8952 A.getAAFor<AAMemoryLocation>(QueryingAA: *this, IRP: FnPos, DepClass: DepClassTy::REQUIRED);
8953 if (!FnAA)
8954 return indicatePessimisticFixpoint();
8955 bool Changed = false;
8956 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8957 AccessKind Kind, MemoryLocationsKind MLK) {
8958 updateStateAndAccessesMap(State&: getState(), MLK, I, Ptr, Changed,
8959 AK: getAccessKindFromInst(I));
8960 return true;
8961 };
8962 if (!FnAA->checkForAllAccessesToMemoryKind(Pred: AccessPred, MLK: ALL_LOCATIONS))
8963 return indicatePessimisticFixpoint();
8964 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8965 }
8966
8967 /// See AbstractAttribute::trackStatistics()
8968 void trackStatistics() const override {
8969 if (isAssumedReadNone())
8970 STATS_DECLTRACK_CS_ATTR(readnone)
8971 }
8972};
8973} // namespace
8974
8975/// ------------------ denormal-fp-math Attribute -------------------------
8976
8977namespace {
8978struct AADenormalFPMathImpl : public AADenormalFPMath {
8979 AADenormalFPMathImpl(const IRPosition &IRP, Attributor &A)
8980 : AADenormalFPMath(IRP, A) {}
8981
8982 const std::string getAsStr(Attributor *A) const override {
8983 std::string Str("AADenormalFPMath[");
8984 raw_string_ostream OS(Str);
8985
8986 DenormalState Known = getKnown();
8987 if (Known.Mode.isValid())
8988 OS << "denormal-fp-math=" << Known.Mode;
8989 else
8990 OS << "invalid";
8991
8992 if (Known.ModeF32.isValid())
8993 OS << " denormal-fp-math-f32=" << Known.ModeF32;
8994 OS << ']';
8995 return Str;
8996 }
8997};
8998
8999struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9000 AADenormalFPMathFunction(const IRPosition &IRP, Attributor &A)
9001 : AADenormalFPMathImpl(IRP, A) {}
9002
9003 void initialize(Attributor &A) override {
9004 const Function *F = getAnchorScope();
9005 DenormalFPEnv DenormEnv = F->getDenormalFPEnv();
9006
9007 Known = DenormalState{.Mode: DenormEnv.DefaultMode, .ModeF32: DenormEnv.F32Mode};
9008 if (isModeFixed())
9009 indicateFixpoint();
9010 }
9011
9012 ChangeStatus updateImpl(Attributor &A) override {
9013 ChangeStatus Change = ChangeStatus::UNCHANGED;
9014
9015 auto CheckCallSite = [=, &Change, &A](AbstractCallSite CS) {
9016 Function *Caller = CS.getInstruction()->getFunction();
9017 LLVM_DEBUG(dbgs() << "[AADenormalFPMath] Call " << Caller->getName()
9018 << "->" << getAssociatedFunction()->getName() << '\n');
9019
9020 const auto *CallerInfo = A.getAAFor<AADenormalFPMath>(
9021 QueryingAA: *this, IRP: IRPosition::function(F: *Caller), DepClass: DepClassTy::REQUIRED);
9022 if (!CallerInfo)
9023 return false;
9024
9025 Change = Change | clampStateAndIndicateChange(S&: this->getState(),
9026 R: CallerInfo->getState());
9027 return true;
9028 };
9029
9030 bool AllCallSitesKnown = true;
9031 if (!A.checkForAllCallSites(Pred: CheckCallSite, QueryingAA: *this, RequireAllCallSites: true, UsedAssumedInformation&: AllCallSitesKnown))
9032 return indicatePessimisticFixpoint();
9033
9034 if (Change == ChangeStatus::CHANGED && isModeFixed())
9035 indicateFixpoint();
9036 return Change;
9037 }
9038
9039 ChangeStatus manifest(Attributor &A) override {
9040 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9041
9042 SmallVector<Attribute, 2> AttrToAdd;
9043 SmallVector<Attribute::AttrKind, 2> AttrToRemove;
9044
9045 // TODO: Change to use DenormalFPEnv everywhere.
9046 DenormalFPEnv KnownEnv(Known.Mode, Known.ModeF32);
9047
9048 if (KnownEnv == DenormalFPEnv::getDefault()) {
9049 AttrToRemove.push_back(Elt: Attribute::DenormalFPEnv);
9050 } else {
9051 AttrToAdd.push_back(Elt: Attribute::get(
9052 Context&: Ctx, Kind: Attribute::DenormalFPEnv,
9053 Val: DenormalFPEnv(Known.Mode, Known.ModeF32).toIntValue()));
9054 }
9055
9056 auto &IRP = getIRPosition();
9057
9058 // TODO: There should be a combined add and remove API.
9059 return A.removeAttrs(IRP, AttrKinds: AttrToRemove) |
9060 A.manifestAttrs(IRP, DeducedAttrs: AttrToAdd, /*ForceReplace=*/true);
9061 }
9062
9063 void trackStatistics() const override {
9064 STATS_DECLTRACK_FN_ATTR(denormal_fpenv)
9065 }
9066};
9067} // namespace
9068
9069/// ------------------ Value Constant Range Attribute -------------------------
9070
9071namespace {
9072struct AAValueConstantRangeImpl : AAValueConstantRange {
9073 using StateType = IntegerRangeState;
9074 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
9075 : AAValueConstantRange(IRP, A) {}
9076
9077 /// See AbstractAttribute::initialize(..).
9078 void initialize(Attributor &A) override {
9079 if (A.hasSimplificationCallback(IRP: getIRPosition())) {
9080 indicatePessimisticFixpoint();
9081 return;
9082 }
9083
9084 // Intersect a range given by SCEV.
9085 intersectKnown(R: getConstantRangeFromSCEV(A, I: getCtxI()));
9086
9087 // Intersect a range given by LVI.
9088 intersectKnown(R: getConstantRangeFromLVI(A, CtxI: getCtxI()));
9089 }
9090
9091 /// See AbstractAttribute::getAsStr().
9092 const std::string getAsStr(Attributor *A) const override {
9093 std::string Str;
9094 llvm::raw_string_ostream OS(Str);
9095 OS << "range(" << getBitWidth() << ")<";
9096 getKnown().print(OS);
9097 OS << " / ";
9098 getAssumed().print(OS);
9099 OS << ">";
9100 return Str;
9101 }
9102
9103 /// Helper function to get a SCEV expr for the associated value at program
9104 /// point \p I.
9105 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
9106 if (!getAnchorScope())
9107 return nullptr;
9108
9109 ScalarEvolution *SE =
9110 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9111 F: *getAnchorScope());
9112
9113 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9114 F: *getAnchorScope());
9115
9116 if (!SE || !LI)
9117 return nullptr;
9118
9119 const SCEV *S = SE->getSCEV(V: &getAssociatedValue());
9120 if (!I)
9121 return S;
9122
9123 return SE->getSCEVAtScope(S, L: LI->getLoopFor(BB: I->getParent()));
9124 }
9125
9126 /// Helper function to get a range from SCEV for the associated value at
9127 /// program point \p I.
9128 ConstantRange getConstantRangeFromSCEV(Attributor &A,
9129 const Instruction *I = nullptr) const {
9130 if (!getAnchorScope())
9131 return getWorstState(BitWidth: getBitWidth());
9132
9133 ScalarEvolution *SE =
9134 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9135 F: *getAnchorScope());
9136
9137 const SCEV *S = getSCEV(A, I);
9138 if (!SE || !S)
9139 return getWorstState(BitWidth: getBitWidth());
9140
9141 return SE->getUnsignedRange(S);
9142 }
9143
9144 /// Helper function to get a range from LVI for the associated value at
9145 /// program point \p I.
9146 ConstantRange
9147 getConstantRangeFromLVI(Attributor &A,
9148 const Instruction *CtxI = nullptr) const {
9149 if (!getAnchorScope())
9150 return getWorstState(BitWidth: getBitWidth());
9151
9152 LazyValueInfo *LVI =
9153 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9154 F: *getAnchorScope());
9155
9156 if (!LVI || !CtxI)
9157 return getWorstState(BitWidth: getBitWidth());
9158 return LVI->getConstantRange(V: &getAssociatedValue(),
9159 CxtI: const_cast<Instruction *>(CtxI),
9160 /*UndefAllowed*/ false);
9161 }
9162
9163 /// Return true if \p CtxI is valid for querying outside analyses.
9164 /// This basically makes sure we do not ask intra-procedural analysis
9165 /// about a context in the wrong function or a context that violates
9166 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
9167 /// if the original context of this AA is OK or should be considered invalid.
9168 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
9169 const Instruction *CtxI,
9170 bool AllowAACtxI) const {
9171 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9172 return false;
9173
9174 // Our context might be in a different function, neither intra-procedural
9175 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
9176 if (!AA::isValidInScope(V: getAssociatedValue(), Scope: CtxI->getFunction()))
9177 return false;
9178
9179 // If the context is not dominated by the value there are paths to the
9180 // context that do not define the value. This cannot be handled by
9181 // LazyValueInfo so we need to bail.
9182 if (auto *I = dyn_cast<Instruction>(Val: &getAssociatedValue())) {
9183 InformationCache &InfoCache = A.getInfoCache();
9184 const DominatorTree *DT =
9185 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
9186 F: *I->getFunction());
9187 return DT && DT->dominates(Def: I, User: CtxI);
9188 }
9189
9190 return true;
9191 }
9192
9193 /// See AAValueConstantRange::getKnownConstantRange(..).
9194 ConstantRange
9195 getKnownConstantRange(Attributor &A,
9196 const Instruction *CtxI = nullptr) const override {
9197 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9198 /* AllowAACtxI */ false))
9199 return getKnown();
9200
9201 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9202 ConstantRange SCEVR = getConstantRangeFromSCEV(A, I: CtxI);
9203 return getKnown().intersectWith(CR: SCEVR).intersectWith(CR: LVIR);
9204 }
9205
9206 /// See AAValueConstantRange::getAssumedConstantRange(..).
9207 ConstantRange
9208 getAssumedConstantRange(Attributor &A,
9209 const Instruction *CtxI = nullptr) const override {
9210 // TODO: Make SCEV use Attributor assumption.
9211 // We may be able to bound a variable range via assumptions in
9212 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
9213 // evolve to x^2 + x, then we can say that y is in [2, 12].
9214 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9215 /* AllowAACtxI */ false))
9216 return getAssumed();
9217
9218 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9219 ConstantRange SCEVR = getConstantRangeFromSCEV(A, I: CtxI);
9220 return getAssumed().intersectWith(CR: SCEVR).intersectWith(CR: LVIR);
9221 }
9222
9223 /// Helper function to create MDNode for range metadata.
9224 static MDNode *
9225 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
9226 const ConstantRange &AssumedConstantRange) {
9227 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(C: ConstantInt::get(
9228 Ty, V: AssumedConstantRange.getLower())),
9229 ConstantAsMetadata::get(C: ConstantInt::get(
9230 Ty, V: AssumedConstantRange.getUpper()))};
9231 return MDNode::get(Context&: Ctx, MDs: LowAndHigh);
9232 }
9233
9234 /// Return true if \p Assumed is included in ranges from instruction \p I.
9235 static bool isBetterRange(const ConstantRange &Assumed,
9236 const Instruction &I) {
9237 if (Assumed.isFullSet())
9238 return false;
9239
9240 std::optional<ConstantRange> Known;
9241
9242 if (const auto *CB = dyn_cast<CallBase>(Val: &I)) {
9243 Known = CB->getRange();
9244 } else if (MDNode *KnownRanges = I.getMetadata(KindID: LLVMContext::MD_range)) {
9245 // If multiple ranges are annotated in IR, we give up to annotate assumed
9246 // range for now.
9247
9248 // TODO: If there exists a known range which containts assumed range, we
9249 // can say assumed range is better.
9250 if (KnownRanges->getNumOperands() > 2)
9251 return false;
9252
9253 ConstantInt *Lower =
9254 mdconst::extract<ConstantInt>(MD: KnownRanges->getOperand(I: 0));
9255 ConstantInt *Upper =
9256 mdconst::extract<ConstantInt>(MD: KnownRanges->getOperand(I: 1));
9257
9258 Known.emplace(args: Lower->getValue(), args: Upper->getValue());
9259 }
9260 return !Known || (*Known != Assumed && Known->contains(CR: Assumed));
9261 }
9262
9263 /// Helper function to set range metadata.
9264 static bool
9265 setRangeMetadataIfisBetterRange(Instruction *I,
9266 const ConstantRange &AssumedConstantRange) {
9267 if (isBetterRange(Assumed: AssumedConstantRange, I: *I)) {
9268 I->setMetadata(KindID: LLVMContext::MD_range,
9269 Node: getMDNodeForConstantRange(Ty: I->getType(), Ctx&: I->getContext(),
9270 AssumedConstantRange));
9271 return true;
9272 }
9273 return false;
9274 }
9275 /// Helper function to set range return attribute.
9276 static bool
9277 setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,
9278 Instruction *I,
9279 const ConstantRange &AssumedConstantRange) {
9280 if (isBetterRange(Assumed: AssumedConstantRange, I: *I)) {
9281 A.manifestAttrs(IRP,
9282 DeducedAttrs: Attribute::get(Context&: I->getContext(), Kind: Attribute::Range,
9283 CR: AssumedConstantRange),
9284 /*ForceReplace*/ true);
9285 return true;
9286 }
9287 return false;
9288 }
9289
9290 /// See AbstractAttribute::manifest()
9291 ChangeStatus manifest(Attributor &A) override {
9292 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9293 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9294 assert(!AssumedConstantRange.isFullSet() && "Invalid state");
9295
9296 auto &V = getAssociatedValue();
9297 if (!AssumedConstantRange.isEmptySet() &&
9298 !AssumedConstantRange.isSingleElement()) {
9299 if (Instruction *I = dyn_cast<Instruction>(Val: &V)) {
9300 assert(I == getCtxI() && "Should not annotate an instruction which is "
9301 "not the context instruction");
9302 if (isa<LoadInst>(Val: I))
9303 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9304 Changed = ChangeStatus::CHANGED;
9305 if (isa<CallInst>(Val: I))
9306 if (setRangeRetAttrIfisBetterRange(A, IRP: getIRPosition(), I,
9307 AssumedConstantRange))
9308 Changed = ChangeStatus::CHANGED;
9309 }
9310 }
9311
9312 return Changed;
9313 }
9314};
9315
9316struct AAValueConstantRangeArgument final
9317 : AAArgumentFromCallSiteArguments<
9318 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9319 true /* BridgeCallBaseContext */> {
9320 using Base = AAArgumentFromCallSiteArguments<
9321 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9322 true /* BridgeCallBaseContext */>;
9323 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9324 : Base(IRP, A) {}
9325
9326 /// See AbstractAttribute::trackStatistics()
9327 void trackStatistics() const override {
9328 STATS_DECLTRACK_ARG_ATTR(value_range)
9329 }
9330};
9331
9332struct AAValueConstantRangeReturned
9333 : AAReturnedFromReturnedValues<AAValueConstantRange,
9334 AAValueConstantRangeImpl,
9335 AAValueConstantRangeImpl::StateType,
9336 /* PropagateCallBaseContext */ true> {
9337 using Base =
9338 AAReturnedFromReturnedValues<AAValueConstantRange,
9339 AAValueConstantRangeImpl,
9340 AAValueConstantRangeImpl::StateType,
9341 /* PropagateCallBaseContext */ true>;
9342 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9343 : Base(IRP, A) {}
9344
9345 /// See AbstractAttribute::initialize(...).
9346 void initialize(Attributor &A) override {
9347 if (!A.isFunctionIPOAmendable(F: *getAssociatedFunction()))
9348 indicatePessimisticFixpoint();
9349 }
9350
9351 /// See AbstractAttribute::trackStatistics()
9352 void trackStatistics() const override {
9353 STATS_DECLTRACK_FNRET_ATTR(value_range)
9354 }
9355};
9356
9357struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9358 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9359 : AAValueConstantRangeImpl(IRP, A) {}
9360
9361 /// See AbstractAttribute::initialize(...).
9362 void initialize(Attributor &A) override {
9363 AAValueConstantRangeImpl::initialize(A);
9364 if (isAtFixpoint())
9365 return;
9366
9367 Value &V = getAssociatedValue();
9368
9369 if (auto *C = dyn_cast<ConstantInt>(Val: &V)) {
9370 unionAssumed(R: ConstantRange(C->getValue()));
9371 indicateOptimisticFixpoint();
9372 return;
9373 }
9374
9375 if (isa<UndefValue>(Val: &V)) {
9376 // Collapse the undef state to 0.
9377 unionAssumed(R: ConstantRange(APInt(getBitWidth(), 0)));
9378 indicateOptimisticFixpoint();
9379 return;
9380 }
9381
9382 if (isa<CallBase>(Val: &V))
9383 return;
9384
9385 if (isa<BinaryOperator>(Val: &V) || isa<CmpInst>(Val: &V) || isa<CastInst>(Val: &V))
9386 return;
9387
9388 // If it is a load instruction with range metadata, use it.
9389 if (LoadInst *LI = dyn_cast<LoadInst>(Val: &V))
9390 if (auto *RangeMD = LI->getMetadata(KindID: LLVMContext::MD_range)) {
9391 intersectKnown(R: getConstantRangeFromMetadata(RangeMD: *RangeMD));
9392 return;
9393 }
9394
9395 // We can work with PHI and select instruction as we traverse their operands
9396 // during update.
9397 if (isa<SelectInst>(Val: V) || isa<PHINode>(Val: V))
9398 return;
9399
9400 // Otherwise we give up.
9401 indicatePessimisticFixpoint();
9402
9403 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
9404 << getAssociatedValue() << "\n");
9405 }
9406
9407 bool calculateBinaryOperator(
9408 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9409 const Instruction *CtxI,
9410 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9411 Value *LHS = BinOp->getOperand(i_nocapture: 0);
9412 Value *RHS = BinOp->getOperand(i_nocapture: 1);
9413
9414 // Simplify the operands first.
9415 bool UsedAssumedInformation = false;
9416 const auto &SimplifiedLHS = A.getAssumedSimplified(
9417 IRP: IRPosition::value(V: *LHS, CBContext: getCallBaseContext()), AA: *this,
9418 UsedAssumedInformation, S: AA::Interprocedural);
9419 if (!SimplifiedLHS.has_value())
9420 return true;
9421 if (!*SimplifiedLHS)
9422 return false;
9423 LHS = *SimplifiedLHS;
9424
9425 const auto &SimplifiedRHS = A.getAssumedSimplified(
9426 IRP: IRPosition::value(V: *RHS, CBContext: getCallBaseContext()), AA: *this,
9427 UsedAssumedInformation, S: AA::Interprocedural);
9428 if (!SimplifiedRHS.has_value())
9429 return true;
9430 if (!*SimplifiedRHS)
9431 return false;
9432 RHS = *SimplifiedRHS;
9433
9434 // TODO: Allow non integers as well.
9435 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9436 return false;
9437
9438 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9439 QueryingAA: *this, IRP: IRPosition::value(V: *LHS, CBContext: getCallBaseContext()),
9440 DepClass: DepClassTy::REQUIRED);
9441 if (!LHSAA)
9442 return false;
9443 QuerriedAAs.push_back(Elt: LHSAA);
9444 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9445
9446 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9447 QueryingAA: *this, IRP: IRPosition::value(V: *RHS, CBContext: getCallBaseContext()),
9448 DepClass: DepClassTy::REQUIRED);
9449 if (!RHSAA)
9450 return false;
9451 QuerriedAAs.push_back(Elt: RHSAA);
9452 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9453
9454 auto AssumedRange = LHSAARange.binaryOp(BinOp: BinOp->getOpcode(), Other: RHSAARange);
9455
9456 T.unionAssumed(R: AssumedRange);
9457
9458 // TODO: Track a known state too.
9459
9460 return T.isValidState();
9461 }
9462
9463 bool calculateCastInst(
9464 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9465 const Instruction *CtxI,
9466 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9467 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
9468 // TODO: Allow non integers as well.
9469 Value *OpV = CastI->getOperand(i_nocapture: 0);
9470
9471 // Simplify the operand first.
9472 bool UsedAssumedInformation = false;
9473 const auto &SimplifiedOpV = A.getAssumedSimplified(
9474 IRP: IRPosition::value(V: *OpV, CBContext: getCallBaseContext()), AA: *this,
9475 UsedAssumedInformation, S: AA::Interprocedural);
9476 if (!SimplifiedOpV.has_value())
9477 return true;
9478 if (!*SimplifiedOpV)
9479 return false;
9480 OpV = *SimplifiedOpV;
9481
9482 if (!OpV->getType()->isIntegerTy())
9483 return false;
9484
9485 auto *OpAA = A.getAAFor<AAValueConstantRange>(
9486 QueryingAA: *this, IRP: IRPosition::value(V: *OpV, CBContext: getCallBaseContext()),
9487 DepClass: DepClassTy::REQUIRED);
9488 if (!OpAA)
9489 return false;
9490 QuerriedAAs.push_back(Elt: OpAA);
9491 T.unionAssumed(R: OpAA->getAssumed().castOp(CastOp: CastI->getOpcode(),
9492 BitWidth: getState().getBitWidth()));
9493 return T.isValidState();
9494 }
9495
9496 bool
9497 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9498 const Instruction *CtxI,
9499 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9500 Value *LHS = CmpI->getOperand(i_nocapture: 0);
9501 Value *RHS = CmpI->getOperand(i_nocapture: 1);
9502
9503 // Simplify the operands first.
9504 bool UsedAssumedInformation = false;
9505 const auto &SimplifiedLHS = A.getAssumedSimplified(
9506 IRP: IRPosition::value(V: *LHS, CBContext: getCallBaseContext()), AA: *this,
9507 UsedAssumedInformation, S: AA::Interprocedural);
9508 if (!SimplifiedLHS.has_value())
9509 return true;
9510 if (!*SimplifiedLHS)
9511 return false;
9512 LHS = *SimplifiedLHS;
9513
9514 const auto &SimplifiedRHS = A.getAssumedSimplified(
9515 IRP: IRPosition::value(V: *RHS, CBContext: getCallBaseContext()), AA: *this,
9516 UsedAssumedInformation, S: AA::Interprocedural);
9517 if (!SimplifiedRHS.has_value())
9518 return true;
9519 if (!*SimplifiedRHS)
9520 return false;
9521 RHS = *SimplifiedRHS;
9522
9523 // TODO: Allow non integers as well.
9524 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9525 return false;
9526
9527 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9528 QueryingAA: *this, IRP: IRPosition::value(V: *LHS, CBContext: getCallBaseContext()),
9529 DepClass: DepClassTy::REQUIRED);
9530 if (!LHSAA)
9531 return false;
9532 QuerriedAAs.push_back(Elt: LHSAA);
9533 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9534 QueryingAA: *this, IRP: IRPosition::value(V: *RHS, CBContext: getCallBaseContext()),
9535 DepClass: DepClassTy::REQUIRED);
9536 if (!RHSAA)
9537 return false;
9538 QuerriedAAs.push_back(Elt: RHSAA);
9539 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9540 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9541
9542 // If one of them is empty set, we can't decide.
9543 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9544 return true;
9545
9546 bool MustTrue = false, MustFalse = false;
9547
9548 auto AllowedRegion =
9549 ConstantRange::makeAllowedICmpRegion(Pred: CmpI->getPredicate(), Other: RHSAARange);
9550
9551 if (AllowedRegion.intersectWith(CR: LHSAARange).isEmptySet())
9552 MustFalse = true;
9553
9554 if (LHSAARange.icmp(Pred: CmpI->getPredicate(), Other: RHSAARange))
9555 MustTrue = true;
9556
9557 assert((!MustTrue || !MustFalse) &&
9558 "Either MustTrue or MustFalse should be false!");
9559
9560 if (MustTrue)
9561 T.unionAssumed(R: ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9562 else if (MustFalse)
9563 T.unionAssumed(R: ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9564 else
9565 T.unionAssumed(R: ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9566
9567 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "
9568 << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))
9569 << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"
9570 << *RHSAA);
9571
9572 // TODO: Track a known state too.
9573 return T.isValidState();
9574 }
9575
9576 /// See AbstractAttribute::updateImpl(...).
9577 ChangeStatus updateImpl(Attributor &A) override {
9578
9579 IntegerRangeState T(getBitWidth());
9580 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9581 Instruction *I = dyn_cast<Instruction>(Val: &V);
9582 if (!I || isa<CallBase>(Val: I)) {
9583
9584 // Simplify the operand first.
9585 bool UsedAssumedInformation = false;
9586 const auto &SimplifiedOpV = A.getAssumedSimplified(
9587 IRP: IRPosition::value(V, CBContext: getCallBaseContext()), AA: *this,
9588 UsedAssumedInformation, S: AA::Interprocedural);
9589 if (!SimplifiedOpV.has_value())
9590 return true;
9591 if (!*SimplifiedOpV)
9592 return false;
9593 Value *VPtr = *SimplifiedOpV;
9594
9595 // If the value is not instruction, we query AA to Attributor.
9596 const auto *AA = A.getAAFor<AAValueConstantRange>(
9597 QueryingAA: *this, IRP: IRPosition::value(V: *VPtr, CBContext: getCallBaseContext()),
9598 DepClass: DepClassTy::REQUIRED);
9599
9600 // Clamp operator is not used to utilize a program point CtxI.
9601 if (AA)
9602 T.unionAssumed(R: AA->getAssumedConstantRange(A, CtxI));
9603 else
9604 return false;
9605
9606 return T.isValidState();
9607 }
9608
9609 SmallVector<const AAValueConstantRange *, 4> QuerriedAAs;
9610 if (auto *BinOp = dyn_cast<BinaryOperator>(Val: I)) {
9611 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9612 return false;
9613 } else if (auto *CmpI = dyn_cast<CmpInst>(Val: I)) {
9614 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9615 return false;
9616 } else if (auto *CastI = dyn_cast<CastInst>(Val: I)) {
9617 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9618 return false;
9619 } else {
9620 // Give up with other instructions.
9621 // TODO: Add other instructions
9622
9623 T.indicatePessimisticFixpoint();
9624 return false;
9625 }
9626
9627 // Catch circular reasoning in a pessimistic way for now.
9628 // TODO: Check how the range evolves and if we stripped anything, see also
9629 // AADereferenceable or AAAlign for similar situations.
9630 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9631 if (QueriedAA != this)
9632 continue;
9633 // If we are in a stady state we do not need to worry.
9634 if (T.getAssumed() == getState().getAssumed())
9635 continue;
9636 T.indicatePessimisticFixpoint();
9637 }
9638
9639 return T.isValidState();
9640 };
9641
9642 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9643 return indicatePessimisticFixpoint();
9644
9645 // Ensure that long def-use chains can't cause circular reasoning either by
9646 // introducing a cutoff below.
9647 if (clampStateAndIndicateChange(S&: getState(), R: T) == ChangeStatus::UNCHANGED)
9648 return ChangeStatus::UNCHANGED;
9649 if (++NumChanges > MaxNumChanges) {
9650 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
9651 << " but only " << MaxNumChanges
9652 << " are allowed to avoid cyclic reasoning.");
9653 return indicatePessimisticFixpoint();
9654 }
9655 return ChangeStatus::CHANGED;
9656 }
9657
9658 /// See AbstractAttribute::trackStatistics()
9659 void trackStatistics() const override {
9660 STATS_DECLTRACK_FLOATING_ATTR(value_range)
9661 }
9662
9663 /// Tracker to bail after too many widening steps of the constant range.
9664 int NumChanges = 0;
9665
9666 /// Upper bound for the number of allowed changes (=widening steps) for the
9667 /// constant range before we give up.
9668 static constexpr int MaxNumChanges = 5;
9669};
9670
9671struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9672 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9673 : AAValueConstantRangeImpl(IRP, A) {}
9674
9675 /// See AbstractAttribute::initialize(...).
9676 ChangeStatus updateImpl(Attributor &A) override {
9677 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
9678 "not be called");
9679 }
9680
9681 /// See AbstractAttribute::trackStatistics()
9682 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
9683};
9684
9685struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9686 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9687 : AAValueConstantRangeFunction(IRP, A) {}
9688
9689 /// See AbstractAttribute::trackStatistics()
9690 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
9691};
9692
9693struct AAValueConstantRangeCallSiteReturned
9694 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9695 AAValueConstantRangeImpl::StateType,
9696 /* IntroduceCallBaseContext */ true> {
9697 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9698 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9699 AAValueConstantRangeImpl::StateType,
9700 /* IntroduceCallBaseContext */ true>(IRP, A) {}
9701
9702 /// See AbstractAttribute::initialize(...).
9703 void initialize(Attributor &A) override {
9704 // If it is a call instruction with range attribute, use the range.
9705 if (CallInst *CI = dyn_cast<CallInst>(Val: &getAssociatedValue())) {
9706 if (std::optional<ConstantRange> Range = CI->getRange())
9707 intersectKnown(R: *Range);
9708 }
9709
9710 AAValueConstantRangeImpl::initialize(A);
9711 }
9712
9713 /// See AbstractAttribute::trackStatistics()
9714 void trackStatistics() const override {
9715 STATS_DECLTRACK_CSRET_ATTR(value_range)
9716 }
9717};
9718struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9719 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9720 : AAValueConstantRangeFloating(IRP, A) {}
9721
9722 /// See AbstractAttribute::manifest()
9723 ChangeStatus manifest(Attributor &A) override {
9724 return ChangeStatus::UNCHANGED;
9725 }
9726
9727 /// See AbstractAttribute::trackStatistics()
9728 void trackStatistics() const override {
9729 STATS_DECLTRACK_CSARG_ATTR(value_range)
9730 }
9731};
9732} // namespace
9733
9734/// ------------------ Potential Values Attribute -------------------------
9735
9736namespace {
9737struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9738 using StateType = PotentialConstantIntValuesState;
9739
9740 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9741 : AAPotentialConstantValues(IRP, A) {}
9742
9743 /// See AbstractAttribute::initialize(..).
9744 void initialize(Attributor &A) override {
9745 if (A.hasSimplificationCallback(IRP: getIRPosition()))
9746 indicatePessimisticFixpoint();
9747 else
9748 AAPotentialConstantValues::initialize(A);
9749 }
9750
9751 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9752 bool &ContainsUndef, bool ForSelf) {
9753 SmallVector<AA::ValueAndContext> Values;
9754 bool UsedAssumedInformation = false;
9755 if (!A.getAssumedSimplifiedValues(IRP, AA: *this, Values, S: AA::Interprocedural,
9756 UsedAssumedInformation)) {
9757 // Avoid recursion when the caller is computing constant values for this
9758 // IRP itself.
9759 if (ForSelf)
9760 return false;
9761 if (!IRP.getAssociatedType()->isIntegerTy())
9762 return false;
9763 auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9764 QueryingAA: *this, IRP, DepClass: DepClassTy::REQUIRED);
9765 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9766 return false;
9767 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9768 S = PotentialValuesAA->getState().getAssumedSet();
9769 return true;
9770 }
9771
9772 // Copy all the constant values, except UndefValue. ContainsUndef is true
9773 // iff Values contains only UndefValue instances. If there are other known
9774 // constants, then UndefValue is dropped.
9775 ContainsUndef = false;
9776 for (auto &It : Values) {
9777 if (isa<UndefValue>(Val: It.getValue())) {
9778 ContainsUndef = true;
9779 continue;
9780 }
9781 auto *CI = dyn_cast<ConstantInt>(Val: It.getValue());
9782 if (!CI)
9783 return false;
9784 S.insert(X: CI->getValue());
9785 }
9786 ContainsUndef &= S.empty();
9787
9788 return true;
9789 }
9790
9791 /// See AbstractAttribute::getAsStr().
9792 const std::string getAsStr(Attributor *A) const override {
9793 std::string Str;
9794 llvm::raw_string_ostream OS(Str);
9795 OS << getState();
9796 return Str;
9797 }
9798
9799 /// See AbstractAttribute::updateImpl(...).
9800 ChangeStatus updateImpl(Attributor &A) override {
9801 return indicatePessimisticFixpoint();
9802 }
9803};
9804
9805struct AAPotentialConstantValuesArgument final
9806 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9807 AAPotentialConstantValuesImpl,
9808 PotentialConstantIntValuesState> {
9809 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9810 AAPotentialConstantValuesImpl,
9811 PotentialConstantIntValuesState>;
9812 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9813 : Base(IRP, A) {}
9814
9815 /// See AbstractAttribute::trackStatistics()
9816 void trackStatistics() const override {
9817 STATS_DECLTRACK_ARG_ATTR(potential_values)
9818 }
9819};
9820
9821struct AAPotentialConstantValuesReturned
9822 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9823 AAPotentialConstantValuesImpl> {
9824 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9825 AAPotentialConstantValuesImpl>;
9826 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9827 : Base(IRP, A) {}
9828
9829 void initialize(Attributor &A) override {
9830 if (!A.isFunctionIPOAmendable(F: *getAssociatedFunction()))
9831 indicatePessimisticFixpoint();
9832 Base::initialize(A);
9833 }
9834
9835 /// See AbstractAttribute::trackStatistics()
9836 void trackStatistics() const override {
9837 STATS_DECLTRACK_FNRET_ATTR(potential_values)
9838 }
9839};
9840
9841struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9842 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9843 : AAPotentialConstantValuesImpl(IRP, A) {}
9844
9845 /// See AbstractAttribute::initialize(..).
9846 void initialize(Attributor &A) override {
9847 AAPotentialConstantValuesImpl::initialize(A);
9848 if (isAtFixpoint())
9849 return;
9850
9851 Value &V = getAssociatedValue();
9852
9853 if (auto *C = dyn_cast<ConstantInt>(Val: &V)) {
9854 unionAssumed(C: C->getValue());
9855 indicateOptimisticFixpoint();
9856 return;
9857 }
9858
9859 if (isa<UndefValue>(Val: &V)) {
9860 unionAssumedWithUndef();
9861 indicateOptimisticFixpoint();
9862 return;
9863 }
9864
9865 if (isa<BinaryOperator>(Val: &V) || isa<ICmpInst>(Val: &V) || isa<CastInst>(Val: &V))
9866 return;
9867
9868 if (isa<SelectInst>(Val: V) || isa<PHINode>(Val: V) || isa<LoadInst>(Val: V))
9869 return;
9870
9871 indicatePessimisticFixpoint();
9872
9873 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
9874 << getAssociatedValue() << "\n");
9875 }
9876
9877 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9878 const APInt &RHS) {
9879 return ICmpInst::compare(LHS, RHS, Pred: ICI->getPredicate());
9880 }
9881
9882 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9883 uint32_t ResultBitWidth) {
9884 Instruction::CastOps CastOp = CI->getOpcode();
9885 switch (CastOp) {
9886 default:
9887 llvm_unreachable("unsupported or not integer cast");
9888 case Instruction::Trunc:
9889 return Src.trunc(width: ResultBitWidth);
9890 case Instruction::SExt:
9891 return Src.sext(width: ResultBitWidth);
9892 case Instruction::ZExt:
9893 return Src.zext(width: ResultBitWidth);
9894 case Instruction::BitCast:
9895 return Src;
9896 }
9897 }
9898
9899 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9900 const APInt &LHS, const APInt &RHS,
9901 bool &SkipOperation, bool &Unsupported) {
9902 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9903 // Unsupported is set to true when the binary operator is not supported.
9904 // SkipOperation is set to true when UB occur with the given operand pair
9905 // (LHS, RHS).
9906 // TODO: we should look at nsw and nuw keywords to handle operations
9907 // that create poison or undef value.
9908 switch (BinOpcode) {
9909 default:
9910 Unsupported = true;
9911 return LHS;
9912 case Instruction::Add:
9913 return LHS + RHS;
9914 case Instruction::Sub:
9915 return LHS - RHS;
9916 case Instruction::Mul:
9917 return LHS * RHS;
9918 case Instruction::UDiv:
9919 if (RHS.isZero()) {
9920 SkipOperation = true;
9921 return LHS;
9922 }
9923 return LHS.udiv(RHS);
9924 case Instruction::SDiv:
9925 if (RHS.isZero()) {
9926 SkipOperation = true;
9927 return LHS;
9928 }
9929 return LHS.sdiv(RHS);
9930 case Instruction::URem:
9931 if (RHS.isZero()) {
9932 SkipOperation = true;
9933 return LHS;
9934 }
9935 return LHS.urem(RHS);
9936 case Instruction::SRem:
9937 if (RHS.isZero()) {
9938 SkipOperation = true;
9939 return LHS;
9940 }
9941 return LHS.srem(RHS);
9942 case Instruction::Shl:
9943 return LHS.shl(ShiftAmt: RHS);
9944 case Instruction::LShr:
9945 return LHS.lshr(ShiftAmt: RHS);
9946 case Instruction::AShr:
9947 return LHS.ashr(ShiftAmt: RHS);
9948 case Instruction::And:
9949 return LHS & RHS;
9950 case Instruction::Or:
9951 return LHS | RHS;
9952 case Instruction::Xor:
9953 return LHS ^ RHS;
9954 }
9955 }
9956
9957 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9958 const APInt &LHS, const APInt &RHS) {
9959 bool SkipOperation = false;
9960 bool Unsupported = false;
9961 APInt Result =
9962 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9963 if (Unsupported)
9964 return false;
9965 // If SkipOperation is true, we can ignore this operand pair (L, R).
9966 if (!SkipOperation)
9967 unionAssumed(C: Result);
9968 return isValidState();
9969 }
9970
9971 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9972 auto AssumedBefore = getAssumed();
9973 Value *LHS = ICI->getOperand(i_nocapture: 0);
9974 Value *RHS = ICI->getOperand(i_nocapture: 1);
9975
9976 bool LHSContainsUndef = false, RHSContainsUndef = false;
9977 SetTy LHSAAPVS, RHSAAPVS;
9978 if (!fillSetWithConstantValues(A, IRP: IRPosition::value(V: *LHS), S&: LHSAAPVS,
9979 ContainsUndef&: LHSContainsUndef, /* ForSelf */ false) ||
9980 !fillSetWithConstantValues(A, IRP: IRPosition::value(V: *RHS), S&: RHSAAPVS,
9981 ContainsUndef&: RHSContainsUndef, /* ForSelf */ false))
9982 return indicatePessimisticFixpoint();
9983
9984 // TODO: make use of undef flag to limit potential values aggressively.
9985 bool MaybeTrue = false, MaybeFalse = false;
9986 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
9987 if (LHSContainsUndef && RHSContainsUndef) {
9988 // The result of any comparison between undefs can be soundly replaced
9989 // with undef.
9990 unionAssumedWithUndef();
9991 } else if (LHSContainsUndef) {
9992 for (const APInt &R : RHSAAPVS) {
9993 bool CmpResult = calculateICmpInst(ICI, LHS: Zero, RHS: R);
9994 MaybeTrue |= CmpResult;
9995 MaybeFalse |= !CmpResult;
9996 if (MaybeTrue & MaybeFalse)
9997 return indicatePessimisticFixpoint();
9998 }
9999 } else if (RHSContainsUndef) {
10000 for (const APInt &L : LHSAAPVS) {
10001 bool CmpResult = calculateICmpInst(ICI, LHS: L, RHS: Zero);
10002 MaybeTrue |= CmpResult;
10003 MaybeFalse |= !CmpResult;
10004 if (MaybeTrue & MaybeFalse)
10005 return indicatePessimisticFixpoint();
10006 }
10007 } else {
10008 for (const APInt &L : LHSAAPVS) {
10009 for (const APInt &R : RHSAAPVS) {
10010 bool CmpResult = calculateICmpInst(ICI, LHS: L, RHS: R);
10011 MaybeTrue |= CmpResult;
10012 MaybeFalse |= !CmpResult;
10013 if (MaybeTrue & MaybeFalse)
10014 return indicatePessimisticFixpoint();
10015 }
10016 }
10017 }
10018 if (MaybeTrue)
10019 unionAssumed(C: APInt(/* numBits */ 1, /* val */ 1));
10020 if (MaybeFalse)
10021 unionAssumed(C: APInt(/* numBits */ 1, /* val */ 0));
10022 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10023 : ChangeStatus::CHANGED;
10024 }
10025
10026 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
10027 auto AssumedBefore = getAssumed();
10028 Value *LHS = SI->getTrueValue();
10029 Value *RHS = SI->getFalseValue();
10030
10031 bool UsedAssumedInformation = false;
10032 std::optional<Constant *> C = A.getAssumedConstant(
10033 V: *SI->getCondition(), AA: *this, UsedAssumedInformation);
10034
10035 // Check if we only need one operand.
10036 bool OnlyLeft = false, OnlyRight = false;
10037 if (C && *C && (*C)->isOneValue())
10038 OnlyLeft = true;
10039 else if (C && *C && (*C)->isNullValue())
10040 OnlyRight = true;
10041
10042 bool LHSContainsUndef = false, RHSContainsUndef = false;
10043 SetTy LHSAAPVS, RHSAAPVS;
10044 if (!OnlyRight &&
10045 !fillSetWithConstantValues(A, IRP: IRPosition::value(V: *LHS), S&: LHSAAPVS,
10046 ContainsUndef&: LHSContainsUndef, /* ForSelf */ false))
10047 return indicatePessimisticFixpoint();
10048
10049 if (!OnlyLeft &&
10050 !fillSetWithConstantValues(A, IRP: IRPosition::value(V: *RHS), S&: RHSAAPVS,
10051 ContainsUndef&: RHSContainsUndef, /* ForSelf */ false))
10052 return indicatePessimisticFixpoint();
10053
10054 if (OnlyLeft || OnlyRight) {
10055 // select (true/false), lhs, rhs
10056 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10057 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10058
10059 if (Undef)
10060 unionAssumedWithUndef();
10061 else {
10062 for (const auto &It : *OpAA)
10063 unionAssumed(C: It);
10064 }
10065
10066 } else if (LHSContainsUndef && RHSContainsUndef) {
10067 // select i1 *, undef , undef => undef
10068 unionAssumedWithUndef();
10069 } else {
10070 for (const auto &It : LHSAAPVS)
10071 unionAssumed(C: It);
10072 for (const auto &It : RHSAAPVS)
10073 unionAssumed(C: It);
10074 }
10075 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10076 : ChangeStatus::CHANGED;
10077 }
10078
10079 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
10080 auto AssumedBefore = getAssumed();
10081 if (!CI->isIntegerCast())
10082 return indicatePessimisticFixpoint();
10083 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
10084 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
10085 Value *Src = CI->getOperand(i_nocapture: 0);
10086
10087 bool SrcContainsUndef = false;
10088 SetTy SrcPVS;
10089 if (!fillSetWithConstantValues(A, IRP: IRPosition::value(V: *Src), S&: SrcPVS,
10090 ContainsUndef&: SrcContainsUndef, /* ForSelf */ false))
10091 return indicatePessimisticFixpoint();
10092
10093 if (SrcContainsUndef)
10094 unionAssumedWithUndef();
10095 else {
10096 for (const APInt &S : SrcPVS) {
10097 APInt T = calculateCastInst(CI, Src: S, ResultBitWidth);
10098 unionAssumed(C: T);
10099 }
10100 }
10101 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10102 : ChangeStatus::CHANGED;
10103 }
10104
10105 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
10106 auto AssumedBefore = getAssumed();
10107 Value *LHS = BinOp->getOperand(i_nocapture: 0);
10108 Value *RHS = BinOp->getOperand(i_nocapture: 1);
10109
10110 bool LHSContainsUndef = false, RHSContainsUndef = false;
10111 SetTy LHSAAPVS, RHSAAPVS;
10112 if (!fillSetWithConstantValues(A, IRP: IRPosition::value(V: *LHS), S&: LHSAAPVS,
10113 ContainsUndef&: LHSContainsUndef, /* ForSelf */ false) ||
10114 !fillSetWithConstantValues(A, IRP: IRPosition::value(V: *RHS), S&: RHSAAPVS,
10115 ContainsUndef&: RHSContainsUndef, /* ForSelf */ false))
10116 return indicatePessimisticFixpoint();
10117
10118 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
10119
10120 // TODO: make use of undef flag to limit potential values aggressively.
10121 if (LHSContainsUndef && RHSContainsUndef) {
10122 if (!calculateBinaryOperatorAndTakeUnion(BinOp, LHS: Zero, RHS: Zero))
10123 return indicatePessimisticFixpoint();
10124 } else if (LHSContainsUndef) {
10125 for (const APInt &R : RHSAAPVS) {
10126 if (!calculateBinaryOperatorAndTakeUnion(BinOp, LHS: Zero, RHS: R))
10127 return indicatePessimisticFixpoint();
10128 }
10129 } else if (RHSContainsUndef) {
10130 for (const APInt &L : LHSAAPVS) {
10131 if (!calculateBinaryOperatorAndTakeUnion(BinOp, LHS: L, RHS: Zero))
10132 return indicatePessimisticFixpoint();
10133 }
10134 } else {
10135 for (const APInt &L : LHSAAPVS) {
10136 for (const APInt &R : RHSAAPVS) {
10137 if (!calculateBinaryOperatorAndTakeUnion(BinOp, LHS: L, RHS: R))
10138 return indicatePessimisticFixpoint();
10139 }
10140 }
10141 }
10142 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10143 : ChangeStatus::CHANGED;
10144 }
10145
10146 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
10147 auto AssumedBefore = getAssumed();
10148 SetTy Incoming;
10149 bool ContainsUndef;
10150 if (!fillSetWithConstantValues(A, IRP: IRPosition::value(V: *Inst), S&: Incoming,
10151 ContainsUndef, /* ForSelf */ true))
10152 return indicatePessimisticFixpoint();
10153 if (ContainsUndef) {
10154 unionAssumedWithUndef();
10155 } else {
10156 for (const auto &It : Incoming)
10157 unionAssumed(C: It);
10158 }
10159 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10160 : ChangeStatus::CHANGED;
10161 }
10162
10163 /// See AbstractAttribute::updateImpl(...).
10164 ChangeStatus updateImpl(Attributor &A) override {
10165 Value &V = getAssociatedValue();
10166 Instruction *I = dyn_cast<Instruction>(Val: &V);
10167
10168 if (auto *ICI = dyn_cast<ICmpInst>(Val: I))
10169 return updateWithICmpInst(A, ICI);
10170
10171 if (auto *SI = dyn_cast<SelectInst>(Val: I))
10172 return updateWithSelectInst(A, SI);
10173
10174 if (auto *CI = dyn_cast<CastInst>(Val: I))
10175 return updateWithCastInst(A, CI);
10176
10177 if (auto *BinOp = dyn_cast<BinaryOperator>(Val: I))
10178 return updateWithBinaryOperator(A, BinOp);
10179
10180 if (isa<PHINode>(Val: I) || isa<LoadInst>(Val: I))
10181 return updateWithInstruction(A, Inst: I);
10182
10183 return indicatePessimisticFixpoint();
10184 }
10185
10186 /// See AbstractAttribute::trackStatistics()
10187 void trackStatistics() const override {
10188 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
10189 }
10190};
10191
10192struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10193 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
10194 : AAPotentialConstantValuesImpl(IRP, A) {}
10195
10196 /// See AbstractAttribute::initialize(...).
10197 ChangeStatus updateImpl(Attributor &A) override {
10198 llvm_unreachable(
10199 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10200 "not be called");
10201 }
10202
10203 /// See AbstractAttribute::trackStatistics()
10204 void trackStatistics() const override {
10205 STATS_DECLTRACK_FN_ATTR(potential_values)
10206 }
10207};
10208
10209struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10210 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
10211 : AAPotentialConstantValuesFunction(IRP, A) {}
10212
10213 /// See AbstractAttribute::trackStatistics()
10214 void trackStatistics() const override {
10215 STATS_DECLTRACK_CS_ATTR(potential_values)
10216 }
10217};
10218
10219struct AAPotentialConstantValuesCallSiteReturned
10220 : AACalleeToCallSite<AAPotentialConstantValues,
10221 AAPotentialConstantValuesImpl> {
10222 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
10223 Attributor &A)
10224 : AACalleeToCallSite<AAPotentialConstantValues,
10225 AAPotentialConstantValuesImpl>(IRP, A) {}
10226
10227 /// See AbstractAttribute::trackStatistics()
10228 void trackStatistics() const override {
10229 STATS_DECLTRACK_CSRET_ATTR(potential_values)
10230 }
10231};
10232
10233struct AAPotentialConstantValuesCallSiteArgument
10234 : AAPotentialConstantValuesFloating {
10235 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
10236 Attributor &A)
10237 : AAPotentialConstantValuesFloating(IRP, A) {}
10238
10239 /// See AbstractAttribute::initialize(..).
10240 void initialize(Attributor &A) override {
10241 AAPotentialConstantValuesImpl::initialize(A);
10242 if (isAtFixpoint())
10243 return;
10244
10245 Value &V = getAssociatedValue();
10246
10247 if (auto *C = dyn_cast<ConstantInt>(Val: &V)) {
10248 unionAssumed(C: C->getValue());
10249 indicateOptimisticFixpoint();
10250 return;
10251 }
10252
10253 if (isa<UndefValue>(Val: &V)) {
10254 unionAssumedWithUndef();
10255 indicateOptimisticFixpoint();
10256 return;
10257 }
10258 }
10259
10260 /// See AbstractAttribute::updateImpl(...).
10261 ChangeStatus updateImpl(Attributor &A) override {
10262 Value &V = getAssociatedValue();
10263 auto AssumedBefore = getAssumed();
10264 auto *AA = A.getAAFor<AAPotentialConstantValues>(
10265 QueryingAA: *this, IRP: IRPosition::value(V), DepClass: DepClassTy::REQUIRED);
10266 if (!AA)
10267 return indicatePessimisticFixpoint();
10268 const auto &S = AA->getAssumed();
10269 unionAssumed(PVS: S);
10270 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10271 : ChangeStatus::CHANGED;
10272 }
10273
10274 /// See AbstractAttribute::trackStatistics()
10275 void trackStatistics() const override {
10276 STATS_DECLTRACK_CSARG_ATTR(potential_values)
10277 }
10278};
10279} // namespace
10280
10281/// ------------------------ NoUndef Attribute ---------------------------------
10282bool AANoUndef::isImpliedByIR(Attributor &A, const IRPosition &IRP,
10283 Attribute::AttrKind ImpliedAttributeKind,
10284 bool IgnoreSubsumingPositions) {
10285 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10286 "Unexpected attribute kind");
10287 if (A.hasAttr(IRP, AKs: {Attribute::NoUndef}, IgnoreSubsumingPositions,
10288 ImpliedAttributeKind: Attribute::NoUndef))
10289 return true;
10290
10291 Value &Val = IRP.getAssociatedValue();
10292 if (IRP.getPositionKind() != IRPosition::IRP_RETURNED &&
10293 isGuaranteedNotToBeUndefOrPoison(V: &Val)) {
10294 LLVMContext &Ctx = Val.getContext();
10295 A.manifestAttrs(IRP, DeducedAttrs: Attribute::get(Context&: Ctx, Kind: Attribute::NoUndef));
10296 return true;
10297 }
10298
10299 return false;
10300}
10301
10302namespace {
10303struct AANoUndefImpl : AANoUndef {
10304 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
10305
10306 /// See AbstractAttribute::initialize(...).
10307 void initialize(Attributor &A) override {
10308 Value &V = getAssociatedValue();
10309 if (isa<UndefValue>(Val: V))
10310 indicatePessimisticFixpoint();
10311 assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));
10312 }
10313
10314 /// See followUsesInMBEC
10315 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10316 AANoUndef::StateType &State) {
10317 const Value *UseV = U->get();
10318 const DominatorTree *DT = nullptr;
10319 AssumptionCache *AC = nullptr;
10320 InformationCache &InfoCache = A.getInfoCache();
10321 if (Function *F = getAnchorScope()) {
10322 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(F: *F);
10323 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(F: *F);
10324 }
10325 State.setKnown(isGuaranteedNotToBeUndefOrPoison(V: UseV, AC, CtxI: I, DT));
10326 bool TrackUse = false;
10327 // Track use for instructions which must produce undef or poison bits when
10328 // at least one operand contains such bits.
10329 if (isa<CastInst>(Val: *I) || isa<GetElementPtrInst>(Val: *I))
10330 TrackUse = true;
10331 return TrackUse;
10332 }
10333
10334 /// See AbstractAttribute::getAsStr().
10335 const std::string getAsStr(Attributor *A) const override {
10336 return getAssumed() ? "noundef" : "may-undef-or-poison";
10337 }
10338
10339 ChangeStatus manifest(Attributor &A) override {
10340 // We don't manifest noundef attribute for dead positions because the
10341 // associated values with dead positions would be replaced with undef
10342 // values.
10343 bool UsedAssumedInformation = false;
10344 if (A.isAssumedDead(IRP: getIRPosition(), QueryingAA: nullptr, FnLivenessAA: nullptr,
10345 UsedAssumedInformation))
10346 return ChangeStatus::UNCHANGED;
10347 // A position whose simplified value does not have any value is
10348 // considered to be dead. We don't manifest noundef in such positions for
10349 // the same reason above.
10350 if (!A.getAssumedSimplified(IRP: getIRPosition(), AA: *this, UsedAssumedInformation,
10351 S: AA::Interprocedural)
10352 .has_value())
10353 return ChangeStatus::UNCHANGED;
10354 return AANoUndef::manifest(A);
10355 }
10356};
10357
10358struct AANoUndefFloating : public AANoUndefImpl {
10359 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10360 : AANoUndefImpl(IRP, A) {}
10361
10362 /// See AbstractAttribute::initialize(...).
10363 void initialize(Attributor &A) override {
10364 AANoUndefImpl::initialize(A);
10365 if (!getState().isAtFixpoint() && getAnchorScope() &&
10366 !getAnchorScope()->isDeclaration())
10367 if (Instruction *CtxI = getCtxI())
10368 followUsesInMBEC(AA&: *this, A, S&: getState(), CtxI&: *CtxI);
10369 }
10370
10371 /// See AbstractAttribute::updateImpl(...).
10372 ChangeStatus updateImpl(Attributor &A) override {
10373 auto VisitValueCB = [&](const IRPosition &IRP) -> bool {
10374 bool IsKnownNoUndef;
10375 return AA::hasAssumedIRAttr<Attribute::NoUndef>(
10376 A, QueryingAA: this, IRP, DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNoUndef);
10377 };
10378
10379 bool Stripped;
10380 bool UsedAssumedInformation = false;
10381 Value *AssociatedValue = &getAssociatedValue();
10382 SmallVector<AA::ValueAndContext> Values;
10383 if (!A.getAssumedSimplifiedValues(IRP: getIRPosition(), AA: *this, Values,
10384 S: AA::AnyScope, UsedAssumedInformation))
10385 Stripped = false;
10386 else
10387 Stripped =
10388 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
10389
10390 if (!Stripped) {
10391 // If we haven't stripped anything we might still be able to use a
10392 // different AA, but only if the IRP changes. Effectively when we
10393 // interpret this not as a call site value but as a floating/argument
10394 // value.
10395 const IRPosition AVIRP = IRPosition::value(V: *AssociatedValue);
10396 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10397 return indicatePessimisticFixpoint();
10398 return ChangeStatus::UNCHANGED;
10399 }
10400
10401 for (const auto &VAC : Values)
10402 if (!VisitValueCB(IRPosition::value(V: *VAC.getValue())))
10403 return indicatePessimisticFixpoint();
10404
10405 return ChangeStatus::UNCHANGED;
10406 }
10407
10408 /// See AbstractAttribute::trackStatistics()
10409 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10410};
10411
10412struct AANoUndefReturned final
10413 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10414 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10415 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10416
10417 /// See AbstractAttribute::trackStatistics()
10418 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10419};
10420
10421struct AANoUndefArgument final
10422 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10423 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10424 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10425
10426 /// See AbstractAttribute::trackStatistics()
10427 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
10428};
10429
10430struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10431 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10432 : AANoUndefFloating(IRP, A) {}
10433
10434 /// See AbstractAttribute::trackStatistics()
10435 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
10436};
10437
10438struct AANoUndefCallSiteReturned final
10439 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10440 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10441 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP, A) {}
10442
10443 /// See AbstractAttribute::trackStatistics()
10444 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
10445};
10446
10447/// ------------------------ NoFPClass Attribute -------------------------------
10448
10449struct AANoFPClassImpl : AANoFPClass {
10450 AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}
10451
10452 void initialize(Attributor &A) override {
10453 const IRPosition &IRP = getIRPosition();
10454
10455 Value &V = IRP.getAssociatedValue();
10456 if (isa<UndefValue>(Val: V)) {
10457 indicateOptimisticFixpoint();
10458 return;
10459 }
10460
10461 SmallVector<Attribute> Attrs;
10462 A.getAttrs(IRP: getIRPosition(), AKs: {Attribute::NoFPClass}, Attrs, IgnoreSubsumingPositions: false);
10463 for (const auto &Attr : Attrs) {
10464 addKnownBits(Bits: Attr.getNoFPClass());
10465 }
10466
10467 Instruction *CtxI = getCtxI();
10468
10469 if (getPositionKind() != IRPosition::IRP_RETURNED) {
10470 const DataLayout &DL = A.getDataLayout();
10471 InformationCache &InfoCache = A.getInfoCache();
10472
10473 const DominatorTree *DT = nullptr;
10474 AssumptionCache *AC = nullptr;
10475 const TargetLibraryInfo *TLI = nullptr;
10476 Function *F = getAnchorScope();
10477 if (F) {
10478 TLI = InfoCache.getTargetLibraryInfoForFunction(F: *F);
10479 if (!F->isDeclaration()) {
10480 DT =
10481 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(F: *F);
10482 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(F: *F);
10483 }
10484 }
10485
10486 SimplifyQuery Q(DL, TLI, DT, AC, CtxI);
10487
10488 KnownFPClass KnownFPClass = computeKnownFPClass(V: &V, InterestedClasses: fcAllFlags, SQ: Q);
10489 addKnownBits(Bits: ~KnownFPClass.KnownFPClasses);
10490 }
10491
10492 if (CtxI)
10493 followUsesInMBEC(AA&: *this, A, S&: getState(), CtxI&: *CtxI);
10494 }
10495
10496 /// See followUsesInMBEC
10497 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10498 AANoFPClass::StateType &State) {
10499 // TODO: Determine what instructions can be looked through.
10500 auto *CB = dyn_cast<CallBase>(Val: I);
10501 if (!CB)
10502 return false;
10503
10504 if (!CB->isArgOperand(U))
10505 return false;
10506
10507 unsigned ArgNo = CB->getArgOperandNo(U);
10508 IRPosition IRP = IRPosition::callsite_argument(CB: *CB, ArgNo);
10509 if (auto *NoFPAA = A.getAAFor<AANoFPClass>(QueryingAA: *this, IRP, DepClass: DepClassTy::NONE))
10510 State.addKnownBits(Bits: NoFPAA->getState().getKnown());
10511 return false;
10512 }
10513
10514 const std::string getAsStr(Attributor *A) const override {
10515 std::string Result = "nofpclass";
10516 raw_string_ostream OS(Result);
10517 OS << getKnownNoFPClass() << '/' << getAssumedNoFPClass();
10518 return Result;
10519 }
10520
10521 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
10522 SmallVectorImpl<Attribute> &Attrs) const override {
10523 Attrs.emplace_back(Args: Attribute::getWithNoFPClass(Context&: Ctx, Mask: getAssumedNoFPClass()));
10524 }
10525};
10526
10527struct AANoFPClassFloating : public AANoFPClassImpl {
10528 AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
10529 : AANoFPClassImpl(IRP, A) {}
10530
10531 /// See AbstractAttribute::updateImpl(...).
10532 ChangeStatus updateImpl(Attributor &A) override {
10533 SmallVector<AA::ValueAndContext> Values;
10534 bool UsedAssumedInformation = false;
10535 if (!A.getAssumedSimplifiedValues(IRP: getIRPosition(), AA: *this, Values,
10536 S: AA::AnyScope, UsedAssumedInformation)) {
10537 Values.push_back(Elt: {getAssociatedValue(), getCtxI()});
10538 }
10539
10540 StateType T;
10541 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10542 const auto *AA = A.getAAFor<AANoFPClass>(QueryingAA: *this, IRP: IRPosition::value(V),
10543 DepClass: DepClassTy::REQUIRED);
10544 if (!AA || this == AA) {
10545 T.indicatePessimisticFixpoint();
10546 } else {
10547 const AANoFPClass::StateType &S =
10548 static_cast<const AANoFPClass::StateType &>(AA->getState());
10549 T ^= S;
10550 }
10551 return T.isValidState();
10552 };
10553
10554 for (const auto &VAC : Values)
10555 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10556 return indicatePessimisticFixpoint();
10557
10558 return clampStateAndIndicateChange(S&: getState(), R: T);
10559 }
10560
10561 /// See AbstractAttribute::trackStatistics()
10562 void trackStatistics() const override {
10563 STATS_DECLTRACK_FNRET_ATTR(nofpclass)
10564 }
10565};
10566
10567struct AANoFPClassReturned final
10568 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10569 AANoFPClassImpl::StateType, false,
10570 Attribute::None, false> {
10571 AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
10572 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10573 AANoFPClassImpl::StateType, false,
10574 Attribute::None, false>(IRP, A) {}
10575
10576 /// See AbstractAttribute::trackStatistics()
10577 void trackStatistics() const override {
10578 STATS_DECLTRACK_FNRET_ATTR(nofpclass)
10579 }
10580};
10581
10582struct AANoFPClassArgument final
10583 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10584 AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
10585 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10586
10587 /// See AbstractAttribute::trackStatistics()
10588 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }
10589};
10590
10591struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10592 AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
10593 : AANoFPClassFloating(IRP, A) {}
10594
10595 /// See AbstractAttribute::trackStatistics()
10596 void trackStatistics() const override {
10597 STATS_DECLTRACK_CSARG_ATTR(nofpclass)
10598 }
10599};
10600
10601struct AANoFPClassCallSiteReturned final
10602 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10603 AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
10604 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10605
10606 /// See AbstractAttribute::trackStatistics()
10607 void trackStatistics() const override {
10608 STATS_DECLTRACK_CSRET_ATTR(nofpclass)
10609 }
10610};
10611
10612struct AACallEdgesImpl : public AACallEdges {
10613 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10614
10615 const SetVector<Function *> &getOptimisticEdges() const override {
10616 return CalledFunctions;
10617 }
10618
10619 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10620
10621 bool hasNonAsmUnknownCallee() const override {
10622 return HasUnknownCalleeNonAsm;
10623 }
10624
10625 const std::string getAsStr(Attributor *A) const override {
10626 return "CallEdges[" + std::to_string(val: HasUnknownCallee) + "," +
10627 std::to_string(val: CalledFunctions.size()) + "]";
10628 }
10629
10630 void trackStatistics() const override {}
10631
10632protected:
10633 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10634 if (CalledFunctions.insert(X: Fn)) {
10635 Change = ChangeStatus::CHANGED;
10636 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
10637 << "\n");
10638 }
10639 }
10640
10641 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10642 if (!HasUnknownCallee)
10643 Change = ChangeStatus::CHANGED;
10644 if (NonAsm && !HasUnknownCalleeNonAsm)
10645 Change = ChangeStatus::CHANGED;
10646 HasUnknownCalleeNonAsm |= NonAsm;
10647 HasUnknownCallee = true;
10648 }
10649
10650private:
10651 /// Optimistic set of functions that might be called by this position.
10652 SetVector<Function *> CalledFunctions;
10653
10654 /// Is there any call with a unknown callee.
10655 bool HasUnknownCallee = false;
10656
10657 /// Is there any call with a unknown callee, excluding any inline asm.
10658 bool HasUnknownCalleeNonAsm = false;
10659};
10660
10661struct AACallEdgesCallSite : public AACallEdgesImpl {
10662 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10663 : AACallEdgesImpl(IRP, A) {}
10664 /// See AbstractAttribute::updateImpl(...).
10665 ChangeStatus updateImpl(Attributor &A) override {
10666 ChangeStatus Change = ChangeStatus::UNCHANGED;
10667
10668 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10669 if (Function *Fn = dyn_cast<Function>(Val: &V)) {
10670 addCalledFunction(Fn, Change);
10671 } else {
10672 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
10673 setHasUnknownCallee(NonAsm: true, Change);
10674 }
10675
10676 // Explore all values.
10677 return true;
10678 };
10679
10680 SmallVector<AA::ValueAndContext> Values;
10681 // Process any value that we might call.
10682 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10683 if (isa<Constant>(Val: V)) {
10684 VisitValue(*V, CtxI);
10685 return;
10686 }
10687
10688 bool UsedAssumedInformation = false;
10689 Values.clear();
10690 if (!A.getAssumedSimplifiedValues(IRP: IRPosition::value(V: *V), AA: *this, Values,
10691 S: AA::AnyScope, UsedAssumedInformation)) {
10692 Values.push_back(Elt: {*V, CtxI});
10693 }
10694 for (auto &VAC : Values)
10695 VisitValue(*VAC.getValue(), VAC.getCtxI());
10696 };
10697
10698 CallBase *CB = cast<CallBase>(Val: getCtxI());
10699
10700 if (auto *IA = dyn_cast<InlineAsm>(Val: CB->getCalledOperand())) {
10701 if (IA->hasSideEffects() &&
10702 !hasAssumption(F: *CB->getCaller(), AssumptionStr: "ompx_no_call_asm") &&
10703 !hasAssumption(CB: *CB, AssumptionStr: "ompx_no_call_asm")) {
10704 setHasUnknownCallee(NonAsm: false, Change);
10705 }
10706 return Change;
10707 }
10708
10709 if (CB->isIndirectCall())
10710 if (auto *IndirectCallAA = A.getAAFor<AAIndirectCallInfo>(
10711 QueryingAA: *this, IRP: getIRPosition(), DepClass: DepClassTy::OPTIONAL))
10712 if (IndirectCallAA->foreachCallee(
10713 CB: [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10714 return Change;
10715
10716 // The most simple case.
10717 ProcessCalledOperand(CB->getCalledOperand(), CB);
10718
10719 // Process callback functions.
10720 SmallVector<const Use *, 4u> CallbackUses;
10721 AbstractCallSite::getCallbackUses(CB: *CB, CallbackUses);
10722 for (const Use *U : CallbackUses)
10723 ProcessCalledOperand(U->get(), CB);
10724
10725 return Change;
10726 }
10727};
10728
10729struct AACallEdgesFunction : public AACallEdgesImpl {
10730 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10731 : AACallEdgesImpl(IRP, A) {}
10732
10733 /// See AbstractAttribute::updateImpl(...).
10734 ChangeStatus updateImpl(Attributor &A) override {
10735 ChangeStatus Change = ChangeStatus::UNCHANGED;
10736
10737 auto ProcessCallInst = [&](Instruction &Inst) {
10738 CallBase &CB = cast<CallBase>(Val&: Inst);
10739
10740 auto *CBEdges = A.getAAFor<AACallEdges>(
10741 QueryingAA: *this, IRP: IRPosition::callsite_function(CB), DepClass: DepClassTy::REQUIRED);
10742 if (!CBEdges)
10743 return false;
10744 if (CBEdges->hasNonAsmUnknownCallee())
10745 setHasUnknownCallee(NonAsm: true, Change);
10746 if (CBEdges->hasUnknownCallee())
10747 setHasUnknownCallee(NonAsm: false, Change);
10748
10749 for (Function *F : CBEdges->getOptimisticEdges())
10750 addCalledFunction(Fn: F, Change);
10751
10752 return true;
10753 };
10754
10755 // Visit all callable instructions.
10756 bool UsedAssumedInformation = false;
10757 if (!A.checkForAllCallLikeInstructions(Pred: ProcessCallInst, QueryingAA: *this,
10758 UsedAssumedInformation,
10759 /* CheckBBLivenessOnly */ true)) {
10760 // If we haven't looked at all call like instructions, assume that there
10761 // are unknown callees.
10762 setHasUnknownCallee(NonAsm: true, Change);
10763 }
10764
10765 return Change;
10766 }
10767};
10768
10769/// -------------------AAInterFnReachability Attribute--------------------------
10770
10771struct AAInterFnReachabilityFunction
10772 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10773 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10774 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10775 : Base(IRP, A) {}
10776
10777 bool instructionCanReach(
10778 Attributor &A, const Instruction &From, const Function &To,
10779 const AA::InstExclusionSetTy *ExclusionSet) const override {
10780 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
10781 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10782
10783 RQITy StackRQI(A, From, To, ExclusionSet, false);
10784 RQITy::Reachable Result;
10785 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
10786 return NonConstThis->isReachableImpl(A, RQI&: StackRQI,
10787 /*IsTemporaryRQI=*/true);
10788 return Result == RQITy::Reachable::Yes;
10789 }
10790
10791 bool isReachableImpl(Attributor &A, RQITy &RQI,
10792 bool IsTemporaryRQI) override {
10793 const Instruction *EntryI =
10794 &RQI.From->getFunction()->getEntryBlock().front();
10795 if (EntryI != RQI.From &&
10796 !instructionCanReach(A, From: *EntryI, To: *RQI.To, ExclusionSet: nullptr))
10797 return rememberResult(A, Result: RQITy::Reachable::No, RQI, UsedExclusionSet: false,
10798 IsTemporaryRQI);
10799
10800 auto CheckReachableCallBase = [&](CallBase *CB) {
10801 auto *CBEdges = A.getAAFor<AACallEdges>(
10802 QueryingAA: *this, IRP: IRPosition::callsite_function(CB: *CB), DepClass: DepClassTy::OPTIONAL);
10803 if (!CBEdges || !CBEdges->getState().isValidState())
10804 return false;
10805 // TODO Check To backwards in this case.
10806 if (CBEdges->hasUnknownCallee())
10807 return false;
10808
10809 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10810 if (Fn == RQI.To)
10811 return false;
10812
10813 if (Fn->isDeclaration()) {
10814 if (Fn->hasFnAttribute(Kind: Attribute::NoCallback))
10815 continue;
10816 // TODO Check To backwards in this case.
10817 return false;
10818 }
10819
10820 if (Fn == getAnchorScope()) {
10821 if (EntryI == RQI.From)
10822 continue;
10823 return false;
10824 }
10825
10826 const AAInterFnReachability *InterFnReachability =
10827 A.getAAFor<AAInterFnReachability>(QueryingAA: *this, IRP: IRPosition::function(F: *Fn),
10828 DepClass: DepClassTy::OPTIONAL);
10829
10830 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10831 if (!InterFnReachability ||
10832 InterFnReachability->instructionCanReach(A, Inst: FnFirstInst, Fn: *RQI.To,
10833 ExclusionSet: RQI.ExclusionSet))
10834 return false;
10835 }
10836 return true;
10837 };
10838
10839 const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10840 QueryingAA: *this, IRP: IRPosition::function(F: *RQI.From->getFunction()),
10841 DepClass: DepClassTy::OPTIONAL);
10842
10843 // Determine call like instructions that we can reach from the inst.
10844 auto CheckCallBase = [&](Instruction &CBInst) {
10845 // There are usually less nodes in the call graph, check inter function
10846 // reachability first.
10847 if (CheckReachableCallBase(cast<CallBase>(Val: &CBInst)))
10848 return true;
10849 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10850 A, From: *RQI.From, To: CBInst, ExclusionSet: RQI.ExclusionSet);
10851 };
10852
10853 bool UsedExclusionSet = /* conservative */ true;
10854 bool UsedAssumedInformation = false;
10855 if (!A.checkForAllCallLikeInstructions(Pred: CheckCallBase, QueryingAA: *this,
10856 UsedAssumedInformation,
10857 /* CheckBBLivenessOnly */ true))
10858 return rememberResult(A, Result: RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10859 IsTemporaryRQI);
10860
10861 return rememberResult(A, Result: RQITy::Reachable::No, RQI, UsedExclusionSet,
10862 IsTemporaryRQI);
10863 }
10864
10865 void trackStatistics() const override {}
10866};
10867} // namespace
10868
10869template <typename AAType>
10870static std::optional<Constant *>
10871askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA,
10872 const IRPosition &IRP, Type &Ty) {
10873 if (!Ty.isIntegerTy())
10874 return nullptr;
10875
10876 // This will also pass the call base context.
10877 const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10878 if (!AA)
10879 return nullptr;
10880
10881 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
10882
10883 if (!COpt.has_value()) {
10884 A.recordDependence(FromAA: *AA, ToAA: QueryingAA, DepClass: DepClassTy::OPTIONAL);
10885 return std::nullopt;
10886 }
10887 if (auto *C = *COpt) {
10888 A.recordDependence(FromAA: *AA, ToAA: QueryingAA, DepClass: DepClassTy::OPTIONAL);
10889 return C;
10890 }
10891 return nullptr;
10892}
10893
10894Value *AAPotentialValues::getSingleValue(
10895 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10896 SmallVectorImpl<AA::ValueAndContext> &Values) {
10897 Type &Ty = *IRP.getAssociatedType();
10898 std::optional<Value *> V;
10899 for (auto &It : Values) {
10900 V = AA::combineOptionalValuesInAAValueLatice(A: V, B: It.getValue(), Ty: &Ty);
10901 if (V.has_value() && !*V)
10902 break;
10903 }
10904 if (!V.has_value())
10905 return UndefValue::get(T: &Ty);
10906 return *V;
10907}
10908
10909namespace {
10910struct AAPotentialValuesImpl : AAPotentialValues {
10911 using StateType = PotentialLLVMValuesState;
10912
10913 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10914 : AAPotentialValues(IRP, A) {}
10915
10916 /// See AbstractAttribute::initialize(..).
10917 void initialize(Attributor &A) override {
10918 if (A.hasSimplificationCallback(IRP: getIRPosition())) {
10919 indicatePessimisticFixpoint();
10920 return;
10921 }
10922 Value *Stripped = getAssociatedValue().stripPointerCasts();
10923 if (isa<Constant>(Val: Stripped) && !isa<ConstantExpr>(Val: Stripped)) {
10924 addValue(A, State&: getState(), V&: *Stripped, CtxI: getCtxI(), S: AA::AnyScope,
10925 AnchorScope: getAnchorScope());
10926 indicateOptimisticFixpoint();
10927 return;
10928 }
10929 AAPotentialValues::initialize(A);
10930 }
10931
10932 /// See AbstractAttribute::getAsStr().
10933 const std::string getAsStr(Attributor *A) const override {
10934 std::string Str;
10935 llvm::raw_string_ostream OS(Str);
10936 OS << getState();
10937 return Str;
10938 }
10939
10940 template <typename AAType>
10941 static std::optional<Value *> askOtherAA(Attributor &A,
10942 const AbstractAttribute &AA,
10943 const IRPosition &IRP, Type &Ty) {
10944 if (isa<Constant>(Val: IRP.getAssociatedValue()))
10945 return &IRP.getAssociatedValue();
10946 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10947 if (!C)
10948 return std::nullopt;
10949 if (*C)
10950 if (auto *CC = AA::getWithType(V&: **C, Ty))
10951 return CC;
10952 return nullptr;
10953 }
10954
10955 virtual void addValue(Attributor &A, StateType &State, Value &V,
10956 const Instruction *CtxI, AA::ValueScope S,
10957 Function *AnchorScope) const {
10958
10959 IRPosition ValIRP = IRPosition::value(V);
10960 if (auto *CB = dyn_cast_or_null<CallBase>(Val: CtxI)) {
10961 for (const auto &U : CB->args()) {
10962 if (U.get() != &V)
10963 continue;
10964 ValIRP = IRPosition::callsite_argument(CB: *CB, ArgNo: CB->getArgOperandNo(U: &U));
10965 break;
10966 }
10967 }
10968
10969 Value *VPtr = &V;
10970 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10971 Type &Ty = *getAssociatedType();
10972 std::optional<Value *> SimpleV =
10973 askOtherAA<AAValueConstantRange>(A, AA: *this, IRP: ValIRP, Ty);
10974 if (SimpleV.has_value() && !*SimpleV) {
10975 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10976 QueryingAA: *this, IRP: ValIRP, DepClass: DepClassTy::OPTIONAL);
10977 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10978 for (const auto &It : PotentialConstantsAA->getAssumedSet())
10979 State.unionAssumed(C: {{*ConstantInt::get(Ty: &Ty, V: It), nullptr}, S});
10980 if (PotentialConstantsAA->undefIsContained())
10981 State.unionAssumed(C: {{*UndefValue::get(T: &Ty), nullptr}, S});
10982 return;
10983 }
10984 }
10985 if (!SimpleV.has_value())
10986 return;
10987
10988 if (*SimpleV)
10989 VPtr = *SimpleV;
10990 }
10991
10992 if (isa<ConstantInt>(Val: VPtr))
10993 CtxI = nullptr;
10994 if (!AA::isValidInScope(V: *VPtr, Scope: AnchorScope))
10995 S = AA::ValueScope(S | AA::Interprocedural);
10996
10997 State.unionAssumed(C: {{*VPtr, CtxI}, S});
10998 }
10999
11000 /// Helper struct to tie a value+context pair together with the scope for
11001 /// which this is the simplified version.
11002 struct ItemInfo {
11003 AA::ValueAndContext I;
11004 AA::ValueScope S;
11005
11006 bool operator==(const ItemInfo &II) const {
11007 return II.I == I && II.S == S;
11008 };
11009 bool operator<(const ItemInfo &II) const {
11010 return std::tie(args: I, args: S) < std::tie(args: II.I, args: II.S);
11011 };
11012 };
11013
11014 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
11015 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11016 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
11017 if (!(CS & S))
11018 continue;
11019
11020 bool UsedAssumedInformation = false;
11021 SmallVector<AA::ValueAndContext> Values;
11022 if (!A.getAssumedSimplifiedValues(IRP, AA: this, Values, S: CS,
11023 UsedAssumedInformation))
11024 return false;
11025
11026 for (auto &It : Values)
11027 ValueScopeMap[It] += CS;
11028 }
11029 for (auto &It : ValueScopeMap)
11030 addValue(A, State&: getState(), V&: *It.first.getValue(), CtxI: It.first.getCtxI(),
11031 S: AA::ValueScope(It.second), AnchorScope: getAnchorScope());
11032
11033 return true;
11034 }
11035
11036 void giveUpOnIntraprocedural(Attributor &A) {
11037 auto NewS = StateType::getBestState(PVS: getState());
11038 for (const auto &It : getAssumedSet()) {
11039 if (It.second == AA::Intraprocedural)
11040 continue;
11041 addValue(A, State&: NewS, V&: *It.first.getValue(), CtxI: It.first.getCtxI(),
11042 S: AA::Interprocedural, AnchorScope: getAnchorScope());
11043 }
11044 assert(!undefIsContained() && "Undef should be an explicit value!");
11045 addValue(A, State&: NewS, V&: getAssociatedValue(), CtxI: getCtxI(), S: AA::Intraprocedural,
11046 AnchorScope: getAnchorScope());
11047 getState() = NewS;
11048 }
11049
11050 /// See AbstractState::indicatePessimisticFixpoint(...).
11051 ChangeStatus indicatePessimisticFixpoint() override {
11052 getState() = StateType::getBestState(PVS: getState());
11053 getState().unionAssumed(C: {{getAssociatedValue(), getCtxI()}, AA::AnyScope});
11054 AAPotentialValues::indicateOptimisticFixpoint();
11055 return ChangeStatus::CHANGED;
11056 }
11057
11058 /// See AbstractAttribute::updateImpl(...).
11059 ChangeStatus updateImpl(Attributor &A) override {
11060 return indicatePessimisticFixpoint();
11061 }
11062
11063 /// See AbstractAttribute::manifest(...).
11064 ChangeStatus manifest(Attributor &A) override {
11065 SmallVector<AA::ValueAndContext> Values;
11066 for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {
11067 Values.clear();
11068 if (!getAssumedSimplifiedValues(A, Values, S))
11069 continue;
11070 Value &OldV = getAssociatedValue();
11071 if (isa<UndefValue>(Val: OldV))
11072 continue;
11073 Value *NewV = getSingleValue(A, AA: *this, IRP: getIRPosition(), Values);
11074 if (!NewV || NewV == &OldV)
11075 continue;
11076 if (getCtxI() &&
11077 !AA::isValidAtPosition(VAC: {*NewV, *getCtxI()}, InfoCache&: A.getInfoCache()))
11078 continue;
11079 if (A.changeAfterManifest(IRP: getIRPosition(), NV&: *NewV))
11080 return ChangeStatus::CHANGED;
11081 }
11082 return ChangeStatus::UNCHANGED;
11083 }
11084
11085 bool getAssumedSimplifiedValues(
11086 Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,
11087 AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {
11088 if (!isValidState())
11089 return false;
11090 bool UsedAssumedInformation = false;
11091 for (const auto &It : getAssumedSet())
11092 if (It.second & S) {
11093 if (RecurseForSelectAndPHI && (isa<PHINode>(Val: It.first.getValue()) ||
11094 isa<SelectInst>(Val: It.first.getValue()))) {
11095 if (A.getAssumedSimplifiedValues(
11096 IRP: IRPosition::inst(I: *cast<Instruction>(Val: It.first.getValue())),
11097 AA: this, Values, S, UsedAssumedInformation))
11098 continue;
11099 }
11100 Values.push_back(Elt: It.first);
11101 }
11102 assert(!undefIsContained() && "Undef should be an explicit value!");
11103 return true;
11104 }
11105};
11106
11107struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11108 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
11109 : AAPotentialValuesImpl(IRP, A) {}
11110
11111 /// See AbstractAttribute::updateImpl(...).
11112 ChangeStatus updateImpl(Attributor &A) override {
11113 auto AssumedBefore = getAssumed();
11114
11115 genericValueTraversal(A, InitialV: &getAssociatedValue());
11116
11117 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11118 : ChangeStatus::CHANGED;
11119 }
11120
11121 /// Helper struct to remember which AAIsDead instances we actually used.
11122 struct LivenessInfo {
11123 const AAIsDead *LivenessAA = nullptr;
11124 bool AnyDead = false;
11125 };
11126
11127 /// Check if \p Cmp is a comparison we can simplify.
11128 ///
11129 /// We handle multiple cases, one in which at least one operand is an
11130 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
11131 /// operand. Return true if successful, in that case Worklist will be updated.
11132 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
11133 CmpInst::Predicate Pred, ItemInfo II,
11134 SmallVectorImpl<ItemInfo> &Worklist) {
11135
11136 // Simplify the operands first.
11137 bool UsedAssumedInformation = false;
11138 SmallVector<AA::ValueAndContext> LHSValues, RHSValues;
11139 auto GetSimplifiedValues = [&](Value &V,
11140 SmallVector<AA::ValueAndContext> &Values) {
11141 if (!A.getAssumedSimplifiedValues(
11142 IRP: IRPosition::value(V, CBContext: getCallBaseContext()), AA: this, Values,
11143 S: AA::Intraprocedural, UsedAssumedInformation)) {
11144 Values.clear();
11145 Values.push_back(Elt: AA::ValueAndContext{V, II.I.getCtxI()});
11146 }
11147 return Values.empty();
11148 };
11149 if (GetSimplifiedValues(*LHS, LHSValues))
11150 return true;
11151 if (GetSimplifiedValues(*RHS, RHSValues))
11152 return true;
11153
11154 LLVMContext &Ctx = LHS->getContext();
11155
11156 InformationCache &InfoCache = A.getInfoCache();
11157 Instruction *CmpI = dyn_cast<Instruction>(Val: &Cmp);
11158 Function *F = CmpI ? CmpI->getFunction() : nullptr;
11159 const auto *DT =
11160 F ? InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(F: *F)
11161 : nullptr;
11162 const auto *TLI =
11163 F ? A.getInfoCache().getTargetLibraryInfoForFunction(F: *F) : nullptr;
11164 auto *AC =
11165 F ? InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(F: *F)
11166 : nullptr;
11167
11168 const DataLayout &DL = A.getDataLayout();
11169 SimplifyQuery Q(DL, TLI, DT, AC, CmpI);
11170
11171 auto CheckPair = [&](Value &LHSV, Value &RHSV) {
11172 if (isa<UndefValue>(Val: LHSV) || isa<UndefValue>(Val: RHSV)) {
11173 addValue(A, State&: getState(), V&: *UndefValue::get(T: Cmp.getType()),
11174 /* CtxI */ nullptr, S: II.S, AnchorScope: getAnchorScope());
11175 return true;
11176 }
11177
11178 // Handle the trivial case first in which we don't even need to think
11179 // about null or non-null.
11180 if (&LHSV == &RHSV &&
11181 (CmpInst::isTrueWhenEqual(predicate: Pred) || CmpInst::isFalseWhenEqual(predicate: Pred))) {
11182 Constant *NewV = ConstantInt::get(Ty: Type::getInt1Ty(C&: Ctx),
11183 V: CmpInst::isTrueWhenEqual(predicate: Pred));
11184 addValue(A, State&: getState(), V&: *NewV, /* CtxI */ nullptr, S: II.S,
11185 AnchorScope: getAnchorScope());
11186 return true;
11187 }
11188
11189 auto *TypedLHS = AA::getWithType(V&: LHSV, Ty&: *LHS->getType());
11190 auto *TypedRHS = AA::getWithType(V&: RHSV, Ty&: *RHS->getType());
11191 if (TypedLHS && TypedRHS) {
11192 Value *NewV = simplifyCmpInst(Predicate: Pred, LHS: TypedLHS, RHS: TypedRHS, Q);
11193 if (NewV && NewV != &Cmp) {
11194 addValue(A, State&: getState(), V&: *NewV, /* CtxI */ nullptr, S: II.S,
11195 AnchorScope: getAnchorScope());
11196 return true;
11197 }
11198 }
11199
11200 // From now on we only handle equalities (==, !=).
11201 if (!CmpInst::isEquality(pred: Pred))
11202 return false;
11203
11204 bool LHSIsNull = isa<ConstantPointerNull>(Val: LHSV);
11205 bool RHSIsNull = isa<ConstantPointerNull>(Val: RHSV);
11206 if (!LHSIsNull && !RHSIsNull)
11207 return false;
11208
11209 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
11210 // non-nullptr operand and if we assume it's non-null we can conclude the
11211 // result of the comparison.
11212 assert((LHSIsNull || RHSIsNull) &&
11213 "Expected nullptr versus non-nullptr comparison at this point");
11214
11215 // The index is the operand that we assume is not null.
11216 unsigned PtrIdx = LHSIsNull;
11217 bool IsKnownNonNull;
11218 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
11219 A, QueryingAA: this, IRP: IRPosition::value(V: *(PtrIdx ? &RHSV : &LHSV)),
11220 DepClass: DepClassTy::REQUIRED, IsKnown&: IsKnownNonNull);
11221 if (!IsAssumedNonNull)
11222 return false;
11223
11224 // The new value depends on the predicate, true for != and false for ==.
11225 Constant *NewV =
11226 ConstantInt::get(Ty: Type::getInt1Ty(C&: Ctx), V: Pred == CmpInst::ICMP_NE);
11227 addValue(A, State&: getState(), V&: *NewV, /* CtxI */ nullptr, S: II.S,
11228 AnchorScope: getAnchorScope());
11229 return true;
11230 };
11231
11232 for (auto &LHSValue : LHSValues)
11233 for (auto &RHSValue : RHSValues)
11234 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11235 return false;
11236 return true;
11237 }
11238
11239 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
11240 SmallVectorImpl<ItemInfo> &Worklist) {
11241 const Instruction *CtxI = II.I.getCtxI();
11242 bool UsedAssumedInformation = false;
11243
11244 std::optional<Constant *> C =
11245 A.getAssumedConstant(V: *SI.getCondition(), AA: *this, UsedAssumedInformation);
11246 bool NoValueYet = !C.has_value();
11247 if (NoValueYet || isa_and_nonnull<UndefValue>(Val: *C))
11248 return true;
11249 if (auto *CI = dyn_cast_or_null<ConstantInt>(Val: *C)) {
11250 if (CI->isZero())
11251 Worklist.push_back(Elt: {.I: {*SI.getFalseValue(), CtxI}, .S: II.S});
11252 else
11253 Worklist.push_back(Elt: {.I: {*SI.getTrueValue(), CtxI}, .S: II.S});
11254 } else if (&SI == &getAssociatedValue()) {
11255 // We could not simplify the condition, assume both values.
11256 Worklist.push_back(Elt: {.I: {*SI.getTrueValue(), CtxI}, .S: II.S});
11257 Worklist.push_back(Elt: {.I: {*SI.getFalseValue(), CtxI}, .S: II.S});
11258 } else {
11259 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11260 IRP: IRPosition::inst(I: SI), AA: *this, UsedAssumedInformation, S: II.S);
11261 if (!SimpleV.has_value())
11262 return true;
11263 if (*SimpleV) {
11264 addValue(A, State&: getState(), V&: **SimpleV, CtxI, S: II.S, AnchorScope: getAnchorScope());
11265 return true;
11266 }
11267 return false;
11268 }
11269 return true;
11270 }
11271
11272 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
11273 SmallVectorImpl<ItemInfo> &Worklist) {
11274 SmallSetVector<Value *, 4> PotentialCopies;
11275 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11276 bool UsedAssumedInformation = false;
11277 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialValues&: PotentialCopies,
11278 PotentialValueOrigins, QueryingAA: *this,
11279 UsedAssumedInformation,
11280 /* OnlyExact */ true)) {
11281 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
11282 "loaded values for load instruction "
11283 << LI << "\n");
11284 return false;
11285 }
11286
11287 // Do not simplify loads that are only used in llvm.assume if we cannot also
11288 // remove all stores that may feed into the load. The reason is that the
11289 // assume is probably worth something as long as the stores are around.
11290 InformationCache &InfoCache = A.getInfoCache();
11291 if (InfoCache.isOnlyUsedByAssume(I: LI)) {
11292 if (!llvm::all_of(Range&: PotentialValueOrigins, P: [&](Instruction *I) {
11293 if (!I || isa<AssumeInst>(Val: I))
11294 return true;
11295 if (auto *SI = dyn_cast<StoreInst>(Val: I))
11296 return A.isAssumedDead(U: SI->getOperandUse(i: 0), QueryingAA: this,
11297 /* LivenessAA */ FnLivenessAA: nullptr,
11298 UsedAssumedInformation,
11299 /* CheckBBLivenessOnly */ false);
11300 return A.isAssumedDead(I: *I, QueryingAA: this, /* LivenessAA */ nullptr,
11301 UsedAssumedInformation,
11302 /* CheckBBLivenessOnly */ false);
11303 })) {
11304 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
11305 "and we cannot delete all the stores: "
11306 << LI << "\n");
11307 return false;
11308 }
11309 }
11310
11311 // Values have to be dynamically unique or we loose the fact that a
11312 // single llvm::Value might represent two runtime values (e.g.,
11313 // stack locations in different recursive calls).
11314 const Instruction *CtxI = II.I.getCtxI();
11315 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
11316 bool AllLocal = ScopeIsLocal;
11317 bool DynamicallyUnique = llvm::all_of(Range&: PotentialCopies, P: [&](Value *PC) {
11318 AllLocal &= AA::isValidInScope(V: *PC, Scope: getAnchorScope());
11319 return AA::isDynamicallyUnique(A, QueryingAA: *this, V: *PC);
11320 });
11321 if (!DynamicallyUnique) {
11322 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
11323 "values are dynamically unique: "
11324 << LI << "\n");
11325 return false;
11326 }
11327
11328 for (auto *PotentialCopy : PotentialCopies) {
11329 if (AllLocal) {
11330 Worklist.push_back(Elt: {.I: {*PotentialCopy, CtxI}, .S: II.S});
11331 } else {
11332 Worklist.push_back(Elt: {.I: {*PotentialCopy, CtxI}, .S: AA::Interprocedural});
11333 }
11334 }
11335 if (!AllLocal && ScopeIsLocal)
11336 addValue(A, State&: getState(), V&: LI, CtxI, S: AA::Intraprocedural, AnchorScope: getAnchorScope());
11337 return true;
11338 }
11339
11340 bool handlePHINode(
11341 Attributor &A, PHINode &PHI, ItemInfo II,
11342 SmallVectorImpl<ItemInfo> &Worklist,
11343 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11344 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
11345 LivenessInfo &LI = LivenessAAs[&F];
11346 if (!LI.LivenessAA)
11347 LI.LivenessAA = A.getAAFor<AAIsDead>(QueryingAA: *this, IRP: IRPosition::function(F),
11348 DepClass: DepClassTy::NONE);
11349 return LI;
11350 };
11351
11352 if (&PHI == &getAssociatedValue()) {
11353 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
11354 const auto *CI =
11355 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11356 F: *PHI.getFunction());
11357
11358 Cycle *C = nullptr;
11359 bool CyclePHI = mayBeInCycle(CI, I: &PHI, /* HeaderOnly */ true, CPtr: &C);
11360 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
11361 BasicBlock *IncomingBB = PHI.getIncomingBlock(i: u);
11362 if (LI.LivenessAA &&
11363 LI.LivenessAA->isEdgeDead(From: IncomingBB, To: PHI.getParent())) {
11364 LI.AnyDead = true;
11365 continue;
11366 }
11367 Value *V = PHI.getIncomingValue(i: u);
11368 if (V == &PHI)
11369 continue;
11370
11371 // If the incoming value is not the PHI but an instruction in the same
11372 // cycle we might have multiple versions of it flying around.
11373 if (CyclePHI && isa<Instruction>(Val: V) &&
11374 (!C || C->contains(Block: cast<Instruction>(Val: V)->getParent())))
11375 return false;
11376
11377 Worklist.push_back(Elt: {.I: {*V, IncomingBB->getTerminator()}, .S: II.S});
11378 }
11379 return true;
11380 }
11381
11382 bool UsedAssumedInformation = false;
11383 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11384 IRP: IRPosition::inst(I: PHI), AA: *this, UsedAssumedInformation, S: II.S);
11385 if (!SimpleV.has_value())
11386 return true;
11387 if (!(*SimpleV))
11388 return false;
11389 addValue(A, State&: getState(), V&: **SimpleV, CtxI: &PHI, S: II.S, AnchorScope: getAnchorScope());
11390 return true;
11391 }
11392
11393 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
11394 /// simplify any operand of the instruction \p I. Return true if successful,
11395 /// in that case Worklist will be updated.
11396 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
11397 SmallVectorImpl<ItemInfo> &Worklist) {
11398 bool SomeSimplified = false;
11399 bool UsedAssumedInformation = false;
11400
11401 SmallVector<Value *, 8> NewOps(I.getNumOperands());
11402 int Idx = 0;
11403 for (Value *Op : I.operands()) {
11404 const auto &SimplifiedOp = A.getAssumedSimplified(
11405 IRP: IRPosition::value(V: *Op, CBContext: getCallBaseContext()), AA: *this,
11406 UsedAssumedInformation, S: AA::Intraprocedural);
11407 // If we are not sure about any operand we are not sure about the entire
11408 // instruction, we'll wait.
11409 if (!SimplifiedOp.has_value())
11410 return true;
11411
11412 if (*SimplifiedOp)
11413 NewOps[Idx] = *SimplifiedOp;
11414 else
11415 NewOps[Idx] = Op;
11416
11417 SomeSimplified |= (NewOps[Idx] != Op);
11418 ++Idx;
11419 }
11420
11421 // We won't bother with the InstSimplify interface if we didn't simplify any
11422 // operand ourselves.
11423 if (!SomeSimplified)
11424 return false;
11425
11426 InformationCache &InfoCache = A.getInfoCache();
11427 Function *F = I.getFunction();
11428 const auto *DT =
11429 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(F: *F);
11430 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(F: *F);
11431 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(F: *F);
11432
11433 const DataLayout &DL = I.getDataLayout();
11434 SimplifyQuery Q(DL, TLI, DT, AC, &I);
11435 Value *NewV = simplifyInstructionWithOperands(I: &I, NewOps, Q);
11436 if (!NewV || NewV == &I)
11437 return false;
11438
11439 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
11440 << *NewV << "\n");
11441 Worklist.push_back(Elt: {.I: {*NewV, II.I.getCtxI()}, .S: II.S});
11442 return true;
11443 }
11444
11445 bool simplifyInstruction(
11446 Attributor &A, Instruction &I, ItemInfo II,
11447 SmallVectorImpl<ItemInfo> &Worklist,
11448 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11449 if (auto *CI = dyn_cast<CmpInst>(Val: &I))
11450 return handleCmp(A, Cmp&: *CI, LHS: CI->getOperand(i_nocapture: 0), RHS: CI->getOperand(i_nocapture: 1),
11451 Pred: CI->getPredicate(), II, Worklist);
11452
11453 switch (I.getOpcode()) {
11454 case Instruction::Select:
11455 return handleSelectInst(A, SI&: cast<SelectInst>(Val&: I), II, Worklist);
11456 case Instruction::PHI:
11457 return handlePHINode(A, PHI&: cast<PHINode>(Val&: I), II, Worklist, LivenessAAs);
11458 case Instruction::Load:
11459 return handleLoadInst(A, LI&: cast<LoadInst>(Val&: I), II, Worklist);
11460 default:
11461 return handleGenericInst(A, I, II, Worklist);
11462 };
11463 return false;
11464 }
11465
11466 void genericValueTraversal(Attributor &A, Value *InitialV) {
11467 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11468
11469 SmallSet<ItemInfo, 16> Visited;
11470 SmallVector<ItemInfo, 16> Worklist;
11471 Worklist.push_back(Elt: {.I: {*InitialV, getCtxI()}, .S: AA::AnyScope});
11472
11473 int Iteration = 0;
11474 do {
11475 ItemInfo II = Worklist.pop_back_val();
11476 Value *V = II.I.getValue();
11477 assert(V);
11478 const Instruction *CtxI = II.I.getCtxI();
11479 AA::ValueScope S = II.S;
11480
11481 // Check if we should process the current value. To prevent endless
11482 // recursion keep a record of the values we followed!
11483 if (!Visited.insert(V: II).second)
11484 continue;
11485
11486 // Make sure we limit the compile time for complex expressions.
11487 if (Iteration++ >= MaxPotentialValuesIterations) {
11488 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
11489 << Iteration << "!\n");
11490 addValue(A, State&: getState(), V&: *V, CtxI, S, AnchorScope: getAnchorScope());
11491 continue;
11492 }
11493
11494 // Explicitly look through calls with a "returned" attribute if we do
11495 // not have a pointer as stripPointerCasts only works on them.
11496 Value *NewV = nullptr;
11497 if (V->getType()->isPointerTy()) {
11498 NewV = AA::getWithType(V&: *V->stripPointerCasts(), Ty&: *V->getType());
11499 } else {
11500 if (auto *CB = dyn_cast<CallBase>(Val: V))
11501 if (auto *Callee =
11502 dyn_cast_if_present<Function>(Val: CB->getCalledOperand())) {
11503 for (Argument &Arg : Callee->args())
11504 if (Arg.hasReturnedAttr()) {
11505 NewV = CB->getArgOperand(i: Arg.getArgNo());
11506 break;
11507 }
11508 }
11509 }
11510 if (NewV && NewV != V) {
11511 Worklist.push_back(Elt: {.I: {*NewV, CtxI}, .S: S});
11512 continue;
11513 }
11514
11515 if (auto *I = dyn_cast<Instruction>(Val: V)) {
11516 if (simplifyInstruction(A, I&: *I, II, Worklist, LivenessAAs))
11517 continue;
11518 }
11519
11520 if (V != InitialV || isa<Argument>(Val: V))
11521 if (recurseForValue(A, IRP: IRPosition::value(V: *V), S: II.S))
11522 continue;
11523
11524 // If we haven't stripped anything we give up.
11525 if (V == InitialV && CtxI == getCtxI()) {
11526 indicatePessimisticFixpoint();
11527 return;
11528 }
11529
11530 addValue(A, State&: getState(), V&: *V, CtxI, S, AnchorScope: getAnchorScope());
11531 } while (!Worklist.empty());
11532
11533 // If we actually used liveness information so we have to record a
11534 // dependence.
11535 for (auto &It : LivenessAAs)
11536 if (It.second.AnyDead)
11537 A.recordDependence(FromAA: *It.second.LivenessAA, ToAA: *this, DepClass: DepClassTy::OPTIONAL);
11538 }
11539
11540 /// See AbstractAttribute::trackStatistics()
11541 void trackStatistics() const override {
11542 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
11543 }
11544};
11545
11546struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11547 using Base = AAPotentialValuesImpl;
11548 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11549 : Base(IRP, A) {}
11550
11551 /// See AbstractAttribute::initialize(..).
11552 void initialize(Attributor &A) override {
11553 auto &Arg = cast<Argument>(Val&: getAssociatedValue());
11554 if (Arg.hasPointeeInMemoryValueAttr())
11555 indicatePessimisticFixpoint();
11556 }
11557
11558 /// See AbstractAttribute::updateImpl(...).
11559 ChangeStatus updateImpl(Attributor &A) override {
11560 auto AssumedBefore = getAssumed();
11561
11562 unsigned ArgNo = getCalleeArgNo();
11563
11564 bool UsedAssumedInformation = false;
11565 SmallVector<AA::ValueAndContext> Values;
11566 auto CallSitePred = [&](AbstractCallSite ACS) {
11567 const auto CSArgIRP = IRPosition::callsite_argument(ACS, ArgNo);
11568 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11569 return false;
11570
11571 if (!A.getAssumedSimplifiedValues(IRP: CSArgIRP, AA: this, Values,
11572 S: AA::Interprocedural,
11573 UsedAssumedInformation))
11574 return false;
11575
11576 return isValidState();
11577 };
11578
11579 if (!A.checkForAllCallSites(Pred: CallSitePred, QueryingAA: *this,
11580 /* RequireAllCallSites */ true,
11581 UsedAssumedInformation))
11582 return indicatePessimisticFixpoint();
11583
11584 Function *Fn = getAssociatedFunction();
11585 bool AnyNonLocal = false;
11586 for (auto &It : Values) {
11587 if (isa<Constant>(Val: It.getValue())) {
11588 addValue(A, State&: getState(), V&: *It.getValue(), CtxI: It.getCtxI(), S: AA::AnyScope,
11589 AnchorScope: getAnchorScope());
11590 continue;
11591 }
11592 if (!AA::isDynamicallyUnique(A, QueryingAA: *this, V: *It.getValue()))
11593 return indicatePessimisticFixpoint();
11594
11595 if (auto *Arg = dyn_cast<Argument>(Val: It.getValue()))
11596 if (Arg->getParent() == Fn) {
11597 addValue(A, State&: getState(), V&: *It.getValue(), CtxI: It.getCtxI(), S: AA::AnyScope,
11598 AnchorScope: getAnchorScope());
11599 continue;
11600 }
11601 addValue(A, State&: getState(), V&: *It.getValue(), CtxI: It.getCtxI(), S: AA::Interprocedural,
11602 AnchorScope: getAnchorScope());
11603 AnyNonLocal = true;
11604 }
11605 assert(!undefIsContained() && "Undef should be an explicit value!");
11606 if (AnyNonLocal)
11607 giveUpOnIntraprocedural(A);
11608
11609 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11610 : ChangeStatus::CHANGED;
11611 }
11612
11613 /// See AbstractAttribute::trackStatistics()
11614 void trackStatistics() const override {
11615 STATS_DECLTRACK_ARG_ATTR(potential_values)
11616 }
11617};
11618
11619struct AAPotentialValuesReturned : public AAPotentialValuesFloating {
11620 using Base = AAPotentialValuesFloating;
11621 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11622 : Base(IRP, A) {}
11623
11624 /// See AbstractAttribute::initialize(..).
11625 void initialize(Attributor &A) override {
11626 Function *F = getAssociatedFunction();
11627 if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {
11628 indicatePessimisticFixpoint();
11629 return;
11630 }
11631
11632 for (Argument &Arg : F->args())
11633 if (Arg.hasReturnedAttr()) {
11634 addValue(A, State&: getState(), V&: Arg, CtxI: nullptr, S: AA::AnyScope, AnchorScope: F);
11635 ReturnedArg = &Arg;
11636 break;
11637 }
11638 if (!A.isFunctionIPOAmendable(F: *F) ||
11639 A.hasSimplificationCallback(IRP: getIRPosition())) {
11640 if (!ReturnedArg)
11641 indicatePessimisticFixpoint();
11642 else
11643 indicateOptimisticFixpoint();
11644 }
11645 }
11646
11647 /// See AbstractAttribute::updateImpl(...).
11648 ChangeStatus updateImpl(Attributor &A) override {
11649 auto AssumedBefore = getAssumed();
11650 bool UsedAssumedInformation = false;
11651
11652 SmallVector<AA::ValueAndContext> Values;
11653 Function *AnchorScope = getAnchorScope();
11654 auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,
11655 bool AddValues) {
11656 for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {
11657 Values.clear();
11658 if (!A.getAssumedSimplifiedValues(IRP: IRPosition::value(V), AA: this, Values, S,
11659 UsedAssumedInformation,
11660 /* RecurseForSelectAndPHI */ true))
11661 return false;
11662 if (!AddValues)
11663 continue;
11664
11665 bool AllInterAreIntra = false;
11666 if (S == AA::Interprocedural)
11667 AllInterAreIntra =
11668 llvm::all_of(Range&: Values, P: [&](const AA::ValueAndContext &VAC) {
11669 return AA::isValidInScope(V: *VAC.getValue(), Scope: AnchorScope);
11670 });
11671
11672 for (const AA::ValueAndContext &VAC : Values) {
11673 addValue(A, State&: getState(), V&: *VAC.getValue(),
11674 CtxI: VAC.getCtxI() ? VAC.getCtxI() : CtxI,
11675 S: AllInterAreIntra ? AA::AnyScope : S, AnchorScope);
11676 }
11677 if (AllInterAreIntra)
11678 break;
11679 }
11680 return true;
11681 };
11682
11683 if (ReturnedArg) {
11684 HandleReturnedValue(*ReturnedArg, nullptr, true);
11685 } else {
11686 auto RetInstPred = [&](Instruction &RetI) {
11687 bool AddValues = true;
11688 if (isa<PHINode>(Val: RetI.getOperand(i: 0)) ||
11689 isa<SelectInst>(Val: RetI.getOperand(i: 0))) {
11690 addValue(A, State&: getState(), V&: *RetI.getOperand(i: 0), CtxI: &RetI, S: AA::AnyScope,
11691 AnchorScope);
11692 AddValues = false;
11693 }
11694 return HandleReturnedValue(*RetI.getOperand(i: 0), &RetI, AddValues);
11695 };
11696
11697 if (!A.checkForAllInstructions(Pred: RetInstPred, QueryingAA: *this, Opcodes: {Instruction::Ret},
11698 UsedAssumedInformation,
11699 /* CheckBBLivenessOnly */ true))
11700 return indicatePessimisticFixpoint();
11701 }
11702
11703 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11704 : ChangeStatus::CHANGED;
11705 }
11706
11707 ChangeStatus manifest(Attributor &A) override {
11708 if (ReturnedArg)
11709 return ChangeStatus::UNCHANGED;
11710 SmallVector<AA::ValueAndContext> Values;
11711 if (!getAssumedSimplifiedValues(A, Values, S: AA::ValueScope::Intraprocedural,
11712 /* RecurseForSelectAndPHI */ true))
11713 return ChangeStatus::UNCHANGED;
11714 Value *NewVal = getSingleValue(A, AA: *this, IRP: getIRPosition(), Values);
11715 if (!NewVal)
11716 return ChangeStatus::UNCHANGED;
11717
11718 ChangeStatus Changed = ChangeStatus::UNCHANGED;
11719 if (auto *Arg = dyn_cast<Argument>(Val: NewVal)) {
11720 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
11721 "Number of function with unique return");
11722 Changed |= A.manifestAttrs(
11723 IRP: IRPosition::argument(Arg: *Arg),
11724 DeducedAttrs: {Attribute::get(Context&: Arg->getContext(), Kind: Attribute::Returned)});
11725 STATS_DECLTRACK_ARG_ATTR(returned);
11726 }
11727
11728 auto RetInstPred = [&](Instruction &RetI) {
11729 Value *RetOp = RetI.getOperand(i: 0);
11730 if (isa<UndefValue>(Val: RetOp) || RetOp == NewVal)
11731 return true;
11732 if (AA::isValidAtPosition(VAC: {*NewVal, RetI}, InfoCache&: A.getInfoCache()))
11733 if (A.changeUseAfterManifest(U&: RetI.getOperandUse(i: 0), NV&: *NewVal))
11734 Changed = ChangeStatus::CHANGED;
11735 return true;
11736 };
11737 bool UsedAssumedInformation = false;
11738 (void)A.checkForAllInstructions(Pred: RetInstPred, QueryingAA: *this, Opcodes: {Instruction::Ret},
11739 UsedAssumedInformation,
11740 /* CheckBBLivenessOnly */ true);
11741 return Changed;
11742 }
11743
11744 ChangeStatus indicatePessimisticFixpoint() override {
11745 return AAPotentialValues::indicatePessimisticFixpoint();
11746 }
11747
11748 /// See AbstractAttribute::trackStatistics()
11749 void trackStatistics() const override{
11750 STATS_DECLTRACK_FNRET_ATTR(potential_values)}
11751
11752 /// The argumented with an existing `returned` attribute.
11753 Argument *ReturnedArg = nullptr;
11754};
11755
11756struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11757 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11758 : AAPotentialValuesImpl(IRP, A) {}
11759
11760 /// See AbstractAttribute::updateImpl(...).
11761 ChangeStatus updateImpl(Attributor &A) override {
11762 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
11763 "not be called");
11764 }
11765
11766 /// See AbstractAttribute::trackStatistics()
11767 void trackStatistics() const override {
11768 STATS_DECLTRACK_FN_ATTR(potential_values)
11769 }
11770};
11771
11772struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11773 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11774 : AAPotentialValuesFunction(IRP, A) {}
11775
11776 /// See AbstractAttribute::trackStatistics()
11777 void trackStatistics() const override {
11778 STATS_DECLTRACK_CS_ATTR(potential_values)
11779 }
11780};
11781
11782struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11783 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11784 : AAPotentialValuesImpl(IRP, A) {}
11785
11786 /// See AbstractAttribute::updateImpl(...).
11787 ChangeStatus updateImpl(Attributor &A) override {
11788 auto AssumedBefore = getAssumed();
11789
11790 Function *Callee = getAssociatedFunction();
11791 if (!Callee)
11792 return indicatePessimisticFixpoint();
11793
11794 bool UsedAssumedInformation = false;
11795 auto *CB = cast<CallBase>(Val: getCtxI());
11796 if (CB->isMustTailCall() &&
11797 !A.isAssumedDead(IRP: IRPosition::inst(I: *CB), QueryingAA: this, FnLivenessAA: nullptr,
11798 UsedAssumedInformation))
11799 return indicatePessimisticFixpoint();
11800
11801 Function *Caller = CB->getCaller();
11802
11803 auto AddScope = [&](AA::ValueScope S) {
11804 SmallVector<AA::ValueAndContext> Values;
11805 if (!A.getAssumedSimplifiedValues(IRP: IRPosition::returned(F: *Callee), AA: this,
11806 Values, S, UsedAssumedInformation))
11807 return false;
11808
11809 for (auto &It : Values) {
11810 Value *V = It.getValue();
11811 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11812 V, CB&: *CB, AA: *this, UsedAssumedInformation);
11813 if (!CallerV.has_value()) {
11814 // Nothing to do as long as no value was determined.
11815 continue;
11816 }
11817 V = *CallerV ? *CallerV : V;
11818 if (*CallerV && AA::isDynamicallyUnique(A, QueryingAA: *this, V: *V)) {
11819 if (recurseForValue(A, IRP: IRPosition::value(V: *V), S))
11820 continue;
11821 }
11822 if (S == AA::Intraprocedural && !AA::isValidInScope(V: *V, Scope: Caller)) {
11823 giveUpOnIntraprocedural(A);
11824 return true;
11825 }
11826 addValue(A, State&: getState(), V&: *V, CtxI: CB, S, AnchorScope: getAnchorScope());
11827 }
11828 return true;
11829 };
11830 if (!AddScope(AA::Intraprocedural))
11831 return indicatePessimisticFixpoint();
11832 if (!AddScope(AA::Interprocedural))
11833 return indicatePessimisticFixpoint();
11834 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11835 : ChangeStatus::CHANGED;
11836 }
11837
11838 ChangeStatus indicatePessimisticFixpoint() override {
11839 return AAPotentialValues::indicatePessimisticFixpoint();
11840 }
11841
11842 /// See AbstractAttribute::trackStatistics()
11843 void trackStatistics() const override {
11844 STATS_DECLTRACK_CSRET_ATTR(potential_values)
11845 }
11846};
11847
11848struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11849 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11850 : AAPotentialValuesFloating(IRP, A) {}
11851
11852 /// See AbstractAttribute::trackStatistics()
11853 void trackStatistics() const override {
11854 STATS_DECLTRACK_CSARG_ATTR(potential_values)
11855 }
11856};
11857} // namespace
11858
11859/// ---------------------- Assumption Propagation ------------------------------
11860namespace {
11861struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11862 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11863 const DenseSet<StringRef> &Known)
11864 : AAAssumptionInfo(IRP, A, Known) {}
11865
11866 /// See AbstractAttribute::manifest(...).
11867 ChangeStatus manifest(Attributor &A) override {
11868 // Don't manifest a universal set if it somehow made it here.
11869 if (getKnown().isUniversal())
11870 return ChangeStatus::UNCHANGED;
11871
11872 const IRPosition &IRP = getIRPosition();
11873 SmallVector<StringRef, 0> Set(getAssumed().getSet().begin(),
11874 getAssumed().getSet().end());
11875 llvm::sort(C&: Set);
11876 return A.manifestAttrs(IRP,
11877 DeducedAttrs: Attribute::get(Context&: IRP.getAnchorValue().getContext(),
11878 Kind: AssumptionAttrKey,
11879 Val: llvm::join(R&: Set, Separator: ",")),
11880 /*ForceReplace=*/true);
11881 }
11882
11883 bool hasAssumption(const StringRef Assumption) const override {
11884 return isValidState() && setContains(Assumption);
11885 }
11886
11887 /// See AbstractAttribute::getAsStr()
11888 const std::string getAsStr(Attributor *A) const override {
11889 const SetContents &Known = getKnown();
11890 const SetContents &Assumed = getAssumed();
11891
11892 SmallVector<StringRef, 0> Set(Known.getSet().begin(), Known.getSet().end());
11893 llvm::sort(C&: Set);
11894 const std::string KnownStr = llvm::join(R&: Set, Separator: ",");
11895
11896 std::string AssumedStr = "Universal";
11897 if (!Assumed.isUniversal()) {
11898 Set.assign(in_start: Assumed.getSet().begin(), in_end: Assumed.getSet().end());
11899 AssumedStr = llvm::join(R&: Set, Separator: ",");
11900 }
11901 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11902 }
11903};
11904
11905/// Propagates assumption information from parent functions to all of their
11906/// successors. An assumption can be propagated if the containing function
11907/// dominates the called function.
11908///
11909/// We start with a "known" set of assumptions already valid for the associated
11910/// function and an "assumed" set that initially contains all possible
11911/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11912/// contents as concrete values are known. The concrete values are seeded by the
11913/// first nodes that are either entries into the call graph, or contains no
11914/// assumptions. Each node is updated as the intersection of the assumed state
11915/// with all of its predecessors.
11916struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11917 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11918 : AAAssumptionInfoImpl(IRP, A,
11919 getAssumptions(F: *IRP.getAssociatedFunction())) {}
11920
11921 /// See AbstractAttribute::updateImpl(...).
11922 ChangeStatus updateImpl(Attributor &A) override {
11923 bool Changed = false;
11924
11925 auto CallSitePred = [&](AbstractCallSite ACS) {
11926 const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11927 QueryingAA: *this, IRP: IRPosition::callsite_function(CB: *ACS.getInstruction()),
11928 DepClass: DepClassTy::REQUIRED);
11929 if (!AssumptionAA)
11930 return false;
11931 // Get the set of assumptions shared by all of this function's callers.
11932 Changed |= getIntersection(RHS: AssumptionAA->getAssumed());
11933 return !getAssumed().empty() || !getKnown().empty();
11934 };
11935
11936 bool UsedAssumedInformation = false;
11937 // Get the intersection of all assumptions held by this node's predecessors.
11938 // If we don't know all the call sites then this is either an entry into the
11939 // call graph or an empty node. This node is known to only contain its own
11940 // assumptions and can be propagated to its successors.
11941 if (!A.checkForAllCallSites(Pred: CallSitePred, QueryingAA: *this, RequireAllCallSites: true,
11942 UsedAssumedInformation))
11943 return indicatePessimisticFixpoint();
11944
11945 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11946 }
11947
11948 void trackStatistics() const override {}
11949};
11950
11951/// Assumption Info defined for call sites.
11952struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11953
11954 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11955 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11956
11957 /// See AbstractAttribute::initialize(...).
11958 void initialize(Attributor &A) override {
11959 const IRPosition &FnPos = IRPosition::function(F: *getAnchorScope());
11960 A.getAAFor<AAAssumptionInfo>(QueryingAA: *this, IRP: FnPos, DepClass: DepClassTy::REQUIRED);
11961 }
11962
11963 /// See AbstractAttribute::updateImpl(...).
11964 ChangeStatus updateImpl(Attributor &A) override {
11965 const IRPosition &FnPos = IRPosition::function(F: *getAnchorScope());
11966 auto *AssumptionAA =
11967 A.getAAFor<AAAssumptionInfo>(QueryingAA: *this, IRP: FnPos, DepClass: DepClassTy::REQUIRED);
11968 if (!AssumptionAA)
11969 return indicatePessimisticFixpoint();
11970 bool Changed = getIntersection(RHS: AssumptionAA->getAssumed());
11971 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11972 }
11973
11974 /// See AbstractAttribute::trackStatistics()
11975 void trackStatistics() const override {}
11976
11977private:
11978 /// Helper to initialized the known set as all the assumptions this call and
11979 /// the callee contain.
11980 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11981 const CallBase &CB = cast<CallBase>(Val&: IRP.getAssociatedValue());
11982 auto Assumptions = getAssumptions(CB);
11983 if (const Function *F = CB.getCaller())
11984 set_union(S1&: Assumptions, S2: getAssumptions(F: *F));
11985 if (Function *F = IRP.getAssociatedFunction())
11986 set_union(S1&: Assumptions, S2: getAssumptions(F: *F));
11987 return Assumptions;
11988 }
11989};
11990} // namespace
11991
11992AACallGraphNode *AACallEdgeIterator::operator*() const {
11993 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11994 A.getOrCreateAAFor<AACallEdges>(IRP: IRPosition::function(F: **I))));
11995}
11996
11997void AttributorCallGraph::print() { llvm::WriteGraph(O&: outs(), G: this); }
11998
11999/// ------------------------ UnderlyingObjects ---------------------------------
12000
12001namespace {
12002struct AAUnderlyingObjectsImpl
12003 : StateWrapper<BooleanState, AAUnderlyingObjects> {
12004 using BaseTy = StateWrapper<BooleanState, AAUnderlyingObjects>;
12005 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
12006
12007 /// See AbstractAttribute::getAsStr().
12008 const std::string getAsStr(Attributor *A) const override {
12009 if (!isValidState())
12010 return "<invalid>";
12011 std::string Str;
12012 llvm::raw_string_ostream OS(Str);
12013 OS << "underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12014 << " objects, intra " << IntraAssumedUnderlyingObjects.size()
12015 << " objects.\n";
12016 if (!InterAssumedUnderlyingObjects.empty()) {
12017 OS << "inter objects:\n";
12018 for (auto *Obj : InterAssumedUnderlyingObjects)
12019 OS << *Obj << '\n';
12020 }
12021 if (!IntraAssumedUnderlyingObjects.empty()) {
12022 OS << "intra objects:\n";
12023 for (auto *Obj : IntraAssumedUnderlyingObjects)
12024 OS << *Obj << '\n';
12025 }
12026 return Str;
12027 }
12028
12029 /// See AbstractAttribute::trackStatistics()
12030 void trackStatistics() const override {}
12031
12032 /// See AbstractAttribute::updateImpl(...).
12033 ChangeStatus updateImpl(Attributor &A) override {
12034 auto &Ptr = getAssociatedValue();
12035
12036 bool UsedAssumedInformation = false;
12037 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12038 AA::ValueScope Scope) {
12039 SmallPtrSet<Value *, 8> SeenObjects;
12040 SmallVector<AA::ValueAndContext> Values;
12041
12042 if (!A.getAssumedSimplifiedValues(IRP: IRPosition::value(V: Ptr), AA: *this, Values,
12043 S: Scope, UsedAssumedInformation))
12044 return UnderlyingObjects.insert(X: &Ptr);
12045
12046 bool Changed = false;
12047
12048 for (unsigned I = 0; I < Values.size(); ++I) {
12049 auto &VAC = Values[I];
12050 auto *Obj = VAC.getValue();
12051 Value *UO = getUnderlyingObject(V: Obj);
12052 if (!SeenObjects.insert(Ptr: UO ? UO : Obj).second)
12053 continue;
12054 if (UO && UO != Obj) {
12055 if (isa<AllocaInst>(Val: UO) || isa<GlobalValue>(Val: UO)) {
12056 Changed |= UnderlyingObjects.insert(X: UO);
12057 continue;
12058 }
12059
12060 const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(
12061 QueryingAA: *this, IRP: IRPosition::value(V: *UO), DepClass: DepClassTy::OPTIONAL);
12062 auto Pred = [&](Value &V) {
12063 if (&V == UO)
12064 Changed |= UnderlyingObjects.insert(X: UO);
12065 else
12066 Values.emplace_back(Args&: V, Args: nullptr);
12067 return true;
12068 };
12069
12070 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12071 llvm_unreachable(
12072 "The forall call should not return false at this position");
12073 UsedAssumedInformation |= !OtherAA->getState().isAtFixpoint();
12074 continue;
12075 }
12076
12077 if (isa<SelectInst>(Val: Obj)) {
12078 Changed |= handleIndirect(A, V&: *Obj, UnderlyingObjects, Scope,
12079 UsedAssumedInformation);
12080 continue;
12081 }
12082 if (auto *PHI = dyn_cast<PHINode>(Val: Obj)) {
12083 // Explicitly look through PHIs as we do not care about dynamically
12084 // uniqueness.
12085 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
12086 Changed |=
12087 handleIndirect(A, V&: *PHI->getIncomingValue(i: u), UnderlyingObjects,
12088 Scope, UsedAssumedInformation);
12089 }
12090 continue;
12091 }
12092
12093 Changed |= UnderlyingObjects.insert(X: Obj);
12094 }
12095
12096 return Changed;
12097 };
12098
12099 bool Changed = false;
12100 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
12101 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
12102 if (!UsedAssumedInformation)
12103 indicateOptimisticFixpoint();
12104 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12105 }
12106
12107 bool forallUnderlyingObjects(
12108 function_ref<bool(Value &)> Pred,
12109 AA::ValueScope Scope = AA::Interprocedural) const override {
12110 if (!isValidState())
12111 return Pred(getAssociatedValue());
12112
12113 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
12114 ? IntraAssumedUnderlyingObjects
12115 : InterAssumedUnderlyingObjects;
12116 for (Value *Obj : AssumedUnderlyingObjects)
12117 if (!Pred(*Obj))
12118 return false;
12119
12120 return true;
12121 }
12122
12123private:
12124 /// Handle the case where the value is not the actual underlying value, such
12125 /// as a phi node or a select instruction.
12126 bool handleIndirect(Attributor &A, Value &V,
12127 SmallSetVector<Value *, 8> &UnderlyingObjects,
12128 AA::ValueScope Scope, bool &UsedAssumedInformation) {
12129 bool Changed = false;
12130 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
12131 QueryingAA: *this, IRP: IRPosition::value(V), DepClass: DepClassTy::OPTIONAL);
12132 auto Pred = [&](Value &V) {
12133 Changed |= UnderlyingObjects.insert(X: &V);
12134 return true;
12135 };
12136 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12137 llvm_unreachable(
12138 "The forall call should not return false at this position");
12139 UsedAssumedInformation |= !AA->getState().isAtFixpoint();
12140 return Changed;
12141 }
12142
12143 /// All the underlying objects collected so far via intra procedural scope.
12144 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12145 /// All the underlying objects collected so far via inter procedural scope.
12146 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12147};
12148
12149struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12150 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
12151 : AAUnderlyingObjectsImpl(IRP, A) {}
12152};
12153
12154struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12155 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
12156 : AAUnderlyingObjectsImpl(IRP, A) {}
12157};
12158
12159struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12160 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
12161 : AAUnderlyingObjectsImpl(IRP, A) {}
12162};
12163
12164struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12165 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
12166 : AAUnderlyingObjectsImpl(IRP, A) {}
12167};
12168
12169struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12170 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
12171 : AAUnderlyingObjectsImpl(IRP, A) {}
12172};
12173
12174struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12175 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
12176 : AAUnderlyingObjectsImpl(IRP, A) {}
12177};
12178
12179struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12180 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
12181 : AAUnderlyingObjectsImpl(IRP, A) {}
12182};
12183} // namespace
12184
12185/// ------------------------ Global Value Info -------------------------------
12186namespace {
12187struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
12188 AAGlobalValueInfoFloating(const IRPosition &IRP, Attributor &A)
12189 : AAGlobalValueInfo(IRP, A) {}
12190
12191 /// See AbstractAttribute::initialize(...).
12192 void initialize(Attributor &A) override {}
12193
12194 bool checkUse(Attributor &A, const Use &U, bool &Follow,
12195 SmallVectorImpl<const Value *> &Worklist) {
12196 Instruction *UInst = dyn_cast<Instruction>(Val: U.getUser());
12197 if (!UInst) {
12198 Follow = true;
12199 return true;
12200 }
12201
12202 LLVM_DEBUG(dbgs() << "[AAGlobalValueInfo] Check use: " << *U.get() << " in "
12203 << *UInst << "\n");
12204
12205 if (auto *Cmp = dyn_cast<ICmpInst>(Val: U.getUser())) {
12206 int Idx = &Cmp->getOperandUse(i: 0) == &U;
12207 if (isa<Constant>(Val: Cmp->getOperand(i_nocapture: Idx)))
12208 return true;
12209 return U == &getAnchorValue();
12210 }
12211
12212 // Explicitly catch return instructions.
12213 if (isa<ReturnInst>(Val: UInst)) {
12214 auto CallSitePred = [&](AbstractCallSite ACS) {
12215 Worklist.push_back(Elt: ACS.getInstruction());
12216 return true;
12217 };
12218 bool UsedAssumedInformation = false;
12219 // TODO: We should traverse the uses or add a "non-call-site" CB.
12220 if (!A.checkForAllCallSites(Pred: CallSitePred, Fn: *UInst->getFunction(),
12221 /*RequireAllCallSites=*/true, QueryingAA: this,
12222 UsedAssumedInformation))
12223 return false;
12224 return true;
12225 }
12226
12227 // For now we only use special logic for call sites. However, the tracker
12228 // itself knows about a lot of other non-capturing cases already.
12229 auto *CB = dyn_cast<CallBase>(Val: UInst);
12230 if (!CB)
12231 return false;
12232 // Direct calls are OK uses.
12233 if (CB->isCallee(U: &U))
12234 return true;
12235 // Non-argument uses are scary.
12236 if (!CB->isArgOperand(U: &U))
12237 return false;
12238 // TODO: Iterate callees.
12239 auto *Fn = dyn_cast<Function>(Val: CB->getCalledOperand());
12240 if (!Fn || !A.isFunctionIPOAmendable(F: *Fn))
12241 return false;
12242
12243 unsigned ArgNo = CB->getArgOperandNo(U: &U);
12244 Worklist.push_back(Elt: Fn->getArg(i: ArgNo));
12245 return true;
12246 }
12247
12248 ChangeStatus updateImpl(Attributor &A) override {
12249 unsigned NumUsesBefore = Uses.size();
12250
12251 SmallPtrSet<const Value *, 8> Visited;
12252 SmallVector<const Value *> Worklist;
12253 Worklist.push_back(Elt: &getAnchorValue());
12254
12255 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
12256 Uses.insert(Ptr: &U);
12257 // TODO(captures): Make this more precise.
12258 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
12259 if (CI.isPassthrough()) {
12260 Follow = true;
12261 return true;
12262 }
12263 return checkUse(A, U, Follow, Worklist);
12264 };
12265 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
12266 Uses.insert(Ptr: &OldU);
12267 return true;
12268 };
12269
12270 while (!Worklist.empty()) {
12271 const Value *V = Worklist.pop_back_val();
12272 if (!Visited.insert(Ptr: V).second)
12273 continue;
12274 if (!A.checkForAllUses(Pred: UsePred, QueryingAA: *this, V: *V,
12275 /* CheckBBLivenessOnly */ true,
12276 LivenessDepClass: DepClassTy::OPTIONAL,
12277 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
12278 return indicatePessimisticFixpoint();
12279 }
12280 }
12281
12282 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12283 : ChangeStatus::CHANGED;
12284 }
12285
12286 bool isPotentialUse(const Use &U) const override {
12287 return !isValidState() || Uses.contains(Ptr: &U);
12288 }
12289
12290 /// See AbstractAttribute::manifest(...).
12291 ChangeStatus manifest(Attributor &A) override {
12292 return ChangeStatus::UNCHANGED;
12293 }
12294
12295 /// See AbstractAttribute::getAsStr().
12296 const std::string getAsStr(Attributor *A) const override {
12297 return "[" + std::to_string(val: Uses.size()) + " uses]";
12298 }
12299
12300 void trackStatistics() const override {
12301 STATS_DECLTRACK_FLOATING_ATTR(GlobalValuesTracked);
12302 }
12303
12304private:
12305 /// Set of (transitive) uses of this GlobalValue.
12306 SmallPtrSet<const Use *, 8> Uses;
12307};
12308} // namespace
12309
12310/// ------------------------ Indirect Call Info -------------------------------
12311namespace {
12312struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12313 AAIndirectCallInfoCallSite(const IRPosition &IRP, Attributor &A)
12314 : AAIndirectCallInfo(IRP, A) {}
12315
12316 /// See AbstractAttribute::initialize(...).
12317 void initialize(Attributor &A) override {
12318 auto *MD = getCtxI()->getMetadata(KindID: LLVMContext::MD_callees);
12319 if (!MD && !A.isClosedWorldModule())
12320 return;
12321
12322 if (MD) {
12323 for (const auto &Op : MD->operands())
12324 if (Function *Callee = mdconst::dyn_extract_or_null<Function>(MD: Op))
12325 PotentialCallees.insert(X: Callee);
12326 } else if (A.isClosedWorldModule()) {
12327 ArrayRef<Function *> IndirectlyCallableFunctions =
12328 A.getInfoCache().getIndirectlyCallableFunctions(A);
12329 PotentialCallees.insert_range(R&: IndirectlyCallableFunctions);
12330 }
12331
12332 if (PotentialCallees.empty())
12333 indicateOptimisticFixpoint();
12334 }
12335
12336 ChangeStatus updateImpl(Attributor &A) override {
12337 CallBase *CB = cast<CallBase>(Val: getCtxI());
12338 const Use &CalleeUse = CB->getCalledOperandUse();
12339 Value *FP = CB->getCalledOperand();
12340
12341 SmallSetVector<Function *, 4> AssumedCalleesNow;
12342 bool AllCalleesKnownNow = AllCalleesKnown;
12343
12344 auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,
12345 bool &UsedAssumedInformation) {
12346 const auto *GIAA = A.getAAFor<AAGlobalValueInfo>(
12347 QueryingAA: *this, IRP: IRPosition::value(V: PotentialCallee), DepClass: DepClassTy::OPTIONAL);
12348 if (!GIAA || GIAA->isPotentialUse(U: CalleeUse))
12349 return true;
12350 UsedAssumedInformation = !GIAA->isAtFixpoint();
12351 return false;
12352 };
12353
12354 auto AddPotentialCallees = [&]() {
12355 for (auto *PotentialCallee : PotentialCallees) {
12356 bool UsedAssumedInformation = false;
12357 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12358 AssumedCalleesNow.insert(X: PotentialCallee);
12359 }
12360 };
12361
12362 // Use simplification to find potential callees, if !callees was present,
12363 // fallback to that set if necessary.
12364 bool UsedAssumedInformation = false;
12365 SmallVector<AA::ValueAndContext> Values;
12366 if (!A.getAssumedSimplifiedValues(IRP: IRPosition::value(V: *FP), AA: this, Values,
12367 S: AA::ValueScope::AnyScope,
12368 UsedAssumedInformation)) {
12369 if (PotentialCallees.empty())
12370 return indicatePessimisticFixpoint();
12371 AddPotentialCallees();
12372 }
12373
12374 // Try to find a reason for \p Fn not to be a potential callee. If none was
12375 // found, add it to the assumed callees set.
12376 auto CheckPotentialCallee = [&](Function &Fn) {
12377 if (!PotentialCallees.empty() && !PotentialCallees.count(key: &Fn))
12378 return false;
12379
12380 auto &CachedResult = FilterResults[&Fn];
12381 if (CachedResult.has_value())
12382 return CachedResult.value();
12383
12384 bool UsedAssumedInformation = false;
12385 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12386 if (!UsedAssumedInformation)
12387 CachedResult = false;
12388 return false;
12389 }
12390
12391 int NumFnArgs = Fn.arg_size();
12392 int NumCBArgs = CB->arg_size();
12393
12394 // Check if any excess argument (which we fill up with poison) is known to
12395 // be UB on undef.
12396 for (int I = NumCBArgs; I < NumFnArgs; ++I) {
12397 bool IsKnown = false;
12398 if (AA::hasAssumedIRAttr<Attribute::NoUndef>(
12399 A, QueryingAA: this, IRP: IRPosition::argument(Arg: *Fn.getArg(i: I)),
12400 DepClass: DepClassTy::OPTIONAL, IsKnown)) {
12401 if (IsKnown)
12402 CachedResult = false;
12403 return false;
12404 }
12405 }
12406
12407 CachedResult = true;
12408 return true;
12409 };
12410
12411 // Check simplification result, prune known UB callees, also restrict it to
12412 // the !callees set, if present.
12413 for (auto &VAC : Values) {
12414 if (isa<UndefValue>(Val: VAC.getValue()))
12415 continue;
12416 if (isa<ConstantPointerNull>(Val: VAC.getValue()) &&
12417 VAC.getValue()->getType()->getPointerAddressSpace() == 0)
12418 continue;
12419 // TODO: Check for known UB, e.g., poison + noundef.
12420 if (auto *VACFn = dyn_cast<Function>(Val: VAC.getValue())) {
12421 if (CheckPotentialCallee(*VACFn))
12422 AssumedCalleesNow.insert(X: VACFn);
12423 continue;
12424 }
12425 if (!PotentialCallees.empty()) {
12426 AddPotentialCallees();
12427 break;
12428 }
12429 AllCalleesKnownNow = false;
12430 }
12431
12432 if (AssumedCalleesNow == AssumedCallees &&
12433 AllCalleesKnown == AllCalleesKnownNow)
12434 return ChangeStatus::UNCHANGED;
12435
12436 std::swap(LHS&: AssumedCallees, RHS&: AssumedCalleesNow);
12437 AllCalleesKnown = AllCalleesKnownNow;
12438 return ChangeStatus::CHANGED;
12439 }
12440
12441 /// See AbstractAttribute::manifest(...).
12442 ChangeStatus manifest(Attributor &A) override {
12443 // If we can't specialize at all, give up now.
12444 if (!AllCalleesKnown && AssumedCallees.empty())
12445 return ChangeStatus::UNCHANGED;
12446
12447 CallBase *CB = cast<CallBase>(Val: getCtxI());
12448 bool UsedAssumedInformation = false;
12449 if (A.isAssumedDead(I: *CB, QueryingAA: this, /*LivenessAA=*/nullptr,
12450 UsedAssumedInformation))
12451 return ChangeStatus::UNCHANGED;
12452
12453 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12454 Value *FP = CB->getCalledOperand();
12455 if (FP->getType()->getPointerAddressSpace())
12456 FP = new AddrSpaceCastInst(FP, PointerType::get(C&: FP->getContext(), AddressSpace: 0),
12457 FP->getName() + ".as0", CB->getIterator());
12458
12459 bool CBIsVoid = CB->getType()->isVoidTy();
12460 BasicBlock::iterator IP = CB->getIterator();
12461 FunctionType *CSFT = CB->getFunctionType();
12462 SmallVector<Value *> CSArgs(CB->args());
12463
12464 // If we know all callees and there are none, the call site is (effectively)
12465 // dead (or UB).
12466 if (AssumedCallees.empty()) {
12467 assert(AllCalleesKnown &&
12468 "Expected all callees to be known if there are none.");
12469 A.changeToUnreachableAfterManifest(I: CB);
12470 return ChangeStatus::CHANGED;
12471 }
12472
12473 // Special handling for the single callee case.
12474 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12475 auto *NewCallee = AssumedCallees.front();
12476 if (isLegalToPromote(CB: *CB, Callee: NewCallee)) {
12477 promoteCall(CB&: *CB, Callee: NewCallee, RetBitCast: nullptr);
12478 NumIndirectCallsPromoted++;
12479 return ChangeStatus::CHANGED;
12480 }
12481 Instruction *NewCall =
12482 CallInst::Create(Func: FunctionCallee(CSFT, NewCallee), Args: CSArgs,
12483 NameStr: CB->getName(), InsertBefore: CB->getIterator());
12484 if (!CBIsVoid)
12485 A.changeAfterManifest(IRP: IRPosition::callsite_returned(CB: *CB), NV&: *NewCall);
12486 A.deleteAfterManifest(I&: *CB);
12487 return ChangeStatus::CHANGED;
12488 }
12489
12490 // For each potential value we create a conditional
12491 //
12492 // ```
12493 // if (ptr == value) value(args);
12494 // else ...
12495 // ```
12496 //
12497 bool SpecializedForAnyCallees = false;
12498 bool SpecializedForAllCallees = AllCalleesKnown;
12499 ICmpInst *LastCmp = nullptr;
12500 SmallVector<Function *, 8> SkippedAssumedCallees;
12501 SmallVector<std::pair<CallInst *, Instruction *>> NewCalls;
12502 for (Function *NewCallee : AssumedCallees) {
12503 if (!A.shouldSpecializeCallSiteForCallee(AA: *this, CB&: *CB, Callee&: *NewCallee,
12504 NumAssumedCallees: AssumedCallees.size())) {
12505 SkippedAssumedCallees.push_back(Elt: NewCallee);
12506 SpecializedForAllCallees = false;
12507 continue;
12508 }
12509 SpecializedForAnyCallees = true;
12510
12511 LastCmp = new ICmpInst(IP, llvm::CmpInst::ICMP_EQ, FP, NewCallee);
12512 Instruction *ThenTI =
12513 SplitBlockAndInsertIfThen(Cond: LastCmp, SplitBefore: IP, /* Unreachable */ false);
12514 BasicBlock *CBBB = CB->getParent();
12515 A.registerManifestAddedBasicBlock(BB&: *ThenTI->getParent());
12516 A.registerManifestAddedBasicBlock(BB&: *IP->getParent());
12517 auto *SplitTI = cast<CondBrInst>(Val: LastCmp->getNextNode());
12518 BasicBlock *ElseBB;
12519 if (&*IP == CB) {
12520 ElseBB = BasicBlock::Create(Context&: ThenTI->getContext(), Name: "",
12521 Parent: ThenTI->getFunction(), InsertBefore: CBBB);
12522 A.registerManifestAddedBasicBlock(BB&: *ElseBB);
12523 IP = UncondBrInst::Create(Target: CBBB, InsertBefore: ElseBB)->getIterator();
12524 SplitTI->replaceUsesOfWith(From: CBBB, To: ElseBB);
12525 } else {
12526 ElseBB = IP->getParent();
12527 ThenTI->replaceUsesOfWith(From: ElseBB, To: CBBB);
12528 }
12529 CastInst *RetBC = nullptr;
12530 CallInst *NewCall = nullptr;
12531 if (isLegalToPromote(CB: *CB, Callee: NewCallee)) {
12532 auto *CBClone = cast<CallBase>(Val: CB->clone());
12533 CBClone->insertBefore(InsertPos: ThenTI->getIterator());
12534 NewCall = &cast<CallInst>(Val&: promoteCall(CB&: *CBClone, Callee: NewCallee, RetBitCast: &RetBC));
12535 NumIndirectCallsPromoted++;
12536 } else {
12537 NewCall = CallInst::Create(Func: FunctionCallee(CSFT, NewCallee), Args: CSArgs,
12538 NameStr: CB->getName(), InsertBefore: ThenTI->getIterator());
12539 }
12540 NewCalls.push_back(Elt: {NewCall, RetBC});
12541 }
12542
12543 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12544 if (!AllCalleesKnown)
12545 return ChangeStatus::UNCHANGED;
12546 MDBuilder MDB(IndirectCB.getContext());
12547 MDNode *Callees = MDB.createCallees(Callees: SkippedAssumedCallees);
12548 IndirectCB.setMetadata(KindID: LLVMContext::MD_callees, Node: Callees);
12549 return ChangeStatus::CHANGED;
12550 };
12551
12552 if (!SpecializedForAnyCallees)
12553 return AttachCalleeMetadata(*CB);
12554
12555 // Check if we need the fallback indirect call still.
12556 if (SpecializedForAllCallees) {
12557 LastCmp->replaceAllUsesWith(V: ConstantInt::getTrue(Context&: LastCmp->getContext()));
12558 LastCmp->eraseFromParent();
12559 new UnreachableInst(IP->getContext(), IP);
12560 IP->eraseFromParent();
12561 } else {
12562 auto *CBClone = cast<CallInst>(Val: CB->clone());
12563 CBClone->setName(CB->getName());
12564 CBClone->insertBefore(BB&: *IP->getParent(), InsertPos: IP);
12565 NewCalls.push_back(Elt: {CBClone, nullptr});
12566 AttachCalleeMetadata(*CBClone);
12567 }
12568
12569 // Check if we need a PHI to merge the results.
12570 if (!CBIsVoid) {
12571 auto *PHI = PHINode::Create(Ty: CB->getType(), NumReservedValues: NewCalls.size(),
12572 NameStr: CB->getName() + ".phi",
12573 InsertBefore: CB->getParent()->getFirstInsertionPt());
12574 for (auto &It : NewCalls) {
12575 CallBase *NewCall = It.first;
12576 Instruction *CallRet = It.second ? It.second : It.first;
12577 if (CallRet->getType() == CB->getType())
12578 PHI->addIncoming(V: CallRet, BB: CallRet->getParent());
12579 else if (NewCall->getType()->isVoidTy())
12580 PHI->addIncoming(V: PoisonValue::get(T: CB->getType()),
12581 BB: NewCall->getParent());
12582 else
12583 llvm_unreachable("Call return should match or be void!");
12584 }
12585 A.changeAfterManifest(IRP: IRPosition::callsite_returned(CB: *CB), NV&: *PHI);
12586 }
12587
12588 A.deleteAfterManifest(I&: *CB);
12589 Changed = ChangeStatus::CHANGED;
12590
12591 return Changed;
12592 }
12593
12594 /// See AbstractAttribute::getAsStr().
12595 const std::string getAsStr(Attributor *A) const override {
12596 return std::string(AllCalleesKnown ? "eliminate" : "specialize") +
12597 " indirect call site with " + std::to_string(val: AssumedCallees.size()) +
12598 " functions";
12599 }
12600
12601 void trackStatistics() const override {
12602 if (AllCalleesKnown) {
12603 STATS_DECLTRACK(
12604 Eliminated, CallSites,
12605 "Number of indirect call sites eliminated via specialization")
12606 } else {
12607 STATS_DECLTRACK(Specialized, CallSites,
12608 "Number of indirect call sites specialized")
12609 }
12610 }
12611
12612 bool foreachCallee(function_ref<bool(Function *)> CB) const override {
12613 return isValidState() && AllCalleesKnown && all_of(Range: AssumedCallees, P: CB);
12614 }
12615
12616private:
12617 /// Map to remember filter results.
12618 DenseMap<Function *, std::optional<bool>> FilterResults;
12619
12620 /// If the !callee metadata was present, this set will contain all potential
12621 /// callees (superset).
12622 SmallSetVector<Function *, 4> PotentialCallees;
12623
12624 /// This set contains all currently assumed calllees, which might grow over
12625 /// time.
12626 SmallSetVector<Function *, 4> AssumedCallees;
12627
12628 /// Flag to indicate if all possible callees are in the AssumedCallees set or
12629 /// if there could be others.
12630 bool AllCalleesKnown = true;
12631};
12632} // namespace
12633
12634/// --------------------- Invariant Load Pointer -------------------------------
12635namespace {
12636
12637struct AAInvariantLoadPointerImpl
12638 : public StateWrapper<BitIntegerState<uint8_t, 15>,
12639 AAInvariantLoadPointer> {
12640
12641 enum {
12642 // pointer does not alias within the bounds of the function
12643 IS_NOALIAS = 1 << 0,
12644 // pointer is not involved in any effectful instructions within the bounds
12645 // of the function
12646 IS_NOEFFECT = 1 << 1,
12647 // loads are invariant within the bounds of the function
12648 IS_LOCALLY_INVARIANT = 1 << 2,
12649 // memory lifetime is constrained within the bounds of the function
12650 IS_LOCALLY_CONSTRAINED = 1 << 3,
12651
12652 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12653 IS_LOCALLY_CONSTRAINED,
12654 };
12655 static_assert(getBestState() == IS_BEST_STATE, "Unexpected best state");
12656
12657 using Base =
12658 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12659
12660 // the BitIntegerState is optimistic about IS_NOALIAS and IS_NOEFFECT, but
12661 // pessimistic about IS_KNOWN_INVARIANT
12662 AAInvariantLoadPointerImpl(const IRPosition &IRP, Attributor &A)
12663 : Base(IRP) {}
12664
12665 bool isKnownInvariant() const final {
12666 return isKnownLocallyInvariant() && isKnown(BitsEncoding: IS_LOCALLY_CONSTRAINED);
12667 }
12668
12669 bool isKnownLocallyInvariant() const final {
12670 if (isKnown(BitsEncoding: IS_LOCALLY_INVARIANT))
12671 return true;
12672 return isKnown(BitsEncoding: IS_NOALIAS | IS_NOEFFECT);
12673 }
12674
12675 bool isAssumedInvariant() const final {
12676 return isAssumedLocallyInvariant() && isAssumed(BitsEncoding: IS_LOCALLY_CONSTRAINED);
12677 }
12678
12679 bool isAssumedLocallyInvariant() const final {
12680 if (isAssumed(BitsEncoding: IS_LOCALLY_INVARIANT))
12681 return true;
12682 return isAssumed(BitsEncoding: IS_NOALIAS | IS_NOEFFECT);
12683 }
12684
12685 ChangeStatus updateImpl(Attributor &A) override {
12686 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12687
12688 Changed |= updateNoAlias(A);
12689 if (requiresNoAlias() && !isAssumed(BitsEncoding: IS_NOALIAS))
12690 return indicatePessimisticFixpoint();
12691
12692 Changed |= updateNoEffect(A);
12693
12694 Changed |= updateLocalInvariance(A);
12695
12696 return Changed;
12697 }
12698
12699 ChangeStatus manifest(Attributor &A) override {
12700 if (!isKnownInvariant())
12701 return ChangeStatus::UNCHANGED;
12702
12703 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12704 const Value *Ptr = &getAssociatedValue();
12705 const auto TagInvariantLoads = [&](const Use &U, bool &) {
12706 if (U.get() != Ptr)
12707 return true;
12708 auto *I = dyn_cast<Instruction>(Val: U.getUser());
12709 if (!I)
12710 return true;
12711
12712 // Ensure that we are only changing uses from the corresponding callgraph
12713 // SSC in the case that the AA isn't run on the entire module
12714 if (!A.isRunOn(Fn: I->getFunction()))
12715 return true;
12716
12717 if (I->hasMetadata(KindID: LLVMContext::MD_invariant_load))
12718 return true;
12719
12720 if (auto *LI = dyn_cast<LoadInst>(Val: I)) {
12721 LI->setMetadata(KindID: LLVMContext::MD_invariant_load,
12722 Node: MDNode::get(Context&: LI->getContext(), MDs: {}));
12723 Changed = ChangeStatus::CHANGED;
12724 }
12725 return true;
12726 };
12727
12728 (void)A.checkForAllUses(Pred: TagInvariantLoads, QueryingAA: *this, V: *Ptr);
12729 return Changed;
12730 }
12731
12732 /// See AbstractAttribute::getAsStr().
12733 const std::string getAsStr(Attributor *) const override {
12734 if (isKnownInvariant())
12735 return "load-invariant pointer";
12736 return "non-invariant pointer";
12737 }
12738
12739 /// See AbstractAttribute::trackStatistics().
12740 void trackStatistics() const override {}
12741
12742private:
12743 /// Indicate that noalias is required for the pointer to be invariant.
12744 bool requiresNoAlias() const {
12745 switch (getPositionKind()) {
12746 default:
12747 // Conservatively default to require noalias.
12748 return true;
12749 case IRP_FLOAT:
12750 case IRP_RETURNED:
12751 case IRP_CALL_SITE:
12752 return false;
12753 case IRP_CALL_SITE_RETURNED: {
12754 const auto &CB = cast<CallBase>(Val&: getAnchorValue());
12755 return !isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
12756 Call: &CB, /*MustPreserveOffset=*/false);
12757 }
12758 case IRP_ARGUMENT: {
12759 const Function *F = getAssociatedFunction();
12760 assert(F && "no associated function for argument");
12761 return !isCallableCC(CC: F->getCallingConv());
12762 }
12763 }
12764 }
12765
12766 bool isExternal() const {
12767 const Function *F = getAssociatedFunction();
12768 if (!F)
12769 return true;
12770 return isCallableCC(CC: F->getCallingConv()) &&
12771 getPositionKind() != IRP_CALL_SITE_RETURNED;
12772 }
12773
12774 ChangeStatus updateNoAlias(Attributor &A) {
12775 if (isKnown(BitsEncoding: IS_NOALIAS) || !isAssumed(BitsEncoding: IS_NOALIAS))
12776 return ChangeStatus::UNCHANGED;
12777
12778 // Try to use AANoAlias.
12779 if (const auto *ANoAlias = A.getOrCreateAAFor<AANoAlias>(
12780 IRP: getIRPosition(), QueryingAA: this, DepClass: DepClassTy::REQUIRED)) {
12781 if (ANoAlias->isKnownNoAlias()) {
12782 addKnownBits(Bits: IS_NOALIAS);
12783 return ChangeStatus::CHANGED;
12784 }
12785
12786 if (!ANoAlias->isAssumedNoAlias()) {
12787 removeAssumedBits(BitsEncoding: IS_NOALIAS);
12788 return ChangeStatus::CHANGED;
12789 }
12790
12791 return ChangeStatus::UNCHANGED;
12792 }
12793
12794 // Try to infer noalias from argument attribute, since it is applicable for
12795 // the duration of the function.
12796 if (const Argument *Arg = getAssociatedArgument()) {
12797 if (Arg->hasNoAliasAttr()) {
12798 addKnownBits(Bits: IS_NOALIAS);
12799 return ChangeStatus::UNCHANGED;
12800 }
12801
12802 // Noalias information is not provided, and cannot be inferred,
12803 // so we conservatively assume the pointer aliases.
12804 removeAssumedBits(BitsEncoding: IS_NOALIAS);
12805 return ChangeStatus::CHANGED;
12806 }
12807
12808 return ChangeStatus::UNCHANGED;
12809 }
12810
12811 ChangeStatus updateNoEffect(Attributor &A) {
12812 if (isKnown(BitsEncoding: IS_NOEFFECT) || !isAssumed(BitsEncoding: IS_NOEFFECT))
12813 return ChangeStatus::UNCHANGED;
12814
12815 if (!getAssociatedFunction())
12816 return indicatePessimisticFixpoint();
12817
12818 if (isa<AllocaInst>(Val: &getAssociatedValue()))
12819 return indicatePessimisticFixpoint();
12820
12821 const auto HasNoEffectLoads = [&](const Use &U, bool &) {
12822 const auto *LI = dyn_cast<LoadInst>(Val: U.getUser());
12823 return !LI || !LI->mayHaveSideEffects();
12824 };
12825 if (!A.checkForAllUses(Pred: HasNoEffectLoads, QueryingAA: *this, V: getAssociatedValue()))
12826 return indicatePessimisticFixpoint();
12827
12828 if (const auto *AMemoryBehavior = A.getOrCreateAAFor<AAMemoryBehavior>(
12829 IRP: getIRPosition(), QueryingAA: this, DepClass: DepClassTy::REQUIRED)) {
12830 // For non-instructions, try to use AAMemoryBehavior to infer the readonly
12831 // attribute
12832 if (!AMemoryBehavior->isAssumedReadOnly())
12833 return indicatePessimisticFixpoint();
12834
12835 if (AMemoryBehavior->isKnownReadOnly()) {
12836 addKnownBits(Bits: IS_NOEFFECT);
12837 return ChangeStatus::UNCHANGED;
12838 }
12839
12840 return ChangeStatus::UNCHANGED;
12841 }
12842
12843 if (const Argument *Arg = getAssociatedArgument()) {
12844 if (Arg->onlyReadsMemory()) {
12845 addKnownBits(Bits: IS_NOEFFECT);
12846 return ChangeStatus::UNCHANGED;
12847 }
12848
12849 // Readonly information is not provided, and cannot be inferred from
12850 // AAMemoryBehavior.
12851 return indicatePessimisticFixpoint();
12852 }
12853
12854 return ChangeStatus::UNCHANGED;
12855 }
12856
12857 ChangeStatus updateLocalInvariance(Attributor &A) {
12858 if (isKnown(BitsEncoding: IS_LOCALLY_INVARIANT) || !isAssumed(BitsEncoding: IS_LOCALLY_INVARIANT))
12859 return ChangeStatus::UNCHANGED;
12860
12861 // try to infer invariance from underlying objects
12862 const auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
12863 IRP: getIRPosition(), QueryingAA: this, DepClass: DepClassTy::REQUIRED);
12864 if (!AUO)
12865 return ChangeStatus::UNCHANGED;
12866
12867 bool UsedAssumedInformation = false;
12868 const auto IsLocallyInvariantLoadIfPointer = [&](const Value &V) {
12869 if (!V.getType()->isPointerTy())
12870 return true;
12871 const auto *IsInvariantLoadPointer =
12872 A.getOrCreateAAFor<AAInvariantLoadPointer>(IRP: IRPosition::value(V), QueryingAA: this,
12873 DepClass: DepClassTy::REQUIRED);
12874 // Conservatively fail if invariance cannot be inferred.
12875 if (!IsInvariantLoadPointer)
12876 return false;
12877
12878 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12879 return true;
12880 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12881 return false;
12882
12883 UsedAssumedInformation = true;
12884 return true;
12885 };
12886 if (!AUO->forallUnderlyingObjects(Pred: IsLocallyInvariantLoadIfPointer))
12887 return indicatePessimisticFixpoint();
12888
12889 if (const auto *CB = dyn_cast<CallBase>(Val: &getAnchorValue())) {
12890 if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
12891 Call: CB, /*MustPreserveOffset=*/false)) {
12892 for (const Value *Arg : CB->args()) {
12893 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12894 return indicatePessimisticFixpoint();
12895 }
12896 }
12897 }
12898
12899 if (!UsedAssumedInformation) {
12900 // Pointer is known and not just assumed to be locally invariant.
12901 addKnownBits(Bits: IS_LOCALLY_INVARIANT);
12902 return ChangeStatus::CHANGED;
12903 }
12904
12905 return ChangeStatus::UNCHANGED;
12906 }
12907};
12908
12909struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12910 AAInvariantLoadPointerFloating(const IRPosition &IRP, Attributor &A)
12911 : AAInvariantLoadPointerImpl(IRP, A) {}
12912};
12913
12914struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12915 AAInvariantLoadPointerReturned(const IRPosition &IRP, Attributor &A)
12916 : AAInvariantLoadPointerImpl(IRP, A) {}
12917
12918 void initialize(Attributor &) override {
12919 removeAssumedBits(BitsEncoding: IS_LOCALLY_CONSTRAINED);
12920 }
12921};
12922
12923struct AAInvariantLoadPointerCallSiteReturned final
12924 : AAInvariantLoadPointerImpl {
12925 AAInvariantLoadPointerCallSiteReturned(const IRPosition &IRP, Attributor &A)
12926 : AAInvariantLoadPointerImpl(IRP, A) {}
12927
12928 void initialize(Attributor &A) override {
12929 const Function *F = getAssociatedFunction();
12930 assert(F && "no associated function for return from call");
12931
12932 if (!F->isDeclaration() && !F->isIntrinsic())
12933 return AAInvariantLoadPointerImpl::initialize(A);
12934
12935 const auto &CB = cast<CallBase>(Val&: getAnchorValue());
12936 if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
12937 Call: &CB, /*MustPreserveOffset=*/false))
12938 return AAInvariantLoadPointerImpl::initialize(A);
12939
12940 if (F->onlyReadsMemory() && F->hasNoSync())
12941 return AAInvariantLoadPointerImpl::initialize(A);
12942
12943 // At this point, the function is opaque, so we conservatively assume
12944 // non-invariance.
12945 indicatePessimisticFixpoint();
12946 }
12947};
12948
12949struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12950 AAInvariantLoadPointerArgument(const IRPosition &IRP, Attributor &A)
12951 : AAInvariantLoadPointerImpl(IRP, A) {}
12952
12953 void initialize(Attributor &) override {
12954 const Function *F = getAssociatedFunction();
12955 assert(F && "no associated function for argument");
12956
12957 if (!isCallableCC(CC: F->getCallingConv())) {
12958 addKnownBits(Bits: IS_LOCALLY_CONSTRAINED);
12959 return;
12960 }
12961
12962 if (!F->hasLocalLinkage())
12963 removeAssumedBits(BitsEncoding: IS_LOCALLY_CONSTRAINED);
12964 }
12965};
12966
12967struct AAInvariantLoadPointerCallSiteArgument final
12968 : AAInvariantLoadPointerImpl {
12969 AAInvariantLoadPointerCallSiteArgument(const IRPosition &IRP, Attributor &A)
12970 : AAInvariantLoadPointerImpl(IRP, A) {}
12971};
12972} // namespace
12973
12974/// ------------------------ Address Space ------------------------------------
12975namespace {
12976
12977template <typename InstType>
12978static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,
12979 Value *OriginalValue, PointerType *NewPtrTy,
12980 bool UseOriginalValue) {
12981 if (U.getOperandNo() != InstType::getPointerOperandIndex())
12982 return false;
12983
12984 if (MemInst->isVolatile()) {
12985 auto *TTI = A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12986 *MemInst->getFunction());
12987 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12988 if (!TTI || !TTI->hasVolatileVariant(MemInst, NewAS))
12989 return false;
12990 }
12991
12992 if (UseOriginalValue) {
12993 A.changeUseAfterManifest(U&: const_cast<Use &>(U), NV&: *OriginalValue);
12994 return true;
12995 }
12996
12997 Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12998 CastInst->insertBefore(MemInst->getIterator());
12999 A.changeUseAfterManifest(U&: const_cast<Use &>(U), NV&: *CastInst);
13000 return true;
13001}
13002
13003struct AAAddressSpaceImpl : public AAAddressSpace {
13004 AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)
13005 : AAAddressSpace(IRP, A) {}
13006
13007 uint32_t getAddressSpace() const override {
13008 assert(isValidState() && "the AA is invalid");
13009 return AssumedAddressSpace;
13010 }
13011
13012 /// See AbstractAttribute::initialize(...).
13013 void initialize(Attributor &A) override {
13014 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13015 "Associated value is not a pointer");
13016
13017 if (!A.getInfoCache().getFlatAddressSpace().has_value()) {
13018 indicatePessimisticFixpoint();
13019 return;
13020 }
13021
13022 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13023 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13024 if (AS != FlatAS) {
13025 [[maybe_unused]] bool R = takeAddressSpace(AS);
13026 assert(R && "The take should happen");
13027 indicateOptimisticFixpoint();
13028 }
13029 }
13030
13031 ChangeStatus updateImpl(Attributor &A) override {
13032 uint32_t OldAddressSpace = AssumedAddressSpace;
13033 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13034
13035 auto CheckAddressSpace = [&](Value &Obj) {
13036 // Ignore undef.
13037 if (isa<UndefValue>(Val: &Obj))
13038 return true;
13039
13040 // If the object already has a non-flat address space, we simply take it.
13041 unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
13042 if (ObjAS != FlatAS)
13043 return takeAddressSpace(AS: ObjAS);
13044
13045 // At this point, we know Obj is in the flat address space. For a final
13046 // attempt, we want to use getAssumedAddrSpace, but first we must get the
13047 // associated function, if possible.
13048 Function *F = nullptr;
13049 if (auto *Arg = dyn_cast<Argument>(Val: &Obj))
13050 F = Arg->getParent();
13051 else if (auto *I = dyn_cast<Instruction>(Val: &Obj))
13052 F = I->getFunction();
13053
13054 // Use getAssumedAddrSpace if the associated function exists.
13055 if (F) {
13056 auto *TTI =
13057 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(F: *F);
13058 unsigned AssumedAS = TTI->getAssumedAddrSpace(V: &Obj);
13059 if (AssumedAS != ~0U)
13060 return takeAddressSpace(AS: AssumedAS);
13061 }
13062
13063 // Now we can't do anything else but to take the flat AS.
13064 return takeAddressSpace(AS: FlatAS);
13065 };
13066
13067 auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(IRP: getIRPosition(), QueryingAA: this,
13068 DepClass: DepClassTy::REQUIRED);
13069 if (!AUO->forallUnderlyingObjects(Pred: CheckAddressSpace))
13070 return indicatePessimisticFixpoint();
13071
13072 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13073 : ChangeStatus::CHANGED;
13074 }
13075
13076 /// See AbstractAttribute::manifest(...).
13077 ChangeStatus manifest(Attributor &A) override {
13078 unsigned NewAS = getAddressSpace();
13079
13080 if (NewAS == InvalidAddressSpace ||
13081 NewAS == getAssociatedType()->getPointerAddressSpace())
13082 return ChangeStatus::UNCHANGED;
13083
13084 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13085
13086 Value *AssociatedValue = &getAssociatedValue();
13087 Value *OriginalValue = peelAddrspacecast(V: AssociatedValue, FlatAS);
13088
13089 PointerType *NewPtrTy =
13090 PointerType::get(C&: getAssociatedType()->getContext(), AddressSpace: NewAS);
13091 bool UseOriginalValue =
13092 OriginalValue->getType()->getPointerAddressSpace() == NewAS;
13093
13094 bool Changed = false;
13095
13096 auto Pred = [&](const Use &U, bool &) {
13097 if (U.get() != AssociatedValue)
13098 return true;
13099 auto *Inst = dyn_cast<Instruction>(Val: U.getUser());
13100 if (!Inst)
13101 return true;
13102 // This is a WA to make sure we only change uses from the corresponding
13103 // CGSCC if the AA is run on CGSCC instead of the entire module.
13104 if (!A.isRunOn(Fn: Inst->getFunction()))
13105 return true;
13106 if (auto *LI = dyn_cast<LoadInst>(Val: Inst)) {
13107 Changed |=
13108 makeChange(A, MemInst: LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13109 } else if (auto *SI = dyn_cast<StoreInst>(Val: Inst)) {
13110 Changed |=
13111 makeChange(A, MemInst: SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13112 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Val: Inst)) {
13113 Changed |=
13114 makeChange(A, MemInst: RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13115 } else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Val: Inst)) {
13116 Changed |=
13117 makeChange(A, MemInst: CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13118 }
13119 return true;
13120 };
13121
13122 // It doesn't matter if we can't check all uses as we can simply
13123 // conservatively ignore those that can not be visited.
13124 (void)A.checkForAllUses(Pred, QueryingAA: *this, V: getAssociatedValue(),
13125 /* CheckBBLivenessOnly */ true);
13126
13127 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13128 }
13129
13130 /// See AbstractAttribute::getAsStr().
13131 const std::string getAsStr(Attributor *A) const override {
13132 if (!isValidState())
13133 return "addrspace(<invalid>)";
13134 return "addrspace(" +
13135 (AssumedAddressSpace == InvalidAddressSpace
13136 ? "none"
13137 : std::to_string(val: AssumedAddressSpace)) +
13138 ")";
13139 }
13140
13141private:
13142 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13143
13144 bool takeAddressSpace(uint32_t AS) {
13145 if (AssumedAddressSpace == InvalidAddressSpace) {
13146 AssumedAddressSpace = AS;
13147 return true;
13148 }
13149 return AssumedAddressSpace == AS;
13150 }
13151
13152 static Value *peelAddrspacecast(Value *V, unsigned FlatAS) {
13153 if (auto *I = dyn_cast<AddrSpaceCastInst>(Val: V)) {
13154 assert(I->getSrcAddressSpace() != FlatAS &&
13155 "there should not be flat AS -> non-flat AS");
13156 return I->getPointerOperand();
13157 }
13158 if (auto *C = dyn_cast<ConstantExpr>(Val: V))
13159 if (C->getOpcode() == Instruction::AddrSpaceCast) {
13160 assert(C->getOperand(0)->getType()->getPointerAddressSpace() !=
13161 FlatAS &&
13162 "there should not be flat AS -> non-flat AS X");
13163 return C->getOperand(i_nocapture: 0);
13164 }
13165 return V;
13166 }
13167};
13168
13169struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13170 AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)
13171 : AAAddressSpaceImpl(IRP, A) {}
13172
13173 void trackStatistics() const override {
13174 STATS_DECLTRACK_FLOATING_ATTR(addrspace);
13175 }
13176};
13177
13178struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13179 AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)
13180 : AAAddressSpaceImpl(IRP, A) {}
13181
13182 /// See AbstractAttribute::initialize(...).
13183 void initialize(Attributor &A) override {
13184 // TODO: we don't rewrite function argument for now because it will need to
13185 // rewrite the function signature and all call sites.
13186 (void)indicatePessimisticFixpoint();
13187 }
13188
13189 void trackStatistics() const override {
13190 STATS_DECLTRACK_FNRET_ATTR(addrspace);
13191 }
13192};
13193
13194struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13195 AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13196 : AAAddressSpaceImpl(IRP, A) {}
13197
13198 void trackStatistics() const override {
13199 STATS_DECLTRACK_CSRET_ATTR(addrspace);
13200 }
13201};
13202
13203struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13204 AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)
13205 : AAAddressSpaceImpl(IRP, A) {}
13206
13207 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }
13208};
13209
13210struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13211 AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13212 : AAAddressSpaceImpl(IRP, A) {}
13213
13214 /// See AbstractAttribute::initialize(...).
13215 void initialize(Attributor &A) override {
13216 // TODO: we don't rewrite call site argument for now because it will need to
13217 // rewrite the function signature of the callee.
13218 (void)indicatePessimisticFixpoint();
13219 }
13220
13221 void trackStatistics() const override {
13222 STATS_DECLTRACK_CSARG_ATTR(addrspace);
13223 }
13224};
13225} // namespace
13226
13227/// ------------------------ No Alias Address Space ---------------------------
13228// This attribute assumes flat address space can alias all other address space
13229
13230// TODO: this is similar to AAAddressSpace, most of the code should be merged.
13231// But merging it created failing cased on gateway test that cannot be
13232// reproduced locally. So should open a separated PR to handle the merge of
13233// AANoAliasAddrSpace and AAAddressSpace attribute
13234
13235namespace {
13236struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {
13237 AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)
13238 : AANoAliasAddrSpace(IRP, A) {}
13239
13240 void initialize(Attributor &A) override {
13241 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13242 "Associated value is not a pointer");
13243
13244 resetASRanges(A);
13245
13246 std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();
13247 if (!FlatAS.has_value()) {
13248 indicatePessimisticFixpoint();
13249 return;
13250 }
13251
13252 removeAS(AS: *FlatAS);
13253
13254 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13255 if (AS != *FlatAS) {
13256 removeAS(AS);
13257 indicateOptimisticFixpoint();
13258 }
13259 }
13260
13261 ChangeStatus updateImpl(Attributor &A) override {
13262 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13263 uint32_t OldAssumed = getAssumed();
13264
13265 auto CheckAddressSpace = [&](Value &Obj) {
13266 if (isa<PoisonValue>(Val: &Obj))
13267 return true;
13268
13269 unsigned AS = Obj.getType()->getPointerAddressSpace();
13270 if (AS == FlatAS)
13271 return false;
13272
13273 removeAS(AS: Obj.getType()->getPointerAddressSpace());
13274 return true;
13275 };
13276
13277 const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
13278 IRP: getIRPosition(), QueryingAA: this, DepClass: DepClassTy::REQUIRED);
13279 if (!AUO->forallUnderlyingObjects(Pred: CheckAddressSpace))
13280 return indicatePessimisticFixpoint();
13281
13282 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13283 : ChangeStatus::CHANGED;
13284 }
13285
13286 /// See AbstractAttribute::manifest(...).
13287 ChangeStatus manifest(Attributor &A) override {
13288 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13289
13290 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13291 if (AS != FlatAS || Map.empty())
13292 return ChangeStatus::UNCHANGED;
13293
13294 LLVMContext &Ctx = getAssociatedValue().getContext();
13295 MDNode *NoAliasASNode = nullptr;
13296 MDBuilder MDB(Ctx);
13297 // Has to use iterator to get the range info.
13298 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13299 if (!I.value())
13300 continue;
13301 unsigned Upper = I.stop();
13302 unsigned Lower = I.start();
13303 if (!NoAliasASNode) {
13304 NoAliasASNode = MDB.createRange(Lo: APInt(32, Lower), Hi: APInt(32, Upper + 1));
13305 continue;
13306 }
13307 MDNode *ASRange = MDB.createRange(Lo: APInt(32, Lower), Hi: APInt(32, Upper + 1));
13308 NoAliasASNode = MDNode::getMostGenericRange(A: NoAliasASNode, B: ASRange);
13309 }
13310
13311 Value *AssociatedValue = &getAssociatedValue();
13312 bool Changed = false;
13313
13314 auto AddNoAliasAttr = [&](const Use &U, bool &) {
13315 if (U.get() != AssociatedValue)
13316 return true;
13317 Instruction *Inst = dyn_cast<Instruction>(Val: U.getUser());
13318 if (!Inst || Inst->hasMetadata(KindID: LLVMContext::MD_noalias_addrspace))
13319 return true;
13320 if (!isa<LoadInst>(Val: Inst) && !isa<StoreInst>(Val: Inst) &&
13321 !isa<AtomicCmpXchgInst>(Val: Inst) && !isa<AtomicRMWInst>(Val: Inst))
13322 return true;
13323 if (!A.isRunOn(Fn: Inst->getFunction()))
13324 return true;
13325 Inst->setMetadata(KindID: LLVMContext::MD_noalias_addrspace, Node: NoAliasASNode);
13326 Changed = true;
13327 return true;
13328 };
13329 (void)A.checkForAllUses(Pred: AddNoAliasAttr, QueryingAA: *this, V: *AssociatedValue,
13330 /*CheckBBLivenessOnly=*/true);
13331 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13332 }
13333
13334 /// See AbstractAttribute::getAsStr().
13335 const std::string getAsStr(Attributor *A) const override {
13336 if (!isValidState())
13337 return "<invalid>";
13338 std::string Str;
13339 raw_string_ostream OS(Str);
13340 OS << "CanNotBeAddrSpace(";
13341 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13342 unsigned Upper = I.stop();
13343 unsigned Lower = I.start();
13344 OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';
13345 }
13346 OS << " )";
13347 return OS.str();
13348 }
13349
13350private:
13351 void removeAS(unsigned AS) {
13352 RangeMap::iterator I = Map.find(x: AS);
13353
13354 if (I != Map.end()) {
13355 unsigned Upper = I.stop();
13356 unsigned Lower = I.start();
13357 I.erase();
13358 if (Upper == Lower)
13359 return;
13360 if (AS != ~((unsigned)0) && AS + 1 <= Upper)
13361 Map.insert(a: AS + 1, b: Upper, /*what ever this variable name is=*/y: true);
13362 if (AS != 0 && Lower <= AS - 1)
13363 Map.insert(a: Lower, b: AS - 1, y: true);
13364 }
13365 }
13366
13367 void resetASRanges(Attributor &A) {
13368 Map.clear();
13369 Map.insert(a: 0, b: A.getInfoCache().getMaxAddrSpace(), y: true);
13370 }
13371};
13372
13373struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13374 AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)
13375 : AANoAliasAddrSpaceImpl(IRP, A) {}
13376
13377 void trackStatistics() const override {
13378 STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);
13379 }
13380};
13381
13382struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13383 AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)
13384 : AANoAliasAddrSpaceImpl(IRP, A) {}
13385
13386 void trackStatistics() const override {
13387 STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);
13388 }
13389};
13390
13391struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13392 AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13393 : AANoAliasAddrSpaceImpl(IRP, A) {}
13394
13395 void trackStatistics() const override {
13396 STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);
13397 }
13398};
13399
13400struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13401 AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)
13402 : AANoAliasAddrSpaceImpl(IRP, A) {}
13403
13404 void trackStatistics() const override {
13405 STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);
13406 }
13407};
13408
13409struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13410 AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13411 : AANoAliasAddrSpaceImpl(IRP, A) {}
13412
13413 void trackStatistics() const override {
13414 STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);
13415 }
13416};
13417} // namespace
13418/// ----------- Allocation Info ----------
13419namespace {
13420struct AAAllocationInfoImpl : public AAAllocationInfo {
13421 AAAllocationInfoImpl(const IRPosition &IRP, Attributor &A)
13422 : AAAllocationInfo(IRP, A) {}
13423
13424 std::optional<TypeSize> getAllocatedSize() const override {
13425 assert(isValidState() && "the AA is invalid");
13426 return AssumedAllocatedSize;
13427 }
13428
13429 std::optional<TypeSize> findInitialAllocationSize(Instruction *I,
13430 const DataLayout &DL) {
13431
13432 // TODO: implement case for malloc like instructions
13433 switch (I->getOpcode()) {
13434 case Instruction::Alloca: {
13435 AllocaInst *AI = cast<AllocaInst>(Val: I);
13436 return AI->getAllocationSize(DL);
13437 }
13438 default:
13439 return std::nullopt;
13440 }
13441 }
13442
13443 ChangeStatus updateImpl(Attributor &A) override {
13444
13445 const IRPosition &IRP = getIRPosition();
13446 Instruction *I = IRP.getCtxI();
13447
13448 // TODO: update check for malloc like calls
13449 if (!isa<AllocaInst>(Val: I))
13450 return indicatePessimisticFixpoint();
13451
13452 bool IsKnownNoCapture;
13453 if (!AA::hasAssumedIRAttr<Attribute::Captures>(
13454 A, QueryingAA: this, IRP, DepClass: DepClassTy::OPTIONAL, IsKnown&: IsKnownNoCapture))
13455 return indicatePessimisticFixpoint();
13456
13457 const AAPointerInfo *PI =
13458 A.getOrCreateAAFor<AAPointerInfo>(IRP, QueryingAA: *this, DepClass: DepClassTy::REQUIRED);
13459
13460 if (!PI)
13461 return indicatePessimisticFixpoint();
13462
13463 if (!PI->getState().isValidState() || PI->reachesReturn())
13464 return indicatePessimisticFixpoint();
13465
13466 const DataLayout &DL = A.getDataLayout();
13467 const auto AllocationSize = findInitialAllocationSize(I, DL);
13468
13469 // If allocation size is nullopt, we give up.
13470 if (!AllocationSize)
13471 return indicatePessimisticFixpoint();
13472
13473 // For zero sized allocations, we give up.
13474 // Since we can't reduce further
13475 if (*AllocationSize == 0)
13476 return indicatePessimisticFixpoint();
13477
13478 int64_t BinSize = PI->numOffsetBins();
13479
13480 // TODO: implement for multiple bins
13481 if (BinSize > 1)
13482 return indicatePessimisticFixpoint();
13483
13484 if (BinSize == 0) {
13485 auto NewAllocationSize = std::make_optional<TypeSize>(args: 0, args: false);
13486 if (!changeAllocationSize(Size: NewAllocationSize))
13487 return ChangeStatus::UNCHANGED;
13488 return ChangeStatus::CHANGED;
13489 }
13490
13491 // TODO: refactor this to be part of multiple bin case
13492 const auto &It = PI->begin();
13493
13494 // TODO: handle if Offset is not zero
13495 if (It->first.Offset != 0)
13496 return indicatePessimisticFixpoint();
13497
13498 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13499
13500 if (SizeOfBin >= *AllocationSize)
13501 return indicatePessimisticFixpoint();
13502
13503 auto NewAllocationSize = std::make_optional<TypeSize>(args: SizeOfBin * 8, args: false);
13504
13505 if (!changeAllocationSize(Size: NewAllocationSize))
13506 return ChangeStatus::UNCHANGED;
13507
13508 return ChangeStatus::CHANGED;
13509 }
13510
13511 /// See AbstractAttribute::manifest(...).
13512 ChangeStatus manifest(Attributor &A) override {
13513
13514 assert(isValidState() &&
13515 "Manifest should only be called if the state is valid.");
13516
13517 Instruction *I = getIRPosition().getCtxI();
13518
13519 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13520
13521 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13522
13523 switch (I->getOpcode()) {
13524 // TODO: add case for malloc like calls
13525 case Instruction::Alloca: {
13526
13527 AllocaInst *AI = cast<AllocaInst>(Val: I);
13528
13529 Type *CharType = Type::getInt8Ty(C&: I->getContext());
13530
13531 auto *NumBytesToValue =
13532 ConstantInt::get(Context&: I->getContext(), V: APInt(32, NumBytesToAllocate));
13533
13534 BasicBlock::iterator insertPt = AI->getIterator();
13535 insertPt = std::next(x: insertPt);
13536 AllocaInst *NewAllocaInst =
13537 new AllocaInst(CharType, AI->getAddressSpace(), NumBytesToValue,
13538 AI->getAlign(), AI->getName(), insertPt);
13539
13540 if (A.changeAfterManifest(IRP: IRPosition::inst(I: *AI), NV&: *NewAllocaInst))
13541 return ChangeStatus::CHANGED;
13542
13543 break;
13544 }
13545 default:
13546 break;
13547 }
13548
13549 return ChangeStatus::UNCHANGED;
13550 }
13551
13552 /// See AbstractAttribute::getAsStr().
13553 const std::string getAsStr(Attributor *A) const override {
13554 if (!isValidState())
13555 return "allocationinfo(<invalid>)";
13556 return "allocationinfo(" +
13557 (AssumedAllocatedSize == HasNoAllocationSize
13558 ? "none"
13559 : std::to_string(val: AssumedAllocatedSize->getFixedValue())) +
13560 ")";
13561 }
13562
13563private:
13564 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13565
13566 // Maintain the computed allocation size of the object.
13567 // Returns (bool) weather the size of the allocation was modified or not.
13568 bool changeAllocationSize(std::optional<TypeSize> Size) {
13569 if (AssumedAllocatedSize == HasNoAllocationSize ||
13570 AssumedAllocatedSize != Size) {
13571 AssumedAllocatedSize = Size;
13572 return true;
13573 }
13574 return false;
13575 }
13576};
13577
13578struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13579 AAAllocationInfoFloating(const IRPosition &IRP, Attributor &A)
13580 : AAAllocationInfoImpl(IRP, A) {}
13581
13582 void trackStatistics() const override {
13583 STATS_DECLTRACK_FLOATING_ATTR(allocationinfo);
13584 }
13585};
13586
13587struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13588 AAAllocationInfoReturned(const IRPosition &IRP, Attributor &A)
13589 : AAAllocationInfoImpl(IRP, A) {}
13590
13591 /// See AbstractAttribute::initialize(...).
13592 void initialize(Attributor &A) override {
13593 // TODO: we don't rewrite function argument for now because it will need to
13594 // rewrite the function signature and all call sites
13595 (void)indicatePessimisticFixpoint();
13596 }
13597
13598 void trackStatistics() const override {
13599 STATS_DECLTRACK_FNRET_ATTR(allocationinfo);
13600 }
13601};
13602
13603struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13604 AAAllocationInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
13605 : AAAllocationInfoImpl(IRP, A) {}
13606
13607 void trackStatistics() const override {
13608 STATS_DECLTRACK_CSRET_ATTR(allocationinfo);
13609 }
13610};
13611
13612struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13613 AAAllocationInfoArgument(const IRPosition &IRP, Attributor &A)
13614 : AAAllocationInfoImpl(IRP, A) {}
13615
13616 void trackStatistics() const override {
13617 STATS_DECLTRACK_ARG_ATTR(allocationinfo);
13618 }
13619};
13620
13621struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13622 AAAllocationInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
13623 : AAAllocationInfoImpl(IRP, A) {}
13624
13625 /// See AbstractAttribute::initialize(...).
13626 void initialize(Attributor &A) override {
13627
13628 (void)indicatePessimisticFixpoint();
13629 }
13630
13631 void trackStatistics() const override {
13632 STATS_DECLTRACK_CSARG_ATTR(allocationinfo);
13633 }
13634};
13635} // namespace
13636
13637const char AANoUnwind::ID = 0;
13638const char AANoSync::ID = 0;
13639const char AANoFree::ID = 0;
13640const char AANonNull::ID = 0;
13641const char AAMustProgress::ID = 0;
13642const char AANoRecurse::ID = 0;
13643const char AANonConvergent::ID = 0;
13644const char AAWillReturn::ID = 0;
13645const char AAUndefinedBehavior::ID = 0;
13646const char AANoAlias::ID = 0;
13647const char AAIntraFnReachability::ID = 0;
13648const char AANoReturn::ID = 0;
13649const char AAIsDead::ID = 0;
13650const char AADereferenceable::ID = 0;
13651const char AAAlign::ID = 0;
13652const char AAInstanceInfo::ID = 0;
13653const char AANoCapture::ID = 0;
13654const char AAValueSimplify::ID = 0;
13655const char AAHeapToStack::ID = 0;
13656const char AAPrivatizablePtr::ID = 0;
13657const char AAMemoryBehavior::ID = 0;
13658const char AAMemoryLocation::ID = 0;
13659const char AAValueConstantRange::ID = 0;
13660const char AAPotentialConstantValues::ID = 0;
13661const char AAPotentialValues::ID = 0;
13662const char AANoUndef::ID = 0;
13663const char AANoFPClass::ID = 0;
13664const char AACallEdges::ID = 0;
13665const char AAInterFnReachability::ID = 0;
13666const char AAPointerInfo::ID = 0;
13667const char AAAssumptionInfo::ID = 0;
13668const char AAUnderlyingObjects::ID = 0;
13669const char AAInvariantLoadPointer::ID = 0;
13670const char AAAddressSpace::ID = 0;
13671const char AANoAliasAddrSpace::ID = 0;
13672const char AAAllocationInfo::ID = 0;
13673const char AAIndirectCallInfo::ID = 0;
13674const char AAGlobalValueInfo::ID = 0;
13675const char AADenormalFPMath::ID = 0;
13676
13677// Macro magic to create the static generator function for attributes that
13678// follow the naming scheme.
13679
13680#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13681 case IRPosition::PK: \
13682 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13683
13684#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13685 case IRPosition::PK: \
13686 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13687 ++NumAAs; \
13688 break;
13689
13690#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13691 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13692 CLASS *AA = nullptr; \
13693 switch (IRP.getPositionKind()) { \
13694 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13695 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13696 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13697 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13698 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13699 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13700 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13701 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13702 } \
13703 return *AA; \
13704 }
13705
13706#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13707 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13708 CLASS *AA = nullptr; \
13709 switch (IRP.getPositionKind()) { \
13710 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13711 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13712 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13713 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13714 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13715 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13716 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13717 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13718 } \
13719 return *AA; \
13720 }
13721
13722#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13723 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13724 CLASS *AA = nullptr; \
13725 switch (IRP.getPositionKind()) { \
13726 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13727 default: \
13728 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13729 " position!"); \
13730 } \
13731 return *AA; \
13732 }
13733
13734#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13735 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13736 CLASS *AA = nullptr; \
13737 switch (IRP.getPositionKind()) { \
13738 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13739 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13740 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13741 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13742 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13743 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13744 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13745 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13746 } \
13747 return *AA; \
13748 }
13749
13750#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13751 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13752 CLASS *AA = nullptr; \
13753 switch (IRP.getPositionKind()) { \
13754 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13755 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13756 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13757 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13758 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13759 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13760 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13761 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13762 } \
13763 return *AA; \
13764 }
13765
13766#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13767 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13768 CLASS *AA = nullptr; \
13769 switch (IRP.getPositionKind()) { \
13770 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13771 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13772 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13773 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13774 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13775 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13776 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13777 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13778 } \
13779 return *AA; \
13780 }
13781
13782CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
13783CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
13784CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
13785CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
13786CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
13787CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation)
13788CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges)
13789CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAssumptionInfo)
13790CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMustProgress)
13791
13792CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
13793CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
13794CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPrivatizablePtr)
13795CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
13796CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
13797CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInstanceInfo)
13798CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
13799CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange)
13800CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialConstantValues)
13801CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues)
13802CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef)
13803CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFPClass)
13804CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo)
13805CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInvariantLoadPointer)
13806CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAddressSpace)
13807CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAliasAddrSpace)
13808CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAllocationInfo)
13809
13810CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)
13811CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
13812CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
13813CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUnderlyingObjects)
13814
13815CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(IRP_CALL_SITE, CallSite,
13816 AAIndirectCallInfo)
13817CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(IRP_FLOAT, Floating,
13818 AAGlobalValueInfo)
13819
13820CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)
13821CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior)
13822CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonConvergent)
13823CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIntraFnReachability)
13824CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInterFnReachability)
13825CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADenormalFPMath)
13826
13827CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)
13828
13829#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13830#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13831#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13832#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13833#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13834#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13835#undef SWITCH_PK_CREATE
13836#undef SWITCH_PK_INV
13837