LLVM 24.0.0git
AttributorAttributes.cpp
Go to the documentation of this file.
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
16
17#include "llvm/ADT/APInt.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/MapVector.h"
23#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SetVector.h"
28#include "llvm/ADT/Statistic.h"
41#include "llvm/IR/Argument.h"
42#include "llvm/IR/Assumptions.h"
44#include "llvm/IR/Attributes.h"
45#include "llvm/IR/BasicBlock.h"
46#include "llvm/IR/Constant.h"
47#include "llvm/IR/Constants.h"
48#include "llvm/IR/DataLayout.h"
50#include "llvm/IR/GlobalValue.h"
51#include "llvm/IR/IRBuilder.h"
52#include "llvm/IR/InlineAsm.h"
53#include "llvm/IR/InstrTypes.h"
54#include "llvm/IR/Instruction.h"
57#include "llvm/IR/IntrinsicsAMDGPU.h"
58#include "llvm/IR/IntrinsicsNVPTX.h"
59#include "llvm/IR/LLVMContext.h"
60#include "llvm/IR/MDBuilder.h"
61#include "llvm/IR/NoFolder.h"
62#include "llvm/IR/Value.h"
63#include "llvm/IR/ValueHandle.h"
78#include <cassert>
79#include <numeric>
80#include <optional>
81#include <string>
82
83using namespace llvm;
84
85#define DEBUG_TYPE "attributor"
86
88 "attributor-manifest-internal", cl::Hidden,
89 cl::desc("Manifest Attributor internal string attributes."),
90 cl::init(false));
91
92static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128),
94
95template <>
97
99
101 "attributor-max-potential-values", cl::Hidden,
102 cl::desc("Maximum number of potential values to be "
103 "tracked for each position."),
105 cl::init(7));
106
108 "attributor-max-potential-values-iterations", cl::Hidden,
109 cl::desc(
110 "Maximum number of iterations we keep dismantling potential values."),
111 cl::init(64));
112
113STATISTIC(NumAAs, "Number of abstract attributes created");
114STATISTIC(NumIndirectCallsPromoted, "Number of indirect calls promoted");
115
116// Some helper macros to deal with statistics tracking.
117//
118// Usage:
119// For simple IR attribute tracking overload trackStatistics in the abstract
120// attribute and choose the right STATS_DECLTRACK_********* macro,
121// e.g.,:
122// void trackStatistics() const override {
123// STATS_DECLTRACK_ARG_ATTR(returned)
124// }
125// If there is a single "increment" side one can use the macro
126// STATS_DECLTRACK with a custom message. If there are multiple increment
127// sides, STATS_DECL and STATS_TRACK can also be used separately.
128//
129#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
130 ("Number of " #TYPE " marked '" #NAME "'")
131#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
132#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
133#define STATS_DECL(NAME, TYPE, MSG) \
134 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
135#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
136#define STATS_DECLTRACK(NAME, TYPE, MSG) \
137 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
138#define STATS_DECLTRACK_ARG_ATTR(NAME) \
139 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
140#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
141 STATS_DECLTRACK(NAME, CSArguments, \
142 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
143#define STATS_DECLTRACK_FN_ATTR(NAME) \
144 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
145#define STATS_DECLTRACK_CS_ATTR(NAME) \
146 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
147#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
148 STATS_DECLTRACK(NAME, FunctionReturn, \
149 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
150#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
151 STATS_DECLTRACK(NAME, CSReturn, \
152 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
153#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
154 STATS_DECLTRACK(NAME, Floating, \
155 ("Number of floating values known to be '" #NAME "'"))
156
157// Specialization of the operator<< for abstract attributes subclasses. This
158// disambiguates situations where multiple operators are applicable.
159namespace llvm {
160#define PIPE_OPERATOR(CLASS) \
161 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
162 return OS << static_cast<const AbstractAttribute &>(AA); \
163 }
164
204
205#undef PIPE_OPERATOR
206
207template <>
209 const DerefState &R) {
210 ChangeStatus CS0 =
211 clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);
212 ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);
213 return CS0 | CS1;
214}
215
216} // namespace llvm
217
218static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
219 bool HeaderOnly, CycleRef *CPtr = nullptr) {
220 if (!CI)
221 return true;
222 auto *BB = I->getParent();
223 CycleRef C = CI->getCycle(BB);
224 if (!C)
225 return false;
226 if (CPtr)
227 *CPtr = C;
228 return !HeaderOnly || BB == CI->getHeader(C);
229}
230
231/// Checks if a type could have padding bytes.
232static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
233 // There is no size information, so be conservative.
234 if (!Ty->isSized())
235 return false;
236
237 // If the alloc size is not equal to the storage size, then there are padding
238 // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
239 if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
240 return false;
241
242 // FIXME: This isn't the right way to check for padding in vectors with
243 // non-byte-size elements.
244 if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))
245 return isDenselyPacked(SeqTy->getElementType(), DL);
246
247 // For array types, check for padding within members.
248 if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))
249 return isDenselyPacked(SeqTy->getElementType(), DL);
250
251 if (!isa<StructType>(Ty))
252 return true;
253
254 // Check for padding within and between elements of a struct.
255 StructType *StructTy = cast<StructType>(Ty);
256 const StructLayout *Layout = DL.getStructLayout(StructTy);
257 uint64_t StartPos = 0;
258 for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
259 Type *ElTy = StructTy->getElementType(I);
260 if (!isDenselyPacked(ElTy, DL))
261 return false;
262 if (StartPos != Layout->getElementOffsetInBits(I))
263 return false;
264 StartPos += DL.getTypeAllocSizeInBits(ElTy);
265 }
266
267 // Check for tail padding.
268 return StartPos == Layout->getSizeInBits();
269}
270
271/// Get pointer operand of memory accessing instruction. If \p I is
272/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
273/// is set to false and the instruction is volatile, return nullptr.
275 bool AllowVolatile) {
276 if (!AllowVolatile && I->isVolatile())
277 return nullptr;
278
279 if (auto *LI = dyn_cast<LoadInst>(I)) {
280 return LI->getPointerOperand();
281 }
282
283 if (auto *SI = dyn_cast<StoreInst>(I)) {
284 return SI->getPointerOperand();
285 }
286
287 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) {
288 return CXI->getPointerOperand();
289 }
290
291 if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {
292 return RMWI->getPointerOperand();
293 }
294
295 return nullptr;
296}
297
298/// Helper function to create a pointer based on \p Ptr, and advanced by \p
299/// Offset bytes.
300static Value *constructPointer(Value *Ptr, int64_t Offset,
301 IRBuilder<NoFolder> &IRB) {
302 LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
303 << "-bytes\n");
304
305 if (Offset)
307 Ptr, Offset, Ptr->getName() + ".b" + Twine(Offset));
308 return Ptr;
309}
310
311static const Value *
313 const Value *Val, const DataLayout &DL, APInt &Offset,
314 bool GetMinOffset, bool AllowNonInbounds,
315 bool UseAssumed = false) {
316
317 auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
318 const IRPosition &Pos = IRPosition::value(V);
319 // Only track dependence if we are going to use the assumed info.
320 const AAValueConstantRange *ValueConstantRangeAA =
321 A.getAAFor<AAValueConstantRange>(QueryingAA, Pos,
322 UseAssumed ? DepClassTy::OPTIONAL
324 if (!ValueConstantRangeAA)
325 return false;
326 ConstantRange Range = UseAssumed ? ValueConstantRangeAA->getAssumed()
327 : ValueConstantRangeAA->getKnown();
328 if (Range.isFullSet())
329 return false;
330
331 // We can only use the lower part of the range because the upper part can
332 // be higher than what the value can really be.
333 if (GetMinOffset)
334 ROffset = Range.getSignedMin();
335 else
336 ROffset = Range.getSignedMax();
337 return true;
338 };
339
340 return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
341 /* AllowInvariant */ true,
342 AttributorAnalysis);
343}
344
345static const Value *
347 const Value *Ptr, int64_t &BytesOffset,
348 const DataLayout &DL, bool AllowNonInbounds = false) {
349 APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
350 const Value *Base =
351 stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,
352 /* GetMinOffset */ true, AllowNonInbounds);
353
354 BytesOffset = OffsetAPInt.getSExtValue();
355 return Base;
356}
357
358/// Clamp the information known for all returned values of a function
359/// (identified by \p QueryingAA) into \p S.
360template <typename AAType, typename StateType = typename AAType::StateType,
361 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
362 bool RecurseForSelectAndPHI = true>
364 Attributor &A, const AAType &QueryingAA, StateType &S,
365 const IRPosition::CallBaseContext *CBContext = nullptr) {
366 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
367 << QueryingAA << " into " << S << "\n");
368
369 assert((QueryingAA.getIRPosition().getPositionKind() ==
371 QueryingAA.getIRPosition().getPositionKind() ==
373 "Can only clamp returned value states for a function returned or call "
374 "site returned position!");
375
376 // Use an optional state as there might not be any return values and we want
377 // to join (IntegerState::operator&) the state of all there are.
378 std::optional<StateType> T;
379
380 // Callback for each possibly returned value.
381 auto CheckReturnValue = [&](Value &RV) -> bool {
382 const IRPosition &RVPos = IRPosition::value(RV, CBContext);
383 // If possible, use the hasAssumedIRAttr interface.
384 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
385 bool IsKnown;
387 A, &QueryingAA, RVPos, DepClassTy::REQUIRED, IsKnown);
388 }
389
390 const AAType *AA =
391 A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);
392 if (!AA)
393 return false;
394 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV
395 << " AA: " << AA->getAsStr(&A) << " @ " << RVPos << "\n");
396 const StateType &AAS = AA->getState();
397 if (!T)
398 T = StateType::getBestState(AAS);
399 *T &= AAS;
400 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
401 << "\n");
402 return T->isValidState();
403 };
404
405 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
407 RecurseForSelectAndPHI))
408 S.indicatePessimisticFixpoint();
409 else if (T)
410 S ^= *T;
411}
412
413namespace {
414/// Helper class for generic deduction: return value -> returned position.
415template <typename AAType, typename BaseType,
416 typename StateType = typename BaseType::StateType,
417 bool PropagateCallBaseContext = false,
418 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
419 bool RecurseForSelectAndPHI = true>
420struct AAReturnedFromReturnedValues : public BaseType {
421 AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
422 : BaseType(IRP, A) {}
423
424 ChangeStatus updateImpl(Attributor &A) override {
425 StateType S(StateType::getBestState(this->getState()));
426 clampReturnedValueStates<AAType, StateType, IRAttributeKind,
427 RecurseForSelectAndPHI>(
428 A, *this, S,
429 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
430 // TODO: If we know we visited all returned values, thus no are assumed
431 // dead, we can take the known information from the state T.
432 return clampStateAndIndicateChange<StateType>(this->getState(), S);
433 }
434};
435
436/// Clamp the information known at all call sites for a given argument
437/// (identified by \p QueryingAA) into \p S.
438template <typename AAType, typename StateType = typename AAType::StateType,
439 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
440static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
441 StateType &S) {
442 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
443 << QueryingAA << " into " << S << "\n");
444
445 assert(QueryingAA.getIRPosition().getPositionKind() ==
447 "Can only clamp call site argument states for an argument position!");
448
449 // Use an optional state as there might not be any return values and we want
450 // to join (IntegerState::operator&) the state of all there are.
451 std::optional<StateType> T;
452
453 // The argument number which is also the call site argument number.
454 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
455
456 auto CallSiteCheck = [&](AbstractCallSite ACS) {
457 const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
458 // Check if a coresponding argument was found or if it is on not associated
459 // (which can happen for callback calls).
460 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
461 return false;
462
463 // If possible, use the hasAssumedIRAttr interface.
464 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
465 bool IsKnown;
467 A, &QueryingAA, ACSArgPos, DepClassTy::REQUIRED, IsKnown);
468 }
469
470 const AAType *AA =
471 A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);
472 if (!AA)
473 return false;
474 LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()
475 << " AA: " << AA->getAsStr(&A) << " @" << ACSArgPos
476 << "\n");
477 const StateType &AAS = AA->getState();
478 if (!T)
479 T = StateType::getBestState(AAS);
480 *T &= AAS;
481 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
482 << "\n");
483 return T->isValidState();
484 };
485
486 bool UsedAssumedInformation = false;
487 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,
488 UsedAssumedInformation))
489 S.indicatePessimisticFixpoint();
490 else if (T)
491 S ^= *T;
492}
493
494/// This function is the bridge between argument position and the call base
495/// context.
496template <typename AAType, typename BaseType,
497 typename StateType = typename AAType::StateType,
498 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
499bool getArgumentStateFromCallBaseContext(Attributor &A,
500 BaseType &QueryingAttribute,
501 IRPosition &Pos, StateType &State) {
503 "Expected an 'argument' position !");
504 const CallBase *CBContext = Pos.getCallBaseContext();
505 if (!CBContext)
506 return false;
507
508 int ArgNo = Pos.getCallSiteArgNo();
509 assert(ArgNo >= 0 && "Invalid Arg No!");
510 const IRPosition CBArgPos = IRPosition::callsite_argument(*CBContext, ArgNo);
511
512 // If possible, use the hasAssumedIRAttr interface.
513 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
514 bool IsKnown;
516 A, &QueryingAttribute, CBArgPos, DepClassTy::REQUIRED, IsKnown);
517 }
518
519 const auto *AA =
520 A.getAAFor<AAType>(QueryingAttribute, CBArgPos, DepClassTy::REQUIRED);
521 if (!AA)
522 return false;
523 const StateType &CBArgumentState =
524 static_cast<const StateType &>(AA->getState());
525
526 LLVM_DEBUG(dbgs() << "[Attributor] Briding Call site context to argument"
527 << "Position:" << Pos << "CB Arg state:" << CBArgumentState
528 << "\n");
529
530 // NOTE: If we want to do call site grouping it should happen here.
531 State ^= CBArgumentState;
532 return true;
533}
534
535/// Helper class for generic deduction: call site argument -> argument position.
536template <typename AAType, typename BaseType,
537 typename StateType = typename AAType::StateType,
538 bool BridgeCallBaseContext = false,
539 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
540struct AAArgumentFromCallSiteArguments : public BaseType {
541 AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
542 : BaseType(IRP, A) {}
543
544 ChangeStatus updateImpl(Attributor &A) override {
545 StateType S = StateType::getBestState(this->getState());
546
547 if (BridgeCallBaseContext) {
548 bool Success =
549 getArgumentStateFromCallBaseContext<AAType, BaseType, StateType,
550 IRAttributeKind>(
551 A, *this, this->getIRPosition(), S);
552 if (Success)
553 return clampStateAndIndicateChange<StateType>(this->getState(), S);
554 }
555 clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(A, *this,
556 S);
557
558 // TODO: If we know we visited all incoming values, thus no are assumed
559 // dead, we can take the known information from the state T.
560 return clampStateAndIndicateChange<StateType>(this->getState(), S);
561 }
562};
563
564/// Helper class for generic replication: function returned -> cs returned.
565template <typename AAType, typename BaseType,
566 typename StateType = typename BaseType::StateType,
567 bool IntroduceCallBaseContext = false,
568 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
569struct AACalleeToCallSite : public BaseType {
570 AACalleeToCallSite(const IRPosition &IRP, Attributor &A) : BaseType(IRP, A) {}
571
572 ChangeStatus updateImpl(Attributor &A) override {
573 auto IRPKind = this->getIRPosition().getPositionKind();
575 IRPKind == IRPosition::IRP_CALL_SITE) &&
576 "Can only wrap function returned positions for call site "
577 "returned positions!");
578 auto &S = this->getState();
579
580 CallBase &CB = cast<CallBase>(this->getAnchorValue());
581 if (IntroduceCallBaseContext)
582 LLVM_DEBUG(dbgs() << "[Attributor] Introducing call base context:" << CB
583 << "\n");
584
585 ChangeStatus Changed = ChangeStatus::UNCHANGED;
586 auto CalleePred = [&](ArrayRef<const Function *> Callees) {
587 for (const Function *Callee : Callees) {
588 // The returned position of the callee does not describe the call if
589 // the call uses a different return type.
590 if (IRPKind == IRPosition::IRP_CALL_SITE_RETURNED &&
591 Callee->getReturnType() != CB.getType())
592 return false;
593 IRPosition FnPos =
595 ? IRPosition::returned(*Callee,
596 IntroduceCallBaseContext ? &CB : nullptr)
597 : IRPosition::function(
598 *Callee, IntroduceCallBaseContext ? &CB : nullptr);
599 // If possible, use the hasAssumedIRAttr interface.
600 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
601 bool IsKnown;
603 A, this, FnPos, DepClassTy::REQUIRED, IsKnown))
604 return false;
605 continue;
606 }
607
608 const AAType *AA =
609 A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);
610 if (!AA)
611 return false;
612 Changed |= clampStateAndIndicateChange(S, AA->getState());
613 if (S.isAtFixpoint())
614 return S.isValidState();
615 }
616 return true;
617 };
618 if (!A.checkForAllCallees(CalleePred, *this, CB))
619 return S.indicatePessimisticFixpoint();
620 return Changed;
621 }
622};
623
624/// Helper function to accumulate uses.
625template <class AAType, typename StateType = typename AAType::StateType>
626static void followUsesInContext(AAType &AA, Attributor &A,
628 const Instruction *CtxI,
630 StateType &State) {
631 auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);
632 for (unsigned u = 0; u < Uses.size(); ++u) {
633 const Use *U = Uses[u];
634 if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
635 bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
636 if (Found && AA.followUseInMBEC(A, U, UserI, State))
637 Uses.insert_range(llvm::make_pointer_range(UserI->uses()));
638 }
639 }
640}
641
642/// Use the must-be-executed-context around \p I to add information into \p S.
643/// The AAType class is required to have `followUseInMBEC` method with the
644/// following signature and behaviour:
645///
646/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)
647/// U - Underlying use.
648/// I - The user of the \p U.
649/// Returns true if the value should be tracked transitively.
650///
651template <class AAType, typename StateType = typename AAType::StateType>
652static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,
653 Instruction &CtxI) {
654 const Value &Val = AA.getIRPosition().getAssociatedValue();
655 if (isa<ConstantData>(Val))
656 return;
657
659 A.getInfoCache().getMustBeExecutedContextExplorer();
660 if (!Explorer)
661 return;
662
663 // Container for (transitive) uses of the associated value.
665 for (const Use &U : Val.uses())
666 Uses.insert(&U);
667
668 followUsesInContext<AAType>(AA, A, *Explorer, &CtxI, Uses, S);
669
670 if (S.isAtFixpoint())
671 return;
672
674 auto Pred = [&](const Instruction *I) {
675 if (const CondBrInst *Br = dyn_cast<CondBrInst>(I))
676 BrInsts.push_back(Br);
677 return true;
678 };
679
680 // Here, accumulate conditional branch instructions in the context. We
681 // explore the child paths and collect the known states. The disjunction of
682 // those states can be merged to its own state. Let ParentState_i be a state
683 // to indicate the known information for an i-th branch instruction in the
684 // context. ChildStates are created for its successors respectively.
685 //
686 // ParentS_1 = ChildS_{1, 1} /\ ChildS_{1, 2} /\ ... /\ ChildS_{1, n_1}
687 // ParentS_2 = ChildS_{2, 1} /\ ChildS_{2, 2} /\ ... /\ ChildS_{2, n_2}
688 // ...
689 // ParentS_m = ChildS_{m, 1} /\ ChildS_{m, 2} /\ ... /\ ChildS_{m, n_m}
690 //
691 // Known State |= ParentS_1 \/ ParentS_2 \/... \/ ParentS_m
692 //
693 // FIXME: Currently, recursive branches are not handled. For example, we
694 // can't deduce that ptr must be dereferenced in below function.
695 //
696 // void f(int a, int c, int *ptr) {
697 // if(a)
698 // if (b) {
699 // *ptr = 0;
700 // } else {
701 // *ptr = 1;
702 // }
703 // else {
704 // if (b) {
705 // *ptr = 0;
706 // } else {
707 // *ptr = 1;
708 // }
709 // }
710 // }
711
712 Explorer->checkForAllContext(&CtxI, Pred);
713 for (const CondBrInst *Br : BrInsts) {
714 StateType ParentState;
715
716 // The known state of the parent state is a conjunction of children's
717 // known states so it is initialized with a best state.
718 ParentState.indicateOptimisticFixpoint();
719
720 for (const BasicBlock *BB : Br->successors()) {
721 StateType ChildState;
722
723 size_t BeforeSize = Uses.size();
724 followUsesInContext(AA, A, *Explorer, &BB->front(), Uses, ChildState);
725
726 // Erase uses which only appear in the child.
727 for (auto It = Uses.begin() + BeforeSize; It != Uses.end();)
728 It = Uses.erase(It);
729
730 ParentState &= ChildState;
731 }
732
733 // Use only known state.
734 S += ParentState;
735 }
736}
737} // namespace
738
739/// ------------------------ PointerInfo ---------------------------------------
740
741namespace llvm {
742namespace AA {
743namespace PointerInfo {
744
745struct State;
746
747} // namespace PointerInfo
748} // namespace AA
749
750/// Helper for AA::PointerInfo::Access DenseMap/Set usage.
751template <>
754 static unsigned getHashValue(const Access &A);
755 static bool isEqual(const Access &LHS, const Access &RHS);
756};
757
758/// Helper that allows RangeTy as a key in a DenseMap.
759template <> struct DenseMapInfo<AA::RangeTy> {
765
766 static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {
767 return A == B;
768 }
769};
770
771} // namespace llvm
772
773/// A type to track pointer/struct usage and accesses for AAPointerInfo.
775 /// Return the best possible representable state.
776 static State getBestState(const State &SIS) { return State(); }
777
778 /// Return the worst possible representable state.
779 static State getWorstState(const State &SIS) {
780 State R;
781 R.indicatePessimisticFixpoint();
782 return R;
783 }
784
785 State() = default;
786 State(State &&SIS) = default;
787
788 const State &getAssumed() const { return *this; }
789
790 bool isValidState() const override { return BS.isValidState(); }
791
792 bool isAtFixpoint() const override { return BS.isAtFixpoint(); }
793
795 BS.indicateOptimisticFixpoint();
797 }
798
800 BS.indicatePessimisticFixpoint();
802 }
803
804 State &operator=(const State &R) {
805 if (this == &R)
806 return *this;
807 BS = R.BS;
808 AccessList = R.AccessList;
809 OffsetBins = R.OffsetBins;
810 RemoteIMap = R.RemoteIMap;
811 ReturnedOffsets = R.ReturnedOffsets;
812 return *this;
813 }
814
816 if (this == &R)
817 return *this;
818 std::swap(BS, R.BS);
819 std::swap(AccessList, R.AccessList);
820 std::swap(OffsetBins, R.OffsetBins);
821 std::swap(RemoteIMap, R.RemoteIMap);
822 std::swap(ReturnedOffsets, R.ReturnedOffsets);
823 return *this;
824 }
825
826 /// Add a new Access to the state at offset \p Offset and with size \p Size.
827 /// The access is associated with \p I, writes \p Content (if anything), and
828 /// is of kind \p Kind. If an Access already exists for the same \p I and same
829 /// \p RemoteI, the two are combined, potentially losing information about
830 /// offset and size. The resulting access must now be moved from its original
831 /// OffsetBin to the bin for its new offset.
832 ///
833 /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
835 Instruction &I, std::optional<Value *> Content,
837 Instruction *RemoteI = nullptr);
838
841 int64_t numOffsetBins() const { return OffsetBins.size(); }
842
843 const AAPointerInfo::Access &getAccess(unsigned Index) const {
844 return AccessList[Index];
845 }
846
847protected:
848 // Every memory instruction results in an Access object. We maintain a list of
849 // all Access objects that we own, along with the following maps:
850 //
851 // - OffsetBins: RangeTy -> { Access }
852 // - RemoteIMap: RemoteI x LocalI -> Access
853 //
854 // A RemoteI is any instruction that accesses memory. RemoteI is different
855 // from LocalI if and only if LocalI is a call; then RemoteI is some
856 // instruction in the callgraph starting from LocalI. Multiple paths in the
857 // callgraph from LocalI to RemoteI may produce multiple accesses, but these
858 // are all combined into a single Access object. This may result in loss of
859 // information in RangeTy in the Access object.
863
864 /// Flag to determine if the underlying pointer is reaching a return statement
865 /// in the associated function or not. Returns in other functions cause
866 /// invalidation.
868
869 /// See AAPointerInfo::forallInterferingAccesses.
870 template <typename F>
872 if (!isValidState() || !ReturnedOffsets.isUnassigned())
873 return false;
874
875 for (const auto &It : OffsetBins) {
876 AA::RangeTy ItRange = It.getFirst();
877 if (!Range.mayOverlap(ItRange))
878 continue;
879 bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();
880 for (auto Index : It.getSecond()) {
881 auto &Access = AccessList[Index];
882 if (!CB(Access, IsExact))
883 return false;
884 }
885 }
886 return true;
887 }
888
889 /// See AAPointerInfo::forallInterferingAccesses.
890 template <typename F>
892 AA::RangeTy &Range) const {
893 if (!isValidState() || !ReturnedOffsets.isUnassigned())
894 return false;
895
896 auto LocalList = RemoteIMap.find(&I);
897 if (LocalList == RemoteIMap.end()) {
898 return true;
899 }
900
901 for (unsigned Index : LocalList->getSecond()) {
902 for (auto &R : AccessList[Index]) {
903 Range &= R;
904 if (Range.offsetAndSizeAreUnknown())
905 break;
906 }
907 }
909 }
910
911private:
912 /// State to track fixpoint and validity.
913 BooleanState BS;
914};
915
918 std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,
919 Instruction *RemoteI) {
920 RemoteI = RemoteI ? RemoteI : &I;
921
922 // Check if we have an access for this instruction, if not, simply add it.
923 auto &LocalList = RemoteIMap[RemoteI];
924 bool AccExists = false;
925 unsigned AccIndex = AccessList.size();
926 for (auto Index : LocalList) {
927 auto &A = AccessList[Index];
928 if (A.getLocalInst() == &I) {
929 AccExists = true;
930 AccIndex = Index;
931 break;
932 }
933 }
934
935 auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {
936 LLVM_DEBUG(if (ToAdd.size()) dbgs()
937 << "[AAPointerInfo] Inserting access in new offset bins\n";);
938
939 for (auto Key : ToAdd) {
940 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
941 OffsetBins[Key].insert(AccIndex);
942 }
943 };
944
945 if (!AccExists) {
946 AccessList.emplace_back(&I, RemoteI, Ranges, Content, Kind, Ty);
947 assert((AccessList.size() == AccIndex + 1) &&
948 "New Access should have been at AccIndex");
949 LocalList.push_back(AccIndex);
950 AddToBins(AccessList[AccIndex].getRanges());
952 }
953
954 // Combine the new Access with the existing Access, and then update the
955 // mapping in the offset bins.
956 AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);
957 auto &Current = AccessList[AccIndex];
958 auto Before = Current;
959 Current &= Acc;
960 if (Current == Before)
962
963 auto &ExistingRanges = Before.getRanges();
964 auto &NewRanges = Current.getRanges();
965
966 // Ranges that are in the old access but not the new access need to be removed
967 // from the offset bins.
969 AAPointerInfo::RangeList::set_difference(ExistingRanges, NewRanges, ToRemove);
970 LLVM_DEBUG(if (ToRemove.size()) dbgs()
971 << "[AAPointerInfo] Removing access from old offset bins\n";);
972
973 for (auto Key : ToRemove) {
974 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
975 assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");
976 auto &Bin = OffsetBins[Key];
977 assert(Bin.count(AccIndex) &&
978 "Expected bin to actually contain the Access.");
979 Bin.erase(AccIndex);
980 }
981
982 // Ranges that are in the new access but not the old access need to be added
983 // to the offset bins.
985 AAPointerInfo::RangeList::set_difference(NewRanges, ExistingRanges, ToAdd);
986 AddToBins(ToAdd);
988}
989
990namespace {
991
992#ifndef NDEBUG
994 const AAPointerInfo::OffsetInfo &OI) {
995 OS << llvm::interleaved_array(OI);
996 return OS;
997}
998#endif // NDEBUG
999
1000struct AAPointerInfoImpl
1001 : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1003 AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
1004
1005 const std::string getAsStr(Attributor *A) const override {
1006 return std::string("PointerInfo ") +
1007 (isValidState() ? (std::string("#") +
1008 std::to_string(OffsetBins.size()) + " bins")
1009 : "<invalid>") +
1010 (reachesReturn()
1011 ? (" (returned:" +
1012 join(map_range(ReturnedOffsets,
1013 [](int64_t O) { return std::to_string(O); }),
1014 ", ") +
1015 ")")
1016 : "");
1017 }
1018
1019 ChangeStatus manifest(Attributor &A) override {
1020 return AAPointerInfo::manifest(A);
1021 }
1022
1023 const_bin_iterator begin() const override { return State::begin(); }
1024 const_bin_iterator end() const override { return State::end(); }
1025 int64_t numOffsetBins() const override { return State::numOffsetBins(); }
1026 bool reachesReturn() const override {
1027 return !ReturnedOffsets.isUnassigned();
1028 }
1029 void addReturnedOffsetsTo(OffsetInfo &OI) const override {
1030 if (ReturnedOffsets.isUnknown()) {
1031 OI.setUnknown();
1032 return;
1033 }
1034
1035 OffsetInfo MergedOI;
1036 for (auto Offset : ReturnedOffsets) {
1037 OffsetInfo TmpOI = OI;
1038 TmpOI.addToAll(Offset);
1039 MergedOI.merge(TmpOI);
1040 }
1041 OI = std::move(MergedOI);
1042 }
1043
1044 ChangeStatus setReachesReturn(const OffsetInfo &ReachedReturnedOffsets) {
1045 if (ReturnedOffsets.isUnknown())
1046 return ChangeStatus::UNCHANGED;
1047 if (ReachedReturnedOffsets.isUnknown()) {
1048 ReturnedOffsets.setUnknown();
1049 return ChangeStatus::CHANGED;
1050 }
1051 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1052 return ChangeStatus::CHANGED;
1053 return ChangeStatus::UNCHANGED;
1054 }
1055
1056 bool forallInterferingAccesses(
1057 AA::RangeTy Range,
1058 function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
1059 const override {
1060 return State::forallInterferingAccesses(Range, CB);
1061 }
1062
1063 bool forallInterferingAccesses(
1064 Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
1065 bool FindInterferingWrites, bool FindInterferingReads,
1066 function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
1067 AA::RangeTy &Range,
1068 function_ref<bool(const Access &)> SkipCB) const override {
1069 HasBeenWrittenTo = false;
1070
1071 SmallPtrSet<const Access *, 8> DominatingWrites;
1072 SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;
1073
1074 Function &Scope = *I.getFunction();
1075 bool IsKnownNoSync;
1076 bool IsAssumedNoSync = AA::hasAssumedIRAttr<Attribute::NoSync>(
1077 A, &QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL,
1078 IsKnownNoSync);
1079 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
1080 IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);
1081 bool AllInSameNoSyncFn = IsAssumedNoSync;
1082 bool InstIsExecutedByInitialThreadOnly =
1083 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);
1084
1085 // If the function is not ending in aligned barriers, we need the stores to
1086 // be in aligned barriers. The load being in one is not sufficient since the
1087 // store might be executed by a thread that disappears after, causing the
1088 // aligned barrier guarding the load to unblock and the load to read a value
1089 // that has no CFG path to the load.
1090 bool InstIsExecutedInAlignedRegion =
1091 FindInterferingReads && ExecDomainAA &&
1092 ExecDomainAA->isExecutedInAlignedRegion(A, I);
1093
1094 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1095 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1096
1097 InformationCache &InfoCache = A.getInfoCache();
1098 bool IsThreadLocalObj =
1099 AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);
1100
1101 // Helper to determine if we need to consider threading, which we cannot
1102 // right now. However, if the function is (assumed) nosync or the thread
1103 // executing all instructions is the main thread only we can ignore
1104 // threading. Also, thread-local objects do not require threading reasoning.
1105 // Finally, we can ignore threading if either access is executed in an
1106 // aligned region.
1107 auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
1108 if (IsThreadLocalObj || AllInSameNoSyncFn)
1109 return true;
1110 const auto *FnExecDomainAA =
1111 I.getFunction() == &Scope
1112 ? ExecDomainAA
1113 : A.lookupAAFor<AAExecutionDomain>(
1114 IRPosition::function(*I.getFunction()), &QueryingAA,
1115 DepClassTy::NONE);
1116 if (!FnExecDomainAA)
1117 return false;
1118 if (InstIsExecutedInAlignedRegion ||
1119 (FindInterferingWrites &&
1120 FnExecDomainAA->isExecutedInAlignedRegion(A, I))) {
1121 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1122 return true;
1123 }
1124 if (InstIsExecutedByInitialThreadOnly &&
1125 FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
1126 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1127 return true;
1128 }
1129 return false;
1130 };
1131
1132 // Helper to determine if the access is executed by the same thread as the
1133 // given instruction, for now it is sufficient to avoid any potential
1134 // threading effects as we cannot deal with them anyway.
1135 auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
1136 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1137 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1138 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1139 };
1140
1141 // TODO: Use inter-procedural reachability and dominance.
1142 bool IsKnownNoRecurse;
1144 A, this, IRPosition::function(Scope), DepClassTy::OPTIONAL,
1145 IsKnownNoRecurse);
1146
1147 // TODO: Use reaching kernels from AAKernelInfo (or move it to
1148 // AAExecutionDomain) such that we allow scopes other than kernels as long
1149 // as the reaching kernels are disjoint.
1150 bool InstInKernel = A.getInfoCache().isKernel(Scope);
1151 bool ObjHasKernelLifetime = false;
1152 const bool UseDominanceReasoning =
1153 FindInterferingWrites && IsKnownNoRecurse;
1154 const DominatorTree *DT =
1155 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);
1156
1157 // Helper to check if a value has "kernel lifetime", that is it will not
1158 // outlive a GPU kernel. This is true for shared, constant, and local
1159 // globals on AMD and NVIDIA GPUs.
1160 auto HasKernelLifetime = [&](Value *V, Module &M) {
1161 if (!AA::isGPU(M))
1162 return false;
1163 unsigned VAS = V->getType()->getPointerAddressSpace();
1164 return AA::isGPUSharedAddressSpace(M, VAS) ||
1167 };
1168
1169 // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
1170 // to determine if we should look at reachability from the callee. For
1171 // certain pointers we know the lifetime and we do not have to step into the
1172 // callee to determine reachability as the pointer would be dead in the
1173 // callee. See the conditional initialization below.
1174 std::function<bool(const Function &)> IsLiveInCalleeCB;
1175
1176 if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {
1177 // If the alloca containing function is not recursive the alloca
1178 // must be dead in the callee.
1179 const Function *AIFn = AI->getFunction();
1180 ObjHasKernelLifetime = A.getInfoCache().isKernel(*AIFn);
1181 bool IsKnownNoRecurse;
1183 A, this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL,
1184 IsKnownNoRecurse)) {
1185 IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
1186 }
1187 } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {
1188 // If the global has kernel lifetime we can stop if we reach a kernel
1189 // as it is "dead" in the (unknown) callees.
1190 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1191 if (ObjHasKernelLifetime)
1192 IsLiveInCalleeCB = [&A](const Function &Fn) {
1193 return !A.getInfoCache().isKernel(Fn);
1194 };
1195 }
1196
1197 // Set of accesses/instructions that will overwrite the result and are
1198 // therefore blockers in the reachability traversal.
1199 AA::InstExclusionSetTy ExclusionSet;
1200
1201 auto AccessCB = [&](const Access &Acc, bool Exact) {
1202 Function *AccScope = Acc.getRemoteInst()->getFunction();
1203 bool AccInSameScope = AccScope == &Scope;
1204
1205 // If the object has kernel lifetime we can ignore accesses only reachable
1206 // by other kernels. For now we only skip accesses *in* other kernels.
1207 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1208 A.getInfoCache().isKernel(*AccScope))
1209 return true;
1210
1211 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
1212 if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))
1213 ExclusionSet.insert(Acc.getRemoteInst());
1214 }
1215
1216 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1217 (!FindInterferingReads || !Acc.isRead()))
1218 return true;
1219
1220 bool Dominates = FindInterferingWrites && DT && Exact &&
1221 Acc.isMustAccess() && AccInSameScope &&
1222 DT->dominates(Acc.getRemoteInst(), &I);
1223 if (Dominates)
1224 DominatingWrites.insert(&Acc);
1225
1226 // Track if all interesting accesses are in the same `nosync` function as
1227 // the given instruction.
1228 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;
1229
1230 InterferingAccesses.push_back({&Acc, Exact});
1231 return true;
1232 };
1233 if (!State::forallInterferingAccesses(I, AccessCB, Range))
1234 return false;
1235
1236 HasBeenWrittenTo = !DominatingWrites.empty();
1237
1238 // Dominating writes form a chain, find the least/lowest member.
1239 Instruction *LeastDominatingWriteInst = nullptr;
1240 for (const Access *Acc : DominatingWrites) {
1241 if (!LeastDominatingWriteInst) {
1242 LeastDominatingWriteInst = Acc->getRemoteInst();
1243 } else if (DT->dominates(LeastDominatingWriteInst,
1244 Acc->getRemoteInst())) {
1245 LeastDominatingWriteInst = Acc->getRemoteInst();
1246 }
1247 }
1248
1249 // Helper to determine if we can skip a specific write access.
1250 auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
1251 if (SkipCB && SkipCB(Acc))
1252 return true;
1253 if (!CanIgnoreThreading(Acc))
1254 return false;
1255
1256 // Check read (RAW) dependences and write (WAR) dependences as necessary.
1257 // If we successfully excluded all effects we are interested in, the
1258 // access can be skipped.
1259 bool ReadChecked = !FindInterferingReads;
1260 bool WriteChecked = !FindInterferingWrites;
1261
1262 // If the instruction cannot reach the access, the former does not
1263 // interfere with what the access reads.
1264 if (!ReadChecked) {
1265 if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,
1266 &ExclusionSet, IsLiveInCalleeCB))
1267 ReadChecked = true;
1268 }
1269 // If the instruction cannot be reach from the access, the latter does not
1270 // interfere with what the instruction reads.
1271 if (!WriteChecked) {
1272 if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,
1273 &ExclusionSet, IsLiveInCalleeCB))
1274 WriteChecked = true;
1275 }
1276
1277 // If we still might be affected by the write of the access but there are
1278 // dominating writes in the function of the instruction
1279 // (HasBeenWrittenTo), we can try to reason that the access is overwritten
1280 // by them. This would have happend above if they are all in the same
1281 // function, so we only check the inter-procedural case. Effectively, we
1282 // want to show that there is no call after the dominting write that might
1283 // reach the access, and when it returns reach the instruction with the
1284 // updated value. To this end, we iterate all call sites, check if they
1285 // might reach the instruction without going through another access
1286 // (ExclusionSet) and at the same time might reach the access. However,
1287 // that is all part of AAInterFnReachability.
1288 if (!WriteChecked && HasBeenWrittenTo &&
1289 Acc.getRemoteInst()->getFunction() != &Scope) {
1290
1291 const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
1292 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1293 if (FnReachabilityAA) {
1294 // Without going backwards in the call tree, can we reach the access
1295 // from the least dominating write. Do not allow to pass the
1296 // instruction itself either.
1297 bool Inserted = ExclusionSet.insert(&I).second;
1298
1299 if (!FnReachabilityAA->instructionCanReach(
1300 A, *LeastDominatingWriteInst,
1301 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1302 WriteChecked = true;
1303
1304 if (Inserted)
1305 ExclusionSet.erase(&I);
1306 }
1307 }
1308
1309 if (ReadChecked && WriteChecked)
1310 return true;
1311
1312 if (!DT || !UseDominanceReasoning)
1313 return false;
1314 if (!DominatingWrites.count(&Acc))
1315 return false;
1316 return LeastDominatingWriteInst != Acc.getRemoteInst();
1317 };
1318
1319 // Run the user callback on all accesses we cannot skip and return if
1320 // that succeeded for all or not.
1321 for (auto &It : InterferingAccesses) {
1322 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1323 !CanSkipAccess(*It.first, It.second)) {
1324 if (!UserCB(*It.first, It.second))
1325 return false;
1326 }
1327 }
1328 return true;
1329 }
1330
1331 ChangeStatus translateAndAddStateFromCallee(Attributor &A,
1332 const AAPointerInfo &OtherAA,
1333 CallBase &CB) {
1334 using namespace AA::PointerInfo;
1335 if (!OtherAA.getState().isValidState() || !isValidState())
1336 return indicatePessimisticFixpoint();
1337
1338 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1339 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1340 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1341 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1342
1343 // Combine the accesses bin by bin.
1344 const auto &State = OtherAAImpl.getState();
1345 for (const auto &It : State) {
1346 for (auto Index : It.getSecond()) {
1347 const auto &RAcc = State.getAccess(Index);
1348 if (IsByval && !RAcc.isRead())
1349 continue;
1350 bool UsedAssumedInformation = false;
1351 AccessKind AK = RAcc.getKind();
1352 auto Content = A.translateArgumentToCallSiteContent(
1353 RAcc.getContent(), CB, *this, UsedAssumedInformation);
1354 AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1355 AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1356
1357 Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,
1358 RAcc.getType(), RAcc.getRemoteInst());
1359 }
1360 }
1361 return Changed;
1362 }
1363
1364 ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
1365 const OffsetInfo &Offsets, CallBase &CB,
1366 bool IsMustAcc) {
1367 using namespace AA::PointerInfo;
1368 if (!OtherAA.getState().isValidState() || !isValidState())
1369 return indicatePessimisticFixpoint();
1370
1371 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1372
1373 // Combine the accesses bin by bin.
1374 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1375 const auto &State = OtherAAImpl.getState();
1376 for (const auto &It : State) {
1377 for (auto Index : It.getSecond()) {
1378 const auto &RAcc = State.getAccess(Index);
1379 if (!IsMustAcc && RAcc.isAssumption())
1380 continue;
1381 for (auto Offset : Offsets) {
1382 auto NewRanges = Offset == AA::RangeTy::Unknown
1384 : RAcc.getRanges();
1385 if (!NewRanges.isUnknown()) {
1386 NewRanges.addToAllOffsets(Offset);
1387 }
1388 AccessKind AK = RAcc.getKind();
1389 if (!IsMustAcc)
1390 AK = AccessKind((AK & ~AK_MUST) | AK_MAY);
1391 Changed |= addAccess(A, NewRanges, CB, RAcc.getContent(), AK,
1392 RAcc.getType(), RAcc.getRemoteInst());
1393 }
1394 }
1395 }
1396 return Changed;
1397 }
1398
1399 /// Statistic tracking for all AAPointerInfo implementations.
1400 void trackPointerInfoStatistics(const IRPosition &IRP) const {}
1401
1402 /// Dump the state into \p O.
1403 void dumpState(raw_ostream &O) {
1404 for (auto &It : OffsetBins) {
1405 O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
1406 << "] : " << It.getSecond().size() << "\n";
1407 for (auto AccIndex : It.getSecond()) {
1408 auto &Acc = AccessList[AccIndex];
1409 O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
1410 if (Acc.getLocalInst() != Acc.getRemoteInst())
1411 O << " --> " << *Acc.getRemoteInst()
1412 << "\n";
1413 if (!Acc.isWrittenValueYetUndetermined()) {
1414 if (isa_and_nonnull<Function>(Acc.getWrittenValue()))
1415 O << " - c: func " << Acc.getWrittenValue()->getName()
1416 << "\n";
1417 else if (Acc.getWrittenValue())
1418 O << " - c: " << *Acc.getWrittenValue() << "\n";
1419 else
1420 O << " - c: <unknown>\n";
1421 }
1422 }
1423 }
1424 }
1425};
1426
1427struct AAPointerInfoFloating : public AAPointerInfoImpl {
1429 AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
1430 : AAPointerInfoImpl(IRP, A) {}
1431
1432 /// Deal with an access and signal if it was handled successfully.
1433 bool handleAccess(Attributor &A, Instruction &I,
1434 std::optional<Value *> Content, AccessKind Kind,
1435 OffsetInfo::VecTy &Offsets, ChangeStatus &Changed,
1436 Type &Ty) {
1437 using namespace AA::PointerInfo;
1439 const DataLayout &DL = A.getDataLayout();
1440 TypeSize AccessSize = DL.getTypeStoreSize(&Ty);
1441 if (!AccessSize.isScalable())
1442 Size = AccessSize.getFixedValue();
1443
1444 // Make a strictly ascending list of offsets as required by addAccess()
1445 SmallVector<int64_t> OffsetsSorted(Offsets.begin(), Offsets.end());
1446 llvm::sort(OffsetsSorted);
1447
1449 if (!VT || VT->getElementCount().isScalable() ||
1450 !Content.value_or(nullptr) || !isa<Constant>(*Content) ||
1451 (*Content)->getType() != VT ||
1452 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1453 Changed =
1454 Changed | addAccess(A, {OffsetsSorted, Size}, I, Content, Kind, &Ty);
1455 } else {
1456 // Handle vector stores with constant content element-wise.
1457 // TODO: We could look for the elements or create instructions
1458 // representing them.
1459 // TODO: We need to push the Content into the range abstraction
1460 // (AA::RangeTy) to allow different content values for different
1461 // ranges. ranges. Hence, support vectors storing different values.
1462 Type *ElementType = VT->getElementType();
1463 int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();
1464 auto *ConstContent = cast<Constant>(*Content);
1465 Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());
1466 SmallVector<int64_t> ElementOffsets(OffsetsSorted.begin(),
1467 OffsetsSorted.end());
1468
1469 for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1470 Value *ElementContent = ConstantExpr::getExtractElement(
1471 ConstContent, ConstantInt::get(Int32Ty, i));
1472
1473 // Add the element access.
1474 Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,
1475 ElementContent, Kind, ElementType);
1476
1477 // Advance the offsets for the next element.
1478 for (auto &ElementOffset : ElementOffsets)
1479 ElementOffset += ElementSize;
1480 }
1481 }
1482 return true;
1483 };
1484
1485 ChangeStatus updateImpl(Attributor &A) override;
1486
1487 /// If the indices to \p GEP can be traced to constants, incorporate all
1488 /// of these into \p UsrOI.
1489 ///
1490 /// \return true iff \p UsrOI is updated.
1491 bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
1492 OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
1493 const GEPOperator *GEP);
1494
1495 void trackStatistics() const override {
1496 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1497 }
1498};
1499
1500bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
1501 const DataLayout &DL,
1502 OffsetInfo &UsrOI,
1503 const OffsetInfo &PtrOI,
1504 const GEPOperator *GEP) {
1505 unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
1506 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1507 APInt ConstantOffset(BitWidth, 0);
1508
1509 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1510 "Don't look for constant values if the offset has already been "
1511 "determined to be unknown.");
1512
1513 if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
1514 UsrOI.setUnknown();
1515 return true;
1516 }
1517
1518 LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "
1519 << (VariableOffsets.empty() ? "" : "not") << " constant "
1520 << *GEP << "\n");
1521
1522 auto Union = PtrOI;
1523 Union.addToAll(ConstantOffset.getSExtValue());
1524
1525 // Each VI in VariableOffsets has a set of potential constant values. Every
1526 // combination of elements, picked one each from these sets, is separately
1527 // added to the original set of offsets, thus resulting in more offsets.
1528 for (const auto &VI : VariableOffsets) {
1529 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
1530 *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);
1531 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1532 UsrOI.setUnknown();
1533 return true;
1534 }
1535
1536 // UndefValue is treated as a zero, which leaves Union as is.
1537 if (PotentialConstantsAA->undefIsContained())
1538 continue;
1539
1540 // We need at least one constant in every set to compute an actual offset.
1541 // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
1542 // don't actually exist. In other words, the absence of constant values
1543 // implies that the operation can be assumed dead for now.
1544 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1545 if (AssumedSet.empty())
1546 return false;
1547
1548 OffsetInfo Product;
1549 for (const auto &ConstOffset : AssumedSet) {
1550 auto CopyPerOffset = Union;
1551 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1552 VI.second.getZExtValue());
1553 Product.merge(CopyPerOffset);
1554 }
1555 Union = Product;
1556 }
1557
1558 UsrOI = std::move(Union);
1559 return true;
1560}
1561
1562ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
1563 using namespace AA::PointerInfo;
1565 const DataLayout &DL = A.getDataLayout();
1566 Value &AssociatedValue = getAssociatedValue();
1567
1568 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1569 OffsetInfoMap[&AssociatedValue].insert(0);
1570
1571 auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
1572 // One does not simply walk into a map and assign a reference to a possibly
1573 // new location. That can cause an invalidation before the assignment
1574 // happens, like so:
1575 //
1576 // OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
1577 //
1578 // The RHS is a reference that may be invalidated by an insertion caused by
1579 // the LHS. So we ensure that the side-effect of the LHS happens first.
1580
1581 assert(OffsetInfoMap.contains(CurPtr) &&
1582 "CurPtr does not exist in the map!");
1583
1584 auto &UsrOI = OffsetInfoMap[Usr];
1585 auto &PtrOI = OffsetInfoMap[CurPtr];
1586 assert(!PtrOI.isUnassigned() &&
1587 "Cannot pass through if the input Ptr was not visited!");
1588 UsrOI.merge(PtrOI);
1589 Follow = true;
1590 return true;
1591 };
1592
1593 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1594 Value *CurPtr = U.get();
1595 User *Usr = U.getUser();
1596 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usr
1597 << "\n");
1598 assert(OffsetInfoMap.count(CurPtr) &&
1599 "The current pointer offset should have been seeded!");
1600 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1601 "Current pointer should be assigned");
1602
1603 // Only address space casts are followed; other casts of a pointer (e.g.,
1604 // ptrtoint, ptrtoaddr, or a bitcast to a byte type) do not produce a
1605 // pointer that can be tracked.
1607 return HandlePassthroughUser(Usr, CurPtr, Follow);
1608
1609 if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {
1610 // Note the order here, the Usr access might change the map, CurPtr is
1611 // already in it though.
1612 auto &UsrOI = OffsetInfoMap[Usr];
1613 auto &PtrOI = OffsetInfoMap[CurPtr];
1614
1615 if (UsrOI.isUnknown())
1616 return true;
1617
1618 if (PtrOI.isUnknown()) {
1619 Follow = true;
1620 UsrOI.setUnknown();
1621 return true;
1622 }
1623
1624 Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
1625 return true;
1626 }
1627 if (isa<SelectInst>(Usr))
1628 return HandlePassthroughUser(Usr, CurPtr, Follow);
1629 // Returns are allowed if they are in the associated functions. Users can
1630 // then check the call site return. Returns from other functions can't be
1631 // tracked and are cause for invalidation.
1632 if (auto *RI = dyn_cast<ReturnInst>(Usr)) {
1633 if (RI->getFunction() == getAssociatedFunction()) {
1634 auto &PtrOI = OffsetInfoMap[CurPtr];
1635 Changed |= setReachesReturn(PtrOI);
1636 return true;
1637 }
1638 return false;
1639 }
1640
1641 // For PHIs we need to take care of the recurrence explicitly as the value
1642 // might change while we iterate through a loop. For now, we give up if
1643 // the PHI is not invariant.
1644 if (auto *PHI = dyn_cast<PHINode>(Usr)) {
1645 // Note the order here, the Usr access might change the map, CurPtr is
1646 // already in it though.
1647 auto [PhiIt, IsFirstPHIUser] = OffsetInfoMap.try_emplace(PHI);
1648 auto &UsrOI = PhiIt->second;
1649 auto &PtrOI = OffsetInfoMap[CurPtr];
1650
1651 // Check if the PHI operand has already an unknown offset as we can't
1652 // improve on that anymore.
1653 if (PtrOI.isUnknown()) {
1654 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "
1655 << *CurPtr << " in " << *PHI << "\n");
1656 Follow = !UsrOI.isUnknown();
1657 UsrOI.setUnknown();
1658 return true;
1659 }
1660
1661 // Check if the PHI is invariant (so far).
1662 if (UsrOI == PtrOI) {
1663 assert(!PtrOI.isUnassigned() &&
1664 "Cannot assign if the current Ptr was not visited!");
1665 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)");
1666 return true;
1667 }
1668
1669 // Check if the PHI operand can be traced back to AssociatedValue.
1670 APInt Offset(
1671 DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),
1672 0);
1673 Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
1674 DL, Offset, /* AllowNonInbounds */ true);
1675 auto It = OffsetInfoMap.find(CurPtrBase);
1676 if (It == OffsetInfoMap.end()) {
1677 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "
1678 << *CurPtr << " in " << *PHI
1679 << " (base: " << *CurPtrBase << ")\n");
1680 UsrOI.setUnknown();
1681 Follow = true;
1682 return true;
1683 }
1684
1685 // Check if the PHI operand is not dependent on the PHI itself. Every
1686 // recurrence is a cyclic net of PHIs in the data flow, and has an
1687 // equivalent Cycle in the control flow. One of those PHIs must be in the
1688 // header of that control flow Cycle. This is independent of the choice of
1689 // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
1690 // every Cycle header; if such a node is marked unknown, this will
1691 // eventually propagate through the whole net of PHIs in the recurrence.
1692 const auto *CI =
1693 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1694 *PHI->getFunction());
1695 if (mayBeInCycle(CI, cast<Instruction>(Usr), /* HeaderOnly */ true)) {
1696 auto BaseOI = It->getSecond();
1697 BaseOI.addToAll(Offset.getZExtValue());
1698 if (IsFirstPHIUser || BaseOI == UsrOI) {
1699 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtr
1700 << " in " << *Usr << "\n");
1701 return HandlePassthroughUser(Usr, CurPtr, Follow);
1702 }
1703
1704 LLVM_DEBUG(
1705 dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
1706 << *CurPtr << " in " << *PHI << "\n");
1707 UsrOI.setUnknown();
1708 Follow = true;
1709 return true;
1710 }
1711
1712 UsrOI.merge(PtrOI);
1713 Follow = true;
1714 return true;
1715 }
1716
1717 if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {
1718 // If the access is to a pointer that may or may not be the associated
1719 // value, e.g. due to a PHI, we cannot assume it will be read.
1720 AccessKind AK = AccessKind::AK_R;
1721 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1722 AK = AccessKind(AK | AccessKind::AK_MUST);
1723 else
1724 AK = AccessKind(AK | AccessKind::AK_MAY);
1725 if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,
1726 OffsetInfoMap[CurPtr].Offsets, Changed,
1727 *LoadI->getType()))
1728 return false;
1729
1730 auto IsAssumption = [](Instruction &I) {
1731 if (auto *II = dyn_cast<IntrinsicInst>(&I))
1732 return II->isAssumeLikeIntrinsic();
1733 return false;
1734 };
1735
1736 auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
1737 // Check if the assumption and the load are executed together without
1738 // memory modification.
1739 do {
1740 if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
1741 return true;
1742 FromI = FromI->getNextNode();
1743 } while (FromI && FromI != ToI);
1744 return false;
1745 };
1746
1747 BasicBlock *BB = LoadI->getParent();
1748 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1749 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1750 return false;
1751 BasicBlock *IntrBB = IntrI.getParent();
1752 if (IntrI.getParent() == BB) {
1753 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1754 return false;
1755 } else {
1756 auto PredIt = pred_begin(IntrBB);
1757 if (PredIt == pred_end(IntrBB))
1758 return false;
1759 if ((*PredIt) != BB)
1760 return false;
1761 if (++PredIt != pred_end(IntrBB))
1762 return false;
1763 for (auto *SuccBB : successors(BB)) {
1764 if (SuccBB == IntrBB)
1765 continue;
1766 if (isa<UnreachableInst>(SuccBB->getTerminator()))
1767 continue;
1768 return false;
1769 }
1770 if (IsImpactedInRange(LoadI->getNextNode(), BB->getTerminator()))
1771 return false;
1772 if (IsImpactedInRange(&IntrBB->front(), &IntrI))
1773 return false;
1774 }
1775 return true;
1776 };
1777
1778 std::pair<Value *, IntrinsicInst *> Assumption;
1779 for (const Use &LoadU : LoadI->uses()) {
1780 if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {
1781 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1782 continue;
1783 for (const Use &CmpU : CmpI->uses()) {
1784 if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {
1785 if (!IsValidAssume(*IntrI))
1786 continue;
1787 int Idx = CmpI->getOperandUse(0) == LoadU;
1788 Assumption = {CmpI->getOperand(Idx), IntrI};
1789 break;
1790 }
1791 }
1792 }
1793 if (Assumption.first)
1794 break;
1795 }
1796
1797 // Check if we found an assumption associated with this load.
1798 if (!Assumption.first || !Assumption.second)
1799 return true;
1800
1801 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "
1802 << *Assumption.second << ": " << *LoadI
1803 << " == " << *Assumption.first << "\n");
1804 bool UsedAssumedInformation = false;
1805 std::optional<Value *> Content = nullptr;
1806 if (Assumption.first)
1807 Content =
1808 A.getAssumedSimplified(*Assumption.first, *this,
1809 UsedAssumedInformation, AA::Interprocedural);
1810 return handleAccess(
1811 A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1812 OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());
1813 }
1814
1815 auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
1816 ArrayRef<Value *> OtherOps, AccessKind AK) {
1817 for (auto *OtherOp : OtherOps) {
1818 if (OtherOp == CurPtr) {
1819 LLVM_DEBUG(
1820 dbgs()
1821 << "[AAPointerInfo] Escaping use in store like instruction " << I
1822 << "\n");
1823 return false;
1824 }
1825 }
1826
1827 // If the access is to a pointer that may or may not be the associated
1828 // value, e.g. due to a PHI, we cannot assume it will be written.
1829 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1830 AK = AccessKind(AK | AccessKind::AK_MUST);
1831 else
1832 AK = AccessKind(AK | AccessKind::AK_MAY);
1833 bool UsedAssumedInformation = false;
1834 std::optional<Value *> Content = nullptr;
1835 if (ValueOp)
1836 Content = A.getAssumedSimplified(
1837 *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
1838 return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1839 Changed, ValueTy);
1840 };
1841
1842 if (auto *StoreI = dyn_cast<StoreInst>(Usr))
1843 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1844 *StoreI->getValueOperand()->getType(),
1845 {StoreI->getValueOperand()}, AccessKind::AK_W);
1846 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
1847 return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
1848 {RMWI->getValOperand()}, AccessKind::AK_RW);
1849 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
1850 return HandleStoreLike(
1851 *CXI, nullptr, *CXI->getNewValOperand()->getType(),
1852 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1853 AccessKind::AK_RW);
1854
1855 if (auto *CB = dyn_cast<CallBase>(Usr)) {
1856 if (CB->isLifetimeStartOrEnd())
1857 return true;
1858 const auto *TLI =
1859 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->getFunction());
1860 if (getFreedOperand(CB, TLI) == U)
1861 return true;
1862 if (CB->isArgOperand(&U)) {
1863 unsigned ArgNo = CB->getArgOperandNo(&U);
1864 const auto *CSArgPI = A.getAAFor<AAPointerInfo>(
1865 *this, IRPosition::callsite_argument(*CB, ArgNo),
1867 if (!CSArgPI)
1868 return false;
1869 bool IsArgMustAcc = (getUnderlyingObject(CurPtr) == &AssociatedValue);
1870 Changed = translateAndAddState(A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1871 IsArgMustAcc) |
1872 Changed;
1873 if (!CSArgPI->reachesReturn())
1874 return isValidState();
1875
1877 if (!Callee || Callee->arg_size() <= ArgNo)
1878 return false;
1879 bool UsedAssumedInformation = false;
1880 auto ReturnedValue = A.getAssumedSimplified(
1881 IRPosition::returned(*Callee), *this, UsedAssumedInformation,
1883 auto *ReturnedArg =
1884 dyn_cast_or_null<Argument>(ReturnedValue.value_or(nullptr));
1885 auto *Arg = Callee->getArg(ArgNo);
1886 if (ReturnedArg && Arg != ReturnedArg)
1887 return true;
1888 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1889 const auto *CSRetPI = A.getAAFor<AAPointerInfo>(
1891 if (!CSRetPI)
1892 return false;
1893 OffsetInfo OI = OffsetInfoMap[CurPtr];
1894 CSArgPI->addReturnedOffsetsTo(OI);
1895 Changed =
1896 translateAndAddState(A, *CSRetPI, OI, *CB, IsRetMustAcc) | Changed;
1897 return isValidState();
1898 }
1899 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CB
1900 << "\n");
1901 return false;
1902 }
1903
1904 LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n");
1905 return false;
1906 };
1907 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
1908 assert(OffsetInfoMap.count(OldU) && "Old use should be known already!");
1909 assert(!OffsetInfoMap[OldU].isUnassigned() && "Old use should be assinged");
1910 if (OffsetInfoMap.count(NewU)) {
1911 LLVM_DEBUG({
1912 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1913 dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
1914 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]
1915 << "\n";
1916 }
1917 });
1918 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1919 }
1920 bool Unused;
1921 return HandlePassthroughUser(NewU.get(), OldU.get(), Unused);
1922 };
1923 if (!A.checkForAllUses(UsePred, *this, AssociatedValue,
1924 /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,
1925 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
1926 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n");
1927 return indicatePessimisticFixpoint();
1928 }
1929
1930 LLVM_DEBUG({
1931 dbgs() << "Accesses by bin after update:\n";
1932 dumpState(dbgs());
1933 });
1934
1935 return Changed;
1936}
1937
1938struct AAPointerInfoReturned final : AAPointerInfoImpl {
1939 AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
1940 : AAPointerInfoImpl(IRP, A) {}
1941
1942 ChangeStatus updateImpl(Attributor &A) override {
1943 return indicatePessimisticFixpoint();
1944 }
1945
1946 void trackStatistics() const override {
1947 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1948 }
1949};
1950
1951struct AAPointerInfoArgument final : AAPointerInfoFloating {
1952 AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
1953 : AAPointerInfoFloating(IRP, A) {}
1954
1955 void trackStatistics() const override {
1956 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1957 }
1958};
1959
1960struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1961 AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
1962 : AAPointerInfoFloating(IRP, A) {}
1963
1964 ChangeStatus updateImpl(Attributor &A) override {
1965 using namespace AA::PointerInfo;
1966 // We handle memory intrinsics explicitly, at least the first (=
1967 // destination) and second (=source) arguments as we know how they are
1968 // accessed.
1969 if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
1970 int64_t LengthVal = AA::RangeTy::Unknown;
1971 if (auto Length = MI->getLengthInBytes())
1972 LengthVal = Length->getSExtValue();
1973 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1974 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1975 if (ArgNo > 1) {
1976 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
1977 << *MI << "\n");
1978 return indicatePessimisticFixpoint();
1979 } else {
1980 auto Kind =
1981 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1982 Changed =
1983 Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);
1984 }
1985 LLVM_DEBUG({
1986 dbgs() << "Accesses by bin after update:\n";
1987 dumpState(dbgs());
1988 });
1989
1990 return Changed;
1991 }
1992
1993 // TODO: Once we have call site specific value information we can provide
1994 // call site specific liveness information and then it makes
1995 // sense to specialize attributes for call sites arguments instead of
1996 // redirecting requests to the callee argument.
1997 Argument *Arg = getAssociatedArgument();
1998 if (Arg) {
1999 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2000 auto *ArgAA =
2001 A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
2002 if (ArgAA && ArgAA->getState().isValidState())
2003 return translateAndAddStateFromCallee(A, *ArgAA,
2004 *cast<CallBase>(getCtxI()));
2005 if (!Arg->getParent()->isDeclaration())
2006 return indicatePessimisticFixpoint();
2007 }
2008
2009 bool IsKnownNoCapture;
2011 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2012 return indicatePessimisticFixpoint();
2013
2014 bool IsKnown = false;
2015 if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
2016 return ChangeStatus::UNCHANGED;
2017 bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);
2018 auto Kind =
2019 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2020 return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,
2021 nullptr);
2022 }
2023
2024 void trackStatistics() const override {
2025 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2026 }
2027};
2028
2029struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2030 AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
2031 : AAPointerInfoFloating(IRP, A) {}
2032
2033 void trackStatistics() const override {
2034 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2035 }
2036};
2037} // namespace
2038
2039/// -----------------------NoUnwind Function Attribute--------------------------
2040
2041namespace {
2042struct AANoUnwindImpl : AANoUnwind {
2043 AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}
2044
2045 void initialize(Attributor &A) override {
2046 bool IsKnown;
2048 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2049 (void)IsKnown;
2050 }
2051
2052 const std::string getAsStr(Attributor *A) const override {
2053 return getAssumed() ? "nounwind" : "may-unwind";
2054 }
2055
2056 ChangeStatus updateImpl(Attributor &A) override {
2057 auto Opcodes = {
2058 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
2059 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
2060 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
2061
2062 auto CheckForNoUnwind = [&](Instruction &I) {
2063 if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
2064 return true;
2065
2066 if (const auto *CB = dyn_cast<CallBase>(&I)) {
2067 bool IsKnownNoUnwind;
2069 A, this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED,
2070 IsKnownNoUnwind);
2071 }
2072 return false;
2073 };
2074
2075 bool UsedAssumedInformation = false;
2076 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
2077 UsedAssumedInformation))
2078 return indicatePessimisticFixpoint();
2079
2080 return ChangeStatus::UNCHANGED;
2081 }
2082};
2083
2084struct AANoUnwindFunction final : public AANoUnwindImpl {
2085 AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
2086 : AANoUnwindImpl(IRP, A) {}
2087
2088 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
2089};
2090
2091/// NoUnwind attribute deduction for a call sites.
2092struct AANoUnwindCallSite final
2093 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2094 AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
2095 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP, A) {}
2096
2097 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }
2098};
2099} // namespace
2100
2101/// ------------------------ NoSync Function Attribute -------------------------
2102
2103bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
2104 switch (CB.getIntrinsicID()) {
2105 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2106 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2107 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2108 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2109 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2110 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2111 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2112 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2113 return true;
2114 case Intrinsic::amdgcn_s_barrier:
2115 if (ExecutedAligned)
2116 return true;
2117 break;
2118 default:
2119 break;
2120 }
2121 return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));
2122}
2123
2125 if (!I->isAtomic())
2126 return false;
2127
2128 if (auto *FI = dyn_cast<FenceInst>(I))
2129 // All legal orderings for fence are stronger than monotonic.
2130 return FI->getSyncScopeID() != SyncScope::SingleThread;
2131 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
2132 // Unordered is not a legal ordering for cmpxchg.
2133 return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
2134 AI->getFailureOrdering() != AtomicOrdering::Monotonic);
2135 }
2136
2137 AtomicOrdering Ordering;
2138 switch (I->getOpcode()) {
2139 case Instruction::AtomicRMW:
2140 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
2141 break;
2142 case Instruction::Store:
2143 Ordering = cast<StoreInst>(I)->getOrdering();
2144 break;
2145 case Instruction::Load:
2146 Ordering = cast<LoadInst>(I)->getOrdering();
2147 break;
2148 default:
2150 "New atomic operations need to be known in the attributor.");
2151 }
2152
2153 return (Ordering != AtomicOrdering::Unordered &&
2154 Ordering != AtomicOrdering::Monotonic);
2155}
2156
2157namespace {
2158struct AANoSyncImpl : AANoSync {
2159 AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}
2160
2161 void initialize(Attributor &A) override {
2162 bool IsKnown;
2163 assert(!AA::hasAssumedIRAttr<Attribute::NoSync>(A, nullptr, getIRPosition(),
2164 DepClassTy::NONE, IsKnown));
2165 (void)IsKnown;
2166 }
2167
2168 const std::string getAsStr(Attributor *A) const override {
2169 return getAssumed() ? "nosync" : "may-sync";
2170 }
2171
2172 ChangeStatus updateImpl(Attributor &A) override;
2173};
2174
2175ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
2176
2177 auto CheckRWInstForNoSync = [&](Instruction &I) {
2178 return AA::isNoSyncInst(A, I, *this);
2179 };
2180
2181 auto CheckForNoSync = [&](Instruction &I) {
2182 // At this point we handled all read/write effects and they are all
2183 // nosync, so they can be skipped.
2184 if (I.mayReadOrWriteMemory())
2185 return true;
2186
2187 bool IsKnown;
2188 CallBase &CB = cast<CallBase>(I);
2191 IsKnown))
2192 return true;
2193
2194 // non-convergent and readnone imply nosync.
2195 return !CB.isConvergent();
2196 };
2197
2198 bool UsedAssumedInformation = false;
2199 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
2200 UsedAssumedInformation) ||
2201 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
2202 UsedAssumedInformation))
2203 return indicatePessimisticFixpoint();
2204
2206}
2207
2208struct AANoSyncFunction final : public AANoSyncImpl {
2209 AANoSyncFunction(const IRPosition &IRP, Attributor &A)
2210 : AANoSyncImpl(IRP, A) {}
2211
2212 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
2213};
2214
2215/// NoSync attribute deduction for a call sites.
2216struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2217 AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
2218 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP, A) {}
2219
2220 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }
2221};
2222} // namespace
2223
2224/// ------------------------ No-Free Attributes ----------------------------
2225
2226namespace {
2227struct AANoFreeImpl : public AANoFree {
2228 AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}
2229
2230 void initialize(Attributor &A) override {
2231 bool IsKnown;
2232 assert(!AA::hasAssumedIRAttr<Attribute::NoFree>(A, nullptr, getIRPosition(),
2233 DepClassTy::NONE, IsKnown));
2234 (void)IsKnown;
2235 }
2236
2237 ChangeStatus updateImpl(Attributor &A) override {
2238 auto CheckForNoFree = [&](Instruction &I) {
2239 if (auto *CB = dyn_cast<CallBase>(&I)) {
2240 bool IsKnown;
2242 A, this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED,
2243 IsKnown);
2244 }
2245 // Make sure that synchronization cannot establish happens-before with a
2246 // free on another thread.
2247 return AA::isNoSyncInst(A, I, *this);
2248 };
2249
2250 bool UsedAssumedInformation = false;
2251 if (!A.checkForAllReadWriteInstructions(CheckForNoFree, *this,
2252 UsedAssumedInformation) ||
2253 !A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
2254 UsedAssumedInformation))
2255 return indicatePessimisticFixpoint();
2256
2257 return ChangeStatus::UNCHANGED;
2258 }
2259
2260 const std::string getAsStr(Attributor *A) const override {
2261 return getAssumed() ? "nofree" : "may-free";
2262 }
2263};
2264
2265struct AANoFreeFunction final : public AANoFreeImpl {
2266 AANoFreeFunction(const IRPosition &IRP, Attributor &A)
2267 : AANoFreeImpl(IRP, A) {}
2268
2269 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
2270};
2271
2272/// NoFree attribute deduction for a call sites.
2273struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2274 AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
2275 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP, A) {}
2276
2277 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
2278};
2279
2280/// NoFree attribute for floating values.
2281struct AANoFreeFloating : AANoFreeImpl {
2282 AANoFreeFloating(const IRPosition &IRP, Attributor &A)
2283 : AANoFreeImpl(IRP, A) {}
2284
2285 void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}
2286
2287 /// See Abstract Attribute::updateImpl(...).
2288 ChangeStatus updateImpl(Attributor &A) override {
2289 const IRPosition &IRP = getIRPosition();
2290
2291 bool IsKnown;
2294 DepClassTy::OPTIONAL, IsKnown))
2295 return ChangeStatus::UNCHANGED;
2296
2297 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2298 auto Pred = [&](const Use &U, bool &Follow) -> bool {
2299 Instruction *UserI = cast<Instruction>(U.getUser());
2300 if (auto *CB = dyn_cast<CallBase>(UserI)) {
2301 if (CB->isBundleOperand(&U))
2302 return false;
2303 if (!CB->isArgOperand(&U))
2304 return true;
2305 unsigned ArgNo = CB->getArgOperandNo(&U);
2306
2307 // Even if the argument is nofree, we still need to check for nocapture,
2308 // as the call may capture the argument without freeing it, and the
2309 // captured argument is freed later.
2310 bool IsKnown;
2312 A, this, IRPosition::callsite_argument(*CB, ArgNo),
2313 DepClassTy::REQUIRED, IsKnown))
2314 return false;
2315
2316 const AANoCapture *NoCaptureAA = nullptr;
2318 A, this, IRPosition::callsite_argument(*CB, ArgNo),
2319 DepClassTy::REQUIRED, IsKnown,
2320 /*IgnoreSubsumingPositions=*/false, &NoCaptureAA)) {
2321 if (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
2322 Follow = true;
2323 return true;
2324 }
2325 return false;
2326 }
2327
2328 return true;
2329 }
2330
2331 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
2332 if (!capturesAnyProvenance(CI))
2333 return true;
2335 Follow = true;
2336 return true;
2337 }
2338
2339 if (isa<ReturnInst>(UserI) && getIRPosition().isArgumentPosition())
2340 return true;
2341
2342 // Capturing user.
2343 return false;
2344 };
2345 if (!A.checkForAllUses(Pred, *this, AssociatedValue))
2346 return indicatePessimisticFixpoint();
2347
2348 return ChangeStatus::UNCHANGED;
2349 }
2350};
2351
2352/// NoFree attribute for a call site argument.
2353struct AANoFreeArgument final : AANoFreeFloating {
2354 AANoFreeArgument(const IRPosition &IRP, Attributor &A)
2355 : AANoFreeFloating(IRP, A) {}
2356
2357 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }
2358};
2359
2360/// NoFree attribute for call site arguments.
2361struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2362 AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
2363 : AANoFreeFloating(IRP, A) {}
2364
2365 ChangeStatus updateImpl(Attributor &A) override {
2366 // TODO: Once we have call site specific value information we can provide
2367 // call site specific liveness information and then it makes
2368 // sense to specialize attributes for call sites arguments instead of
2369 // redirecting requests to the callee argument.
2370 Argument *Arg = getAssociatedArgument();
2371 if (!Arg)
2372 return indicatePessimisticFixpoint();
2373 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2374 bool IsKnown;
2376 DepClassTy::REQUIRED, IsKnown))
2377 return ChangeStatus::UNCHANGED;
2378 return indicatePessimisticFixpoint();
2379 }
2380
2381 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nofree) };
2382};
2383
2384/// NoFree attribute for function return value.
2385struct AANoFreeReturned final : AANoFreeFloating {
2386 AANoFreeReturned(const IRPosition &IRP, Attributor &A)
2387 : AANoFreeFloating(IRP, A) {
2388 llvm_unreachable("NoFree is not applicable to function returns!");
2389 }
2390
2391 void initialize(Attributor &A) override {
2392 llvm_unreachable("NoFree is not applicable to function returns!");
2393 }
2394
2395 ChangeStatus updateImpl(Attributor &A) override {
2396 llvm_unreachable("NoFree is not applicable to function returns!");
2397 }
2398
2399 void trackStatistics() const override {}
2400};
2401
2402/// NoFree attribute deduction for a call site return value.
2403struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2404 AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
2405 : AANoFreeFloating(IRP, A) {}
2406
2407 ChangeStatus manifest(Attributor &A) override {
2408 return ChangeStatus::UNCHANGED;
2409 }
2410 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }
2411};
2412} // namespace
2413
2414/// ------------------------ NonNull Argument Attribute ------------------------
2415
2417 Attribute::AttrKind ImpliedAttributeKind,
2418 bool IgnoreSubsumingPositions) {
2420 AttrKinds.push_back(Attribute::NonNull);
2423 AttrKinds.push_back(Attribute::Dereferenceable);
2424 if (A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2425 return true;
2426
2427 DominatorTree *DT = nullptr;
2428 AssumptionCache *AC = nullptr;
2429 InformationCache &InfoCache = A.getInfoCache();
2430 if (const Function *Fn = IRP.getAnchorScope()) {
2431 if (!Fn->isDeclaration()) {
2434 }
2435 }
2436
2438 if (IRP.getPositionKind() != IRP_RETURNED) {
2439 Worklist.push_back({IRP.getAssociatedValue(), IRP.getCtxI()});
2440 } else {
2441 bool UsedAssumedInformation = false;
2442 if (!A.checkForAllInstructions(
2443 [&](Instruction &I) {
2444 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2445 return true;
2446 },
2447 IRP.getAssociatedFunction(), nullptr, {Instruction::Ret},
2448 UsedAssumedInformation, false, /*CheckPotentiallyDead=*/true))
2449 return false;
2450 }
2451
2452 if (llvm::any_of(Worklist, [&](AA::ValueAndContext VAC) {
2453 return !isKnownNonZero(
2454 VAC.getValue(),
2455 SimplifyQuery(A.getDataLayout(), DT, AC, VAC.getCtxI()));
2456 }))
2457 return false;
2458
2459 A.manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(),
2460 Attribute::NonNull)});
2461 return true;
2462}
2463
2464namespace {
2465static int64_t getKnownNonNullAndDerefBytesForUse(
2466 Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
2467 const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
2468 TrackUse = false;
2469
2470 const Value *UseV = U->get();
2471 if (!UseV->getType()->isPointerTy())
2472 return 0;
2473
2474 // We need to follow common pointer manipulation uses to the accesses they
2475 // feed into. We can try to be smart to avoid looking through things we do not
2476 // like for now, e.g., non-inbounds GEPs.
2477 if (isa<CastInst>(I)) {
2478 TrackUse = true;
2479 return 0;
2480 }
2481
2483 TrackUse = true;
2484 return 0;
2485 }
2486
2487 Type *PtrTy = UseV->getType();
2488 const Function *F = I->getFunction();
2491 const DataLayout &DL = A.getInfoCache().getDL();
2492 if (const auto *CB = dyn_cast<CallBase>(I)) {
2493 if (CB->isBundleOperand(U)) {
2494 auto OBU = CB->getOperandBundleForOperand(U->getOperandNo());
2495 switch (getBundleAttrFromOBU(OBU)) {
2496 case BundleAttr::NonNull:
2497 IsNonNull = true;
2498 break;
2499 case BundleAttr::Dereferenceable: {
2500 IsNonNull |= !NullPointerIsDefined;
2502 if (auto *CI = dyn_cast<ConstantInt>(Count))
2503 return CI->getZExtValue();
2504 } break;
2505 default:
2506 break;
2507 }
2508 return 0;
2509 }
2510
2511 if (CB->isCallee(U)) {
2512 IsNonNull |= !NullPointerIsDefined;
2513 return 0;
2514 }
2515
2516 unsigned ArgNo = CB->getArgOperandNo(U);
2517 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
2518 // As long as we only use known information there is no need to track
2519 // dependences here.
2520 bool IsKnownNonNull;
2522 DepClassTy::NONE, IsKnownNonNull);
2523 IsNonNull |= IsKnownNonNull;
2524 auto *DerefAA =
2525 A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
2526 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2527 }
2528
2529 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
2530 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2531 Loc->Size.isScalable() || I->isVolatile())
2532 return 0;
2533
2534 int64_t Offset;
2535 const Value *Base =
2536 getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);
2537 if (Base && Base == &AssociatedValue) {
2538 int64_t DerefBytes = Loc->Size.getValue() + Offset;
2539 IsNonNull |= !NullPointerIsDefined;
2540 return std::max(int64_t(0), DerefBytes);
2541 }
2542
2543 /// Corner case when an offset is 0.
2545 /*AllowNonInbounds*/ true);
2546 if (Base && Base == &AssociatedValue && Offset == 0) {
2547 int64_t DerefBytes = Loc->Size.getValue();
2548 IsNonNull |= !NullPointerIsDefined;
2549 return std::max(int64_t(0), DerefBytes);
2550 }
2551
2552 return 0;
2553}
2554
2555struct AANonNullImpl : AANonNull {
2556 AANonNullImpl(const IRPosition &IRP, Attributor &A) : AANonNull(IRP, A) {}
2557
2558 void initialize(Attributor &A) override {
2559 Value &V = *getAssociatedValue().stripPointerCasts();
2561 indicatePessimisticFixpoint();
2562 return;
2563 }
2564
2565 if (Instruction *CtxI = getCtxI())
2566 followUsesInMBEC(*this, A, getState(), *CtxI);
2567 }
2568
2569 /// See followUsesInMBEC
2570 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
2571 AANonNull::StateType &State) {
2572 bool IsNonNull = false;
2573 bool TrackUse = false;
2574 getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,
2575 IsNonNull, TrackUse);
2576 State.setKnown(IsNonNull);
2577 return TrackUse;
2578 }
2579
2580 const std::string getAsStr(Attributor *A) const override {
2581 return getAssumed() ? "nonnull" : "may-null";
2582 }
2583};
2584
2585/// NonNull attribute for a floating value.
2586struct AANonNullFloating : public AANonNullImpl {
2587 AANonNullFloating(const IRPosition &IRP, Attributor &A)
2588 : AANonNullImpl(IRP, A) {}
2589
2590 ChangeStatus updateImpl(Attributor &A) override {
2591 auto CheckIRP = [&](const IRPosition &IRP) {
2592 bool IsKnownNonNull;
2594 A, *this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2595 };
2596
2597 bool Stripped;
2598 bool UsedAssumedInformation = false;
2599 Value *AssociatedValue = &getAssociatedValue();
2601 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
2602 AA::AnyScope, UsedAssumedInformation))
2603 Stripped = false;
2604 else
2605 Stripped =
2606 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
2607
2608 if (!Stripped) {
2609 bool IsKnown;
2610 if (auto *PHI = dyn_cast<PHINode>(AssociatedValue))
2611 if (llvm::all_of(PHI->incoming_values(), [&](Value *Op) {
2612 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2613 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2614 IsKnown);
2615 }))
2616 return ChangeStatus::UNCHANGED;
2617 if (auto *Select = dyn_cast<SelectInst>(AssociatedValue))
2619 A, this, IRPosition::value(*Select->getFalseValue()),
2620 DepClassTy::OPTIONAL, IsKnown) &&
2622 A, this, IRPosition::value(*Select->getTrueValue()),
2623 DepClassTy::OPTIONAL, IsKnown))
2624 return ChangeStatus::UNCHANGED;
2625
2626 // If we haven't stripped anything we might still be able to use a
2627 // different AA, but only if the IRP changes. Effectively when we
2628 // interpret this not as a call site value but as a floating/argument
2629 // value.
2630 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
2631 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2632 return indicatePessimisticFixpoint();
2633 return ChangeStatus::UNCHANGED;
2634 }
2635
2636 for (const auto &VAC : Values)
2637 if (!CheckIRP(IRPosition::value(*VAC.getValue())))
2638 return indicatePessimisticFixpoint();
2639
2640 return ChangeStatus::UNCHANGED;
2641 }
2642
2643 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2644};
2645
2646/// NonNull attribute for function return value.
2647struct AANonNullReturned final
2648 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2649 false, AANonNull::IRAttributeKind, false> {
2650 AANonNullReturned(const IRPosition &IRP, Attributor &A)
2651 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2652 false, Attribute::NonNull, false>(IRP, A) {
2653 }
2654
2655 const std::string getAsStr(Attributor *A) const override {
2656 return getAssumed() ? "nonnull" : "may-null";
2657 }
2658
2659 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2660};
2661
2662/// NonNull attribute for function argument.
2663struct AANonNullArgument final
2664 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2665 AANonNullArgument(const IRPosition &IRP, Attributor &A)
2666 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}
2667
2668 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
2669};
2670
2671struct AANonNullCallSiteArgument final : AANonNullFloating {
2672 AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
2673 : AANonNullFloating(IRP, A) {}
2674
2675 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
2676};
2677
2678/// NonNull attribute for a call site return position.
2679struct AANonNullCallSiteReturned final
2680 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2681 AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
2682 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP, A) {}
2683
2684 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
2685};
2686} // namespace
2687
2688/// ------------------------ Must-Progress Attributes --------------------------
2689namespace {
2690struct AAMustProgressImpl : public AAMustProgress {
2691 AAMustProgressImpl(const IRPosition &IRP, Attributor &A)
2692 : AAMustProgress(IRP, A) {}
2693
2694 void initialize(Attributor &A) override {
2695 bool IsKnown;
2697 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2698 (void)IsKnown;
2699 }
2700
2701 const std::string getAsStr(Attributor *A) const override {
2702 return getAssumed() ? "mustprogress" : "may-not-progress";
2703 }
2704};
2705
2706struct AAMustProgressFunction final : AAMustProgressImpl {
2707 AAMustProgressFunction(const IRPosition &IRP, Attributor &A)
2708 : AAMustProgressImpl(IRP, A) {}
2709
2710 ChangeStatus updateImpl(Attributor &A) override {
2711 bool IsKnown;
2713 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2714 if (IsKnown)
2715 return indicateOptimisticFixpoint();
2716 return ChangeStatus::UNCHANGED;
2717 }
2718
2719 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2720 IRPosition IPos = IRPosition::callsite_function(*ACS.getInstruction());
2721 bool IsKnownMustProgress;
2723 A, this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2724 /* IgnoreSubsumingPositions */ true);
2725 };
2726
2727 bool AllCallSitesKnown = true;
2728 if (!A.checkForAllCallSites(CheckForMustProgress, *this,
2729 /* RequireAllCallSites */ true,
2730 AllCallSitesKnown))
2731 return indicatePessimisticFixpoint();
2732
2733 return ChangeStatus::UNCHANGED;
2734 }
2735
2736 void trackStatistics() const override {
2737 STATS_DECLTRACK_FN_ATTR(mustprogress)
2738 }
2739};
2740
2741/// MustProgress attribute deduction for a call sites.
2742struct AAMustProgressCallSite final : AAMustProgressImpl {
2743 AAMustProgressCallSite(const IRPosition &IRP, Attributor &A)
2744 : AAMustProgressImpl(IRP, A) {}
2745
2746 ChangeStatus updateImpl(Attributor &A) override {
2747 // TODO: Once we have call site specific value information we can provide
2748 // call site specific liveness information and then it makes
2749 // sense to specialize attributes for call sites arguments instead of
2750 // redirecting requests to the callee argument.
2751 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
2752 bool IsKnownMustProgress;
2754 A, this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2755 return indicatePessimisticFixpoint();
2756 return ChangeStatus::UNCHANGED;
2757 }
2758
2759 void trackStatistics() const override {
2760 STATS_DECLTRACK_CS_ATTR(mustprogress);
2761 }
2762};
2763} // namespace
2764
2765/// ------------------------ No-Recurse Attributes ----------------------------
2766
2767namespace {
2768struct AANoRecurseImpl : public AANoRecurse {
2769 AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}
2770
2771 void initialize(Attributor &A) override {
2772 bool IsKnown;
2774 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2775 (void)IsKnown;
2776 }
2777
2778 const std::string getAsStr(Attributor *A) const override {
2779 return getAssumed() ? "norecurse" : "may-recurse";
2780 }
2781};
2782
2783struct AANoRecurseFunction final : AANoRecurseImpl {
2784 AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
2785 : AANoRecurseImpl(IRP, A) {}
2786
2787 ChangeStatus updateImpl(Attributor &A) override {
2788
2789 // If all live call sites are known to be no-recurse, we are as well.
2790 auto CallSitePred = [&](AbstractCallSite ACS) {
2791 bool IsKnownNoRecurse;
2793 A, this,
2794 IRPosition::function(*ACS.getInstruction()->getFunction()),
2795 DepClassTy::NONE, IsKnownNoRecurse))
2796 return false;
2797 return IsKnownNoRecurse;
2798 };
2799 bool UsedAssumedInformation = false;
2800 if (A.checkForAllCallSites(CallSitePred, *this, true,
2801 UsedAssumedInformation)) {
2802 // If we know all call sites and all are known no-recurse, we are done.
2803 // If all known call sites, which might not be all that exist, are known
2804 // to be no-recurse, we are not done but we can continue to assume
2805 // no-recurse. If one of the call sites we have not visited will become
2806 // live, another update is triggered.
2807 if (!UsedAssumedInformation)
2808 indicateOptimisticFixpoint();
2809 return ChangeStatus::UNCHANGED;
2810 }
2811
2812 const AAInterFnReachability *EdgeReachability =
2813 A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),
2814 DepClassTy::REQUIRED);
2815 if (EdgeReachability && EdgeReachability->canReach(A, *getAnchorScope()))
2816 return indicatePessimisticFixpoint();
2817 return ChangeStatus::UNCHANGED;
2818 }
2819
2820 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
2821};
2822
2823/// NoRecurse attribute deduction for a call sites.
2824struct AANoRecurseCallSite final
2825 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2826 AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
2827 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP, A) {}
2828
2829 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }
2830};
2831} // namespace
2832
2833/// ------------------------ No-Convergent Attribute --------------------------
2834
2835namespace {
2836struct AANonConvergentImpl : public AANonConvergent {
2837 AANonConvergentImpl(const IRPosition &IRP, Attributor &A)
2838 : AANonConvergent(IRP, A) {}
2839
2840 const std::string getAsStr(Attributor *A) const override {
2841 return getAssumed() ? "non-convergent" : "may-be-convergent";
2842 }
2843};
2844
2845struct AANonConvergentFunction final : AANonConvergentImpl {
2846 AANonConvergentFunction(const IRPosition &IRP, Attributor &A)
2847 : AANonConvergentImpl(IRP, A) {}
2848
2849 ChangeStatus updateImpl(Attributor &A) override {
2850 // If all function calls are known to not be convergent, we are not
2851 // convergent.
2852 auto CalleeIsNotConvergent = [&](Instruction &Inst) {
2853 CallBase &CB = cast<CallBase>(Inst);
2855 if (!Callee || Callee->isIntrinsic()) {
2856 return false;
2857 }
2858 if (Callee->isDeclaration()) {
2859 return !Callee->hasFnAttribute(Attribute::Convergent);
2860 }
2861 const auto *ConvergentAA = A.getAAFor<AANonConvergent>(
2862 *this, IRPosition::function(*Callee), DepClassTy::REQUIRED);
2863 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2864 };
2865
2866 bool UsedAssumedInformation = false;
2867 if (!A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *this,
2868 UsedAssumedInformation)) {
2869 return indicatePessimisticFixpoint();
2870 }
2871 return ChangeStatus::UNCHANGED;
2872 }
2873
2874 ChangeStatus manifest(Attributor &A) override {
2875 if (isKnownNotConvergent() &&
2876 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2877 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2878 return ChangeStatus::CHANGED;
2879 }
2880 return ChangeStatus::UNCHANGED;
2881 }
2882
2883 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(convergent) }
2884};
2885} // namespace
2886
2887/// -------------------- Undefined-Behavior Attributes ------------------------
2888
2889namespace {
2890struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
2891 AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
2892 : AAUndefinedBehavior(IRP, A) {}
2893
2894 struct UBInfo {
2895 enum Kind {
2896 NullPtrAccess,
2897 UndefPtrAccess,
2898 UndefBranchCondition,
2899 UndefReturnValue,
2900 NullReturnViolatesNonNull,
2901 UndefCallArgument,
2902 NullArgViolatesNonNull,
2903 };
2904
2905 Kind K;
2906 std::optional<unsigned> ArgNo;
2907
2908 UBInfo(Kind K) : K(K), ArgNo(std::nullopt) {}
2909
2910 UBInfo(Kind K, std::optional<unsigned> ArgNo) : K(K), ArgNo(ArgNo) {}
2911 };
2912
2913 ChangeStatus updateImpl(Attributor &A) override {
2914 const size_t UBPrevSize = KnownUBInsts.size();
2915 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2916
2917 auto InspectMemAccessInstForUB = [&](Instruction &I) {
2918 // Volatile accesses on null are not necessarily UB.
2919 if (I.isVolatile())
2920 return true;
2921
2922 // Skip instructions that are already saved.
2923 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2924 return true;
2925
2926 // If we reach here, we know we have an instruction
2927 // that accesses memory through a pointer operand,
2928 // for which getPointerOperand() should give it to us.
2929 Value *PtrOp =
2930 const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));
2931 assert(PtrOp &&
2932 "Expected pointer operand of memory accessing instruction");
2933
2934 // Either we stopped and the appropriate action was taken,
2935 // or we got back a simplified value to continue.
2936 std::optional<Value *> SimplifiedPtrOp =
2937 stopOnUndefOrAssumed(A, PtrOp, &I, UBInfo::UndefPtrAccess);
2938 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2939 return true;
2940 const Value *PtrOpVal = *SimplifiedPtrOp;
2941
2942 // A memory access through a pointer is considered UB
2943 // only if the pointer has constant null value.
2944 // TODO: Expand it to not only check constant values.
2945 if (!isa<ConstantPointerNull>(PtrOpVal)) {
2946 AssumedNoUBInsts.insert(&I);
2947 return true;
2948 }
2949 const Type *PtrTy = PtrOpVal->getType();
2950
2951 // Because we only consider instructions inside functions,
2952 // assume that a parent function exists.
2953 const Function *F = I.getFunction();
2954
2955 // A memory access using constant null pointer is only considered UB
2956 // if null pointer is _not_ defined for the target platform.
2958 AssumedNoUBInsts.insert(&I);
2959 else
2960 KnownUBInsts.try_emplace(&I, UBInfo::NullPtrAccess);
2961 return true;
2962 };
2963
2964 auto InspectBrInstForUB = [&](Instruction &I) {
2965 // A conditional branch instruction is considered UB if it has `undef`
2966 // condition.
2967
2968 // Skip instructions that are already saved.
2969 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2970 return true;
2971
2972 // We know we have a branch instruction.
2973 auto *BrInst = cast<CondBrInst>(&I);
2974
2975 // Either we stopped and the appropriate action was taken,
2976 // or we got back a simplified value to continue.
2977 std::optional<Value *> SimplifiedCond = stopOnUndefOrAssumed(
2978 A, BrInst->getCondition(), BrInst, UBInfo::UndefBranchCondition);
2979 if (!SimplifiedCond || !*SimplifiedCond)
2980 return true;
2981 AssumedNoUBInsts.insert(&I);
2982 return true;
2983 };
2984
2985 auto InspectCallSiteForUB = [&](Instruction &I) {
2986 // Check whether a callsite always cause UB or not
2987
2988 // Skip instructions that are already saved.
2989 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2990 return true;
2991
2992 // Check nonnull and noundef argument attribute violation for each
2993 // callsite.
2994 CallBase &CB = cast<CallBase>(I);
2996 if (!Callee)
2997 return true;
2998 for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
2999 // If current argument is known to be simplified to null pointer and the
3000 // corresponding argument position is known to have nonnull attribute,
3001 // the argument is poison. Furthermore, if the argument is poison and
3002 // the position is known to have noundef attriubte, this callsite is
3003 // considered UB.
3004 if (idx >= Callee->arg_size())
3005 break;
3006 Value *ArgVal = CB.getArgOperand(idx);
3007 if (!ArgVal)
3008 continue;
3009 // Here, we handle three cases.
3010 // (1) Not having a value means it is dead. (we can replace the value
3011 // with undef)
3012 // (2) Simplified to undef. The argument violate noundef attriubte.
3013 // (3) Simplified to null pointer where known to be nonnull.
3014 // The argument is a poison value and violate noundef attribute.
3015 IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
3016 bool IsKnownNoUndef;
3018 A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3019 if (!IsKnownNoUndef)
3020 continue;
3021 bool UsedAssumedInformation = false;
3022 std::optional<Value *> SimplifiedVal =
3023 A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,
3024 UsedAssumedInformation, AA::Interprocedural);
3025 if (UsedAssumedInformation)
3026 continue;
3027 if (SimplifiedVal && !*SimplifiedVal)
3028 return true;
3029 if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {
3030 KnownUBInsts.try_emplace(&I, UBInfo(UBInfo::UndefCallArgument, idx));
3031 continue;
3032 }
3033 if (!ArgVal->getType()->isPointerTy() ||
3034 !isa<ConstantPointerNull>(**SimplifiedVal))
3035 continue;
3036 bool IsKnownNonNull;
3038 A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3039 if (IsKnownNonNull)
3040 KnownUBInsts.try_emplace(&I,
3041 UBInfo(UBInfo::NullArgViolatesNonNull, idx));
3042 }
3043 return true;
3044 };
3045
3046 auto InspectReturnInstForUB = [&](Instruction &I) {
3047 auto &RI = cast<ReturnInst>(I);
3048 // Either we stopped and the appropriate action was taken,
3049 // or we got back a simplified return value to continue.
3050 std::optional<Value *> SimplifiedRetValue = stopOnUndefOrAssumed(
3051 A, RI.getReturnValue(), &I, UBInfo::UndefReturnValue);
3052 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3053 return true;
3054
3055 // Check if a return instruction always cause UB or not
3056 // Note: It is guaranteed that the returned position of the anchor
3057 // scope has noundef attribute when this is called.
3058 // We also ensure the return position is not "assumed dead"
3059 // because the returned value was then potentially simplified to
3060 // `undef` in AAReturnedValues without removing the `noundef`
3061 // attribute yet.
3062
3063 // When the returned position has noundef attriubte, UB occurs in the
3064 // following cases.
3065 // (1) Returned value is known to be undef.
3066 // (2) The value is known to be a null pointer and the returned
3067 // position has nonnull attribute (because the returned value is
3068 // poison).
3069 if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {
3070 bool IsKnownNonNull;
3072 A, this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE,
3073 IsKnownNonNull);
3074 if (IsKnownNonNull)
3075 KnownUBInsts.try_emplace(&I, UBInfo::NullReturnViolatesNonNull);
3076 }
3077
3078 return true;
3079 };
3080
3081 bool UsedAssumedInformation = false;
3082 A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
3083 {Instruction::Load, Instruction::Store,
3084 Instruction::AtomicCmpXchg,
3085 Instruction::AtomicRMW},
3086 UsedAssumedInformation,
3087 /* CheckBBLivenessOnly */ true);
3088 A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::CondBr},
3089 UsedAssumedInformation,
3090 /* CheckBBLivenessOnly */ true);
3091 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
3092 UsedAssumedInformation);
3093
3094 // If the returned position of the anchor scope has noundef attriubte, check
3095 // all returned instructions.
3096 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3097 const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
3098 if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
3099 bool IsKnownNoUndef;
3101 A, this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3102 if (IsKnownNoUndef)
3103 A.checkForAllInstructions(InspectReturnInstForUB, *this,
3104 {Instruction::Ret}, UsedAssumedInformation,
3105 /* CheckBBLivenessOnly */ true);
3106 }
3107 }
3108
3109 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3110 UBPrevSize != KnownUBInsts.size())
3111 return ChangeStatus::CHANGED;
3112 return ChangeStatus::UNCHANGED;
3113 }
3114
3115 bool isKnownToCauseUB(Instruction *I) const override {
3116 return KnownUBInsts.count(I);
3117 }
3118
3119 bool isAssumedToCauseUB(Instruction *I) const override {
3120 // In simple words, if an instruction is not in the assumed to _not_
3121 // cause UB, then it is assumed UB (that includes those
3122 // in the KnownUBInsts set). The rest is boilerplate
3123 // is to ensure that it is one of the instructions we test
3124 // for UB.
3125
3126 switch (I->getOpcode()) {
3127 case Instruction::Load:
3128 case Instruction::Store:
3129 case Instruction::AtomicCmpXchg:
3130 case Instruction::AtomicRMW:
3131 case Instruction::CondBr:
3132 return !AssumedNoUBInsts.count(I);
3133 default:
3134 return false;
3135 }
3136 return false;
3137 }
3138
3139 /// Emit an optimization remark explaining why \p I is known to cause UB,
3140 /// per \p Info, right before it is replaced with 'unreachable'.
3141 static void emitUBRemark(Attributor &A, Instruction *I, const UBInfo &Info) {
3142 auto Remark = [&](OptimizationRemark OR) {
3143 switch (Info.K) {
3144 case UBInfo::NullPtrAccess:
3145 case UBInfo::UndefPtrAccess: {
3146 return OR << "Memory access through a pointer known to be "
3147 << ore::NV("Pointer",
3148 getPointerOperand(I, /*AllowVolatile*/ true))
3149 << " is undefined behavior; replacing with 'unreachable'.";
3150 }
3151 case UBInfo::UndefBranchCondition:
3152 return OR << "Branch condition known to be "
3153 << ore::NV("Condition", cast<CondBrInst>(I)->getCondition())
3154 << " is undefined behavior; replacing with 'unreachable'.";
3155 case UBInfo::UndefReturnValue:
3156 case UBInfo::NullReturnViolatesNonNull:
3157 return OR << "Value returned known to be "
3158 << ore::NV("ReturnValue",
3159 cast<ReturnInst>(I)->getReturnValue())
3160 << " is undefined behavior; replacing with 'unreachable'.";
3161 case UBInfo::UndefCallArgument:
3162 case UBInfo::NullArgViolatesNonNull: {
3163 bool IsUndef = Info.K == UBInfo::UndefCallArgument;
3164 CallBase &CB = *cast<CallBase>(I);
3165 OR << "Argument " << ore::NV("ArgNo", *Info.ArgNo)
3166 << " passed to parameter of ";
3167 if (auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand()))
3168 OR << ore::NV("Callee", Callee);
3169 else
3170 OR << "the callee";
3171 return OR << " known to be "
3172 << ore::NV("Argument", IsUndef ? "undef" : "null")
3173 << " is undefined behavior; replacing with 'unreachable'.";
3174 }
3175 }
3176 llvm_unreachable("Unknown UBInfo::Kind");
3177 };
3178 A.emitRemark<OptimizationRemark>(I, "UndefinedBehavior", Remark);
3179 }
3180
3181 ChangeStatus manifest(Attributor &A) override {
3182 if (KnownUBInsts.empty())
3183 return ChangeStatus::UNCHANGED;
3184 for (const auto &[I, Info] : KnownUBInsts) {
3185 emitUBRemark(A, I, Info);
3186 A.changeToUnreachableAfterManifest(I);
3187 }
3188 return ChangeStatus::CHANGED;
3189 }
3190
3191 const std::string getAsStr(Attributor *A) const override {
3192 return getAssumed() ? "undefined-behavior" : "no-ub";
3193 }
3194
3195 /// Note: The correctness of this analysis depends on the fact that the
3196 /// following 2 sets will stop changing after some point.
3197 /// "Change" here means that their size changes.
3198 /// The size of each set is monotonically increasing
3199 /// (we only add items to them) and it is upper bounded by the number of
3200 /// instructions in the processed function (we can never save more
3201 /// elements in either set than this number). Hence, at some point,
3202 /// they will stop increasing.
3203 /// Consequently, at some point, both sets will have stopped
3204 /// changing, effectively making the analysis reach a fixpoint.
3205
3206 /// Note: These 2 sets are disjoint and an instruction can be considered
3207 /// one of 3 things:
3208 /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
3209 /// the KnownUBInsts set.
3210 /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
3211 /// has a reason to assume it).
3212 /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
3213 /// could not find a reason to assume or prove that it can cause UB,
3214 /// hence it assumes it doesn't. We have a set for these instructions
3215 /// so that we don't reprocess them in every update.
3216 /// Note however that instructions in this set may cause UB.
3217
3218protected:
3219 /// A map from all live instructions _known_ to cause UB to the reason why,
3220 /// used to build actionable optimization remarks in manifest().
3221 MapVector<Instruction *, UBInfo> KnownUBInsts;
3222
3223private:
3224 /// A set of all the (live) instructions that are assumed to _not_ cause UB.
3225 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3226
3227 // Should be called on updates in which if we're processing an instruction
3228 // \p I that depends on a value \p V, one of the following has to happen:
3229 // - If the value is assumed, then stop.
3230 // - If the value is known but undef, then consider it UB for \p K.
3231 // - Otherwise, do specific processing with the simplified value.
3232 // We return std::nullopt in the first 2 cases to signify that an appropriate
3233 // action was taken and the caller should stop.
3234 // Otherwise, we return the simplified value that the caller should
3235 // use for specific processing.
3236 std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
3237 Instruction *I, UBInfo::Kind K) {
3238 bool UsedAssumedInformation = false;
3239 std::optional<Value *> SimplifiedV =
3240 A.getAssumedSimplified(IRPosition::value(*V), *this,
3241 UsedAssumedInformation, AA::Interprocedural);
3242 if (!UsedAssumedInformation) {
3243 // Don't depend on assumed values.
3244 if (!SimplifiedV) {
3245 // If it is known (which we tested above) but it doesn't have a value,
3246 // then we can assume `undef` and hence the instruction is UB.
3247 KnownUBInsts.try_emplace(I, K);
3248 return std::nullopt;
3249 }
3250 if (!*SimplifiedV)
3251 return nullptr;
3252 V = *SimplifiedV;
3253 }
3254 if (isa<UndefValue>(V)) {
3255 KnownUBInsts.try_emplace(I, K);
3256 return std::nullopt;
3257 }
3258 return V;
3259 }
3260};
3261
3262struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3263 AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
3264 : AAUndefinedBehaviorImpl(IRP, A) {}
3265
3266 void trackStatistics() const override {
3267 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3268 "Number of instructions known to have UB");
3269 BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) +=
3270 KnownUBInsts.size();
3271 }
3272};
3273} // namespace
3274
3275/// ------------------------ Will-Return Attributes ----------------------------
3276
3277namespace {
3278// Helper function that checks whether a function has any cycle which we don't
3279// know if it is bounded or not.
3280// Loops with maximum trip count are considered bounded, any other cycle not.
3281static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
3282 ScalarEvolution *SE =
3283 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
3284 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
3285 // If either SCEV or LoopInfo is not available for the function then we assume
3286 // any cycle to be unbounded cycle.
3287 // We use scc_iterator which uses Tarjan algorithm to find all the maximal
3288 // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
3289 if (!SE || !LI) {
3290 for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
3291 if (SCCI.hasCycle())
3292 return true;
3293 return false;
3294 }
3295
3296 // If there's irreducible control, the function may contain non-loop cycles.
3298 return true;
3299
3300 // Any loop that does not have a max trip count is considered unbounded cycle.
3301 for (auto *L : LI->getLoopsInPreorder()) {
3302 if (!SE->getSmallConstantMaxTripCount(L))
3303 return true;
3304 }
3305 return false;
3306}
3307
3308struct AAWillReturnImpl : public AAWillReturn {
3309 AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
3310 : AAWillReturn(IRP, A) {}
3311
3312 void initialize(Attributor &A) override {
3313 bool IsKnown;
3315 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3316 (void)IsKnown;
3317 }
3318
3319 /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
3320 bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
3321 if (!A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3322 return false;
3323
3324 bool IsKnown;
3325 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3326 return IsKnown || !KnownOnly;
3327 return false;
3328 }
3329
3330 ChangeStatus updateImpl(Attributor &A) override {
3331 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3332 return ChangeStatus::UNCHANGED;
3333
3334 auto CheckForWillReturn = [&](Instruction &I) {
3336 bool IsKnown;
3338 A, this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3339 if (IsKnown)
3340 return true;
3341 } else {
3342 return false;
3343 }
3344 bool IsKnownNoRecurse;
3346 A, this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3347 };
3348
3349 bool UsedAssumedInformation = false;
3350 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
3351 UsedAssumedInformation))
3352 return indicatePessimisticFixpoint();
3353
3354 auto CheckForVolatile = [&](Instruction &I) {
3355 // Volatile operations are not willreturn.
3356 return !I.isVolatile();
3357 };
3358 if (!A.checkForAllInstructions(CheckForVolatile, *this,
3359 {Instruction::Load, Instruction::Store,
3360 Instruction::AtomicCmpXchg,
3361 Instruction::AtomicRMW},
3362 UsedAssumedInformation))
3363 return indicatePessimisticFixpoint();
3364
3365 return ChangeStatus::UNCHANGED;
3366 }
3367
3368 const std::string getAsStr(Attributor *A) const override {
3369 return getAssumed() ? "willreturn" : "may-noreturn";
3370 }
3371};
3372
3373struct AAWillReturnFunction final : AAWillReturnImpl {
3374 AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
3375 : AAWillReturnImpl(IRP, A) {}
3376
3377 void initialize(Attributor &A) override {
3378 AAWillReturnImpl::initialize(A);
3379
3380 Function *F = getAnchorScope();
3381 assert(F && "Did expect an anchor function");
3382 if (F->isDeclaration() || mayContainUnboundedCycle(*F, A))
3383 indicatePessimisticFixpoint();
3384 }
3385
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 ChangeStatus updateImpl(Attributor &A) override {
3396 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3397 return ChangeStatus::UNCHANGED;
3398
3399 return AACalleeToCallSite::updateImpl(A);
3400 }
3401
3402 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }
3403};
3404} // namespace
3405
3406/// -------------------AAIntraFnReachability Attribute--------------------------
3407
3408/// All information associated with a reachability query. This boilerplate code
3409/// is used by both AAIntraFnReachability and AAInterFnReachability, with
3410/// different \p ToTy values.
3411template <typename ToTy> struct ReachabilityQueryInfo {
3412 enum class Reachable {
3415 };
3416
3417 /// Start here,
3418 const Instruction *From = nullptr;
3419 /// reach this place,
3420 const ToTy *To = nullptr;
3421 /// without going through any of these instructions,
3423 /// and remember if it worked:
3425
3426 /// Precomputed hash for this RQI.
3427 unsigned Hash = 0;
3428
3429 unsigned computeHashValue() const {
3430 assert(Hash == 0 && "Computed hash twice!");
3433 return const_cast<ReachabilityQueryInfo<ToTy> *>(this)->Hash =
3434 detail::combineHashValue(PairDMI ::getHashValue({From, To}),
3435 InstSetDMI::getHashValue(ExclusionSet));
3436 }
3437
3439 : From(From), To(To) {}
3440
3441 /// Constructor replacement to ensure unique and stable sets are used for the
3442 /// cache.
3444 const AA::InstExclusionSetTy *ES, bool MakeUnique)
3445 : From(&From), To(&To), ExclusionSet(ES) {
3446
3447 if (!ES || ES->empty()) {
3448 ExclusionSet = nullptr;
3449 } else if (MakeUnique) {
3450 ExclusionSet = A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3451 }
3452 }
3453
3456};
3457
3458namespace llvm {
3459template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
3462
3463 static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
3464 return RQI->Hash ? RQI->Hash : RQI->computeHashValue();
3465 }
3466 static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
3467 const ReachabilityQueryInfo<ToTy> *RHS) {
3468 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3469 return false;
3470 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3471 }
3472};
3473
3474} // namespace llvm
3475
3476namespace {
3477
3478template <typename BaseTy, typename ToTy>
3479struct CachedReachabilityAA : public BaseTy {
3480 using RQITy = ReachabilityQueryInfo<ToTy>;
3481
3482 CachedReachabilityAA(const IRPosition &IRP, Attributor &A) : BaseTy(IRP, A) {}
3483
3484 bool isQueryAA() const override { return true; }
3485
3486 ChangeStatus updateImpl(Attributor &A) override {
3487 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3488 for (unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3489 RQITy *RQI = QueryVector[u];
3490 if (RQI->Result == RQITy::Reachable::No &&
3491 isReachableImpl(A, *RQI, /*IsTemporaryRQI=*/false))
3492 Changed = ChangeStatus::CHANGED;
3493 }
3494 return Changed;
3495 }
3496
3497 virtual bool isReachableImpl(Attributor &A, RQITy &RQI,
3498 bool IsTemporaryRQI) = 0;
3499
3500 bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
3501 RQITy &RQI, bool UsedExclusionSet, bool IsTemporaryRQI) {
3502 RQI.Result = Result;
3503
3504 // Remove the temporary RQI from the cache.
3505 if (IsTemporaryRQI)
3506 QueryCache.erase(&RQI);
3507
3508 // Insert a plain RQI (w/o exclusion set) if that makes sense. Two options:
3509 // 1) If it is reachable, it doesn't matter if we have an exclusion set for
3510 // this query. 2) We did not use the exclusion set, potentially because
3511 // there is none.
3512 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3513 RQITy PlainRQI(RQI.From, RQI.To);
3514 if (!QueryCache.count(&PlainRQI)) {
3515 RQITy *RQIPtr = new (A.Allocator) RQITy(RQI.From, RQI.To);
3516 RQIPtr->Result = Result;
3517 QueryVector.push_back(RQIPtr);
3518 QueryCache.insert(RQIPtr);
3519 }
3520 }
3521
3522 // Check if we need to insert a new permanent RQI with the exclusion set.
3523 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3524 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3525 "Did not expect empty set!");
3526 RQITy *RQIPtr = new (A.Allocator)
3527 RQITy(A, *RQI.From, *RQI.To, RQI.ExclusionSet, true);
3528 assert(RQIPtr->Result == RQITy::Reachable::No && "Already reachable?");
3529 RQIPtr->Result = Result;
3530 assert(!QueryCache.count(RQIPtr));
3531 QueryVector.push_back(RQIPtr);
3532 QueryCache.insert(RQIPtr);
3533 }
3534
3535 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3536 A.registerForUpdate(*this);
3537 return Result == RQITy::Reachable::Yes;
3538 }
3539
3540 const std::string getAsStr(Attributor *A) const override {
3541 // TODO: Return the number of reachable queries.
3542 return "#queries(" + std::to_string(QueryVector.size()) + ")";
3543 }
3544
3545 bool checkQueryCache(Attributor &A, RQITy &StackRQI,
3546 typename RQITy::Reachable &Result) {
3547 if (!this->getState().isValidState()) {
3548 Result = RQITy::Reachable::Yes;
3549 return true;
3550 }
3551
3552 // If we have an exclusion set we might be able to find our answer by
3553 // ignoring it first.
3554 if (StackRQI.ExclusionSet) {
3555 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3556 auto It = QueryCache.find(&PlainRQI);
3557 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3558 Result = RQITy::Reachable::No;
3559 return true;
3560 }
3561 }
3562
3563 auto It = QueryCache.find(&StackRQI);
3564 if (It != QueryCache.end()) {
3565 Result = (*It)->Result;
3566 return true;
3567 }
3568
3569 // Insert a temporary for recursive queries. We will replace it with a
3570 // permanent entry later.
3571 QueryCache.insert(&StackRQI);
3572 return false;
3573 }
3574
3575private:
3576 SmallVector<RQITy *> QueryVector;
3577 DenseSet<RQITy *> QueryCache;
3578};
3579
3580struct AAIntraFnReachabilityFunction final
3581 : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3582 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3583 AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
3584 : Base(IRP, A) {
3585 DT = A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3586 *IRP.getAssociatedFunction());
3587 }
3588
3589 bool isAssumedReachable(
3590 Attributor &A, const Instruction &From, const Instruction &To,
3591 const AA::InstExclusionSetTy *ExclusionSet) const override {
3592 auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
3593 if (&From == &To)
3594 return true;
3595
3596 RQITy StackRQI(A, From, To, ExclusionSet, false);
3597 RQITy::Reachable Result;
3598 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
3599 return NonConstThis->isReachableImpl(A, StackRQI,
3600 /*IsTemporaryRQI=*/true);
3601 return Result == RQITy::Reachable::Yes;
3602 }
3603
3604 ChangeStatus updateImpl(Attributor &A) override {
3605 // We only depend on liveness. DeadEdges is all we care about, check if any
3606 // of them changed.
3607 auto *LivenessAA =
3608 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3609 if (LivenessAA &&
3610 llvm::all_of(DeadEdges,
3611 [&](const auto &DeadEdge) {
3612 return LivenessAA->isEdgeDead(DeadEdge.first,
3613 DeadEdge.second);
3614 }) &&
3615 llvm::all_of(DeadBlocks, [&](const BasicBlock *BB) {
3616 return LivenessAA->isAssumedDead(BB);
3617 })) {
3618 return ChangeStatus::UNCHANGED;
3619 }
3620 DeadEdges.clear();
3621 DeadBlocks.clear();
3622 return Base::updateImpl(A);
3623 }
3624
3625 bool isReachableImpl(Attributor &A, RQITy &RQI,
3626 bool IsTemporaryRQI) override {
3627 const Instruction *Origin = RQI.From;
3628 bool UsedExclusionSet = false;
3629
3630 auto WillReachInBlock = [&](const Instruction &From, const Instruction &To,
3631 const AA::InstExclusionSetTy *ExclusionSet) {
3632 const Instruction *IP = &From;
3633 while (IP && IP != &To) {
3634 if (ExclusionSet && IP != Origin && ExclusionSet->count(IP)) {
3635 UsedExclusionSet = true;
3636 break;
3637 }
3638 IP = IP->getNextNode();
3639 }
3640 return IP == &To;
3641 };
3642
3643 const BasicBlock *FromBB = RQI.From->getParent();
3644 const BasicBlock *ToBB = RQI.To->getParent();
3645 assert(FromBB->getParent() == ToBB->getParent() &&
3646 "Not an intra-procedural query!");
3647
3648 // Check intra-block reachability, however, other reaching paths are still
3649 // possible.
3650 if (FromBB == ToBB &&
3651 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3652 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3653 IsTemporaryRQI);
3654
3655 // Check if reaching the ToBB block is sufficient or if even that would not
3656 // ensure reaching the target. In the latter case we are done.
3657 if (!WillReachInBlock(ToBB->front(), *RQI.To, RQI.ExclusionSet))
3658 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3659 IsTemporaryRQI);
3660
3661 const Function *Fn = FromBB->getParent();
3662 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3663 if (RQI.ExclusionSet)
3664 for (auto *I : *RQI.ExclusionSet)
3665 if (I->getFunction() == Fn)
3666 ExclusionBlocks.insert(I->getParent());
3667
3668 // Check if we make it out of the FromBB block at all.
3669 if (ExclusionBlocks.count(FromBB) &&
3670 !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
3671 RQI.ExclusionSet))
3672 return rememberResult(A, RQITy::Reachable::No, RQI, true, IsTemporaryRQI);
3673
3674 auto *LivenessAA =
3675 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3676 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3677 DeadBlocks.insert(ToBB);
3678 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3679 IsTemporaryRQI);
3680 }
3681
3682 SmallPtrSet<const BasicBlock *, 16> Visited;
3684 Worklist.push_back(FromBB);
3685
3686 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3687 while (!Worklist.empty()) {
3688 const BasicBlock *BB = Worklist.pop_back_val();
3689 if (!Visited.insert(BB).second)
3690 continue;
3691 for (const BasicBlock *SuccBB : successors(BB)) {
3692 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3693 LocalDeadEdges.insert({BB, SuccBB});
3694 continue;
3695 }
3696 // We checked before if we just need to reach the ToBB block.
3697 if (SuccBB == ToBB)
3698 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3699 IsTemporaryRQI);
3700 if (DT && ExclusionBlocks.empty() && DT->dominates(BB, ToBB))
3701 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3702 IsTemporaryRQI);
3703
3704 if (ExclusionBlocks.count(SuccBB)) {
3705 UsedExclusionSet = true;
3706 continue;
3707 }
3708 Worklist.push_back(SuccBB);
3709 }
3710 }
3711
3712 DeadEdges.insert_range(LocalDeadEdges);
3713 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3714 IsTemporaryRQI);
3715 }
3716
3717 void trackStatistics() const override {}
3718
3719private:
3720 // Set of assumed dead blocks we used in the last query. If any changes we
3721 // update the state.
3722 DenseSet<const BasicBlock *> DeadBlocks;
3723
3724 // Set of assumed dead edges we used in the last query. If any changes we
3725 // update the state.
3726 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3727
3728 /// The dominator tree of the function to short-circuit reasoning.
3729 const DominatorTree *DT = nullptr;
3730};
3731} // namespace
3732
3733/// ------------------------ NoAlias Argument Attribute ------------------------
3734
3736 Attribute::AttrKind ImpliedAttributeKind,
3737 bool IgnoreSubsumingPositions) {
3738 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3739 "Unexpected attribute kind");
3740 Value *Val = &IRP.getAssociatedValue();
3742 if (isa<AllocaInst>(Val))
3743 return true;
3744 } else {
3745 IgnoreSubsumingPositions = true;
3746 }
3747
3748 if (isa<UndefValue>(Val))
3749 return true;
3750
3751 if (isa<ConstantPointerNull>(Val) &&
3754 return true;
3755
3756 if (A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3757 IgnoreSubsumingPositions, Attribute::NoAlias))
3758 return true;
3759
3760 return false;
3761}
3762
3763namespace {
3764struct AANoAliasImpl : AANoAlias {
3765 AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
3766 assert(getAssociatedType()->isPointerTy() &&
3767 "Noalias is a pointer attribute");
3768 }
3769
3770 const std::string getAsStr(Attributor *A) const override {
3771 return getAssumed() ? "noalias" : "may-alias";
3772 }
3773};
3774
3775/// NoAlias attribute for a floating value.
3776struct AANoAliasFloating final : AANoAliasImpl {
3777 AANoAliasFloating(const IRPosition &IRP, Attributor &A)
3778 : AANoAliasImpl(IRP, A) {}
3779
3780 ChangeStatus updateImpl(Attributor &A) override {
3781 // TODO: Implement this.
3782 return indicatePessimisticFixpoint();
3783 }
3784
3785 void trackStatistics() const override {
3787 }
3788};
3789
3790/// NoAlias attribute for an argument.
3791struct AANoAliasArgument final
3792 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3793 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3794 AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
3795
3796 ChangeStatus updateImpl(Attributor &A) override {
3797 // We have to make sure no-alias on the argument does not break
3798 // synchronization when this is a callback argument, see also [1] below.
3799 // If synchronization cannot be affected, we delegate to the base updateImpl
3800 // function, otherwise we give up for now.
3801
3802 // If the function is no-sync, no-alias cannot break synchronization.
3803 bool IsKnownNoSycn;
3805 A, this, IRPosition::function_scope(getIRPosition()),
3806 DepClassTy::OPTIONAL, IsKnownNoSycn))
3807 return Base::updateImpl(A);
3808
3809 // If the argument is read-only, no-alias cannot break synchronization.
3810 bool IsKnown;
3811 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3812 return Base::updateImpl(A);
3813
3814 // If the argument is never passed through callbacks, no-alias cannot break
3815 // synchronization.
3816 bool UsedAssumedInformation = false;
3817 if (A.checkForAllCallSites(
3818 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,
3819 true, UsedAssumedInformation))
3820 return Base::updateImpl(A);
3821
3822 // TODO: add no-alias but make sure it doesn't break synchronization by
3823 // introducing fake uses. See:
3824 // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
3825 // International Workshop on OpenMP 2018,
3826 // http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf
3827
3828 return indicatePessimisticFixpoint();
3829 }
3830
3831 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
3832};
3833
3834struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3835 AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
3836 : AANoAliasImpl(IRP, A) {}
3837
3838 /// Determine if the underlying value may alias with the call site argument
3839 /// \p OtherArgNo of \p ICS (= the underlying call site).
3840 bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
3841 const AAMemoryBehavior &MemBehaviorAA,
3842 const CallBase &CB, unsigned OtherArgNo) {
3843 // We do not need to worry about aliasing with the underlying IRP.
3844 if (this->getCallSiteArgNo() == (int)OtherArgNo)
3845 return false;
3846
3847 // If it is not a pointer or pointer vector we do not alias.
3848 const Value *ArgOp = CB.getArgOperand(OtherArgNo);
3849 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
3850 return false;
3851
3852 auto *CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
3853 *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);
3854
3855 // If the argument is readnone, there is no read-write aliasing.
3856 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3857 A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3858 return false;
3859 }
3860
3861 // If the argument is readonly and the underlying value is readonly, there
3862 // is no read-write aliasing.
3863 bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
3864 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3865 IsReadOnly) {
3866 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3867 A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3868 return false;
3869 }
3870
3871 // We have to utilize actual alias analysis queries so we need the object.
3872 if (!AAR)
3873 AAR = A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3874 *getAnchorScope());
3875
3876 // Try to rule it out at the call site.
3877 bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);
3878 LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "
3879 "callsite arguments: "
3880 << getAssociatedValue() << " " << *ArgOp << " => "
3881 << (IsAliasing ? "" : "no-") << "alias \n");
3882
3883 return IsAliasing;
3884 }
3885
3886 bool isKnownNoAliasDueToNoAliasPreservation(
3887 Attributor &A, AAResults *&AAR, const AAMemoryBehavior &MemBehaviorAA) {
3888 // We can deduce "noalias" if the following conditions hold.
3889 // (i) Associated value is assumed to be noalias in the definition.
3890 // (ii) Associated value is assumed to be no-capture in all the uses
3891 // possibly executed before this callsite.
3892 // (iii) There is no other pointer argument which could alias with the
3893 // value.
3894
3895 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3896 const Function *ScopeFn = VIRP.getAnchorScope();
3897 // Check whether the value is captured in the scope using AANoCapture.
3898 // Look at CFG and check only uses possibly executed before this
3899 // callsite.
3900 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
3901 Instruction *UserI = cast<Instruction>(U.getUser());
3902
3903 // If UserI is the curr instruction and there is a single potential use of
3904 // the value in UserI we allow the use.
3905 // TODO: We should inspect the operands and allow those that cannot alias
3906 // with the value.
3907 if (UserI == getCtxI() && UserI->getNumOperands() == 1)
3908 return true;
3909
3910 if (ScopeFn) {
3911 if (auto *CB = dyn_cast<CallBase>(UserI)) {
3912 if (CB->isArgOperand(&U)) {
3913
3914 unsigned ArgNo = CB->getArgOperandNo(&U);
3915
3916 bool IsKnownNoCapture;
3918 A, this, IRPosition::callsite_argument(*CB, ArgNo),
3919 DepClassTy::OPTIONAL, IsKnownNoCapture))
3920 return true;
3921 }
3922 }
3923
3925 A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,
3926 [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
3927 return true;
3928 }
3929
3930 // TODO: We should track the capturing uses in AANoCapture but the problem
3931 // is CGSCC runs. For those we would need to "allow" AANoCapture for
3932 // a value in the module slice.
3933 // TODO(captures): Make this more precise.
3934 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
3935 if (capturesNothing(CI))
3936 return true;
3937 if (CI.isPassthrough()) {
3938 Follow = true;
3939 return true;
3940 }
3941 LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserI << "\n");
3942 return false;
3943 };
3944
3945 bool IsKnownNoCapture;
3946 const AANoCapture *NoCaptureAA = nullptr;
3947 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
3948 A, this, VIRP, DepClassTy::NONE, IsKnownNoCapture, false, &NoCaptureAA);
3949 if (!IsAssumedNoCapture &&
3950 (!NoCaptureAA || !NoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
3951 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
3952 LLVM_DEBUG(
3953 dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
3954 << " cannot be noalias as it is potentially captured\n");
3955 return false;
3956 }
3957 }
3958 if (NoCaptureAA)
3959 A.recordDependence(*NoCaptureAA, *this, DepClassTy::OPTIONAL);
3960
3961 // Check there is no other pointer argument which could alias with the
3962 // value passed at this call site.
3963 // TODO: AbstractCallSite
3964 const auto &CB = cast<CallBase>(getAnchorValue());
3965 for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
3966 if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
3967 return false;
3968
3969 return true;
3970 }
3971
3972 ChangeStatus updateImpl(Attributor &A) override {
3973 // If the argument is readnone we are done as there are no accesses via the
3974 // argument.
3975 auto *MemBehaviorAA =
3976 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
3977 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
3978 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3979 return ChangeStatus::UNCHANGED;
3980 }
3981
3982 bool IsKnownNoAlias;
3983 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3985 A, this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
3986 LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()
3987 << " is not no-alias at the definition\n");
3988 return indicatePessimisticFixpoint();
3989 }
3990
3991 AAResults *AAR = nullptr;
3992 if (MemBehaviorAA &&
3993 isKnownNoAliasDueToNoAliasPreservation(A, AAR, *MemBehaviorAA)) {
3994 LLVM_DEBUG(
3995 dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n");
3996 return ChangeStatus::UNCHANGED;
3997 }
3998
3999 return indicatePessimisticFixpoint();
4000 }
4001
4002 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }
4003};
4004
4005/// NoAlias attribute for function return value.
4006struct AANoAliasReturned final : AANoAliasImpl {
4007 AANoAliasReturned(const IRPosition &IRP, Attributor &A)
4008 : AANoAliasImpl(IRP, A) {}
4009
4010 ChangeStatus updateImpl(Attributor &A) override {
4011
4012 auto CheckReturnValue = [&](Value &RV) -> bool {
4013 if (Constant *C = dyn_cast<Constant>(&RV))
4014 if (C->isNullValue() || isa<UndefValue>(C))
4015 return true;
4016
4017 /// For now, we can only deduce noalias if we have call sites.
4018 /// FIXME: add more support.
4019 if (!isa<CallBase>(&RV))
4020 return false;
4021
4022 const IRPosition &RVPos = IRPosition::value(RV);
4023 bool IsKnownNoAlias;
4025 A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4026 return false;
4027
4028 bool IsKnownNoCapture;
4029 const AANoCapture *NoCaptureAA = nullptr;
4030 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
4031 A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
4032 &NoCaptureAA);
4033 return IsAssumedNoCapture ||
4034 (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned());
4035 };
4036
4037 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
4038 return indicatePessimisticFixpoint();
4039
4040 return ChangeStatus::UNCHANGED;
4041 }
4042
4043 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
4044};
4045
4046/// NoAlias attribute deduction for a call site return value.
4047struct AANoAliasCallSiteReturned final
4048 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4049 AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
4050 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP, A) {}
4051
4052 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }
4053};
4054} // namespace
4055
4056/// -------------------AAIsDead Function Attribute-----------------------
4057
4058namespace {
4059struct AAIsDeadValueImpl : public AAIsDead {
4060 AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4061
4062 bool isAssumedDead() const override { return isAssumed(IS_DEAD); }
4063
4064 bool isKnownDead() const override { return isKnown(IS_DEAD); }
4065
4066 bool isAssumedDead(const BasicBlock *BB) const override { return false; }
4067
4068 bool isKnownDead(const BasicBlock *BB) const override { return false; }
4069
4070 bool isAssumedDead(const Instruction *I) const override {
4071 return I == getCtxI() && isAssumedDead();
4072 }
4073
4074 bool isKnownDead(const Instruction *I) const override {
4075 return isAssumedDead(I) && isKnownDead();
4076 }
4077
4078 const std::string getAsStr(Attributor *A) const override {
4079 return isAssumedDead() ? "assumed-dead" : "assumed-live";
4080 }
4081
4082 /// Check if all uses are assumed dead.
4083 bool areAllUsesAssumedDead(Attributor &A, Value &V) {
4084 // Callers might not check the type, void has no uses.
4085 if (V.getType()->isVoidTy() || V.use_empty())
4086 return true;
4087
4088 // If we replace a value with a constant there are no uses left afterwards.
4089 if (!isa<Constant>(V)) {
4090 if (auto *I = dyn_cast<Instruction>(&V))
4091 if (!A.isRunOn(*I->getFunction()))
4092 return false;
4093 bool UsedAssumedInformation = false;
4094 std::optional<Constant *> C =
4095 A.getAssumedConstant(V, *this, UsedAssumedInformation);
4096 if (!C || *C)
4097 return true;
4098 }
4099
4100 auto UsePred = [&](const Use &U, bool &Follow) { return false; };
4101 // Explicitly set the dependence class to required because we want a long
4102 // chain of N dependent instructions to be considered live as soon as one is
4103 // without going through N update cycles. This is not required for
4104 // correctness.
4105 return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,
4106 DepClassTy::REQUIRED,
4107 /* IgnoreDroppableUses */ false);
4108 }
4109
4110 /// Determine if \p I is assumed to be side-effect free.
4111 bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
4113 return true;
4114
4115 if (!I->isTerminator() && !I->mayHaveSideEffects())
4116 return true;
4117
4118 auto *CB = dyn_cast<CallBase>(I);
4119 if (!CB || isa<IntrinsicInst>(CB))
4120 return false;
4121
4122 const IRPosition &CallIRP = IRPosition::callsite_function(*CB);
4123
4124 bool IsKnownNoUnwind;
4126 A, this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4127 return false;
4128
4129 bool IsKnown;
4130 return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);
4131 }
4132};
4133
4134struct AAIsDeadFloating : public AAIsDeadValueImpl {
4135 AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
4136 : AAIsDeadValueImpl(IRP, A) {}
4137
4138 void initialize(Attributor &A) override {
4139 AAIsDeadValueImpl::initialize(A);
4140
4141 if (isa<UndefValue>(getAssociatedValue())) {
4142 indicatePessimisticFixpoint();
4143 return;
4144 }
4145
4146 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4147 if (!isAssumedSideEffectFree(A, I)) {
4149 indicatePessimisticFixpoint();
4150 else
4151 removeAssumedBits(HAS_NO_EFFECT);
4152 }
4153 }
4154
4155 bool isDeadFence(Attributor &A, FenceInst &FI) {
4156 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
4157 IRPosition::function(*FI.getFunction()), *this, DepClassTy::NONE);
4158 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4159 return false;
4160 A.recordDependence(*ExecDomainAA, *this, DepClassTy::OPTIONAL);
4161 return true;
4162 }
4163
4164 bool isDeadStore(Attributor &A, StoreInst &SI,
4165 SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
4166 // Lang ref now states volatile store is not UB/dead, let's skip them.
4167 if (SI.isVolatile())
4168 return false;
4169
4170 // If we are collecting assumes to be deleted we are in the manifest stage.
4171 // It's problematic to collect the potential copies again now so we use the
4172 // cached ones.
4173 bool UsedAssumedInformation = false;
4174 if (!AssumeOnlyInst) {
4175 PotentialCopies.clear();
4176 if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,
4177 UsedAssumedInformation)) {
4178 LLVM_DEBUG(
4179 dbgs()
4180 << "[AAIsDead] Could not determine potential copies of store!\n");
4181 return false;
4182 }
4183 }
4184 LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()
4185 << " potential copies.\n");
4186
4187 InformationCache &InfoCache = A.getInfoCache();
4188 return llvm::all_of(PotentialCopies, [&](Value *V) {
4189 if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,
4190 UsedAssumedInformation))
4191 return true;
4192 if (auto *LI = dyn_cast<LoadInst>(V)) {
4193 if (llvm::all_of(LI->uses(), [&](const Use &U) {
4194 auto &UserI = cast<Instruction>(*U.getUser());
4195 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4196 if (AssumeOnlyInst)
4197 AssumeOnlyInst->insert(&UserI);
4198 return true;
4199 }
4200 return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);
4201 })) {
4202 return true;
4203 }
4204 }
4205 LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *V
4206 << " is assumed live!\n");
4207 return false;
4208 });
4209 }
4210
4211 const std::string getAsStr(Attributor *A) const override {
4212 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4214 if (isValidState())
4215 return "assumed-dead-store";
4217 if (isValidState())
4218 return "assumed-dead-fence";
4219 return AAIsDeadValueImpl::getAsStr(A);
4220 }
4221
4222 ChangeStatus updateImpl(Attributor &A) override {
4223 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4224 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
4225 if (!isDeadStore(A, *SI))
4226 return indicatePessimisticFixpoint();
4227 } else if (auto *FI = dyn_cast_or_null<FenceInst>(I)) {
4228 if (!isDeadFence(A, *FI))
4229 return indicatePessimisticFixpoint();
4230 } else {
4231 if (!isAssumedSideEffectFree(A, I))
4232 return indicatePessimisticFixpoint();
4233 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4234 return indicatePessimisticFixpoint();
4235 }
4237 }
4238
4239 bool isRemovableStore() const override {
4240 return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());
4241 }
4242
4243 ChangeStatus manifest(Attributor &A) override {
4244 Value &V = getAssociatedValue();
4245 if (auto *I = dyn_cast<Instruction>(&V)) {
4246 // If we get here we basically know the users are all dead. We check if
4247 // isAssumedSideEffectFree returns true here again because it might not be
4248 // the case and only the users are dead but the instruction (=call) is
4249 // still needed.
4250 if (auto *SI = dyn_cast<StoreInst>(I)) {
4251 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4252 bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);
4253 (void)IsDead;
4254 assert(IsDead && "Store was assumed to be dead!");
4255 A.deleteAfterManifest(*I);
4256 for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
4257 Instruction *AOI = AssumeOnlyInst[i];
4258 for (auto *Usr : AOI->users())
4259 AssumeOnlyInst.insert(cast<Instruction>(Usr));
4260 A.deleteAfterManifest(*AOI);
4261 }
4262 return ChangeStatus::CHANGED;
4263 }
4264 if (auto *FI = dyn_cast<FenceInst>(I)) {
4265 assert(isDeadFence(A, *FI));
4266 A.deleteAfterManifest(*FI);
4267 return ChangeStatus::CHANGED;
4268 }
4269 if (isAssumedSideEffectFree(A, I) && !I->isTerminator()) {
4270 A.deleteAfterManifest(*I);
4271 return ChangeStatus::CHANGED;
4272 }
4273 }
4275 }
4276
4277 void trackStatistics() const override {
4279 }
4280
4281private:
4282 // The potential copies of a dead store, used for deletion during manifest.
4283 SmallSetVector<Value *, 4> PotentialCopies;
4284};
4285
4286struct AAIsDeadArgument : public AAIsDeadFloating {
4287 AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
4288 : AAIsDeadFloating(IRP, A) {}
4289
4290 ChangeStatus manifest(Attributor &A) override {
4291 Argument &Arg = *getAssociatedArgument();
4292 if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
4293 if (A.registerFunctionSignatureRewrite(
4294 Arg, /* ReplacementTypes */ {},
4297 return ChangeStatus::CHANGED;
4298 }
4299 return ChangeStatus::UNCHANGED;
4300 }
4301
4302 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) }
4303};
4304
4305struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
4306 AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
4307 : AAIsDeadValueImpl(IRP, A) {}
4308
4309 void initialize(Attributor &A) override {
4310 AAIsDeadValueImpl::initialize(A);
4311 if (isa<UndefValue>(getAssociatedValue()))
4312 indicatePessimisticFixpoint();
4313 }
4314
4315 ChangeStatus updateImpl(Attributor &A) override {
4316 // TODO: Once we have call site specific value information we can provide
4317 // call site specific liveness information and then it makes
4318 // sense to specialize attributes for call sites arguments instead of
4319 // redirecting requests to the callee argument.
4320 Argument *Arg = getAssociatedArgument();
4321 if (!Arg)
4322 return indicatePessimisticFixpoint();
4323 const IRPosition &ArgPos = IRPosition::argument(*Arg);
4324 auto *ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);
4325 if (!ArgAA)
4326 return indicatePessimisticFixpoint();
4327 return clampStateAndIndicateChange(getState(), ArgAA->getState());
4328 }
4329
4330 ChangeStatus manifest(Attributor &A) override {
4331 CallBase &CB = cast<CallBase>(getAnchorValue());
4332 Use &U = CB.getArgOperandUse(getCallSiteArgNo());
4333 assert(!isa<UndefValue>(U.get()) &&
4334 "Expected undef values to be filtered out!");
4335 UndefValue &UV = *UndefValue::get(U->getType());
4336 if (A.changeUseAfterManifest(U, UV))
4337 return ChangeStatus::CHANGED;
4338 return ChangeStatus::UNCHANGED;
4339 }
4340
4341 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) }
4342};
4343
4344struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
4345 AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
4346 : AAIsDeadFloating(IRP, A) {}
4347
4348 bool isAssumedDead() const override {
4349 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4350 }
4351
4352 void initialize(Attributor &A) override {
4353 AAIsDeadFloating::initialize(A);
4354 if (isa<UndefValue>(getAssociatedValue())) {
4355 indicatePessimisticFixpoint();
4356 return;
4357 }
4358
4359 // We track this separately as a secondary state.
4360 IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());
4361 }
4362
4363 ChangeStatus updateImpl(Attributor &A) override {
4364 ChangeStatus Changed = ChangeStatus::UNCHANGED;
4365 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {
4366 IsAssumedSideEffectFree = false;
4367 Changed = ChangeStatus::CHANGED;
4368 }
4369 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4370 return indicatePessimisticFixpoint();
4371 return Changed;
4372 }
4373
4374 void trackStatistics() const override {
4375 if (IsAssumedSideEffectFree)
4377 else
4378 STATS_DECLTRACK_CSRET_ATTR(UnusedResult)
4379 }
4380
4381 const std::string getAsStr(Attributor *A) const override {
4382 return isAssumedDead()
4383 ? "assumed-dead"
4384 : (getAssumed() ? "assumed-dead-users" : "assumed-live");
4385 }
4386
4387private:
4388 bool IsAssumedSideEffectFree = true;
4389};
4390
4391struct AAIsDeadReturned : public AAIsDeadValueImpl {
4392 AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
4393 : AAIsDeadValueImpl(IRP, A) {}
4394
4395 ChangeStatus updateImpl(Attributor &A) override {
4396
4397 bool UsedAssumedInformation = false;
4398 A.checkForAllInstructions([](Instruction &) { return true; }, *this,
4399 {Instruction::Ret}, UsedAssumedInformation);
4400
4401 auto PredForCallSite = [&](AbstractCallSite ACS) {
4402 if (ACS.isCallbackCall() || !ACS.getInstruction())
4403 return false;
4404 return areAllUsesAssumedDead(A, *ACS.getInstruction());
4405 };
4406
4407 if (!A.checkForAllCallSites(PredForCallSite, *this, true,
4408 UsedAssumedInformation))
4409 return indicatePessimisticFixpoint();
4410
4411 return ChangeStatus::UNCHANGED;
4412 }
4413
4414 ChangeStatus manifest(Attributor &A) override {
4415 // TODO: Rewrite the signature to return void?
4416 bool AnyChange = false;
4417 UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());
4418 auto RetInstPred = [&](Instruction &I) {
4419 ReturnInst &RI = cast<ReturnInst>(I);
4421 AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
4422 return true;
4423 };
4424 bool UsedAssumedInformation = false;
4425 A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
4426 UsedAssumedInformation);
4427 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4428 }
4429
4430 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) }
4431};
4432
4433struct AAIsDeadFunction : public AAIsDead {
4434 AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4435
4436 void initialize(Attributor &A) override {
4437 Function *F = getAnchorScope();
4438 assert(F && "Did expect an anchor function");
4439 if (!isAssumedDeadInternalFunction(A)) {
4440 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4441 assumeLive(A, F->getEntryBlock());
4442 }
4443 }
4444
4445 bool isAssumedDeadInternalFunction(Attributor &A) {
4446 if (!getAnchorScope()->hasLocalLinkage())
4447 return false;
4448 // An AA that will not be updated is fixed pessimistically right after
4449 // initialization, so an assumed-dead result would be discarded. Checking
4450 // the call sites recursively initializes the liveness of every internal
4451 // caller, which in CGSCC cleanup repeats for each callee SCC.
4452 if (!A.shouldUpdateAA<AAIsDead>(getIRPosition()))
4453 return false;
4454 bool UsedAssumedInformation = false;
4455 return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,
4456 true, UsedAssumedInformation);
4457 }
4458
4459 const std::string getAsStr(Attributor *A) const override {
4460 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
4461 std::to_string(getAnchorScope()->size()) + "][#TBEP " +
4462 std::to_string(ToBeExploredFrom.size()) + "][#KDE " +
4463 std::to_string(KnownDeadEnds.size()) + "]";
4464 }
4465
4466 ChangeStatus manifest(Attributor &A) override {
4467 assert(getState().isValidState() &&
4468 "Attempted to manifest an invalid state!");
4469
4470 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
4471 Function &F = *getAnchorScope();
4472
4473 if (AssumedLiveBlocks.empty()) {
4474 A.deleteAfterManifest(F);
4475 return ChangeStatus::CHANGED;
4476 }
4477
4478 // Flag to determine if we can change an invoke to a call assuming the
4479 // callee is nounwind. This is not possible if the personality of the
4480 // function allows to catch asynchronous exceptions.
4481 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
4482
4483 KnownDeadEnds.set_union(ToBeExploredFrom);
4484 for (const Instruction *DeadEndI : KnownDeadEnds) {
4485 auto *CB = dyn_cast<CallBase>(DeadEndI);
4486 if (!CB)
4487 continue;
4488 bool IsKnownNoReturn;
4490 A, this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL,
4491 IsKnownNoReturn);
4492 if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))
4493 continue;
4494
4495 if (auto *II = dyn_cast<InvokeInst>(DeadEndI))
4496 A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));
4497 else
4498 A.changeToUnreachableAfterManifest(
4499 const_cast<Instruction *>(DeadEndI->getNextNode()));
4500 HasChanged = ChangeStatus::CHANGED;
4501 }
4502
4503 STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.");
4504 for (BasicBlock &BB : F)
4505 if (!AssumedLiveBlocks.count(&BB)) {
4506 A.deleteAfterManifest(BB);
4507 ++BUILD_STAT_NAME(AAIsDead, BasicBlock);
4508 HasChanged = ChangeStatus::CHANGED;
4509 }
4510
4511 return HasChanged;
4512 }
4513
4514 ChangeStatus updateImpl(Attributor &A) override;
4515
4516 bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
4517 assert(From->getParent() == getAnchorScope() &&
4518 To->getParent() == getAnchorScope() &&
4519 "Used AAIsDead of the wrong function");
4520 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4521 }
4522
4523 void trackStatistics() const override {}
4524
4525 /// Returns true if the function is assumed dead.
4526 bool isAssumedDead() const override { return false; }
4527
4528 bool isKnownDead() const override { return false; }
4529
4530 bool isAssumedDead(const BasicBlock *BB) const override {
4531 assert(BB->getParent() == getAnchorScope() &&
4532 "BB must be in the same anchor scope function.");
4533
4534 if (!getAssumed())
4535 return false;
4536 return !AssumedLiveBlocks.count(BB);
4537 }
4538
4539 bool isKnownDead(const BasicBlock *BB) const override {
4540 return getKnown() && isAssumedDead(BB);
4541 }
4542
4543 bool isAssumedDead(const Instruction *I) const override {
4544 assert(I->getParent()->getParent() == getAnchorScope() &&
4545 "Instruction must be in the same anchor scope function.");
4546
4547 if (!getAssumed())
4548 return false;
4549
4550 // If it is not in AssumedLiveBlocks then it for sure dead.
4551 // Otherwise, it can still be after noreturn call in a live block.
4552 if (!AssumedLiveBlocks.count(I->getParent()))
4553 return true;
4554
4555 // If it is not after a liveness barrier it is live.
4556 const Instruction *PrevI = I->getPrevNode();
4557 while (PrevI) {
4558 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4559 return true;
4560 PrevI = PrevI->getPrevNode();
4561 }
4562 return false;
4563 }
4564
4565 bool isKnownDead(const Instruction *I) const override {
4566 return getKnown() && isAssumedDead(I);
4567 }
4568
4569 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
4570 /// that internal function called from \p BB should now be looked at.
4571 bool assumeLive(Attributor &A, const BasicBlock &BB) {
4572 if (!AssumedLiveBlocks.insert(&BB).second)
4573 return false;
4574
4575 if (!A.isDuringDeduction())
4576 return true;
4577
4578 // We assume that all of BB is (probably) live now and if there are calls to
4579 // internal functions we will assume that those are now live as well. This
4580 // is a performance optimization for blocks with calls to a lot of internal
4581 // functions. It can however cause dead functions to be treated as live.
4582 for (const Instruction &I : BB)
4583 if (const auto *CB = dyn_cast<CallBase>(&I))
4585 if (F->hasLocalLinkage()) {
4586 LLVM_DEBUG({
4587 dbgs() << "[AAIsDead] Seeding live internal callee ";
4588 F->printAsOperand(dbgs(), /*PrintType=*/false);
4589 dbgs() << " from ";
4590 BB.getParent()->printAsOperand(dbgs(), /*PrintType=*/false);
4591 dbgs() << "\n";
4592 });
4593 A.markLiveInternalFunction(*F);
4594 }
4595 return true;
4596 }
4597
4598 /// Collection of instructions that need to be explored again, e.g., we
4599 /// did assume they do not transfer control to (one of their) successors.
4600 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4601
4602 /// Collection of instructions that are known to not transfer control.
4603 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4604
4605 /// Collection of all assumed live edges
4606 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4607
4608 /// Collection of all assumed live BasicBlocks.
4609 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4610};
4611
4612static bool
4613identifyAliveSuccessors(Attributor &A, const CallBase &CB,
4614 AbstractAttribute &AA,
4615 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4616 const IRPosition &IPos = IRPosition::callsite_function(CB);
4617
4618 bool IsKnownNoReturn;
4620 A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoReturn))
4621 return !IsKnownNoReturn;
4622 if (CB.isTerminator())
4623 AliveSuccessors.push_back(&CB.getSuccessor(0)->front());
4624 else
4625 AliveSuccessors.push_back(CB.getNextNode());
4626 return false;
4627}
4628
4629static bool
4630identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
4631 AbstractAttribute &AA,
4632 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4633 bool UsedAssumedInformation =
4634 identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);
4635
4636 // First, determine if we can change an invoke to a call assuming the
4637 // callee is nounwind. This is not possible if the personality of the
4638 // function allows to catch asynchronous exceptions.
4639 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {
4640 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4641 } else {
4642 const IRPosition &IPos = IRPosition::callsite_function(II);
4643
4644 bool IsKnownNoUnwind;
4646 A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
4647 UsedAssumedInformation |= !IsKnownNoUnwind;
4648 } else {
4649 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4650 }
4651 }
4652 return UsedAssumedInformation;
4653}
4654
4655static bool
4656identifyAliveSuccessors(Attributor &, const UncondBrInst &BI,
4657 AbstractAttribute &,
4658 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4659 AliveSuccessors.push_back(&BI.getSuccessor()->front());
4660 return false;
4661}
4662
4663static bool
4664identifyAliveSuccessors(Attributor &A, const CondBrInst &BI,
4665 AbstractAttribute &AA,
4666 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4667 bool UsedAssumedInformation = false;
4668 std::optional<Constant *> C =
4669 A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);
4670 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4671 // No value yet, assume both edges are dead.
4672 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4673 const BasicBlock *SuccBB =
4674 BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());
4675 AliveSuccessors.push_back(&SuccBB->front());
4676 } else {
4677 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4678 AliveSuccessors.push_back(&BI.getSuccessor(1)->front());
4679 UsedAssumedInformation = false;
4680 }
4681 return UsedAssumedInformation;
4682}
4683
4684static bool
4685identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
4686 AbstractAttribute &AA,
4687 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4688 bool UsedAssumedInformation = false;
4690 if (!A.getAssumedSimplifiedValues(IRPosition::value(*SI.getCondition()), &AA,
4692 UsedAssumedInformation)) {
4693 // Something went wrong, assume all successors are live.
4694 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4695 AliveSuccessors.push_back(&SuccBB->front());
4696 return false;
4697 }
4698
4699 if (Values.empty() ||
4700 (Values.size() == 1 &&
4701 isa_and_nonnull<UndefValue>(Values.front().getValue()))) {
4702 // No valid value yet, assume all edges are dead.
4703 return UsedAssumedInformation;
4704 }
4705
4706 Type &Ty = *SI.getCondition()->getType();
4707 SmallPtrSet<ConstantInt *, 8> Constants;
4708 auto CheckForConstantInt = [&](Value *V) {
4709 if (auto *CI = dyn_cast_if_present<ConstantInt>(AA::getWithType(*V, Ty))) {
4710 Constants.insert(CI);
4711 return true;
4712 }
4713 return false;
4714 };
4715
4716 if (!all_of(Values, [&](AA::ValueAndContext &VAC) {
4717 return CheckForConstantInt(VAC.getValue());
4718 })) {
4719 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4720 AliveSuccessors.push_back(&SuccBB->front());
4721 return UsedAssumedInformation;
4722 }
4723
4724 unsigned MatchedCases = 0;
4725 for (const auto &CaseIt : SI.cases()) {
4726 if (Constants.count(CaseIt.getCaseValue())) {
4727 ++MatchedCases;
4728 AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());
4729 }
4730 }
4731
4732 // If all potential values have been matched, we will not visit the default
4733 // case.
4734 if (MatchedCases < Constants.size())
4735 AliveSuccessors.push_back(&SI.getDefaultDest()->front());
4736 return UsedAssumedInformation;
4737}
4738
4739ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
4741
4742 if (AssumedLiveBlocks.empty()) {
4743 if (isAssumedDeadInternalFunction(A))
4745
4746 Function *F = getAnchorScope();
4747 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4748 assumeLive(A, F->getEntryBlock());
4749 Change = ChangeStatus::CHANGED;
4750 }
4751
4752 LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"
4753 << getAnchorScope()->size() << "] BBs and "
4754 << ToBeExploredFrom.size() << " exploration points and "
4755 << KnownDeadEnds.size() << " known dead ends\n");
4756
4757 // Copy and clear the list of instructions we need to explore from. It is
4758 // refilled with instructions the next update has to look at.
4759 SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
4760 ToBeExploredFrom.end());
4761 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4762
4764 while (!Worklist.empty()) {
4765 const Instruction *I = Worklist.pop_back_val();
4766 LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n");
4767
4768 // Fast forward for uninteresting instructions. We could look for UB here
4769 // though.
4770 while (!I->isTerminator() && !isa<CallBase>(I))
4771 I = I->getNextNode();
4772
4773 AliveSuccessors.clear();
4774
4775 bool UsedAssumedInformation = false;
4776 switch (I->getOpcode()) {
4777 // TODO: look for (assumed) UB to backwards propagate "deadness".
4778 default:
4779 assert(I->isTerminator() &&
4780 "Expected non-terminators to be handled already!");
4781 for (const BasicBlock *SuccBB : successors(I->getParent()))
4782 AliveSuccessors.push_back(&SuccBB->front());
4783 break;
4784 case Instruction::Call:
4785 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),
4786 *this, AliveSuccessors);
4787 break;
4788 case Instruction::Invoke:
4789 UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),
4790 *this, AliveSuccessors);
4791 break;
4792 case Instruction::UncondBr:
4793 UsedAssumedInformation = identifyAliveSuccessors(
4794 A, cast<UncondBrInst>(*I), *this, AliveSuccessors);
4795 break;
4796 case Instruction::CondBr:
4797 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CondBrInst>(*I),
4798 *this, AliveSuccessors);
4799 break;
4800 case Instruction::Switch:
4801 UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),
4802 *this, AliveSuccessors);
4803 break;
4804 }
4805
4806 if (UsedAssumedInformation) {
4807 NewToBeExploredFrom.insert(I);
4808 } else if (AliveSuccessors.empty() ||
4809 (I->isTerminator() &&
4810 AliveSuccessors.size() < I->getNumSuccessors())) {
4811 if (KnownDeadEnds.insert(I))
4812 Change = ChangeStatus::CHANGED;
4813 }
4814
4815 LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "
4816 << AliveSuccessors.size() << " UsedAssumedInformation: "
4817 << UsedAssumedInformation << "\n");
4818
4819 for (const Instruction *AliveSuccessor : AliveSuccessors) {
4820 if (!I->isTerminator()) {
4821 assert(AliveSuccessors.size() == 1 &&
4822 "Non-terminator expected to have a single successor!");
4823 Worklist.push_back(AliveSuccessor);
4824 } else {
4825 // record the assumed live edge
4826 auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());
4827 if (AssumedLiveEdges.insert(Edge).second)
4828 Change = ChangeStatus::CHANGED;
4829 if (assumeLive(A, *AliveSuccessor->getParent()))
4830 Worklist.push_back(AliveSuccessor);
4831 }
4832 }
4833 }
4834
4835 // Check if the content of ToBeExploredFrom changed, ignore the order.
4836 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4837 llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {
4838 return !ToBeExploredFrom.count(I);
4839 })) {
4840 Change = ChangeStatus::CHANGED;
4841 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4842 }
4843
4844 // If we know everything is live there is no need to query for liveness.
4845 // Instead, indicating a pessimistic fixpoint will cause the state to be
4846 // "invalid" and all queries to be answered conservatively without lookups.
4847 // To be in this state we have to (1) finished the exploration and (3) not
4848 // discovered any non-trivial dead end and (2) not ruled unreachable code
4849 // dead.
4850 if (ToBeExploredFrom.empty() &&
4851 getAnchorScope()->size() == AssumedLiveBlocks.size() &&
4852 llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {
4853 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4854 }))
4855 return indicatePessimisticFixpoint();
4856 return Change;
4857}
4858
4859/// Liveness information for a call sites.
4860struct AAIsDeadCallSite final : AAIsDeadFunction {
4861 AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
4862 : AAIsDeadFunction(IRP, A) {}
4863
4864 void initialize(Attributor &A) override {
4865 // TODO: Once we have call site specific value information we can provide
4866 // call site specific liveness information and then it makes
4867 // sense to specialize attributes for call sites instead of
4868 // redirecting requests to the callee.
4869 llvm_unreachable("Abstract attributes for liveness are not "
4870 "supported for call sites yet!");
4871 }
4872
4873 ChangeStatus updateImpl(Attributor &A) override {
4874 return indicatePessimisticFixpoint();
4875 }
4876
4877 void trackStatistics() const override {}
4878};
4879} // namespace
4880
4881/// -------------------- Dereferenceable Argument Attribute --------------------
4882
4883namespace {
4884struct AADereferenceableImpl : AADereferenceable {
4885 AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
4886 : AADereferenceable(IRP, A) {}
4887 using StateType = DerefState;
4888
4889 void initialize(Attributor &A) override {
4890 Value &V = *getAssociatedValue().stripPointerCasts();
4892 A.getAttrs(getIRPosition(),
4893 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4894 Attrs, /* IgnoreSubsumingPositions */ false);
4895 for (const Attribute &Attr : Attrs)
4896 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4897
4898 // Ensure we initialize the non-null AA (if necessary).
4899 bool IsKnownNonNull;
4901 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
4902
4903 bool CanBeNull;
4904 takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(
4905 A.getDataLayout(), CanBeNull, /*CanBeFreed=*/nullptr));
4906
4907 if (Instruction *CtxI = getCtxI())
4908 followUsesInMBEC(*this, A, getState(), *CtxI);
4909 }
4910
4911 StateType &getState() override { return *this; }
4912 const StateType &getState() const override { return *this; }
4913
4914 /// Helper function for collecting accessed bytes in must-be-executed-context
4915 void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
4916 DerefState &State) {
4917 const Value *UseV = U->get();
4918 if (!UseV->getType()->isPointerTy())
4919 return;
4920
4921 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
4922 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
4923 return;
4924
4925 int64_t Offset;
4927 Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);
4928 if (Base && Base == &getAssociatedValue())
4929 State.addAccessedBytes(Offset, Loc->Size.getValue());
4930 }
4931
4932 /// See followUsesInMBEC
4933 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
4934 AADereferenceable::StateType &State) {
4935 bool IsNonNull = false;
4936 bool TrackUse = false;
4937 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4938 A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);
4939 LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytes
4940 << " for instruction " << *I << "\n");
4941
4942 addAccessedBytesForUse(A, U, I, State);
4943 State.takeKnownDerefBytesMaximum(DerefBytes);
4944 return TrackUse;
4945 }
4946
4947 ChangeStatus manifest(Attributor &A) override {
4948 ChangeStatus Change = AADereferenceable::manifest(A);
4949 bool IsKnownNonNull;
4950 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
4951 A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
4952 if (IsAssumedNonNull &&
4953 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
4954 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
4955 return ChangeStatus::CHANGED;
4956 }
4957 return Change;
4958 }
4959
4960 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
4961 SmallVectorImpl<Attribute> &Attrs) const override {
4962 // TODO: Add *_globally support
4963 bool IsKnownNonNull;
4964 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
4965 A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
4966 if (IsAssumedNonNull)
4967 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
4968 Ctx, getAssumedDereferenceableBytes()));
4969 else
4970 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
4971 Ctx, getAssumedDereferenceableBytes()));
4972 }
4973
4974 const std::string getAsStr(Attributor *A) const override {
4975 if (!getAssumedDereferenceableBytes())
4976 return "unknown-dereferenceable";
4977 bool IsKnownNonNull;
4978 bool IsAssumedNonNull = false;
4979 if (A)
4981 *A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
4982 return std::string("dereferenceable") +
4983 (IsAssumedNonNull ? "" : "_or_null") +
4984 (isAssumedGlobal() ? "_globally" : "") + "<" +
4985 std::to_string(getKnownDereferenceableBytes()) + "-" +
4986 std::to_string(getAssumedDereferenceableBytes()) + ">" +
4987 (!A ? " [non-null is unknown]" : "");
4988 }
4989};
4990
4991/// Dereferenceable attribute for a floating value.
4992struct AADereferenceableFloating : AADereferenceableImpl {
4993 AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
4994 : AADereferenceableImpl(IRP, A) {}
4995
4996 ChangeStatus updateImpl(Attributor &A) override {
4997 bool Stripped;
4998 bool UsedAssumedInformation = false;
5000 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5001 AA::AnyScope, UsedAssumedInformation)) {
5002 Values.push_back({getAssociatedValue(), getCtxI()});
5003 Stripped = false;
5004 } else {
5005 Stripped = Values.size() != 1 ||
5006 Values.front().getValue() != &getAssociatedValue();
5007 }
5008
5009 const DataLayout &DL = A.getDataLayout();
5010 DerefState T;
5011
5012 auto VisitValueCB = [&](const Value &V) -> bool {
5013 unsigned IdxWidth =
5014 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
5015 APInt Offset(IdxWidth, 0);
5017 A, *this, &V, DL, Offset, /* GetMinOffset */ false,
5018 /* AllowNonInbounds */ true);
5019
5020 const auto *AA = A.getAAFor<AADereferenceable>(
5021 *this, IRPosition::value(*Base), DepClassTy::REQUIRED);
5022 int64_t DerefBytes = 0;
5023 if (!AA || (!Stripped && this == AA)) {
5024 // Use IR information if we did not strip anything.
5025 // TODO: track globally.
5026 bool CanBeNull;
5027 DerefBytes = Base->getPointerDereferenceableBytes(
5028 DL, CanBeNull, /*CanBeFreed=*/nullptr);
5029 T.GlobalState.indicatePessimisticFixpoint();
5030 } else {
5031 const DerefState &DS = AA->getState();
5032 DerefBytes = DS.DerefBytesState.getAssumed();
5033 T.GlobalState &= DS.GlobalState;
5034 }
5035
5036 // For now we do not try to "increase" dereferenceability due to negative
5037 // indices as we first have to come up with code to deal with loops and
5038 // for overflows of the dereferenceable bytes.
5039 int64_t OffsetSExt = Offset.getSExtValue();
5040 if (OffsetSExt < 0)
5041 OffsetSExt = 0;
5042
5043 T.takeAssumedDerefBytesMinimum(
5044 std::max(int64_t(0), DerefBytes - OffsetSExt));
5045
5046 if (this == AA) {
5047 if (!Stripped) {
5048 // If nothing was stripped IR information is all we got.
5049 T.takeKnownDerefBytesMaximum(
5050 std::max(int64_t(0), DerefBytes - OffsetSExt));
5051 T.indicatePessimisticFixpoint();
5052 } else if (OffsetSExt > 0) {
5053 // If something was stripped but there is circular reasoning we look
5054 // for the offset. If it is positive we basically decrease the
5055 // dereferenceable bytes in a circular loop now, which will simply
5056 // drive them down to the known value in a very slow way which we
5057 // can accelerate.
5058 T.indicatePessimisticFixpoint();
5059 }
5060 }
5061
5062 return T.isValidState();
5063 };
5064
5065 for (const auto &VAC : Values)
5066 if (!VisitValueCB(*VAC.getValue()))
5067 return indicatePessimisticFixpoint();
5068
5069 return clampStateAndIndicateChange(getState(), T);
5070 }
5071
5072 void trackStatistics() const override {
5073 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
5074 }
5075};
5076
5077/// Dereferenceable attribute for a return value.
5078struct AADereferenceableReturned final
5079 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5080 using Base =
5081 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5082 AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
5083 : Base(IRP, A) {}
5084
5085 void trackStatistics() const override {
5086 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
5087 }
5088};
5089
5090/// Dereferenceable attribute for an argument
5091struct AADereferenceableArgument final
5092 : AAArgumentFromCallSiteArguments<AADereferenceable,
5093 AADereferenceableImpl> {
5094 using Base =
5095 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5096 AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
5097 : Base(IRP, A) {}
5098
5099 void trackStatistics() const override {
5100 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
5101 }
5102};
5103
5104/// Dereferenceable attribute for a call site argument.
5105struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5106 AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
5107 : AADereferenceableFloating(IRP, A) {}
5108
5109 void trackStatistics() const override {
5110 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
5111 }
5112};
5113
5114/// Dereferenceable attribute deduction for a call site return value.
5115struct AADereferenceableCallSiteReturned final
5116 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5117 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5118 AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
5119 : Base(IRP, A) {}
5120
5121 void trackStatistics() const override {
5122 STATS_DECLTRACK_CS_ATTR(dereferenceable);
5123 }
5124};
5125} // namespace
5126
5127// ------------------------ Align Argument Attribute ------------------------
5128
5129namespace {
5130
5131static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
5132 Value &AssociatedValue, const Use *U,
5133 const Instruction *I, bool &TrackUse) {
5134 // We need to follow common pointer manipulation uses to the accesses they
5135 // feed into.
5136 if (isa<CastInst>(I)) {
5137 // Follow all but ptr2int casts.
5138 TrackUse = !isa<PtrToIntInst>(I);
5139 return 0;
5140 }
5141 if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
5142 if (GEP->hasAllConstantIndices())
5143 TrackUse = true;
5144 return 0;
5145 }
5146 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
5147 switch (II->getIntrinsicID()) {
5148 case Intrinsic::ptrmask: {
5149 // Is it appropriate to pull attribute in initialization?
5150 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5151 QueryingAA, IRPosition::value(*II->getOperand(1)), DepClassTy::NONE);
5152 const auto *AlignAA = A.getAAFor<AAAlign>(
5153 QueryingAA, IRPosition::value(*II), DepClassTy::NONE);
5154 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5155 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5157 Align ConstAlign = Align::fromLog2(ShiftValue);
5158 if (ConstAlign >= AlignAA->getKnownAlign())
5159 return Align(1).value();
5160 }
5161 if (AlignAA)
5162 return AlignAA->getKnownAlign().value();
5163 break;
5164 }
5165 case Intrinsic::amdgcn_make_buffer_rsrc: {
5166 const auto *AlignAA = A.getAAFor<AAAlign>(
5167 QueryingAA, IRPosition::value(*II), DepClassTy::NONE);
5168 if (AlignAA)
5169 return AlignAA->getKnownAlign().value();
5170 break;
5171 }
5172 default:
5173 break;
5174 }
5175
5176 MaybeAlign MA;
5177 if (const auto *CB = dyn_cast<CallBase>(I)) {
5178 if (CB->isBundleOperand(U) || CB->isCallee(U))
5179 return 0;
5180
5181 unsigned ArgNo = CB->getArgOperandNo(U);
5182 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
5183 // As long as we only use known information there is no need to track
5184 // dependences here.
5185 auto *AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);
5186 if (AlignAA)
5187 MA = MaybeAlign(AlignAA->getKnownAlign());
5188 }
5189
5190 const DataLayout &DL = A.getDataLayout();
5191 const Value *UseV = U->get();
5192 if (auto *SI = dyn_cast<StoreInst>(I)) {
5193 if (SI->getPointerOperand() == UseV)
5194 MA = SI->getAlign();
5195 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
5196 if (LI->getPointerOperand() == UseV)
5197 MA = LI->getAlign();
5198 } else if (auto *AI = dyn_cast<AtomicRMWInst>(I)) {
5199 if (AI->getPointerOperand() == UseV)
5200 MA = AI->getAlign();
5201 } else if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
5202 if (AI->getPointerOperand() == UseV)
5203 MA = AI->getAlign();
5204 }
5205
5206 if (!MA || *MA <= QueryingAA.getKnownAlign())
5207 return 0;
5208
5209 unsigned Alignment = MA->value();
5210 int64_t Offset;
5211
5212 if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
5213 if (Base == &AssociatedValue) {
5214 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5215 // So we can say that the maximum power of two which is a divisor of
5216 // gcd(Offset, Alignment) is an alignment.
5217
5218 uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);
5220 }
5221 }
5222
5223 return Alignment;
5224}
5225
5226struct AAAlignImpl : AAAlign {
5227 AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}
5228
5229 void initialize(Attributor &A) override {
5231 A.getAttrs(getIRPosition(), {Attribute::Alignment}, Attrs);
5232 for (const Attribute &Attr : Attrs)
5233 takeKnownMaximum(Attr.getValueAsInt());
5234
5235 Value &V = *getAssociatedValue().stripPointerCasts();
5236 takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());
5237
5238 if (Instruction *CtxI = getCtxI())
5239 followUsesInMBEC(*this, A, getState(), *CtxI);
5240 }
5241
5242 ChangeStatus manifest(Attributor &A) override {
5243 ChangeStatus InstrChanged = ChangeStatus::UNCHANGED;
5244
5245 // Check for users that allow alignment annotations.
5246 Value &AssociatedValue = getAssociatedValue();
5247 if (isa<ConstantData>(AssociatedValue))
5248 return ChangeStatus::UNCHANGED;
5249
5250 for (const Use &U : AssociatedValue.uses()) {
5251 if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
5252 if (SI->getPointerOperand() == &AssociatedValue)
5253 if (SI->getAlign() < getAssumedAlign()) {
5254 STATS_DECLTRACK(AAAlign, Store,
5255 "Number of times alignment added to a store");
5256 SI->setAlignment(getAssumedAlign());
5257 InstrChanged = ChangeStatus::CHANGED;
5258 }
5259 } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
5260 if (LI->getPointerOperand() == &AssociatedValue)
5261 if (LI->getAlign() < getAssumedAlign()) {
5262 LI->setAlignment(getAssumedAlign());
5263 STATS_DECLTRACK(AAAlign, Load,
5264 "Number of times alignment added to a load");
5265 InstrChanged = ChangeStatus::CHANGED;
5266 }
5267 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(U.getUser())) {
5268 if (RMW->getPointerOperand() == &AssociatedValue) {
5269 if (RMW->getAlign() < getAssumedAlign()) {
5270 STATS_DECLTRACK(AAAlign, AtomicRMW,
5271 "Number of times alignment added to atomicrmw");
5272
5273 RMW->setAlignment(getAssumedAlign());
5274 InstrChanged = ChangeStatus::CHANGED;
5275 }
5276 }
5277 } else if (auto *CAS = dyn_cast<AtomicCmpXchgInst>(U.getUser())) {
5278 if (CAS->getPointerOperand() == &AssociatedValue) {
5279 if (CAS->getAlign() < getAssumedAlign()) {
5280 STATS_DECLTRACK(AAAlign, AtomicCmpXchg,
5281 "Number of times alignment added to cmpxchg");
5282 CAS->setAlignment(getAssumedAlign());
5283 InstrChanged = ChangeStatus::CHANGED;
5284 }
5285 }
5286 }
5287 }
5288
5289 ChangeStatus Changed = AAAlign::manifest(A);
5290
5291 Align InheritAlign =
5292 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5293 if (InheritAlign >= getAssumedAlign())
5294 return InstrChanged;
5295 return Changed | InstrChanged;
5296 }
5297
5298 // TODO: Provide a helper to determine the implied ABI alignment and check in
5299 // the existing manifest method and a new one for AAAlignImpl that value
5300 // to avoid making the alignment explicit if it did not improve.
5301
5302 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5303 SmallVectorImpl<Attribute> &Attrs) const override {
5304 if (getAssumedAlign() > 1)
5305 Attrs.emplace_back(
5306 Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
5307 }
5308
5309 /// See followUsesInMBEC
5310 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5311 AAAlign::StateType &State) {
5312 bool TrackUse = false;
5313
5314 unsigned int KnownAlign =
5315 getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
5316 State.takeKnownMaximum(KnownAlign);
5317
5318 return TrackUse;
5319 }
5320
5321 const std::string getAsStr(Attributor *A) const override {
5322 return "align<" + std::to_string(getKnownAlign().value()) + "-" +
5323 std::to_string(getAssumedAlign().value()) + ">";
5324 }
5325};
5326
5327/// Align attribute for a floating value.
5328struct AAAlignFloating : AAAlignImpl {
5329 AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}
5330
5331 ChangeStatus updateImpl(Attributor &A) override {
5332 const DataLayout &DL = A.getDataLayout();
5333
5334 bool Stripped;
5335 bool UsedAssumedInformation = false;
5337 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5338 AA::AnyScope, UsedAssumedInformation)) {
5339 Values.push_back({getAssociatedValue(), getCtxI()});
5340 Stripped = false;
5341 } else {
5342 Stripped = Values.size() != 1 ||
5343 Values.front().getValue() != &getAssociatedValue();
5344 }
5345
5346 StateType T;
5347 auto VisitValueCB = [&](Value &V) -> bool {
5349 return true;
5350 const auto *AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),
5351 DepClassTy::REQUIRED);
5352 if (!AA || (!Stripped && this == AA)) {
5353 int64_t Offset;
5354 unsigned Alignment = 1;
5355 if (const Value *Base =
5357 // TODO: Use AAAlign for the base too.
5358 Align PA = Base->getPointerAlignment(DL);
5359 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5360 // So we can say that the maximum power of two which is a divisor of
5361 // gcd(Offset, Alignment) is an alignment.
5362
5363 uint32_t gcd =
5364 std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));
5366 } else {
5367 Alignment = V.getPointerAlignment(DL).value();
5368 }
5369 // Use only IR information if we did not strip anything.
5370 T.takeKnownMaximum(Alignment);
5371 T.indicatePessimisticFixpoint();
5372 } else {
5373 // Use abstract attribute information.
5374 const AAAlign::StateType &DS = AA->getState();
5375 T ^= DS;
5376 }
5377 return T.isValidState();
5378 };
5379
5380 for (const auto &VAC : Values) {
5381 if (!VisitValueCB(*VAC.getValue()))
5382 return indicatePessimisticFixpoint();
5383 }
5384
5385 // TODO: If we know we visited all incoming values, thus no are assumed
5386 // dead, we can take the known information from the state T.
5387 return clampStateAndIndicateChange(getState(), T);
5388 }
5389
5390 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
5391};
5392
5393/// Align attribute for function return value.
5394struct AAAlignReturned final
5395 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5396 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5397 AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5398
5399 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
5400};
5401
5402/// Align attribute for function argument.
5403struct AAAlignArgument final
5404 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5405 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5406 AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5407
5408 ChangeStatus manifest(Attributor &A) override {
5409 // If the associated argument is involved in a must-tail call we give up
5410 // because we would need to keep the argument alignments of caller and
5411 // callee in-sync. Just does not seem worth the trouble right now.
5412 if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5413 return ChangeStatus::UNCHANGED;
5414 return Base::manifest(A);
5415 }
5416
5417 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
5418};
5419
5420struct AAAlignCallSiteArgument final : AAAlignFloating {
5421 AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
5422 : AAAlignFloating(IRP, A) {}
5423
5424 ChangeStatus manifest(Attributor &A) override {
5425 // If the associated argument is involved in a must-tail call we give up
5426 // because we would need to keep the argument alignments of caller and
5427 // callee in-sync. Just does not seem worth the trouble right now.
5428 if (Argument *Arg = getAssociatedArgument())
5429 if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5430 return ChangeStatus::UNCHANGED;
5431 ChangeStatus Changed = AAAlignImpl::manifest(A);
5432 Align InheritAlign =
5433 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5434 if (InheritAlign >= getAssumedAlign())
5435 Changed = ChangeStatus::UNCHANGED;
5436 return Changed;
5437 }
5438
5439 ChangeStatus updateImpl(Attributor &A) override {
5440 ChangeStatus Changed = AAAlignFloating::updateImpl(A);
5441 if (Argument *Arg = getAssociatedArgument()) {
5442 // We only take known information from the argument
5443 // so we do not need to track a dependence.
5444 const auto *ArgAlignAA = A.getAAFor<AAAlign>(
5445 *this, IRPosition::argument(*Arg), DepClassTy::NONE);
5446 if (ArgAlignAA)
5447 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5448 }
5449 return Changed;
5450 }
5451
5452 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
5453};
5454
5455/// Align attribute deduction for a call site return value.
5456struct AAAlignCallSiteReturned final
5457 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5458 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5459 AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
5460 : Base(IRP, A) {}
5461
5462 ChangeStatus updateImpl(Attributor &A) override {
5463 Instruction *I = getIRPosition().getCtxI();
5464 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
5465 switch (II->getIntrinsicID()) {
5466 case Intrinsic::ptrmask: {
5468 bool Valid = false;
5469
5470 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5471 *this, IRPosition::value(*II->getOperand(1)), DepClassTy::REQUIRED);
5472 if (ConstVals && ConstVals->isValidState()) {
5473 unsigned ShiftValue =
5474 std::min(ConstVals->getAssumedMinTrailingZeros(),
5475 Value::MaxAlignmentExponent);
5476 Alignment = Align::fromLog2(ShiftValue);
5477 Valid = true;
5478 }
5479
5480 const auto *AlignAA =
5481 A.getAAFor<AAAlign>(*this, IRPosition::value(*(II->getOperand(0))),
5482 DepClassTy::REQUIRED);
5483 if (AlignAA) {
5484 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5485 Valid = true;
5486 }
5487
5488 if (Valid)
5490 this->getState(),
5491 std::min(this->getAssumedAlign(), Alignment).value());
5492 break;
5493 }
5494 // FIXME: Should introduce target specific sub-attributes and letting
5495 // getAAfor<AAAlign> lead to create sub-attribute to handle target
5496 // specific intrinsics.
5497 case Intrinsic::amdgcn_make_buffer_rsrc: {
5498 const auto *AlignAA =
5499 A.getAAFor<AAAlign>(*this, IRPosition::value(*(II->getOperand(0))),
5500 DepClassTy::REQUIRED);
5501 if (AlignAA)
5503 this->getState(), AlignAA->getAssumedAlign().value());
5504 break;
5505 }
5506 default:
5507 break;
5508 }
5509 }
5510 return Base::updateImpl(A);
5511 };
5512 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
5513};
5514} // namespace
5515
5516/// ------------------ Function No-Return Attribute ----------------------------
5517namespace {
5518struct AANoReturnImpl : public AANoReturn {
5519 AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}
5520
5521 void initialize(Attributor &A) override {
5522 bool IsKnown;
5524 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5525 (void)IsKnown;
5526 }
5527
5528 const std::string getAsStr(Attributor *A) const override {
5529 return getAssumed() ? "noreturn" : "may-return";
5530 }
5531
5532 ChangeStatus updateImpl(Attributor &A) override {
5533 auto CheckForNoReturn = [](Instruction &) { return false; };
5534 bool UsedAssumedInformation = false;
5535 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
5536 {(unsigned)Instruction::Ret},
5537 UsedAssumedInformation))
5538 return indicatePessimisticFixpoint();
5539 return ChangeStatus::UNCHANGED;
5540 }
5541};
5542
5543struct AANoReturnFunction final : AANoReturnImpl {
5544 AANoReturnFunction(const IRPosition &IRP, Attributor &A)
5545 : AANoReturnImpl(IRP, A) {}
5546
5547 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
5548};
5549
5550/// NoReturn attribute deduction for a call sites.
5551struct AANoReturnCallSite final
5552 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5553 AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
5554 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP, A) {}
5555
5556 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
5557};
5558} // namespace
5559
5560/// ----------------------- Instance Info ---------------------------------
5561
5562namespace {
5563/// A class to hold the state of for no-capture attributes.
5564struct AAInstanceInfoImpl : public AAInstanceInfo {
5565 AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
5566 : AAInstanceInfo(IRP, A) {}
5567
5568 void initialize(Attributor &A) override {
5569 Value &V = getAssociatedValue();
5570 if (auto *C = dyn_cast<Constant>(&V)) {
5571 if (C->isThreadDependent())
5572 indicatePessimisticFixpoint();
5573 else
5574 indicateOptimisticFixpoint();
5575 return;
5576 }
5577 if (auto *CB = dyn_cast<CallBase>(&V))
5578 if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
5579 !CB->mayReadFromMemory()) {
5580 indicateOptimisticFixpoint();
5581 return;
5582 }
5583 if (auto *I = dyn_cast<Instruction>(&V)) {
5584 const auto *CI =
5585 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5586 *I->getFunction());
5587 if (mayBeInCycle(CI, I, /* HeaderOnly */ false)) {
5588 indicatePessimisticFixpoint();
5589 return;
5590 }
5591 }
5592 }
5593
5594 ChangeStatus updateImpl(Attributor &A) override {
5595 ChangeStatus Changed = ChangeStatus::UNCHANGED;
5596
5597 Value &V = getAssociatedValue();
5598 const Function *Scope = nullptr;
5599 if (auto *I = dyn_cast<Instruction>(&V))
5600 Scope = I->getFunction();
5601 if (auto *A = dyn_cast<Argument>(&V)) {
5602 Scope = A->getParent();
5603 if (!Scope->hasLocalLinkage())
5604 return Changed;
5605 }
5606 if (!Scope)
5607 return indicateOptimisticFixpoint();
5608
5609 bool IsKnownNoRecurse;
5611 A, this, IRPosition::function(*Scope), DepClassTy::OPTIONAL,
5612 IsKnownNoRecurse))
5613 return Changed;
5614
5615 auto UsePred = [&](const Use &U, bool &Follow) {
5616 const Instruction *UserI = dyn_cast<Instruction>(U.getUser());
5617 if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||
5618 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
5619 Follow = true;
5620 return true;
5621 }
5622 if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||
5623 (isa<StoreInst>(UserI) &&
5624 cast<StoreInst>(UserI)->getValueOperand() != U.get()))
5625 return true;
5626 if (auto *CB = dyn_cast<CallBase>(UserI)) {
5627 // This check is not guaranteeing uniqueness but for now that we cannot
5628 // end up with two versions of \p U thinking it was one.
5630 if (!Callee || !Callee->hasLocalLinkage())
5631 return true;
5632 if (!CB->isArgOperand(&U))
5633 return false;
5634 const auto *ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
5636 DepClassTy::OPTIONAL);
5637 if (!ArgInstanceInfoAA ||
5638 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5639 return false;
5640 // If this call base might reach the scope again we might forward the
5641 // argument back here. This is very conservative.
5643 A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,
5644 [Scope](const Function &Fn) { return &Fn != Scope; }))
5645 return false;
5646 return true;
5647 }
5648 return false;
5649 };
5650
5651 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
5652 if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {
5653 auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
5654 if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&
5655 AA::isDynamicallyUnique(A, *this, *Ptr))
5656 return true;
5657 }
5658 return false;
5659 };
5660
5661 if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,
5662 DepClassTy::OPTIONAL,
5663 /* IgnoreDroppableUses */ true, EquivalentUseCB))
5664 return indicatePessimisticFixpoint();
5665
5666 return Changed;
5667 }
5668
5669 const std::string getAsStr(Attributor *A) const override {
5670 return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
5671 }
5672
5673 void trackStatistics() const override {}
5674};
5675
5676/// InstanceInfo attribute for floating values.
5677struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5678 AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
5679 : AAInstanceInfoImpl(IRP, A) {}
5680};
5681
5682/// NoCapture attribute for function arguments.
5683struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5684 AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
5685 : AAInstanceInfoFloating(IRP, A) {}
5686};
5687
5688/// InstanceInfo attribute for call site arguments.
5689struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5690 AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
5691 : AAInstanceInfoImpl(IRP, A) {}
5692
5693 ChangeStatus updateImpl(Attributor &A) override {
5694 // TODO: Once we have call site specific value information we can provide
5695 // call site specific liveness information and then it makes
5696 // sense to specialize attributes for call sites arguments instead of
5697 // redirecting requests to the callee argument.
5698 Argument *Arg = getAssociatedArgument();
5699 if (!Arg)
5700 return indicatePessimisticFixpoint();
5701 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5702 auto *ArgAA =
5703 A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);
5704 if (!ArgAA)
5705 return indicatePessimisticFixpoint();
5706 return clampStateAndIndicateChange(getState(), ArgAA->getState());
5707 }
5708};
5709
5710/// InstanceInfo attribute for function return value.
5711struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5712 AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
5713 : AAInstanceInfoImpl(IRP, A) {
5714 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5715 }
5716
5717 void initialize(Attributor &A) override {
5718 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5719 }
5720
5721 ChangeStatus updateImpl(Attributor &A) override {
5722 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5723 }
5724};
5725
5726/// InstanceInfo attribute deduction for a call site return value.
5727struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5728 AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
5729 : AAInstanceInfoFloating(IRP, A) {}
5730};
5731} // namespace
5732
5733/// ----------------------- Variable Capturing ---------------------------------
5735 Attribute::AttrKind ImpliedAttributeKind,
5736 bool IgnoreSubsumingPositions) {
5737 assert(ImpliedAttributeKind == Attribute::Captures &&
5738 "Unexpected attribute kind");
5739 Value &V = IRP.getAssociatedValue();
5740 if (!isa<Constant>(V) && !IRP.isArgumentPosition())
5741 return V.use_empty();
5742
5743 // You cannot "capture" null if it is not a valid pointer.
5744 if (isa<UndefValue>(V) ||
5748 return true;
5749 }
5750
5752 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5753 /* IgnoreSubsumingPositions */ true);
5754 for (const Attribute &Attr : Attrs)
5755 if (capturesNothing(Attr.getCaptureInfo()))
5756 return true;
5757
5759 if (Argument *Arg = IRP.getAssociatedArgument()) {
5761 A.getAttrs(IRPosition::argument(*Arg),
5762 {Attribute::Captures, Attribute::ByVal}, Attrs,
5763 /* IgnoreSubsumingPositions */ true);
5764 bool ArgNoCapture = any_of(Attrs, [](Attribute Attr) {
5765 return Attr.getKindAsEnum() == Attribute::ByVal ||
5767 });
5768 if (ArgNoCapture) {
5769 A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(
5770 V.getContext(), CaptureInfo::none()));
5771 return true;
5772 }
5773 }
5774
5775 if (const Function *F = IRP.getAssociatedFunction()) {
5776 // Check what state the associated function can actually capture.
5779 if (State.isKnown(NO_CAPTURE)) {
5780 A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(V.getContext(),
5782 return true;
5783 }
5784 }
5785
5786 return false;
5787}
5788
5789/// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
5790/// depending on the ability of the function associated with \p IRP to capture
5791/// state in memory and through "returning/throwing", respectively.
5793 const Function &F,
5794 BitIntegerState &State) {
5795 // TODO: Once we have memory behavior attributes we should use them here.
5796
5797 // If we know we cannot communicate or write to memory, we do not care about
5798 // ptr2int anymore. The value can still be captured by whether the function
5799 // returns.
5800 bool ReadOnly = F.onlyReadsMemory();
5801 bool NoThrow = F.doesNotThrow();
5802 bool WillReturn = F.willReturn();
5803 bool IsVoidReturn = F.getReturnType()->isVoidTy();
5804 if (ReadOnly && NoThrow && WillReturn && IsVoidReturn) {
5805 State.addKnownBits(NO_CAPTURE);
5806 return;
5807 }
5808
5809 // A function cannot capture state in memory if it only reads memory, it can
5810 // however return/throw state and the state might be influenced by the
5811 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5812 if (ReadOnly)
5813 State.addKnownBits(NOT_CAPTURED_IN_MEM);
5814
5815 // A function cannot communicate state back if it does not through
5816 // exceptions and doesn not return values.
5817 if (NoThrow && IsVoidReturn)
5818 State.addKnownBits(NOT_CAPTURED_IN_RET);
5819
5820 // Check existing "returned" attributes.
5821 int ArgNo = IRP.getCalleeArgNo();
5822 if (!NoThrow || ArgNo < 0 ||
5823 !F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5824 return;
5825
5826 for (unsigned U = 0, E = F.arg_size(); U < E; ++U)
5827 if (F.hasParamAttribute(U, Attribute::Returned)) {
5828 if (U == unsigned(ArgNo))
5829 State.removeAssumedBits(NOT_CAPTURED_IN_RET);
5830 else if (ReadOnly && WillReturn)
5831 State.addKnownBits(NO_CAPTURE);
5832 else
5833 State.addKnownBits(NOT_CAPTURED_IN_RET);
5834 break;
5835 }
5836}
5837
5838namespace {
5839/// A class to hold the state of for no-capture attributes.
5840struct AANoCaptureImpl : public AANoCapture {
5841 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5842
5843 void initialize(Attributor &A) override {
5844 bool IsKnown;
5846 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5847 (void)IsKnown;
5848 }
5849
5850 ChangeStatus updateImpl(Attributor &A) override;
5851
5852 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5853 SmallVectorImpl<Attribute> &Attrs) const override {
5854 if (!isAssumedNoCaptureMaybeReturned())
5855 return;
5856
5857 if (isArgumentPosition()) {
5858 if (isAssumedNoCapture())
5859 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
5860 else if (ManifestInternal)
5861 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
5862 }
5863 }
5864
5865 const std::string getAsStr(Attributor *A) const override {
5866 if (isKnownNoCapture())
5867 return "known not-captured";
5868 if (isAssumedNoCapture())
5869 return "assumed not-captured";
5870 if (isKnownNoCaptureMaybeReturned())
5871 return "known not-captured-maybe-returned";
5872 if (isAssumedNoCaptureMaybeReturned())
5873 return "assumed not-captured-maybe-returned";
5874 return "assumed-captured";
5875 }
5876
5877 /// Check the use \p U and update \p State accordingly. Return true if we
5878 /// should continue to update the state.
5879 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
5880 bool &Follow) {
5881 Instruction *UInst = cast<Instruction>(U.getUser());
5882 LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "
5883 << *UInst << "\n");
5884
5885 // Deal with ptr2int by following uses.
5886 if (isa<PtrToIntInst>(UInst)) {
5887 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
5888 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5889 /* Return */ true);
5890 }
5891
5892 // For stores we already checked if we can follow them, if they make it
5893 // here we give up.
5894 if (isa<StoreInst>(UInst))
5895 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5896 /* Return */ true);
5897
5898 // Explicitly catch return instructions.
5899 if (isa<ReturnInst>(UInst)) {
5900 if (UInst->getFunction() == getAnchorScope())
5901 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5902 /* Return */ true);
5903 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5904 /* Return */ true);
5905 }
5906
5907 // For now we only use special logic for call sites. However, the tracker
5908 // itself knows about a lot of other non-capturing cases already.
5909 auto *CB = dyn_cast<CallBase>(UInst);
5910 if (!CB || !CB->isArgOperand(&U))
5911 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5912 /* Return */ true);
5913
5914 unsigned ArgNo = CB->getArgOperandNo(&U);
5915 const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
5916 // If we have a abstract no-capture attribute for the argument we can use
5917 // it to justify a non-capture attribute here. This allows recursion!
5918 bool IsKnownNoCapture;
5919 const AANoCapture *ArgNoCaptureAA = nullptr;
5920 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
5921 A, this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
5922 &ArgNoCaptureAA);
5923 if (IsAssumedNoCapture)
5924 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5925 /* Return */ false);
5926 if (ArgNoCaptureAA && ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
5927 Follow = true;
5928 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5929 /* Return */ false);
5930 }
5931
5932 // Lastly, we could not find a reason no-capture can be assumed so we don't.
5933 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5934 /* Return */ true);
5935 }
5936
5937 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
5938 /// \p CapturedInRet, then return true if we should continue updating the
5939 /// state.
5940 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
5941 bool CapturedInInt, bool CapturedInRet) {
5942 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
5943 << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
5944 if (CapturedInMem)
5945 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
5946 if (CapturedInInt)
5947 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
5948 if (CapturedInRet)
5949 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
5950 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
5951 }
5952};
5953
5954ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
5955 const IRPosition &IRP = getIRPosition();
5956 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
5957 : &IRP.getAssociatedValue();
5958 if (!V)
5959 return indicatePessimisticFixpoint();
5960
5961 const Function *F =
5962 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
5963
5964 // TODO: Is the checkForAllUses below useful for constants?
5965 if (!F)
5966 return indicatePessimisticFixpoint();
5967
5969 const IRPosition &FnPos = IRPosition::function(*F);
5970
5971 // Readonly means we cannot capture through memory.
5972 bool IsKnown;
5973 if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
5974 T.addKnownBits(NOT_CAPTURED_IN_MEM);
5975 if (IsKnown)
5976 addKnownBits(NOT_CAPTURED_IN_MEM);
5977 }
5978
5979 // Make sure all returned values are different than the underlying value.
5980 // TODO: we could do this in a more sophisticated way inside
5981 // AAReturnedValues, e.g., track all values that escape through returns
5982 // directly somehow.
5983 auto CheckReturnedArgs = [&](bool &UsedAssumedInformation) {
5985 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*F), this, Values,
5987 UsedAssumedInformation))
5988 return false;
5989 bool SeenConstant = false;
5990 for (const AA::ValueAndContext &VAC : Values) {
5991 if (isa<Constant>(VAC.getValue())) {
5992 if (SeenConstant)
5993 return false;
5994 SeenConstant = true;
5995 } else if (!isa<Argument>(VAC.getValue()) ||
5996 VAC.getValue() == getAssociatedArgument())
5997 return false;
5998 }
5999 return true;
6000 };
6001
6002 bool IsKnownNoUnwind;
6004 A, this, FnPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
6005 bool IsVoidTy = F->getReturnType()->isVoidTy();
6006 bool UsedAssumedInformation = false;
6007 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6008 T.addKnownBits(NOT_CAPTURED_IN_RET);
6009 // If the function only reads memory and does not return the value, the
6010 // value can still be captured by whether the function returns.
6011 bool IsKnownWillReturn;
6012 bool IsAssumedWillReturn = AA::hasAssumedIRAttr<Attribute::WillReturn>(
6013 A, this, FnPos, DepClassTy::OPTIONAL, IsKnownWillReturn);
6014 if (IsAssumedWillReturn && T.isKnown(NOT_CAPTURED_IN_MEM))
6016 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6017 addKnownBits(NOT_CAPTURED_IN_RET);
6018 if (IsKnownWillReturn && isKnown(NOT_CAPTURED_IN_MEM))
6019 return indicateOptimisticFixpoint();
6020 }
6021 }
6022 }
6023
6024 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
6025 // TODO(captures): Make this more precise.
6026 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
6027 if (capturesNothing(CI))
6028 return true;
6029 if (CI.isPassthrough()) {
6030 Follow = true;
6031 return true;
6032 }
6033 return checkUse(A, T, U, Follow);
6034 };
6035
6036 if (!A.checkForAllUses(UseCheck, *this, *V))
6037 return indicatePessimisticFixpoint();
6038
6039 AANoCapture::StateType &S = getState();
6040 auto Assumed = S.getAssumed();
6041 S.intersectAssumedBits(T.getAssumed());
6042 if (!isAssumedNoCaptureMaybeReturned())
6043 return indicatePessimisticFixpoint();
6044 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
6046}
6047
6048/// NoCapture attribute for function arguments.
6049struct AANoCaptureArgument final : AANoCaptureImpl {
6050 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
6051 : AANoCaptureImpl(IRP, A) {}
6052
6053 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
6054};
6055
6056/// NoCapture attribute for call site arguments.
6057struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6058 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
6059 : AANoCaptureImpl(IRP, A) {}
6060
6061 ChangeStatus updateImpl(Attributor &A) override {
6062 // TODO: Once we have call site specific value information we can provide
6063 // call site specific liveness information and then it makes
6064 // sense to specialize attributes for call sites arguments instead of
6065 // redirecting requests to the callee argument.
6066 Argument *Arg = getAssociatedArgument();
6067 if (!Arg)
6068 return indicatePessimisticFixpoint();
6069 const IRPosition &ArgPos = IRPosition::argument(*Arg);
6070 bool IsKnownNoCapture;
6071 const AANoCapture *ArgAA = nullptr;
6073 A, this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
6074 &ArgAA))
6075 return ChangeStatus::UNCHANGED;
6076 if (!ArgAA || !ArgAA->isAssumedNoCaptureMaybeReturned())
6077 return indicatePessimisticFixpoint();
6078 return clampStateAndIndicateChange(getState(), ArgAA->getState());
6079 }
6080
6081 void trackStatistics() const override {
6083 };
6084};
6085
6086/// NoCapture attribute for floating values.
6087struct AANoCaptureFloating final : AANoCaptureImpl {
6088 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
6089 : AANoCaptureImpl(IRP, A) {}
6090
6091 void trackStatistics() const override {
6093 }
6094};
6095
6096/// NoCapture attribute for function return value.
6097struct AANoCaptureReturned final : AANoCaptureImpl {
6098 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
6099 : AANoCaptureImpl(IRP, A) {
6100 llvm_unreachable("NoCapture is not applicable to function returns!");
6101 }
6102
6103 void initialize(Attributor &A) override {
6104 llvm_unreachable("NoCapture is not applicable to function returns!");
6105 }
6106
6107 ChangeStatus updateImpl(Attributor &A) override {
6108 llvm_unreachable("NoCapture is not applicable to function returns!");
6109 }
6110
6111 void trackStatistics() const override {}
6112};
6113
6114/// NoCapture attribute deduction for a call site return value.
6115struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6116 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
6117 : AANoCaptureImpl(IRP, A) {}
6118
6119 void initialize(Attributor &A) override {
6120 const Function *F = getAnchorScope();
6121 // Check what state the associated function can actually capture.
6122 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
6123 }
6124
6125 void trackStatistics() const override {
6127 }
6128};
6129} // namespace
6130
6131/// ------------------ Value Simplify Attribute ----------------------------
6132
6133bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6134 // FIXME: Add a typecast support.
6137 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6138 return false;
6139
6140 LLVM_DEBUG({
6142 dbgs() << "[ValueSimplify] is assumed to be "
6143 << **SimplifiedAssociatedValue << "\n";
6144 else
6145 dbgs() << "[ValueSimplify] is assumed to be <none>\n";
6146 });
6147 return true;
6148}
6149
6150namespace {
6151struct AAValueSimplifyImpl : AAValueSimplify {
6152 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6153 : AAValueSimplify(IRP, A) {}
6154
6155 void initialize(Attributor &A) override {
6156 if (getAssociatedValue().getType()->isVoidTy())
6157 indicatePessimisticFixpoint();
6158 if (A.hasSimplificationCallback(getIRPosition()))
6159 indicatePessimisticFixpoint();
6160 }
6161
6162 const std::string getAsStr(Attributor *A) const override {
6163 LLVM_DEBUG({
6164 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";
6165 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6166 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";
6167 });
6168 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6169 : "not-simple";
6170 }
6171
6172 void trackStatistics() const override {}
6173
6174 std::optional<Value *>
6175 getAssumedSimplifiedValue(Attributor &A) const override {
6176 return SimplifiedAssociatedValue;
6177 }
6178
6179 /// Ensure the return value is \p V with type \p Ty, if not possible return
6180 /// nullptr. If \p Check is true we will only verify such an operation would
6181 /// suceed and return a non-nullptr value if that is the case. No IR is
6182 /// generated or modified.
6183 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6184 bool Check) {
6185 if (auto *TypedV = AA::getWithType(V, Ty))
6186 return TypedV;
6187 if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
6188 return Check ? &V
6189 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6190 &V, &Ty, "", CtxI->getIterator());
6191 return nullptr;
6192 }
6193
6194 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6195 /// If \p Check is true we will only verify such an operation would suceed and
6196 /// return a non-nullptr value if that is the case. No IR is generated or
6197 /// modified.
6198 static Value *reproduceInst(Attributor &A,
6199 const AbstractAttribute &QueryingAA,
6200 Instruction &I, Type &Ty, Instruction *CtxI,
6201 bool Check, ValueToValueMapTy &VMap) {
6202 assert(CtxI && "Cannot reproduce an instruction without context!");
6203 if (Check && (I.mayReadFromMemory() ||
6204 !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
6205 /* TLI */ nullptr)))
6206 return nullptr;
6207 for (Value *Op : I.operands()) {
6208 Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
6209 if (!NewOp) {
6210 assert(Check && "Manifest of new value unexpectedly failed!");
6211 return nullptr;
6212 }
6213 if (!Check)
6214 VMap[Op] = NewOp;
6215 }
6216 if (Check)
6217 return &I;
6218
6219 Instruction *CloneI = I.clone();
6220 // TODO: Try to salvage debug information here.
6221 CloneI->setDebugLoc(DebugLoc());
6222 VMap[&I] = CloneI;
6223 CloneI->insertBefore(CtxI->getIterator());
6224 RemapInstruction(CloneI, VMap);
6225 return CloneI;
6226 }
6227
6228 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6229 /// If \p Check is true we will only verify such an operation would suceed and
6230 /// return a non-nullptr value if that is the case. No IR is generated or
6231 /// modified.
6232 static Value *reproduceValue(Attributor &A,
6233 const AbstractAttribute &QueryingAA, Value &V,
6234 Type &Ty, Instruction *CtxI, bool Check,
6235 ValueToValueMapTy &VMap) {
6236 if (const auto &NewV = VMap.lookup(&V))
6237 return NewV;
6238 bool UsedAssumedInformation = false;
6239 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6240 V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6241 if (!SimpleV.has_value())
6242 return PoisonValue::get(&Ty);
6243 Value *EffectiveV = &V;
6244 if (*SimpleV)
6245 EffectiveV = *SimpleV;
6246 if (auto *C = dyn_cast<Constant>(EffectiveV))
6247 return C;
6248 if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
6249 A.getInfoCache()))
6250 return ensureType(A, *EffectiveV, Ty, CtxI, Check);
6251 if (auto *I = dyn_cast<Instruction>(EffectiveV))
6252 if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
6253 return ensureType(A, *NewV, Ty, CtxI, Check);
6254 return nullptr;
6255 }
6256
6257 /// Return a value we can use as replacement for the associated one, or
6258 /// nullptr if we don't have one that makes sense.
6259 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6260 Value *NewV = SimplifiedAssociatedValue
6261 ? *SimplifiedAssociatedValue
6262 : UndefValue::get(getAssociatedType());
6263 if (NewV && NewV != &getAssociatedValue()) {
6264 ValueToValueMapTy VMap;
6265 // First verify we can reprduce the value with the required type at the
6266 // context location before we actually start modifying the IR.
6267 if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6268 /* CheckOnly */ true, VMap))
6269 return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6270 /* CheckOnly */ false, VMap);
6271 }
6272 return nullptr;
6273 }
6274
6275 /// Helper function for querying AAValueSimplify and updating candidate.
6276 /// \param IRP The value position we are trying to unify with SimplifiedValue
6277 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6278 const IRPosition &IRP, bool Simplify = true) {
6279 bool UsedAssumedInformation = false;
6280 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6281 if (Simplify)
6282 QueryingValueSimplified = A.getAssumedSimplified(
6283 IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6284 return unionAssumed(QueryingValueSimplified);
6285 }
6286
6287 /// Returns a candidate is found or not
6288 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6289 if (!getAssociatedValue().getType()->isIntegerTy())
6290 return false;
6291
6292 // This will also pass the call base context.
6293 const auto *AA =
6294 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6295 if (!AA)
6296 return false;
6297
6298 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
6299
6300 if (!COpt) {
6301 SimplifiedAssociatedValue = std::nullopt;
6302 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6303 return true;
6304 }
6305 if (auto *C = *COpt) {
6306 SimplifiedAssociatedValue = C;
6307 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6308 return true;
6309 }
6310 return false;
6311 }
6312
6313 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6314 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6315 return true;
6316 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6317 return true;
6318 return false;
6319 }
6320
6321 ChangeStatus manifest(Attributor &A) override {
6322 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6323 for (auto &U : getAssociatedValue().uses()) {
6324 // Check if we need to adjust the insertion point to make sure the IR is
6325 // valid.
6326 Instruction *IP = dyn_cast<Instruction>(U.getUser());
6327 if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
6328 IP = PHI->getIncomingBlock(U)->getTerminator();
6329 if (auto *NewV = manifestReplacementValue(A, IP)) {
6330 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()
6331 << " -> " << *NewV << " :: " << *this << "\n");
6332 if (A.changeUseAfterManifest(U, *NewV))
6333 Changed = ChangeStatus::CHANGED;
6334 }
6335 }
6336
6337 return Changed | AAValueSimplify::manifest(A);
6338 }
6339
6340 ChangeStatus indicatePessimisticFixpoint() override {
6341 SimplifiedAssociatedValue = &getAssociatedValue();
6342 return AAValueSimplify::indicatePessimisticFixpoint();
6343 }
6344};
6345
6346struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6347 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6348 : AAValueSimplifyImpl(IRP, A) {}
6349
6350 void initialize(Attributor &A) override {
6351 AAValueSimplifyImpl::initialize(A);
6352 if (A.hasAttr(getIRPosition(),
6353 {Attribute::InAlloca, Attribute::Preallocated,
6354 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6355 /* IgnoreSubsumingPositions */ true))
6356 indicatePessimisticFixpoint();
6357 }
6358
6359 ChangeStatus updateImpl(Attributor &A) override {
6360 // Byval is only replacable if it is readonly otherwise we would write into
6361 // the replaced value and not the copy that byval creates implicitly.
6362 Argument *Arg = getAssociatedArgument();
6363 if (Arg->hasByValAttr()) {
6364 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6365 // there is no race by not copying a constant byval.
6366 bool IsKnown;
6367 if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
6368 return indicatePessimisticFixpoint();
6369 }
6370
6371 auto Before = SimplifiedAssociatedValue;
6372
6373 auto PredForCallSite = [&](AbstractCallSite ACS) {
6374 const IRPosition &ACSArgPos =
6375 IRPosition::callsite_argument(ACS, getCallSiteArgNo());
6376 // Check if a coresponding argument was found or if it is on not
6377 // associated (which can happen for callback calls).
6378 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6379 return false;
6380
6381 // Simplify the argument operand explicitly and check if the result is
6382 // valid in the current scope. This avoids refering to simplified values
6383 // in other functions, e.g., we don't want to say a an argument in a
6384 // static function is actually an argument in a different function.
6385 bool UsedAssumedInformation = false;
6386 std::optional<Constant *> SimpleArgOp =
6387 A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
6388 if (!SimpleArgOp)
6389 return true;
6390 if (!*SimpleArgOp)
6391 return false;
6392 if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
6393 return false;
6394 return unionAssumed(*SimpleArgOp);
6395 };
6396
6397 // Generate a answer specific to a call site context.
6398 bool Success;
6399 bool UsedAssumedInformation = false;
6400 if (hasCallBaseContext() &&
6401 getCallBaseContext()->getCalledOperand() == Arg->getParent())
6402 Success = PredForCallSite(
6403 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6404 else
6405 Success = A.checkForAllCallSites(PredForCallSite, *this, true,
6406 UsedAssumedInformation);
6407
6408 if (!Success)
6409 if (!askSimplifiedValueForOtherAAs(A))
6410 return indicatePessimisticFixpoint();
6411
6412 // If a candidate was found in this update, return CHANGED.
6413 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6414 : ChangeStatus ::CHANGED;
6415 }
6416
6417 void trackStatistics() const override {
6418 STATS_DECLTRACK_ARG_ATTR(value_simplify)
6419 }
6420};
6421
6422struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6423 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6424 : AAValueSimplifyImpl(IRP, A) {}
6425
6426 std::optional<Value *>
6427 getAssumedSimplifiedValue(Attributor &A) const override {
6428 if (!isValidState())
6429 return nullptr;
6430 return SimplifiedAssociatedValue;
6431 }
6432
6433 ChangeStatus updateImpl(Attributor &A) override {
6434 auto Before = SimplifiedAssociatedValue;
6435
6436 auto ReturnInstCB = [&](Instruction &I) {
6437 auto &RI = cast<ReturnInst>(I);
6438 return checkAndUpdate(
6439 A, *this,
6440 IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
6441 };
6442
6443 bool UsedAssumedInformation = false;
6444 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
6445 UsedAssumedInformation))
6446 if (!askSimplifiedValueForOtherAAs(A))
6447 return indicatePessimisticFixpoint();
6448
6449 // If a candidate was found in this update, return CHANGED.
6450 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6451 : ChangeStatus ::CHANGED;
6452 }
6453
6454 ChangeStatus manifest(Attributor &A) override {
6455 // We queried AAValueSimplify for the returned values so they will be
6456 // replaced if a simplified form was found. Nothing to do here.
6457 return ChangeStatus::UNCHANGED;
6458 }
6459
6460 void trackStatistics() const override {
6461 STATS_DECLTRACK_FNRET_ATTR(value_simplify)
6462 }
6463};
6464
6465struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6466 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6467 : AAValueSimplifyImpl(IRP, A) {}
6468
6469 void initialize(Attributor &A) override {
6470 AAValueSimplifyImpl::initialize(A);
6471 Value &V = getAnchorValue();
6472
6473 // TODO: add other stuffs
6474 if (isa<Constant>(V))
6475 indicatePessimisticFixpoint();
6476 }
6477
6478 ChangeStatus updateImpl(Attributor &A) override {
6479 auto Before = SimplifiedAssociatedValue;
6480 if (!askSimplifiedValueForOtherAAs(A))
6481 return indicatePessimisticFixpoint();
6482
6483 // If a candidate was found in this update, return CHANGED.
6484 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6485 : ChangeStatus ::CHANGED;
6486 }
6487
6488 void trackStatistics() const override {
6489 STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
6490 }
6491};
6492
6493struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6494 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6495 : AAValueSimplifyImpl(IRP, A) {}
6496
6497 void initialize(Attributor &A) override {
6498 SimplifiedAssociatedValue = nullptr;
6499 indicateOptimisticFixpoint();
6500 }
6501 ChangeStatus updateImpl(Attributor &A) override {
6503 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6504 }
6505 void trackStatistics() const override {
6506 STATS_DECLTRACK_FN_ATTR(value_simplify)
6507 }
6508};
6509
6510struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6511 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6512 : AAValueSimplifyFunction(IRP, A) {}
6513 void trackStatistics() const override {
6514 STATS_DECLTRACK_CS_ATTR(value_simplify)
6515 }
6516};
6517
6518struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6519 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6520 : AAValueSimplifyImpl(IRP, A) {}
6521
6522 void initialize(Attributor &A) override {
6523 AAValueSimplifyImpl::initialize(A);
6524 Function *Fn = getAssociatedFunction();
6525 assert(Fn && "Did expect an associted function");
6526 for (Argument &Arg : Fn->args()) {
6527 if (Arg.hasReturnedAttr()) {
6528 auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
6529 Arg.getArgNo());
6531 checkAndUpdate(A, *this, IRP))
6532 indicateOptimisticFixpoint();
6533 else
6534 indicatePessimisticFixpoint();
6535 return;
6536 }
6537 }
6538 }
6539
6540 ChangeStatus updateImpl(Attributor &A) override {
6541 return indicatePessimisticFixpoint();
6542 }
6543
6544 void trackStatistics() const override {
6545 STATS_DECLTRACK_CSRET_ATTR(value_simplify)
6546 }
6547};
6548
6549struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6550 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6551 : AAValueSimplifyFloating(IRP, A) {}
6552
6553 ChangeStatus manifest(Attributor &A) override {
6554 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6555 // TODO: We should avoid simplification duplication to begin with.
6556 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6557 IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
6558 if (FloatAA && FloatAA->getState().isValidState())
6559 return Changed;
6560
6561 if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
6562 Use &U = cast<CallBase>(&getAnchorValue())
6563 ->getArgOperandUse(getCallSiteArgNo());
6564 if (A.changeUseAfterManifest(U, *NewV))
6565 Changed = ChangeStatus::CHANGED;
6566 }
6567
6568 return Changed | AAValueSimplify::manifest(A);
6569 }
6570
6571 void trackStatistics() const override {
6572 STATS_DECLTRACK_CSARG_ATTR(value_simplify)
6573 }
6574};
6575} // namespace
6576
6577/// Collect the non-musttail tail calls in the function of \p QueryingAA. Tail
6578/// calls cannot access allocas of the caller.
6579/// TODO: Be smarter about new allocas escaping into tail calls.
6580static bool collectTailCalls(Attributor &A, const AbstractAttribute &QueryingAA,
6581 SmallVectorImpl<CallInst *> &TailCalls) {
6582 bool UsedAssumedInformation = false;
6583 return A.checkForAllInstructions(
6584 [&](Instruction &I) {
6585 auto &CI = cast<CallInst>(I);
6586 if (CI.isTailCall() && !CI.isMustTailCall())
6587 TailCalls.push_back(&CI);
6588 return true;
6589 },
6590 QueryingAA, {Instruction::Call}, UsedAssumedInformation);
6591}
6592
6593/// ----------------------- Heap-To-Stack Conversion ---------------------------
6594namespace {
6595struct AAHeapToStackFunction final : public AAHeapToStack {
6596
6597 static bool isGlobalizedLocal(const CallBase &CB) {
6598 Attribute A = CB.getFnAttr("alloc-family");
6599 return A.isValid() && A.getValueAsString() == "__kmpc_alloc_shared";
6600 }
6601
6602 struct AllocationInfo {
6603 /// The call that allocates the memory.
6604 CallBase *const CB;
6605
6606 /// Whether this allocation is an OpenMP globalized local variable.
6607 bool IsGlobalizedLocal = false;
6608
6609 /// The status wrt. a rewrite.
6610 enum {
6611 STACK_DUE_TO_USE,
6612 STACK_DUE_TO_FREE,
6613 INVALID,
6614 } Status = STACK_DUE_TO_USE;
6615
6616 /// Flag to indicate if we encountered a use that might free this allocation
6617 /// but which is not in the deallocation infos.
6618 bool HasPotentiallyFreeingUnknownUses = false;
6619
6620 /// Flag to indicate that we should place the new alloca in the function
6621 /// entry block rather than where the call site (CB) is.
6622 bool MoveAllocaIntoEntry = true;
6623
6624 /// The set of free calls that use this allocation.
6625 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6626 };
6627
6628 struct DeallocationInfo {
6629 /// The call that deallocates the memory.
6630 CallBase *const CB;
6631 /// The value freed by the call.
6632 Value *FreedOp;
6633
6634 /// Flag to indicate if we don't know all objects this deallocation might
6635 /// free.
6636 bool MightFreeUnknownObjects = false;
6637
6638 /// The set of allocation calls that are potentially freed.
6639 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6640 };
6641
6642 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6643 : AAHeapToStack(IRP, A) {}
6644
6645 ~AAHeapToStackFunction() override {
6646 // Ensure we call the destructor so we release any memory allocated in the
6647 // sets.
6648 for (auto &It : AllocationInfos)
6649 It.second->~AllocationInfo();
6650 for (auto &It : DeallocationInfos)
6651 It.second->~DeallocationInfo();
6652 }
6653
6654 void initialize(Attributor &A) override {
6655 AAHeapToStack::initialize(A);
6656
6657 const Function *F = getAnchorScope();
6658 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6659
6660 auto AllocationIdentifierCB = [&](Instruction &I) {
6661 CallBase *CB = dyn_cast<CallBase>(&I);
6662 if (!CB)
6663 return true;
6664 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6665 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
6666 return true;
6667 }
6668 // To do heap to stack, we need to know that the allocation itself is
6669 // removable once uses are rewritten, and that we can initialize the
6670 // alloca to the same pattern as the original allocation result.
6671 if (isRemovableAlloc(CB, TLI)) {
6672 auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
6673 if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
6674 AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
6675 AllocationInfos[CB] = AI;
6676 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6677 }
6678 }
6679 return true;
6680 };
6681
6682 bool UsedAssumedInformation = false;
6683 bool Success = A.checkForAllCallLikeInstructions(
6684 AllocationIdentifierCB, *this, UsedAssumedInformation,
6685 /* CheckBBLivenessOnly */ false,
6686 /* CheckPotentiallyDead */ true);
6687 (void)Success;
6688 assert(Success && "Did not expect the call base visit callback to fail!");
6689
6691 [](const IRPosition &, const AbstractAttribute *,
6692 bool &) -> std::optional<Value *> { return nullptr; };
6693 for (const auto &It : AllocationInfos)
6694 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6695 SCB);
6696 for (const auto &It : DeallocationInfos)
6697 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6698 SCB);
6699 }
6700
6701 const std::string getAsStr(Attributor *A) const override {
6702 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6703 for (const auto &It : AllocationInfos) {
6704 if (It.second->Status == AllocationInfo::INVALID)
6705 ++NumInvalidMallocs;
6706 else
6707 ++NumH2SMallocs;
6708 }
6709 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
6710 std::to_string(NumInvalidMallocs);
6711 }
6712
6713 void trackStatistics() const override {
6714 STATS_DECL(
6715 MallocCalls, Function,
6716 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6717 for (const auto &It : AllocationInfos)
6718 if (It.second->Status != AllocationInfo::INVALID)
6719 ++BUILD_STAT_NAME(MallocCalls, Function);
6720 }
6721
6722 bool isAssumedHeapToStack(const CallBase &CB) const override {
6723 if (isValidState())
6724 if (AllocationInfo *AI =
6725 AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
6726 return AI->Status != AllocationInfo::INVALID;
6727 return false;
6728 }
6729
6730 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6731 if (!isValidState())
6732 return false;
6733
6734 for (const auto &It : AllocationInfos) {
6735 AllocationInfo &AI = *It.second;
6736 if (AI.Status == AllocationInfo::INVALID)
6737 continue;
6738
6739 if (AI.PotentialFreeCalls.count(&CB))
6740 return true;
6741 }
6742
6743 return false;
6744 }
6745
6746 ChangeStatus manifest(Attributor &A) override {
6747 assert(getState().isValidState() &&
6748 "Attempted to manifest an invalid state!");
6749
6750 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6751 Function *F = getAnchorScope();
6752 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6753
6754 // The new allocas may escape into tail calls.
6756 if (any_of(AllocationInfos,
6757 [](const std::pair<CallBase *, AllocationInfo *> &It) {
6758 return It.second->Status != AllocationInfo::INVALID;
6759 }) &&
6760 !collectTailCalls(A, *this, TailCalls))
6761 return ChangeStatus::UNCHANGED;
6762
6763 for (auto &It : AllocationInfos) {
6764 AllocationInfo &AI = *It.second;
6765 if (AI.Status == AllocationInfo::INVALID)
6766 continue;
6767
6768 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6769 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
6770 A.deleteAfterManifest(*FreeCall);
6771 HasChanged = ChangeStatus::CHANGED;
6772 }
6773
6774 LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB
6775 << "\n");
6776
6777 auto Remark = [&](OptimizationRemark OR) {
6778 if (AI.IsGlobalizedLocal)
6779 return OR << "Moving globalized variable to the stack.";
6780 return OR << "Moving memory allocation from the heap to the stack.";
6781 };
6782 if (AI.IsGlobalizedLocal)
6783 A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
6784 else
6785 A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);
6786
6787 const DataLayout &DL = A.getInfoCache().getDL();
6788 Value *Size;
6789 std::optional<APInt> SizeAPI = getSize(A, *this, AI);
6790 if (SizeAPI) {
6791 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6792 } else {
6793 ObjectSizeOpts Opts;
6794 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6795 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6796 assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&
6797 cast<ConstantInt>(SizeOffsetPair.Offset)->isZero());
6798 Size = SizeOffsetPair.Size;
6799 }
6800
6801 BasicBlock::iterator IP = AI.MoveAllocaIntoEntry
6802 ? F->getEntryBlock().begin()
6803 : AI.CB->getIterator();
6804
6805 Align Alignment(1);
6806 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6807 Alignment = std::max(Alignment, *RetAlign);
6808 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
6809 std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
6810 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6811 "Expected an alignment during manifest!");
6812 Alignment =
6813 std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
6814 }
6815
6816 // TODO: Hoist the alloca towards the function entry.
6817 unsigned AS = DL.getAllocaAddrSpace();
6818 Instruction *Alloca =
6819 new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
6820 AI.CB->getName() + ".h2s", IP);
6821
6822 if (Alloca->getType() != AI.CB->getType())
6823 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6824 Alloca, AI.CB->getType(), "malloc_cast", AI.CB->getIterator());
6825
6826 auto *I8Ty = Type::getInt8Ty(F->getContext());
6827 auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
6828 assert(InitVal &&
6829 "Must be able to materialize initial memory state of allocation");
6830
6831 A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);
6832
6833 if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
6834 auto *NBB = II->getNormalDest();
6835 UncondBrInst::Create(NBB, AI.CB->getParent());
6836 A.deleteAfterManifest(*AI.CB);
6837 } else {
6838 A.deleteAfterManifest(*AI.CB);
6839 }
6840
6841 // Initialize the alloca with the same value as used by the allocation
6842 // function. We can skip undef as the initial value of an alloc is
6843 // undef, and the memset would simply end up being DSEd.
6844 if (!isa<UndefValue>(InitVal)) {
6845 IRBuilder<> Builder(Alloca->getNextNode());
6846 // TODO: Use alignment above if align!=1
6847 Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
6848 }
6849 HasChanged = ChangeStatus::CHANGED;
6850 }
6851
6852 for (CallInst *CI : TailCalls)
6853 CI->setTailCall(false);
6854
6855 return HasChanged;
6856 }
6857
6858 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
6859 Value &V) {
6860 bool UsedAssumedInformation = false;
6861 std::optional<Constant *> SimpleV =
6862 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6863 if (!SimpleV)
6864 return APInt(64, 0);
6865 if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
6866 return CI->getValue();
6867 return std::nullopt;
6868 }
6869
6870 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
6871 AllocationInfo &AI) {
6872 auto Mapper = [&](const Value *V) -> const Value * {
6873 bool UsedAssumedInformation = false;
6874 if (std::optional<Constant *> SimpleV =
6875 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6876 if (*SimpleV)
6877 return *SimpleV;
6878 return V;
6879 };
6880
6881 const Function *F = getAnchorScope();
6882 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6883 return getAllocSize(AI.CB, TLI, Mapper);
6884 }
6885
6886 /// Collection of all malloc-like calls in a function with associated
6887 /// information.
6888 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6889
6890 /// Collection of all free-like calls in a function with associated
6891 /// information.
6892 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6893
6894 ChangeStatus updateImpl(Attributor &A) override;
6895};
6896
6897ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
6899 const Function *F = getAnchorScope();
6900 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6901
6902 const auto *LivenessAA =
6903 A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);
6904
6905 MustBeExecutedContextExplorer *Explorer =
6906 A.getInfoCache().getMustBeExecutedContextExplorer();
6907
6908 bool StackIsAccessibleByOtherThreads =
6909 A.getInfoCache().stackIsAccessibleByOtherThreads();
6910
6911 LoopInfo *LI =
6912 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6913 std::optional<bool> MayContainIrreducibleControl;
6914 auto IsInLoop = [&](BasicBlock &BB) {
6915 if (&F->getEntryBlock() == &BB)
6916 return false;
6917 if (!MayContainIrreducibleControl.has_value())
6918 MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
6919 if (*MayContainIrreducibleControl)
6920 return true;
6921 if (!LI)
6922 return true;
6923 return LI->getLoopFor(&BB) != nullptr;
6924 };
6925
6926 // Flag to ensure we update our deallocation information at most once per
6927 // updateImpl call and only if we use the free check reasoning.
6928 bool HasUpdatedFrees = false;
6929
6930 auto UpdateFrees = [&]() {
6931 HasUpdatedFrees = true;
6932
6933 for (auto &It : DeallocationInfos) {
6934 DeallocationInfo &DI = *It.second;
6935 // For now we cannot use deallocations that have unknown inputs, skip
6936 // them.
6937 if (DI.MightFreeUnknownObjects)
6938 continue;
6939
6940 // No need to analyze dead calls, ignore them instead.
6941 bool UsedAssumedInformation = false;
6942 if (A.isAssumedDead(*DI.CB, this, LivenessAA, UsedAssumedInformation,
6943 /* CheckBBLivenessOnly */ true))
6944 continue;
6945
6946 // Use the non-optimistic version to get the freed object.
6947 Value *Obj = getUnderlyingObject(DI.FreedOp);
6948 if (!Obj) {
6949 LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");
6950 DI.MightFreeUnknownObjects = true;
6951 continue;
6952 }
6953
6954 // Free of null and undef can be ignored as no-ops (or UB in the latter
6955 // case).
6957 continue;
6958
6959 CallBase *ObjCB = dyn_cast<CallBase>(Obj);
6960 if (!ObjCB) {
6961 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj
6962 << "\n");
6963 DI.MightFreeUnknownObjects = true;
6964 continue;
6965 }
6966
6967 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
6968 if (!AI) {
6969 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj
6970 << "\n");
6971 DI.MightFreeUnknownObjects = true;
6972 continue;
6973 }
6974
6975 DI.PotentialAllocationCalls.insert(ObjCB);
6976 }
6977 };
6978
6979 auto FreeCheck = [&](AllocationInfo &AI) {
6980 // If the stack is not accessible by other threads, the "must-free" logic
6981 // doesn't apply as the pointer could be shared and needs to be places in
6982 // "shareable" memory.
6983 if (!StackIsAccessibleByOtherThreads) {
6984 bool IsKnownNoSycn;
6986 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoSycn)) {
6987 LLVM_DEBUG(
6988 dbgs() << "[H2S] found an escaping use, stack is not accessible by "
6989 "other threads and function is not nosync:\n");
6990 return false;
6991 }
6992 }
6993 if (!HasUpdatedFrees)
6994 UpdateFrees();
6995
6996 // TODO: Allow multi exit functions that have different free calls.
6997 if (AI.PotentialFreeCalls.size() != 1) {
6998 LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "
6999 << AI.PotentialFreeCalls.size() << "\n");
7000 return false;
7001 }
7002 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7003 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7004 if (!DI) {
7005 LLVM_DEBUG(
7006 dbgs() << "[H2S] unique free call was not known as deallocation call "
7007 << *UniqueFree << "\n");
7008 return false;
7009 }
7010 if (DI->MightFreeUnknownObjects) {
7011 LLVM_DEBUG(
7012 dbgs() << "[H2S] unique free call might free unknown allocations\n");
7013 return false;
7014 }
7015 if (DI->PotentialAllocationCalls.empty())
7016 return true;
7017 if (DI->PotentialAllocationCalls.size() > 1) {
7018 LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "
7019 << DI->PotentialAllocationCalls.size()
7020 << " different allocations\n");
7021 return false;
7022 }
7023 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7024 LLVM_DEBUG(
7025 dbgs()
7026 << "[H2S] unique free call not known to free this allocation but "
7027 << **DI->PotentialAllocationCalls.begin() << "\n");
7028 return false;
7029 }
7030
7031 // __kmpc_alloc_shared and __kmpc_free_shared are by construction matched.
7032 if (!AI.IsGlobalizedLocal) {
7033 Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
7034 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7035 LLVM_DEBUG(dbgs() << "[H2S] unique free call might not be executed "
7036 "with the allocation "
7037 << *UniqueFree << "\n");
7038 return false;
7039 }
7040 }
7041 return true;
7042 };
7043
7044 auto UsesCheck = [&](AllocationInfo &AI) {
7045 bool ValidUsesOnly = true;
7046
7047 auto Pred = [&](const Use &U, bool &Follow) -> bool {
7048 Instruction *UserI = cast<Instruction>(U.getUser());
7049 if (isa<LoadInst>(UserI))
7050 return true;
7051 if (auto *SI = dyn_cast<StoreInst>(UserI)) {
7052 if (SI->getValueOperand() == U.get()) {
7054 << "[H2S] escaping store to memory: " << *UserI << "\n");
7055 ValidUsesOnly = false;
7056 } else {
7057 // A store into the malloc'ed memory is fine.
7058 }
7059 return true;
7060 }
7061 if (auto *CB = dyn_cast<CallBase>(UserI)) {
7062 // A musttail call cannot access allocas of the caller, and its marker
7063 // cannot be removed.
7064 if (CB->isMustTailCall()) {
7065 LLVM_DEBUG(dbgs() << "[H2S] musttail user: " << *UserI << "\n");
7066 ValidUsesOnly = false;
7067 return true;
7068 }
7069
7070 if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
7071 return true;
7072 if (DeallocationInfos.count(CB)) {
7073 AI.PotentialFreeCalls.insert(CB);
7074 return true;
7075 }
7076
7077 unsigned ArgNo = CB->getArgOperandNo(&U);
7078 auto CBIRP = IRPosition::callsite_argument(*CB, ArgNo);
7079
7080 bool IsKnownNoCapture;
7081 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7082 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoCapture);
7083
7084 // If a call site argument use is nofree, we are fine.
7085 bool IsKnownNoFree;
7086 bool IsAssumedNoFree = AA::hasAssumedIRAttr<Attribute::NoFree>(
7087 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoFree);
7088
7089 if (!IsAssumedNoCapture ||
7090 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7091 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7092
7093 // Emit a missed remark if this is missed OpenMP globalization.
7094 auto Remark = [&](OptimizationRemarkMissed ORM) {
7095 return ORM
7096 << "Could not move globalized variable to the stack. "
7097 "Variable is potentially captured in call. Mark "
7098 "parameter as `__attribute__((noescape))` to override.";
7099 };
7100
7101 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7102 A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);
7103
7104 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
7105 ValidUsesOnly = false;
7106 }
7107 return true;
7108 }
7109
7110 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
7111 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
7112 Follow = true;
7113 return true;
7114 }
7115 // Unknown user for which we can not track uses further (in a way that
7116 // makes sense).
7117 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
7118 ValidUsesOnly = false;
7119 return true;
7120 };
7121 if (!A.checkForAllUses(Pred, *this, *AI.CB, /* CheckBBLivenessOnly */ false,
7122 DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,
7123 [&](const Use &OldU, const Use &NewU) {
7124 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7125 return !SI || StackIsAccessibleByOtherThreads ||
7126 AA::isAssumedThreadLocalObject(
7127 A, *SI->getPointerOperand(), *this);
7128 }))
7129 return false;
7130 return ValidUsesOnly;
7131 };
7132
7133 // The actual update starts here. We look at all allocations and depending on
7134 // their status perform the appropriate check(s).
7135 for (auto &It : AllocationInfos) {
7136 AllocationInfo &AI = *It.second;
7137 if (AI.Status == AllocationInfo::INVALID)
7138 continue;
7139
7140 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
7141 std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
7142 if (!APAlign) {
7143 // Can't generate an alloca which respects the required alignment
7144 // on the allocation.
7145 LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB
7146 << "\n");
7147 AI.Status = AllocationInfo::INVALID;
7149 continue;
7150 }
7151 if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
7152 !APAlign->isPowerOf2()) {
7153 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign
7154 << "\n");
7155 AI.Status = AllocationInfo::INVALID;
7157 continue;
7158 }
7159 }
7160
7161 std::optional<APInt> Size = getSize(A, *this, AI);
7162 if (!AI.IsGlobalizedLocal && MaxHeapToStackSize != -1) {
7163 if (!Size || Size->ugt(MaxHeapToStackSize)) {
7164 LLVM_DEBUG({
7165 if (!Size)
7166 dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";
7167 else
7168 dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "
7169 << MaxHeapToStackSize << "\n";
7170 });
7171
7172 AI.Status = AllocationInfo::INVALID;
7174 continue;
7175 }
7176 }
7177
7178 switch (AI.Status) {
7179 case AllocationInfo::STACK_DUE_TO_USE:
7180 if (UsesCheck(AI))
7181 break;
7182 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7183 [[fallthrough]];
7184 case AllocationInfo::STACK_DUE_TO_FREE:
7185 if (FreeCheck(AI))
7186 break;
7187 AI.Status = AllocationInfo::INVALID;
7189 break;
7190 case AllocationInfo::INVALID:
7191 llvm_unreachable("Invalid allocations should never reach this point!");
7192 };
7193
7194 // Check if we still think we can move it into the entry block. If the
7195 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7196 // ignore the potential complications associated with loops.
7197 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7198 if (AI.MoveAllocaIntoEntry &&
7199 (!Size.has_value() ||
7200 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7201 AI.MoveAllocaIntoEntry = false;
7202 }
7203
7204 return Changed;
7205}
7206} // namespace
7207
7208/// ----------------------- Privatizable Pointers ------------------------------
7209namespace {
7210struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
7211 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7212 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7213
7214 ChangeStatus indicatePessimisticFixpoint() override {
7215 AAPrivatizablePtr::indicatePessimisticFixpoint();
7216 PrivatizableType = nullptr;
7217 return ChangeStatus::CHANGED;
7218 }
7219
7220 /// Identify the type we can chose for a private copy of the underlying
7221 /// argument. std::nullopt means it is not clear yet, nullptr means there is
7222 /// none.
7223 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7224
7225 /// Return a privatizable type that encloses both T0 and T1.
7226 /// TODO: This is merely a stub for now as we should manage a mapping as well.
7227 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7228 std::optional<Type *> T1) {
7229 if (!T0)
7230 return T1;
7231 if (!T1)
7232 return T0;
7233 if (T0 == T1)
7234 return T0;
7235 return nullptr;
7236 }
7237
7238 std::optional<Type *> getPrivatizableType() const override {
7239 return PrivatizableType;
7240 }
7241
7242 const std::string getAsStr(Attributor *A) const override {
7243 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7244 }
7245
7246protected:
7247 std::optional<Type *> PrivatizableType;
7248};
7249
7250// TODO: Do this for call site arguments (probably also other values) as well.
7251
7252struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
7253 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7254 : AAPrivatizablePtrImpl(IRP, A) {}
7255
7256 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7257 // If this is a byval argument and we know all the call sites (so we can
7258 // rewrite them), there is no need to check them explicitly.
7259 bool UsedAssumedInformation = false;
7261 A.getAttrs(getIRPosition(), {Attribute::ByVal}, Attrs,
7262 /* IgnoreSubsumingPositions */ true);
7263 if (!Attrs.empty() &&
7264 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
7265 true, UsedAssumedInformation))
7266 return Attrs[0].getValueAsType();
7267
7268 std::optional<Type *> Ty;
7269 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7270
7271 // Make sure the associated call site argument has the same type at all call
7272 // sites and it is an allocation we know is safe to privatize, for now that
7273 // means we only allow alloca instructions.
7274 // TODO: We can additionally analyze the accesses in the callee to create
7275 // the type from that information instead. That is a little more
7276 // involved and will be done in a follow up patch.
7277 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7278 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7279 // Check if a coresponding argument was found or if it is one not
7280 // associated (which can happen for callback calls).
7281 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7282 return false;
7283
7284 // Check that all call sites agree on a type.
7285 auto *PrivCSArgAA =
7286 A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
7287 if (!PrivCSArgAA)
7288 return false;
7289 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7290
7291 LLVM_DEBUG({
7292 dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
7293 if (CSTy && *CSTy)
7294 (*CSTy)->print(dbgs());
7295 else if (CSTy)
7296 dbgs() << "<nullptr>";
7297 else
7298 dbgs() << "<none>";
7299 });
7300
7301 Ty = combineTypes(Ty, CSTy);
7302
7303 LLVM_DEBUG({
7304 dbgs() << " : New Type: ";
7305 if (Ty && *Ty)
7306 (*Ty)->print(dbgs());
7307 else if (Ty)
7308 dbgs() << "<nullptr>";
7309 else
7310 dbgs() << "<none>";
7311 dbgs() << "\n";
7312 });
7313
7314 return !Ty || *Ty;
7315 };
7316
7317 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7318 UsedAssumedInformation))
7319 return nullptr;
7320 return Ty;
7321 }
7322
7323 ChangeStatus updateImpl(Attributor &A) override {
7324 PrivatizableType = identifyPrivatizableType(A);
7325 if (!PrivatizableType)
7326 return ChangeStatus::UNCHANGED;
7327 if (!*PrivatizableType)
7328 return indicatePessimisticFixpoint();
7329
7330 // The dependence is optional so we don't give up once we give up on the
7331 // alignment.
7332 A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
7333 DepClassTy::OPTIONAL);
7334
7335 // Avoid arguments with padding for now.
7336 if (!A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7337 !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
7338 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
7339 return indicatePessimisticFixpoint();
7340 }
7341
7342 // Collect the types that will replace the privatizable type in the function
7343 // signature.
7344 SmallVector<Type *, 16> ReplacementTypes;
7345 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7346
7347 // Verify callee and caller agree on how the promoted argument would be
7348 // passed.
7349 Function &Fn = *getIRPosition().getAnchorScope();
7350 const auto *TTI =
7351 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7352 if (!TTI) {
7353 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
7354 << Fn.getName() << "\n");
7355 return indicatePessimisticFixpoint();
7356 }
7357
7358 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7359 CallBase *CB = ACS.getInstruction();
7360 return TTI->areTypesABICompatible(
7361 CB->getCaller(),
7363 ReplacementTypes);
7364 };
7365 bool UsedAssumedInformation = false;
7366 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7367 UsedAssumedInformation)) {
7368 LLVM_DEBUG(
7369 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
7370 << Fn.getName() << "\n");
7371 return indicatePessimisticFixpoint();
7372 }
7373
7374 // Register a rewrite of the argument.
7375 Argument *Arg = getAssociatedArgument();
7376 if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7377 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");
7378 return indicatePessimisticFixpoint();
7379 }
7380
7381 unsigned ArgNo = Arg->getArgNo();
7382
7383 // Helper to check if for the given call site the associated argument is
7384 // passed to a callback where the privatization would be different.
7385 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7386 SmallVector<const Use *, 4> CallbackUses;
7387 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7388 for (const Use *U : CallbackUses) {
7389 AbstractCallSite CBACS(U);
7390 assert(CBACS && CBACS.isCallbackCall());
7391 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7392 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7393
7394 LLVM_DEBUG({
7395 dbgs()
7396 << "[AAPrivatizablePtr] Argument " << *Arg
7397 << "check if can be privatized in the context of its parent ("
7398 << Arg->getParent()->getName()
7399 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7400 "callback ("
7401 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7402 << ")\n[AAPrivatizablePtr] " << CBArg << " : "
7403 << CBACS.getCallArgOperand(CBArg) << " vs "
7404 << CB.getArgOperand(ArgNo) << "\n"
7405 << "[AAPrivatizablePtr] " << CBArg << " : "
7406 << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";
7407 });
7408
7409 if (CBArgNo != int(ArgNo))
7410 continue;
7411 const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7412 *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
7413 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7414 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7415 if (!CBArgPrivTy)
7416 continue;
7417 if (*CBArgPrivTy == PrivatizableType)
7418 continue;
7419 }
7420
7421 LLVM_DEBUG({
7422 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7423 << " cannot be privatized in the context of its parent ("
7424 << Arg->getParent()->getName()
7425 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7426 "callback ("
7427 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7428 << ").\n[AAPrivatizablePtr] for which the argument "
7429 "privatization is not compatible.\n";
7430 });
7431 return false;
7432 }
7433 }
7434 return true;
7435 };
7436
7437 // Helper to check if for the given call site the associated argument is
7438 // passed to a direct call where the privatization would be different.
7439 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7440 CallBase *DC = cast<CallBase>(ACS.getInstruction());
7441 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7442 assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&
7443 "Expected a direct call operand for callback call operand");
7444
7445 Function *DCCallee =
7447 LLVM_DEBUG({
7448 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7449 << " check if be privatized in the context of its parent ("
7450 << Arg->getParent()->getName()
7451 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7452 "direct call of ("
7453 << DCArgNo << "@" << DCCallee->getName() << ").\n";
7454 });
7455
7456 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7457 const auto *DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7458 *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
7459 DepClassTy::REQUIRED);
7460 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7461 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7462 if (!DCArgPrivTy)
7463 return true;
7464 if (*DCArgPrivTy == PrivatizableType)
7465 return true;
7466 }
7467 }
7468
7469 LLVM_DEBUG({
7470 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7471 << " cannot be privatized in the context of its parent ("
7472 << Arg->getParent()->getName()
7473 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7474 "direct call of ("
7476 << ").\n[AAPrivatizablePtr] for which the argument "
7477 "privatization is not compatible.\n";
7478 });
7479 return false;
7480 };
7481
7482 // Helper to check if the associated argument is used at the given abstract
7483 // call site in a way that is incompatible with the privatization assumed
7484 // here.
7485 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7486 if (ACS.isDirectCall())
7487 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7488 if (ACS.isCallbackCall())
7489 return IsCompatiblePrivArgOfDirectCS(ACS);
7490 return false;
7491 };
7492
7493 if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
7494 UsedAssumedInformation))
7495 return indicatePessimisticFixpoint();
7496
7497 return ChangeStatus::UNCHANGED;
7498 }
7499
7500 /// Given a type to private \p PrivType, collect the constituates (which are
7501 /// used) in \p ReplacementTypes.
7502 static void
7503 identifyReplacementTypes(Type *PrivType,
7504 SmallVectorImpl<Type *> &ReplacementTypes) {
7505 // TODO: For now we expand the privatization type to the fullest which can
7506 // lead to dead arguments that need to be removed later.
7507 assert(PrivType && "Expected privatizable type!");
7508
7509 // Traverse the type, extract constituate types on the outermost level.
7510 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7511 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7512 ReplacementTypes.push_back(PrivStructType->getElementType(u));
7513 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7514 ReplacementTypes.append(PrivArrayType->getNumElements(),
7515 PrivArrayType->getElementType());
7516 } else {
7517 ReplacementTypes.push_back(PrivType);
7518 }
7519 }
7520
7521 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7522 /// The values needed are taken from the arguments of \p F starting at
7523 /// position \p ArgNo.
7524 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7525 unsigned ArgNo, BasicBlock::iterator IP) {
7526 assert(PrivType && "Expected privatizable type!");
7527
7528 IRBuilder<NoFolder> IRB(IP);
7529 const DataLayout &DL = F.getDataLayout();
7530
7531 // Traverse the type, build GEPs and stores.
7532 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7533 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7534 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7535 Value *Ptr =
7536 constructPointer(&Base, PrivStructLayout->getElementOffset(u), IRB);
7537 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7538 }
7539 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7540 Type *PointeeTy = PrivArrayType->getElementType();
7541 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7542 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7543 Value *Ptr = constructPointer(&Base, u * PointeeTySize, IRB);
7544 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7545 }
7546 } else {
7547 new StoreInst(F.getArg(ArgNo), &Base, IP);
7548 }
7549 }
7550
7551 /// Extract values from \p Base according to the type \p PrivType at the
7552 /// call position \p ACS. The values are appended to \p ReplacementValues.
7553 void createReplacementValues(Align Alignment, Type *PrivType,
7554 AbstractCallSite ACS, Value *Base,
7555 SmallVectorImpl<Value *> &ReplacementValues) {
7556 assert(Base && "Expected base value!");
7557 assert(PrivType && "Expected privatizable type!");
7558 Instruction *IP = ACS.getInstruction();
7559
7560 IRBuilder<NoFolder> IRB(IP);
7561 const DataLayout &DL = IP->getDataLayout();
7562
7563 // Traverse the type, build GEPs and loads.
7564 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7565 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7566 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7567 Type *PointeeTy = PrivStructType->getElementType(u);
7568 Value *Ptr =
7569 constructPointer(Base, PrivStructLayout->getElementOffset(u), IRB);
7570 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7571 L->setAlignment(Alignment);
7572 ReplacementValues.push_back(L);
7573 }
7574 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7575 Type *PointeeTy = PrivArrayType->getElementType();
7576 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7577 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7578 Value *Ptr = constructPointer(Base, u * PointeeTySize, IRB);
7579 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7580 L->setAlignment(Alignment);
7581 ReplacementValues.push_back(L);
7582 }
7583 } else {
7584 LoadInst *L = new LoadInst(PrivType, Base, "", IP->getIterator());
7585 L->setAlignment(Alignment);
7586 ReplacementValues.push_back(L);
7587 }
7588 }
7589
7590 ChangeStatus manifest(Attributor &A) override {
7591 if (!PrivatizableType)
7592 return ChangeStatus::UNCHANGED;
7593 assert(*PrivatizableType && "Expected privatizable type!");
7594
7595 Argument *Arg = getAssociatedArgument();
7596 // Query AAAlign attribute for alignment of associated argument to
7597 // determine the best alignment of loads.
7598 const auto *AlignAA =
7599 A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
7600
7601 // Callback to repair the associated function. A new alloca is placed at the
7602 // beginning and initialized with the values passed through arguments. The
7603 // new alloca replaces the use of the old pointer argument.
7605 [=](const Attributor::ArgumentReplacementInfo &ARI,
7606 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7607 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7609 const DataLayout &DL = IP->getDataLayout();
7610 unsigned AS = DL.getAllocaAddrSpace();
7611 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7612 Arg->getName() + ".priv", IP);
7613 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7614 ArgIt->getArgNo(), IP);
7615
7616 if (AI->getType() != Arg->getType())
7617 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7618 AI, Arg->getType(), "", IP);
7619 Arg->replaceAllUsesWith(AI);
7620
7621 // The new alloca may escape into tail calls. Find them here, as calls
7622 // may have been replaced or deleted since manifest.
7623 for (Instruction &I : instructions(ReplacementFn)) {
7624 auto *CI = dyn_cast<CallInst>(&I);
7625 if (CI && CI->isTailCall() && !CI->isMustTailCall())
7626 CI->setTailCall(false);
7627 }
7628 };
7629
7630 // Callback to repair a call site of the associated function. The elements
7631 // of the privatizable type are loaded prior to the call and passed to the
7632 // new function version.
7634 [=](const Attributor::ArgumentReplacementInfo &ARI,
7635 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7636 // When no alignment is specified for the load instruction,
7637 // natural alignment is assumed.
7638 createReplacementValues(
7639 AlignAA ? AlignAA->getAssumedAlign() : Align(0),
7640 *PrivatizableType, ACS,
7641 ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
7642 NewArgOperands);
7643 };
7644
7645 // Collect the types that will replace the privatizable type in the function
7646 // signature.
7647 SmallVector<Type *, 16> ReplacementTypes;
7648 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7649
7650 // Register a rewrite of the argument.
7651 if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7652 std::move(FnRepairCB),
7653 std::move(ACSRepairCB)))
7654 return ChangeStatus::CHANGED;
7655 return ChangeStatus::UNCHANGED;
7656 }
7657
7658 void trackStatistics() const override {
7659 STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);
7660 }
7661};
7662
7663struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
7664 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7665 : AAPrivatizablePtrImpl(IRP, A) {}
7666
7667 void initialize(Attributor &A) override {
7668 // TODO: We can privatize more than arguments.
7669 indicatePessimisticFixpoint();
7670 }
7671
7672 ChangeStatus updateImpl(Attributor &A) override {
7673 llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
7674 "updateImpl will not be called");
7675 }
7676
7677 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7678 Value *Obj = getUnderlyingObject(&getAssociatedValue());
7679 if (!Obj) {
7680 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
7681 return nullptr;
7682 }
7683
7684 if (auto *AI = dyn_cast<AllocaInst>(Obj))
7685 if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
7686 if (CI->isOne())
7687 return AI->getAllocatedType();
7688 if (auto *Arg = dyn_cast<Argument>(Obj)) {
7689 auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7690 *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
7691 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7692 return PrivArgAA->getPrivatizableType();
7693 }
7694
7695 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
7696 "alloca nor privatizable argument: "
7697 << *Obj << "!\n");
7698 return nullptr;
7699 }
7700
7701 void trackStatistics() const override {
7702 STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);
7703 }
7704};
7705
7706struct AAPrivatizablePtrCallSiteArgument final
7707 : public AAPrivatizablePtrFloating {
7708 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7709 : AAPrivatizablePtrFloating(IRP, A) {}
7710
7711 void initialize(Attributor &A) override {
7712 if (A.hasAttr(getIRPosition(), Attribute::ByVal))
7713 indicateOptimisticFixpoint();
7714 }
7715
7716 ChangeStatus updateImpl(Attributor &A) override {
7717 PrivatizableType = identifyPrivatizableType(A);
7718 if (!PrivatizableType)
7719 return ChangeStatus::UNCHANGED;
7720 if (!*PrivatizableType)
7721 return indicatePessimisticFixpoint();
7722
7723 const IRPosition &IRP = getIRPosition();
7724 bool IsKnownNoCapture;
7725 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7726 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7727 if (!IsAssumedNoCapture) {
7728 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");
7729 return indicatePessimisticFixpoint();
7730 }
7731
7732 bool IsKnownNoAlias;
7734 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7735 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");
7736 return indicatePessimisticFixpoint();
7737 }
7738
7739 bool IsKnown;
7740 if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
7741 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");
7742 return indicatePessimisticFixpoint();
7743 }
7744
7745 return ChangeStatus::UNCHANGED;
7746 }
7747
7748 void trackStatistics() const override {
7749 STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);
7750 }
7751};
7752
7753struct AAPrivatizablePtrCallSiteReturned final
7754 : public AAPrivatizablePtrFloating {
7755 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7756 : AAPrivatizablePtrFloating(IRP, A) {}
7757
7758 void initialize(Attributor &A) override {
7759 // TODO: We can privatize more than arguments.
7760 indicatePessimisticFixpoint();
7761 }
7762
7763 void trackStatistics() const override {
7764 STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);
7765 }
7766};
7767
7768struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
7769 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7770 : AAPrivatizablePtrFloating(IRP, A) {}
7771
7772 void initialize(Attributor &A) override {
7773 // TODO: We can privatize more than arguments.
7774 indicatePessimisticFixpoint();
7775 }
7776
7777 void trackStatistics() const override {
7778 STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);
7779 }
7780};
7781} // namespace
7782
7783/// -------------------- Memory Behavior Attributes ----------------------------
7784/// Includes read-none, read-only, and write-only.
7785/// ----------------------------------------------------------------------------
7786namespace {
7787struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
7788 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7789 : AAMemoryBehavior(IRP, A) {}
7790
7791 void initialize(Attributor &A) override {
7792 intersectAssumedBits(BEST_STATE);
7793 getKnownStateFromValue(A, getIRPosition(), getState());
7794 AAMemoryBehavior::initialize(A);
7795 }
7796
7797 /// Return the memory behavior information encoded in the IR for \p IRP.
7798 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
7799 BitIntegerState &State,
7800 bool IgnoreSubsumingPositions = false) {
7802 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7803 for (const Attribute &Attr : Attrs) {
7804 switch (Attr.getKindAsEnum()) {
7805 case Attribute::ReadNone:
7806 State.addKnownBits(NO_ACCESSES);
7807 break;
7808 case Attribute::ReadOnly:
7809 State.addKnownBits(NO_WRITES);
7810 break;
7811 case Attribute::WriteOnly:
7812 State.addKnownBits(NO_READS);
7813 break;
7814 default:
7815 llvm_unreachable("Unexpected attribute!");
7816 }
7817 }
7818
7819 // Only a call site anchor performs the accesses of the position. A floating
7820 // value is only defined by its anchor, e.g., a loaded pointer may be
7821 // written through even though the load does not write.
7823 if (Kind == IRPosition::IRP_CALL_SITE ||
7825 if (auto *CB = dyn_cast<CallBase>(&IRP.getAnchorValue())) {
7827 if (!isRefSet(MR))
7828 State.addKnownBits(NO_READS);
7829 if (!isModSet(MR))
7830 State.addKnownBits(NO_WRITES);
7831 }
7832 }
7833 }
7834
7835 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
7836 SmallVectorImpl<Attribute> &Attrs) const override {
7837 assert(Attrs.size() == 0);
7838 if (isAssumedReadNone())
7839 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7840 else if (isAssumedReadOnly())
7841 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7842 else if (isAssumedWriteOnly())
7843 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7844 assert(Attrs.size() <= 1);
7845 }
7846
7847 ChangeStatus manifest(Attributor &A) override {
7848 const IRPosition &IRP = getIRPosition();
7849
7850 if (A.hasAttr(IRP, Attribute::ReadNone,
7851 /* IgnoreSubsumingPositions */ true))
7852 return ChangeStatus::UNCHANGED;
7853
7854 // Check if we would improve the existing attributes first.
7855 SmallVector<Attribute, 4> DeducedAttrs;
7856 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
7857 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
7858 return A.hasAttr(IRP, Attr.getKindAsEnum(),
7859 /* IgnoreSubsumingPositions */ true);
7860 }))
7861 return ChangeStatus::UNCHANGED;
7862
7863 // Clear existing attributes.
7864 A.removeAttrs(IRP, AttrKinds);
7865 // Clear conflicting writable attribute.
7866 if (isAssumedReadOnly())
7867 A.removeAttrs(IRP, Attribute::Writable);
7868
7869 // Use the generic manifest method.
7870 return IRAttribute::manifest(A);
7871 }
7872
7873 const std::string getAsStr(Attributor *A) const override {
7874 if (isAssumedReadNone())
7875 return "readnone";
7876 if (isAssumedReadOnly())
7877 return "readonly";
7878 if (isAssumedWriteOnly())
7879 return "writeonly";
7880 return "may-read/write";
7881 }
7882
7883 /// The set of IR attributes AAMemoryBehavior deals with.
7884 static const Attribute::AttrKind AttrKinds[3];
7885};
7886
7887const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7888 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7889
7890/// Memory behavior attribute for a floating value.
7891struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7892 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7893 : AAMemoryBehaviorImpl(IRP, A) {}
7894
7895 ChangeStatus updateImpl(Attributor &A) override;
7896
7897 void trackStatistics() const override {
7898 if (isAssumedReadNone())
7900 else if (isAssumedReadOnly())
7902 else if (isAssumedWriteOnly())
7904 }
7905
7906private:
7907 /// Return true if users of \p UserI might access the underlying
7908 /// variable/location described by \p U and should therefore be analyzed.
7909 bool followUsersOfUseIn(Attributor &A, const Use &U,
7910 const Instruction *UserI);
7911
7912 /// Update the state according to the effect of use \p U in \p UserI.
7913 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
7914};
7915
7916/// Memory behavior attribute for function argument.
7917struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
7918 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
7919 : AAMemoryBehaviorFloating(IRP, A) {}
7920
7921 void initialize(Attributor &A) override {
7922 intersectAssumedBits(BEST_STATE);
7923 const IRPosition &IRP = getIRPosition();
7924 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
7925 // can query it when we use has/getAttr. That would allow us to reuse the
7926 // initialize of the base class here.
7927 bool HasByVal = A.hasAttr(IRP, {Attribute::ByVal},
7928 /* IgnoreSubsumingPositions */ true);
7929 getKnownStateFromValue(A, IRP, getState(),
7930 /* IgnoreSubsumingPositions */ HasByVal);
7931 }
7932
7933 ChangeStatus manifest(Attributor &A) override {
7934 // TODO: Pointer arguments are not supported on vectors of pointers yet.
7935 if (!getAssociatedValue().getType()->isPointerTy())
7936 return ChangeStatus::UNCHANGED;
7937
7938 // TODO: From readattrs.ll: "inalloca parameters are always
7939 // considered written"
7940 if (A.hasAttr(getIRPosition(),
7941 {Attribute::InAlloca, Attribute::Preallocated})) {
7942 removeKnownBits(NO_WRITES);
7943 removeAssumedBits(NO_WRITES);
7944 }
7945 A.removeAttrs(getIRPosition(), AttrKinds);
7946 return AAMemoryBehaviorFloating::manifest(A);
7947 }
7948
7949 void trackStatistics() const override {
7950 if (isAssumedReadNone())
7951 STATS_DECLTRACK_ARG_ATTR(readnone)
7952 else if (isAssumedReadOnly())
7953 STATS_DECLTRACK_ARG_ATTR(readonly)
7954 else if (isAssumedWriteOnly())
7955 STATS_DECLTRACK_ARG_ATTR(writeonly)
7956 }
7957};
7958
7959struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
7960 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
7961 : AAMemoryBehaviorArgument(IRP, A) {}
7962
7963 void initialize(Attributor &A) override {
7964 // If we don't have an associated attribute this is either a variadic call
7965 // or an indirect call, either way, nothing to do here.
7966 Argument *Arg = getAssociatedArgument();
7967 if (!Arg) {
7968 indicatePessimisticFixpoint();
7969 return;
7970 }
7971 if (Arg->hasByValAttr()) {
7972 addKnownBits(NO_WRITES);
7973 removeKnownBits(NO_READS);
7974 removeAssumedBits(NO_READS);
7975 }
7976 AAMemoryBehaviorArgument::initialize(A);
7977 if (getAssociatedFunction()->isDeclaration())
7978 indicatePessimisticFixpoint();
7979 }
7980
7981 ChangeStatus updateImpl(Attributor &A) override {
7982 // TODO: Once we have call site specific value information we can provide
7983 // call site specific liveness liveness information and then it makes
7984 // sense to specialize attributes for call sites arguments instead of
7985 // redirecting requests to the callee argument.
7986 Argument *Arg = getAssociatedArgument();
7987 const IRPosition &ArgPos = IRPosition::argument(*Arg);
7988 auto *ArgAA =
7989 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
7990 if (!ArgAA)
7991 return indicatePessimisticFixpoint();
7992 return clampStateAndIndicateChange(getState(), ArgAA->getState());
7993 }
7994
7995 void trackStatistics() const override {
7996 if (isAssumedReadNone())
7998 else if (isAssumedReadOnly())
8000 else if (isAssumedWriteOnly())
8002 }
8003};
8004
8005/// Memory behavior attribute for a call site return position.
8006struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8007 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
8008 : AAMemoryBehaviorFloating(IRP, A) {}
8009
8010 void initialize(Attributor &A) override {
8011 AAMemoryBehaviorImpl::initialize(A);
8012 }
8013 ChangeStatus manifest(Attributor &A) override {
8014 // We do not annotate returned values.
8015 return ChangeStatus::UNCHANGED;
8016 }
8017
8018 void trackStatistics() const override {}
8019};
8020
8021/// An AA to represent the memory behavior function attributes.
8022struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
8023 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
8024 : AAMemoryBehaviorImpl(IRP, A) {}
8025
8026 ChangeStatus updateImpl(Attributor &A) override;
8027
8028 ChangeStatus manifest(Attributor &A) override {
8029 // TODO: It would be better to merge this with AAMemoryLocation, so that
8030 // we could determine read/write per location. This would also have the
8031 // benefit of only one place trying to manifest the memory attribute.
8032 Function &F = cast<Function>(getAnchorValue());
8034 if (isAssumedReadNone())
8035 ME = MemoryEffects::none();
8036 else if (isAssumedReadOnly())
8038 else if (isAssumedWriteOnly())
8040
8041 A.removeAttrs(getIRPosition(), AttrKinds);
8042 // Clear conflicting writable attribute.
8043 if (ME.onlyReadsMemory())
8044 for (Argument &Arg : F.args())
8045 A.removeAttrs(IRPosition::argument(Arg), Attribute::Writable);
8046 return A.manifestAttrs(getIRPosition(),
8047 Attribute::getWithMemoryEffects(F.getContext(), ME));
8048 }
8049
8050 void trackStatistics() const override {
8051 if (isAssumedReadNone())
8052 STATS_DECLTRACK_FN_ATTR(readnone)
8053 else if (isAssumedReadOnly())
8054 STATS_DECLTRACK_FN_ATTR(readonly)
8055 else if (isAssumedWriteOnly())
8056 STATS_DECLTRACK_FN_ATTR(writeonly)
8057 }
8058};
8059
8060/// AAMemoryBehavior attribute for call sites.
8061struct AAMemoryBehaviorCallSite final
8062 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8063 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
8064 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP, A) {}
8065
8066 ChangeStatus manifest(Attributor &A) override {
8067 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8068 CallBase &CB = cast<CallBase>(getAnchorValue());
8070 if (isAssumedReadNone())
8071 ME = MemoryEffects::none();
8072 else if (isAssumedReadOnly())
8074 else if (isAssumedWriteOnly())
8076
8077 A.removeAttrs(getIRPosition(), AttrKinds);
8078 // Clear conflicting writable attribute.
8079 if (ME.onlyReadsMemory())
8080 for (Use &U : CB.args())
8081 A.removeAttrs(IRPosition::callsite_argument(CB, U.getOperandNo()),
8082 Attribute::Writable);
8083 return A.manifestAttrs(
8084 getIRPosition(), Attribute::getWithMemoryEffects(CB.getContext(), ME));
8085 }
8086
8087 void trackStatistics() const override {
8088 if (isAssumedReadNone())
8089 STATS_DECLTRACK_CS_ATTR(readnone)
8090 else if (isAssumedReadOnly())
8091 STATS_DECLTRACK_CS_ATTR(readonly)
8092 else if (isAssumedWriteOnly())
8093 STATS_DECLTRACK_CS_ATTR(writeonly)
8094 }
8095};
8096
8097ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8098
8099 // The current assumed state used to determine a change.
8100 auto AssumedState = getAssumed();
8101
8102 auto CheckRWInst = [&](Instruction &I) {
8103 // If the instruction has an own memory behavior state, use it to restrict
8104 // the local state. No further analysis is required as the other memory
8105 // state is as optimistic as it gets.
8106 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8107 const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8109 if (MemBehaviorAA) {
8110 intersectAssumedBits(MemBehaviorAA->getAssumed());
8111 return !isAtFixpoint();
8112 }
8113 }
8114
8115 // Remove access kind modifiers if necessary.
8116 if (I.mayReadFromMemory())
8117 removeAssumedBits(NO_READS);
8118 if (I.mayWriteToMemory())
8119 removeAssumedBits(NO_WRITES);
8120 return !isAtFixpoint();
8121 };
8122
8123 bool UsedAssumedInformation = false;
8124 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8125 UsedAssumedInformation))
8126 return indicatePessimisticFixpoint();
8127
8128 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8130}
8131
8132ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8133
8134 const IRPosition &IRP = getIRPosition();
8135 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8136 AAMemoryBehavior::StateType &S = getState();
8137
8138 // First, check the function scope. We take the known information and we avoid
8139 // work if the assumed information implies the current assumed information for
8140 // this attribute. This is a valid for all but byval arguments.
8141 Argument *Arg = IRP.getAssociatedArgument();
8142 AAMemoryBehavior::base_t FnMemAssumedState =
8144 if (!Arg || !Arg->hasByValAttr()) {
8145 const auto *FnMemAA =
8146 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8147 if (FnMemAA) {
8148 FnMemAssumedState = FnMemAA->getAssumed();
8149 S.addKnownBits(FnMemAA->getKnown());
8150 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8152 }
8153 }
8154
8155 // The current assumed state used to determine a change.
8156 auto AssumedState = S.getAssumed();
8157
8158 // Make sure the value is not captured (except through "return"), if
8159 // it is, any information derived would be irrelevant anyway as we cannot
8160 // check the potential aliases introduced by the capture. However, no need
8161 // to fall back to anythign less optimistic than the function state.
8162 bool IsKnownNoCapture;
8163 const AANoCapture *ArgNoCaptureAA = nullptr;
8164 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
8165 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture, false,
8166 &ArgNoCaptureAA);
8167
8168 if (!IsAssumedNoCapture &&
8169 (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
8170 S.intersectAssumedBits(FnMemAssumedState);
8171 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8173 }
8174
8175 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8176 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8177 Instruction *UserI = cast<Instruction>(U.getUser());
8178 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
8179 << " \n");
8180
8181 // Droppable users, e.g., llvm::assume does not actually perform any action.
8182 if (UserI->isDroppable())
8183 return true;
8184
8185 // Check if the users of UserI should also be visited.
8186 Follow = followUsersOfUseIn(A, U, UserI);
8187
8188 // If UserI might touch memory we analyze the use in detail.
8189 if (UserI->mayReadOrWriteMemory())
8190 analyzeUseIn(A, U, UserI);
8191
8192 return !isAtFixpoint();
8193 };
8194
8195 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8196 return indicatePessimisticFixpoint();
8197
8198 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8200}
8201
8202bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8203 const Instruction *UserI) {
8204 // The loaded value is unrelated to the pointer argument, no need to
8205 // follow the users of the load.
8206 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8207 return false;
8208
8209 // By default we follow all uses assuming UserI might leak information on U,
8210 // we have special handling for call sites operands though.
8211 const auto *CB = dyn_cast<CallBase>(UserI);
8212 if (!CB || !CB->isArgOperand(&U))
8213 return true;
8214
8215 // If the use is a call argument known not to be captured, the users of
8216 // the call do not need to be visited because they have to be unrelated to
8217 // the input. Note that this check is not trivial even though we disallow
8218 // general capturing of the underlying argument. The reason is that the
8219 // call might the argument "through return", which we allow and for which we
8220 // need to check call users.
8221 if (U.get()->getType()->isPointerTy()) {
8222 unsigned ArgNo = CB->getArgOperandNo(&U);
8223 bool IsKnownNoCapture;
8225 A, this, IRPosition::callsite_argument(*CB, ArgNo),
8226 DepClassTy::OPTIONAL, IsKnownNoCapture);
8227 }
8228
8229 return true;
8230}
8231
8232void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8233 const Instruction *UserI) {
8234 assert(UserI->mayReadOrWriteMemory());
8235
8236 switch (UserI->getOpcode()) {
8237 default:
8238 // TODO: Handle all atomics and other side-effect operations we know of.
8239 break;
8240 case Instruction::Load:
8241 // Loads cause the NO_READS property to disappear.
8242 removeAssumedBits(NO_READS);
8243 return;
8244
8245 case Instruction::Store:
8246 // Stores cause the NO_WRITES property to disappear if the use is the
8247 // pointer operand. Note that while capturing was taken care of somewhere
8248 // else we need to deal with stores of the value that is not looked through.
8249 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8250 removeAssumedBits(NO_WRITES);
8251 else
8252 indicatePessimisticFixpoint();
8253 return;
8254
8255 case Instruction::Call:
8256 case Instruction::CallBr:
8257 case Instruction::Invoke: {
8258 // For call sites we look at the argument memory behavior attribute (this
8259 // could be recursive!) in order to restrict our own state.
8260 const auto *CB = cast<CallBase>(UserI);
8261
8262 // Give up on operand bundles.
8263 if (CB->isBundleOperand(&U)) {
8264 indicatePessimisticFixpoint();
8265 return;
8266 }
8267
8268 // Calling a function does read the function pointer, maybe write it if the
8269 // function is self-modifying.
8270 if (CB->isCallee(&U)) {
8271 removeAssumedBits(NO_READS);
8272 break;
8273 }
8274
8275 // Adjust the possible access behavior based on the information on the
8276 // argument.
8277 IRPosition Pos;
8278 if (U.get()->getType()->isPointerTy())
8280 else
8282 const auto *MemBehaviorAA =
8283 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8284 if (!MemBehaviorAA)
8285 break;
8286 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8287 // and at least "known".
8288 intersectAssumedBits(MemBehaviorAA->getAssumed());
8289 return;
8290 }
8291 };
8292
8293 // Generally, look at the "may-properties" and adjust the assumed state if we
8294 // did not trigger special handling before.
8295 if (UserI->mayReadFromMemory())
8296 removeAssumedBits(NO_READS);
8297 if (UserI->mayWriteToMemory())
8298 removeAssumedBits(NO_WRITES);
8299}
8300} // namespace
8301
8302/// -------------------- Memory Locations Attributes ---------------------------
8303/// Includes read-none, argmemonly, inaccessiblememonly,
8304/// inaccessiblememorargmemonly
8305/// ----------------------------------------------------------------------------
8306
8309 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8310 return "all memory";
8312 return "no memory";
8313 std::string S = "memory:";
8314 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8315 S += "stack,";
8316 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8317 S += "constant,";
8319 S += "internal global,";
8321 S += "external global,";
8322 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8323 S += "argument,";
8325 S += "inaccessible,";
8326 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8327 S += "malloced,";
8328 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8329 S += "unknown,";
8330 S.pop_back();
8331 return S;
8332}
8333
8334namespace {
8335struct AAMemoryLocationImpl : public AAMemoryLocation {
8336
8337 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8338 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8339 AccessKind2Accesses.fill(nullptr);
8340 }
8341
8342 ~AAMemoryLocationImpl() override {
8343 // The AccessSets are allocated via a BumpPtrAllocator, we call
8344 // the destructor manually.
8345 for (AccessSet *AS : AccessKind2Accesses)
8346 if (AS)
8347 AS->~AccessSet();
8348 }
8349
8350 void initialize(Attributor &A) override {
8351 intersectAssumedBits(BEST_STATE);
8352 getKnownStateFromValue(A, getIRPosition(), getState());
8353 AAMemoryLocation::initialize(A);
8354 }
8355
8356 /// Return the memory behavior information encoded in the IR for \p IRP.
8357 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8358 BitIntegerState &State,
8359 bool IgnoreSubsumingPositions = false) {
8360 // For internal functions we ignore `argmemonly` and
8361 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8362 // constant propagation. It is unclear if this is the best way but it is
8363 // unlikely this will cause real performance problems. If we are deriving
8364 // attributes for the anchor function we even remove the attribute in
8365 // addition to ignoring it.
8366 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8367 // MemoryEffects::Other as a possible location.
8368 bool UseArgMemOnly = true;
8369 Function *AnchorFn = IRP.getAnchorScope();
8370 if (AnchorFn && A.isRunOn(*AnchorFn))
8371 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8372
8374 A.getAttrs(IRP, {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8375 for (const Attribute &Attr : Attrs) {
8376 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8377 MemoryEffects ME = Attr.getMemoryEffects();
8378 if (ME.doesNotAccessMemory()) {
8379 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8380 continue;
8381 }
8382 if (ME.onlyAccessesInaccessibleMem()) {
8383 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8384 continue;
8385 }
8386 if (ME.onlyAccessesArgPointees()) {
8387 if (UseArgMemOnly)
8388 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8389 else {
8390 // Remove location information, only keep read/write info.
8391 ME = MemoryEffects(ME.getModRef());
8392 A.manifestAttrs(IRP,
8393 Attribute::getWithMemoryEffects(
8394 IRP.getAnchorValue().getContext(), ME),
8395 /*ForceReplace*/ true);
8396 }
8397 continue;
8398 }
8400 if (UseArgMemOnly)
8401 State.addKnownBits(inverseLocation(
8402 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8403 else {
8404 // Remove location information, only keep read/write info.
8405 ME = MemoryEffects(ME.getModRef());
8406 A.manifestAttrs(IRP,
8407 Attribute::getWithMemoryEffects(
8408 IRP.getAnchorValue().getContext(), ME),
8409 /*ForceReplace*/ true);
8410 }
8411 continue;
8412 }
8413 }
8414 }
8415
8416 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
8417 SmallVectorImpl<Attribute> &Attrs) const override {
8418 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8419 assert(Attrs.size() == 0);
8420 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8421 if (isAssumedReadNone())
8422 Attrs.push_back(
8423 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8424 else if (isAssumedInaccessibleMemOnly())
8425 Attrs.push_back(Attribute::getWithMemoryEffects(
8427 else if (isAssumedArgMemOnly())
8428 Attrs.push_back(
8429 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8430 else if (isAssumedInaccessibleOrArgMemOnly())
8431 Attrs.push_back(Attribute::getWithMemoryEffects(
8433 }
8434 assert(Attrs.size() <= 1);
8435 }
8436
8437 ChangeStatus manifest(Attributor &A) override {
8438 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8439 // provide per-location modref information here.
8440 const IRPosition &IRP = getIRPosition();
8441
8442 SmallVector<Attribute, 1> DeducedAttrs;
8443 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
8444 if (DeducedAttrs.size() != 1)
8445 return ChangeStatus::UNCHANGED;
8446 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8447
8448 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8449 IRP.getAnchorValue().getContext(), ME));
8450 }
8451
8452 bool checkForAllAccessesToMemoryKind(
8453 function_ref<bool(const Instruction *, const Value *, AccessKind,
8454 MemoryLocationsKind)>
8455 Pred,
8456 MemoryLocationsKind RequestedMLK) const override {
8457 if (!isValidState())
8458 return false;
8459
8460 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8461 if (AssumedMLK == NO_LOCATIONS)
8462 return true;
8463
8464 unsigned Idx = 0;
8465 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8466 CurMLK *= 2, ++Idx) {
8467 if (CurMLK & RequestedMLK)
8468 continue;
8469
8470 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8471 for (const AccessInfo &AI : *Accesses)
8472 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8473 return false;
8474 }
8475
8476 return true;
8477 }
8478
8479 ChangeStatus indicatePessimisticFixpoint() override {
8480 // If we give up and indicate a pessimistic fixpoint this instruction will
8481 // become an access for all potential access kinds:
8482 // TODO: Add pointers for argmemonly and globals to improve the results of
8483 // checkForAllAccessesToMemoryKind.
8484 bool Changed = false;
8485 MemoryLocationsKind KnownMLK = getKnown();
8486 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8487 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8488 if (!(CurMLK & KnownMLK))
8489 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8490 getAccessKindFromInst(I));
8491 return AAMemoryLocation::indicatePessimisticFixpoint();
8492 }
8493
8494protected:
8495 /// Helper struct to tie together an instruction that has a read or write
8496 /// effect with the pointer it accesses (if any).
8497 struct AccessInfo {
8498
8499 /// The instruction that caused the access.
8500 const Instruction *I;
8501
8502 /// The base pointer that is accessed, or null if unknown.
8503 const Value *Ptr;
8504
8505 /// The kind of access (read/write/read+write).
8507
8508 bool operator==(const AccessInfo &RHS) const {
8509 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8510 }
8511 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8512 if (LHS.I != RHS.I)
8513 return LHS.I < RHS.I;
8514 if (LHS.Ptr != RHS.Ptr)
8515 return LHS.Ptr < RHS.Ptr;
8516 if (LHS.Kind != RHS.Kind)
8517 return LHS.Kind < RHS.Kind;
8518 return false;
8519 }
8520 };
8521
8522 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8523 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8524 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8525 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8526 AccessKind2Accesses;
8527
8528 /// Categorize the pointer arguments of CB that might access memory in
8529 /// AccessedLoc and update the state and access map accordingly.
8530 void
8531 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8532 AAMemoryLocation::StateType &AccessedLocs,
8533 bool &Changed);
8534
8535 /// Return the kind(s) of location that may be accessed by \p V.
8537 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8538
8539 /// Return the access kind as determined by \p I.
8540 AccessKind getAccessKindFromInst(const Instruction *I) {
8541 AccessKind AK = READ_WRITE;
8542 if (I) {
8543 AK = I->mayReadFromMemory() ? READ : NONE;
8544 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8545 }
8546 return AK;
8547 }
8548
8549 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8550 /// an access of kind \p AK to a \p MLK memory location with the access
8551 /// pointer \p Ptr.
8552 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8553 MemoryLocationsKind MLK, const Instruction *I,
8554 const Value *Ptr, bool &Changed,
8555 AccessKind AK = READ_WRITE) {
8556
8557 assert(isPowerOf2_32(MLK) && "Expected a single location set!");
8558 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8559 if (!Accesses)
8560 Accesses = new (Allocator) AccessSet();
8561 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8562 if (MLK == NO_UNKOWN_MEM)
8563 MLK = NO_LOCATIONS;
8564 State.removeAssumedBits(MLK);
8565 }
8566
8567 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8568 /// arguments, and update the state and access map accordingly.
8569 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8570 AAMemoryLocation::StateType &State, bool &Changed,
8571 unsigned AccessAS = 0);
8572
8573 /// Used to allocate access sets.
8575};
8576
8577void AAMemoryLocationImpl::categorizePtrValue(
8578 Attributor &A, const Instruction &I, const Value &Ptr,
8579 AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {
8580 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
8581 << Ptr << " ["
8582 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");
8583
8584 auto Pred = [&](Value &Obj) {
8585 unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();
8586 // TODO: recognize the TBAA used for constant accesses.
8587 MemoryLocationsKind MLK = NO_LOCATIONS;
8588
8589 // Filter accesses to constant (GPU) memory if we have an AS at the access
8590 // site or the object is known to actually have the associated AS.
8591 if (AA::isGPU(A.getModule())) {
8592 if (AA::isGPUConstantAddressSpace(A.getModule(), AccessAS) ||
8593 (AA::isGPUConstantAddressSpace(A.getModule(), ObjectAS) &&
8594 isIdentifiedObject(&Obj)))
8595 return true;
8596 }
8597
8598 if (isa<UndefValue>(&Obj))
8599 return true;
8600 if (isa<Argument>(&Obj)) {
8601 // TODO: For now we do not treat byval arguments as local copies performed
8602 // on the call edge, though, we should. To make that happen we need to
8603 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8604 // would also allow us to mark functions only accessing byval arguments as
8605 // readnone again, arguably their accesses have no effect outside of the
8606 // function, like accesses to allocas.
8607 MLK = NO_ARGUMENT_MEM;
8608 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8609 // Reading constant memory is not treated as a read "effect" by the
8610 // function attr pass so we won't neither. Constants defined by TBAA are
8611 // similar. (We know we do not write it because it is constant.)
8612 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8613 if (GVar->isConstant())
8614 return true;
8615
8616 if (GV->hasLocalLinkage())
8617 MLK = NO_GLOBAL_INTERNAL_MEM;
8618 else
8619 MLK = NO_GLOBAL_EXTERNAL_MEM;
8620 } else if (isa<ConstantPointerNull>(&Obj) && ObjectAS == AccessAS &&
8621 !NullPointerIsDefined(getAssociatedFunction(), AccessAS)) {
8622 // Accessing null is undefined, but not accessing a null pointer cast to
8623 // another address space, which may be a valid address there.
8624 return true;
8625 } else if (isa<AllocaInst>(&Obj)) {
8626 MLK = NO_LOCAL_MEM;
8627 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8628 bool IsKnownNoAlias;
8631 IsKnownNoAlias))
8632 MLK = NO_MALLOCED_MEM;
8633 else
8634 MLK = NO_UNKOWN_MEM;
8635 } else {
8636 MLK = NO_UNKOWN_MEM;
8637 }
8638
8639 assert(MLK != NO_LOCATIONS && "No location specified!");
8640 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
8641 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
8642 updateStateAndAccessesMap(State, MLK, &I, &Obj, Changed,
8643 getAccessKindFromInst(&I));
8644
8645 return true;
8646 };
8647
8648 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
8650 if (!AA || !AA->forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8651 LLVM_DEBUG(
8652 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
8653 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8654 getAccessKindFromInst(&I));
8655 return;
8656 }
8657
8658 LLVM_DEBUG(
8659 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
8660 << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
8661}
8662
8663void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8664 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8665 bool &Changed) {
8666 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8667
8668 // Skip non-pointer arguments.
8669 const Value *ArgOp = CB.getArgOperand(ArgNo);
8670 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8671 continue;
8672
8673 // Skip readnone arguments.
8674 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8675 const auto *ArgOpMemLocationAA =
8676 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8677
8678 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8679 continue;
8680
8681 // Categorize potentially accessed pointer arguments as if there was an
8682 // access instruction with them as pointer.
8683 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8684 }
8685}
8686
8688AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8689 bool &Changed) {
8690 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
8691 << I << "\n");
8692
8693 AAMemoryLocation::StateType AccessedLocs;
8694 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8695
8696 if (auto *CB = dyn_cast<CallBase>(&I)) {
8697
8698 // First check if we assume any memory is access is visible.
8699 const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8701 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
8702 << " [" << CBMemLocationAA << "]\n");
8703 if (!CBMemLocationAA) {
8704 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr,
8705 Changed, getAccessKindFromInst(&I));
8706 return NO_UNKOWN_MEM;
8707 }
8708
8709 if (CBMemLocationAA->isAssumedReadNone())
8710 return NO_LOCATIONS;
8711
8712 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8713 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8714 Changed, getAccessKindFromInst(&I));
8715 return AccessedLocs.getAssumed();
8716 }
8717
8718 uint32_t CBAssumedNotAccessedLocs =
8719 CBMemLocationAA->getAssumedNotAccessedLocation();
8720
8721 // Set the argmemonly and global bit as we handle them separately below.
8722 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8723 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8724
8725 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8726 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8727 continue;
8728 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8729 getAccessKindFromInst(&I));
8730 }
8731
8732 // Now handle global memory if it might be accessed. This is slightly tricky
8733 // as NO_GLOBAL_MEM has multiple bits set.
8734 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8735 if (HasGlobalAccesses) {
8736 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8737 AccessKind Kind, MemoryLocationsKind MLK) {
8738 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8739 getAccessKindFromInst(&I));
8740 return true;
8741 };
8742 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8743 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8744 return AccessedLocs.getWorstState();
8745 }
8746
8747 LLVM_DEBUG(
8748 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
8749 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8750
8751 // Now handle argument memory if it might be accessed.
8752 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8753 if (HasArgAccesses)
8754 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8755
8756 LLVM_DEBUG(
8757 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
8758 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8759
8760 return AccessedLocs.getAssumed();
8761 }
8762
8763 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8764 LLVM_DEBUG(
8765 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
8766 << I << " [" << *Ptr << "]\n");
8767 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed,
8768 Ptr->getType()->getPointerAddressSpace());
8769 return AccessedLocs.getAssumed();
8770 }
8771
8772 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
8773 << I << "\n");
8774 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8775 getAccessKindFromInst(&I));
8776 return AccessedLocs.getAssumed();
8777}
8778
8779/// An AA to represent the memory behavior function attributes.
8780struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8781 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8782 : AAMemoryLocationImpl(IRP, A) {}
8783
8784 ChangeStatus updateImpl(Attributor &A) override {
8785
8786 const auto *MemBehaviorAA =
8787 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8788 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
8789 if (MemBehaviorAA->isKnownReadNone())
8790 return indicateOptimisticFixpoint();
8792 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8793 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8794 return ChangeStatus::UNCHANGED;
8795 }
8796
8797 // The current assumed state used to determine a change.
8798 auto AssumedState = getAssumed();
8799 bool Changed = false;
8800
8801 auto CheckRWInst = [&](Instruction &I) {
8802 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8803 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
8804 << ": " << getMemoryLocationsAsStr(MLK) << "\n");
8805 removeAssumedBits(inverseLocation(MLK, false, false));
8806 // Stop once only the valid bit set in the *not assumed location*, thus
8807 // once we don't actually exclude any memory locations in the state.
8808 return getAssumedNotAccessedLocation() != VALID_STATE;
8809 };
8810
8811 bool UsedAssumedInformation = false;
8812 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8813 UsedAssumedInformation))
8814 return indicatePessimisticFixpoint();
8815
8816 Changed |= AssumedState != getAssumed();
8817 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8818 }
8819
8820 void trackStatistics() const override {
8821 if (isAssumedReadNone())
8822 STATS_DECLTRACK_FN_ATTR(readnone)
8823 else if (isAssumedArgMemOnly())
8824 STATS_DECLTRACK_FN_ATTR(argmemonly)
8825 else if (isAssumedInaccessibleMemOnly())
8826 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
8827 else if (isAssumedInaccessibleOrArgMemOnly())
8828 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
8829 }
8830};
8831
8832/// AAMemoryLocation attribute for call sites.
8833struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8834 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8835 : AAMemoryLocationImpl(IRP, A) {}
8836
8837 ChangeStatus updateImpl(Attributor &A) override {
8838 // TODO: Once we have call site specific value information we can provide
8839 // call site specific liveness liveness information and then it makes
8840 // sense to specialize attributes for call sites arguments instead of
8841 // redirecting requests to the callee argument.
8842 Function *F = getAssociatedFunction();
8843 const IRPosition &FnPos = IRPosition::function(*F);
8844 auto *FnAA =
8845 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
8846 if (!FnAA)
8847 return indicatePessimisticFixpoint();
8848 bool Changed = false;
8849 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8850 AccessKind Kind, MemoryLocationsKind MLK) {
8851 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
8852 getAccessKindFromInst(I));
8853 return true;
8854 };
8855 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8856 return indicatePessimisticFixpoint();
8857 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8858 }
8859
8860 void trackStatistics() const override {
8861 if (isAssumedReadNone())
8862 STATS_DECLTRACK_CS_ATTR(readnone)
8863 }
8864};
8865} // namespace
8866
8867/// ------------------ denormal-fp-math Attribute -------------------------
8868
8869namespace {
8870struct AADenormalFPMathImpl : public AADenormalFPMath {
8871 AADenormalFPMathImpl(const IRPosition &IRP, Attributor &A)
8872 : AADenormalFPMath(IRP, A) {}
8873
8874 const std::string getAsStr(Attributor *A) const override {
8875 std::string Str("AADenormalFPMath[");
8876 raw_string_ostream OS(Str);
8877
8878 DenormalState Known = getKnown();
8879 if (Known.Mode.isValid())
8880 OS << "denormal-fp-math=" << Known.Mode;
8881 else
8882 OS << "invalid";
8883
8884 if (Known.ModeF32.isValid())
8885 OS << " denormal-fp-math-f32=" << Known.ModeF32;
8886 OS << ']';
8887 return Str;
8888 }
8889};
8890
8891struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
8892 AADenormalFPMathFunction(const IRPosition &IRP, Attributor &A)
8893 : AADenormalFPMathImpl(IRP, A) {}
8894
8895 void initialize(Attributor &A) override {
8896 const Function *F = getAnchorScope();
8897 DenormalFPEnv DenormEnv = F->getDenormalFPEnv();
8898
8899 Known = DenormalState{DenormEnv.DefaultMode, DenormEnv.F32Mode};
8900 if (isModeFixed())
8901 indicateFixpoint();
8902 }
8903
8904 ChangeStatus updateImpl(Attributor &A) override {
8905 ChangeStatus Change = ChangeStatus::UNCHANGED;
8906
8907 auto CheckCallSite = [=, &Change, &A](AbstractCallSite CS) {
8908 Function *Caller = CS.getInstruction()->getFunction();
8909 LLVM_DEBUG(dbgs() << "[AADenormalFPMath] Call " << Caller->getName()
8910 << "->" << getAssociatedFunction()->getName() << '\n');
8911
8912 const auto *CallerInfo = A.getAAFor<AADenormalFPMath>(
8913 *this, IRPosition::function(*Caller), DepClassTy::REQUIRED);
8914 if (!CallerInfo)
8915 return false;
8916
8917 Change = Change | clampStateAndIndicateChange(this->getState(),
8918 CallerInfo->getState());
8919 return true;
8920 };
8921
8922 bool AllCallSitesKnown = true;
8923 if (!A.checkForAllCallSites(CheckCallSite, *this, true, AllCallSitesKnown))
8924 return indicatePessimisticFixpoint();
8925
8926 if (Change == ChangeStatus::CHANGED && isModeFixed())
8927 indicateFixpoint();
8928 return Change;
8929 }
8930
8931 ChangeStatus manifest(Attributor &A) override {
8932 LLVMContext &Ctx = getAssociatedFunction()->getContext();
8933
8934 SmallVector<Attribute, 2> AttrToAdd;
8936
8937 // TODO: Change to use DenormalFPEnv everywhere.
8938 DenormalFPEnv KnownEnv(Known.Mode, Known.ModeF32);
8939
8940 if (KnownEnv == DenormalFPEnv::getDefault()) {
8941 AttrToRemove.push_back(Attribute::DenormalFPEnv);
8942 } else {
8943 AttrToAdd.push_back(Attribute::get(
8944 Ctx, Attribute::DenormalFPEnv,
8945 DenormalFPEnv(Known.Mode, Known.ModeF32).toIntValue()));
8946 }
8947
8948 auto &IRP = getIRPosition();
8949
8950 // TODO: There should be a combined add and remove API.
8951 return A.removeAttrs(IRP, AttrToRemove) |
8952 A.manifestAttrs(IRP, AttrToAdd, /*ForceReplace=*/true);
8953 }
8954
8955 void trackStatistics() const override {
8956 STATS_DECLTRACK_FN_ATTR(denormal_fpenv)
8957 }
8958};
8959} // namespace
8960
8961/// ------------------ Value Constant Range Attribute -------------------------
8962
8963namespace {
8964struct AAValueConstantRangeImpl : AAValueConstantRange {
8965 using StateType = IntegerRangeState;
8966 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
8967 : AAValueConstantRange(IRP, A) {}
8968
8969 void initialize(Attributor &A) override {
8970 if (A.hasSimplificationCallback(getIRPosition())) {
8971 indicatePessimisticFixpoint();
8972 return;
8973 }
8974
8975 // Intersect a range given by SCEV.
8976 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
8977
8978 // Intersect a range given by LVI.
8979 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
8980 }
8981
8982 const std::string getAsStr(Attributor *A) const override {
8983 std::string Str;
8984 llvm::raw_string_ostream OS(Str);
8985 OS << "range(" << getBitWidth() << ")<";
8986 getKnown().print(OS);
8987 OS << " / ";
8988 getAssumed().print(OS);
8989 OS << ">";
8990 return Str;
8991 }
8992
8993 /// Helper function to get a SCEV expr for the associated value at program
8994 /// point \p I.
8995 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
8996 if (!getAnchorScope())
8997 return nullptr;
8998
8999 ScalarEvolution *SE =
9000 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9001 *getAnchorScope());
9002
9003 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9004 *getAnchorScope());
9005
9006 if (!SE || !LI)
9007 return nullptr;
9008
9009 const SCEV *S = SE->getSCEV(&getAssociatedValue());
9010 if (!I)
9011 return S;
9012
9013 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
9014 }
9015
9016 /// Helper function to get a range from SCEV for the associated value at
9017 /// program point \p I.
9018 ConstantRange getConstantRangeFromSCEV(Attributor &A,
9019 const Instruction *I = nullptr) const {
9020 if (!getAnchorScope())
9021 return getWorstState(getBitWidth());
9022
9023 ScalarEvolution *SE =
9024 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9025 *getAnchorScope());
9026
9027 const SCEV *S = getSCEV(A, I);
9028 if (!SE || !S)
9029 return getWorstState(getBitWidth());
9030
9031 return SE->getUnsignedRange(S);
9032 }
9033
9034 /// Helper function to get a range from LVI for the associated value at
9035 /// program point \p I.
9036 ConstantRange
9037 getConstantRangeFromLVI(Attributor &A,
9038 const Instruction *CtxI = nullptr) const {
9039 if (!getAnchorScope())
9040 return getWorstState(getBitWidth());
9041
9042 LazyValueInfo *LVI =
9043 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9044 *getAnchorScope());
9045
9046 if (!LVI || !CtxI)
9047 return getWorstState(getBitWidth());
9048 return LVI->getConstantRange(&getAssociatedValue(),
9049 const_cast<Instruction *>(CtxI),
9050 /*UndefAllowed*/ false);
9051 }
9052
9053 /// Return true if \p CtxI is valid for querying outside analyses.
9054 /// This basically makes sure we do not ask intra-procedural analysis
9055 /// about a context in the wrong function or a context that violates
9056 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
9057 /// if the original context of this AA is OK or should be considered invalid.
9058 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
9059 const Instruction *CtxI,
9060 bool AllowAACtxI) const {
9061 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9062 return false;
9063
9064 // Our context might be in a different function, neither intra-procedural
9065 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
9066 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
9067 return false;
9068
9069 // If the context is not dominated by the value there are paths to the
9070 // context that do not define the value. This cannot be handled by
9071 // LazyValueInfo so we need to bail.
9072 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
9073 InformationCache &InfoCache = A.getInfoCache();
9074 const DominatorTree *DT =
9075 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
9076 *I->getFunction());
9077 return DT && DT->dominates(I, CtxI);
9078 }
9079
9080 return true;
9081 }
9082
9083 ConstantRange
9084 getAssumedConstantRange(Attributor &A,
9085 const Instruction *CtxI = nullptr) const override {
9086 // TODO: Make SCEV use Attributor assumption.
9087 // We may be able to bound a variable range via assumptions in
9088 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
9089 // evolve to x^2 + x, then we can say that y is in [2, 12].
9090 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9091 /* AllowAACtxI */ false))
9092 return getAssumed();
9093
9094 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9095 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9096 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9097 }
9098
9099 /// Helper function to create MDNode for range metadata.
9100 static MDNode *
9101 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
9102 const ConstantRange &AssumedConstantRange) {
9103 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
9104 Ty, AssumedConstantRange.getLower())),
9105 ConstantAsMetadata::get(ConstantInt::get(
9106 Ty, AssumedConstantRange.getUpper()))};
9107 return MDNode::get(Ctx, LowAndHigh);
9108 }
9109
9110 /// Return true if \p Assumed is included in ranges from instruction \p I.
9111 static bool isBetterRange(const ConstantRange &Assumed,
9112 const Instruction &I) {
9113 if (Assumed.isFullSet())
9114 return false;
9115
9116 std::optional<ConstantRange> Known;
9117
9118 if (const auto *CB = dyn_cast<CallBase>(&I)) {
9119 Known = CB->getRange();
9120 } else if (MDNode *KnownRanges = I.getMetadata(LLVMContext::MD_range)) {
9121 // If multiple ranges are annotated in IR, we give up to annotate assumed
9122 // range for now.
9123
9124 // TODO: If there exists a known range which containts assumed range, we
9125 // can say assumed range is better.
9126 if (KnownRanges->getNumOperands() > 2)
9127 return false;
9128
9129 ConstantInt *Lower =
9130 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
9131 ConstantInt *Upper =
9132 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
9133
9134 Known.emplace(Lower->getValue(), Upper->getValue());
9135 }
9136 return !Known || (*Known != Assumed && Known->contains(Assumed));
9137 }
9138
9139 /// Helper function to set range metadata.
9140 static bool
9141 setRangeMetadataIfisBetterRange(Instruction *I,
9142 const ConstantRange &AssumedConstantRange) {
9143 if (isBetterRange(AssumedConstantRange, *I)) {
9144 I->setMetadata(LLVMContext::MD_range,
9145 getMDNodeForConstantRange(I->getType(), I->getContext(),
9146 AssumedConstantRange));
9147 return true;
9148 }
9149 return false;
9150 }
9151 /// Helper function to set range return attribute.
9152 static bool
9153 setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,
9154 Instruction *I,
9155 const ConstantRange &AssumedConstantRange) {
9156 if (isBetterRange(AssumedConstantRange, *I)) {
9157 A.manifestAttrs(IRP,
9158 Attribute::get(I->getContext(), Attribute::Range,
9159 AssumedConstantRange),
9160 /*ForceReplace*/ true);
9161 return true;
9162 }
9163 return false;
9164 }
9165
9166 ChangeStatus manifest(Attributor &A) override {
9167 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9168 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9169 assert(!AssumedConstantRange.isFullSet() && "Invalid state");
9170
9171 auto &V = getAssociatedValue();
9172 if (!AssumedConstantRange.isEmptySet() &&
9173 !AssumedConstantRange.isSingleElement()) {
9174 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9175 assert(I == getCtxI() && "Should not annotate an instruction which is "
9176 "not the context instruction");
9177 if (isa<LoadInst>(I))
9178 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9179 Changed = ChangeStatus::CHANGED;
9180 if (isa<CallInst>(I))
9181 if (setRangeRetAttrIfisBetterRange(A, getIRPosition(), I,
9182 AssumedConstantRange))
9183 Changed = ChangeStatus::CHANGED;
9184 }
9185 }
9186
9187 return Changed;
9188 }
9189};
9190
9191struct AAValueConstantRangeArgument final
9192 : AAArgumentFromCallSiteArguments<
9193 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9194 true /* BridgeCallBaseContext */> {
9195 using Base = AAArgumentFromCallSiteArguments<
9196 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9197 true /* BridgeCallBaseContext */>;
9198 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9199 : Base(IRP, A) {}
9200
9201 void trackStatistics() const override {
9202 STATS_DECLTRACK_ARG_ATTR(value_range)
9203 }
9204};
9205
9206struct AAValueConstantRangeReturned
9207 : AAReturnedFromReturnedValues<AAValueConstantRange,
9208 AAValueConstantRangeImpl,
9209 AAValueConstantRangeImpl::StateType,
9210 /* PropagateCallBaseContext */ true> {
9211 using Base =
9212 AAReturnedFromReturnedValues<AAValueConstantRange,
9213 AAValueConstantRangeImpl,
9214 AAValueConstantRangeImpl::StateType,
9215 /* PropagateCallBaseContext */ true>;
9216 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9217 : Base(IRP, A) {}
9218
9219 void initialize(Attributor &A) override {
9220 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9221 indicatePessimisticFixpoint();
9222 }
9223
9224 void trackStatistics() const override {
9225 STATS_DECLTRACK_FNRET_ATTR(value_range)
9226 }
9227};
9228
9229struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9230 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9231 : AAValueConstantRangeImpl(IRP, A) {}
9232
9233 void initialize(Attributor &A) override {
9234 AAValueConstantRangeImpl::initialize(A);
9235 if (isAtFixpoint())
9236 return;
9237
9238 Value &V = getAssociatedValue();
9239
9240 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9241 unionAssumed(ConstantRange(C->getValue()));
9242 indicateOptimisticFixpoint();
9243 return;
9244 }
9245
9246 if (isa<UndefValue>(&V)) {
9247 // Collapse the undef state to 0.
9248 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9249 indicateOptimisticFixpoint();
9250 return;
9251 }
9252
9253 if (isa<CallBase>(&V))
9254 return;
9255
9257 return;
9258
9259 // If it is a load instruction with range metadata, use it.
9260 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9261 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9262 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9263 return;
9264 }
9265
9266 // We can work with PHI and select instruction as we traverse their operands
9267 // during update.
9269 return;
9270
9271 // Otherwise we give up.
9272 indicatePessimisticFixpoint();
9273
9274 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
9275 << getAssociatedValue() << "\n");
9276 }
9277
9278 bool calculateBinaryOperator(
9279 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9280 const Instruction *CtxI,
9281 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9282 Value *LHS = BinOp->getOperand(0);
9283 Value *RHS = BinOp->getOperand(1);
9284
9285 // Simplify the operands first.
9286 bool UsedAssumedInformation = false;
9287 const auto &SimplifiedLHS = A.getAssumedSimplified(
9288 IRPosition::value(*LHS, getCallBaseContext()), *this,
9289 UsedAssumedInformation, AA::Interprocedural);
9290 if (!SimplifiedLHS.has_value())
9291 return true;
9292 if (!*SimplifiedLHS)
9293 return false;
9294 LHS = *SimplifiedLHS;
9295
9296 const auto &SimplifiedRHS = A.getAssumedSimplified(
9297 IRPosition::value(*RHS, getCallBaseContext()), *this,
9298 UsedAssumedInformation, AA::Interprocedural);
9299 if (!SimplifiedRHS.has_value())
9300 return true;
9301 if (!*SimplifiedRHS)
9302 return false;
9303 RHS = *SimplifiedRHS;
9304
9305 // TODO: Allow non integers as well.
9306 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9307 return false;
9308
9309 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9310 *this, IRPosition::value(*LHS, getCallBaseContext()),
9311 DepClassTy::REQUIRED);
9312 if (!LHSAA)
9313 return false;
9314 QuerriedAAs.push_back(LHSAA);
9315 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9316
9317 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9318 *this, IRPosition::value(*RHS, getCallBaseContext()),
9319 DepClassTy::REQUIRED);
9320 if (!RHSAA)
9321 return false;
9322 QuerriedAAs.push_back(RHSAA);
9323 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9324
9325 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9326
9327 T.unionAssumed(AssumedRange);
9328
9329 // TODO: Track a known state too.
9330
9331 return T.isValidState();
9332 }
9333
9334 bool calculateCastInst(
9335 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9336 const Instruction *CtxI,
9337 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9338 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
9339 // TODO: Allow non integers as well.
9340 Value *OpV = CastI->getOperand(0);
9341
9342 // Simplify the operand first.
9343 bool UsedAssumedInformation = false;
9344 const auto &SimplifiedOpV = A.getAssumedSimplified(
9345 IRPosition::value(*OpV, getCallBaseContext()), *this,
9346 UsedAssumedInformation, AA::Interprocedural);
9347 if (!SimplifiedOpV.has_value())
9348 return true;
9349 if (!*SimplifiedOpV)
9350 return false;
9351 OpV = *SimplifiedOpV;
9352
9353 if (!OpV->getType()->isIntegerTy())
9354 return false;
9355
9356 auto *OpAA = A.getAAFor<AAValueConstantRange>(
9357 *this, IRPosition::value(*OpV, getCallBaseContext()),
9358 DepClassTy::REQUIRED);
9359 if (!OpAA)
9360 return false;
9361 QuerriedAAs.push_back(OpAA);
9362 T.unionAssumed(OpAA->getAssumed().castOp(CastI->getOpcode(),
9363 getState().getBitWidth()));
9364 return T.isValidState();
9365 }
9366
9367 bool
9368 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9369 const Instruction *CtxI,
9370 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9371 Value *LHS = CmpI->getOperand(0);
9372 Value *RHS = CmpI->getOperand(1);
9373
9374 // Simplify the operands first.
9375 bool UsedAssumedInformation = false;
9376 const auto &SimplifiedLHS = A.getAssumedSimplified(
9377 IRPosition::value(*LHS, getCallBaseContext()), *this,
9378 UsedAssumedInformation, AA::Interprocedural);
9379 if (!SimplifiedLHS.has_value())
9380 return true;
9381 if (!*SimplifiedLHS)
9382 return false;
9383 LHS = *SimplifiedLHS;
9384
9385 const auto &SimplifiedRHS = A.getAssumedSimplified(
9386 IRPosition::value(*RHS, getCallBaseContext()), *this,
9387 UsedAssumedInformation, AA::Interprocedural);
9388 if (!SimplifiedRHS.has_value())
9389 return true;
9390 if (!*SimplifiedRHS)
9391 return false;
9392 RHS = *SimplifiedRHS;
9393
9394 // TODO: Allow non integers as well.
9395 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9396 return false;
9397
9398 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9399 *this, IRPosition::value(*LHS, getCallBaseContext()),
9400 DepClassTy::REQUIRED);
9401 if (!LHSAA)
9402 return false;
9403 QuerriedAAs.push_back(LHSAA);
9404 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9405 *this, IRPosition::value(*RHS, getCallBaseContext()),
9406 DepClassTy::REQUIRED);
9407 if (!RHSAA)
9408 return false;
9409 QuerriedAAs.push_back(RHSAA);
9410 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9411 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9412
9413 // If one of them is empty set, we can't decide.
9414 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9415 return true;
9416
9417 bool MustTrue = false, MustFalse = false;
9418
9419 auto AllowedRegion =
9421
9422 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9423 MustFalse = true;
9424
9425 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9426 MustTrue = true;
9427
9428 assert((!MustTrue || !MustFalse) &&
9429 "Either MustTrue or MustFalse should be false!");
9430
9431 if (MustTrue)
9432 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9433 else if (MustFalse)
9434 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9435 else
9436 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9437
9438 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "
9439 << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))
9440 << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"
9441 << *RHSAA);
9442
9443 // TODO: Track a known state too.
9444 return T.isValidState();
9445 }
9446
9447 ChangeStatus updateImpl(Attributor &A) override {
9448
9449 IntegerRangeState T(getBitWidth());
9450 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9452 if (!I || isa<CallBase>(I)) {
9453
9454 // Simplify the operand first.
9455 bool UsedAssumedInformation = false;
9456 const auto &SimplifiedOpV = A.getAssumedSimplified(
9457 IRPosition::value(V, getCallBaseContext()), *this,
9458 UsedAssumedInformation, AA::Interprocedural);
9459 if (!SimplifiedOpV.has_value())
9460 return true;
9461 if (!*SimplifiedOpV)
9462 return false;
9463 Value *VPtr = *SimplifiedOpV;
9464
9465 // If the value is not instruction, we query AA to Attributor.
9466 const auto *AA = A.getAAFor<AAValueConstantRange>(
9467 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9468 DepClassTy::REQUIRED);
9469
9470 // Clamp operator is not used to utilize a program point CtxI.
9471 if (AA)
9472 T.unionAssumed(AA->getAssumedConstantRange(A, CtxI));
9473 else
9474 return false;
9475
9476 return T.isValidState();
9477 }
9478
9480 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9481 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9482 return false;
9483 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9484 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9485 return false;
9486 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9487 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9488 return false;
9489 } else {
9490 // Give up with other instructions.
9491 // TODO: Add other instructions
9492
9493 T.indicatePessimisticFixpoint();
9494 return false;
9495 }
9496
9497 // Catch circular reasoning in a pessimistic way for now.
9498 // TODO: Check how the range evolves and if we stripped anything, see also
9499 // AADereferenceable or AAAlign for similar situations.
9500 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9501 if (QueriedAA != this)
9502 continue;
9503 // If we are in a stady state we do not need to worry.
9504 if (T.getAssumed() == getState().getAssumed())
9505 continue;
9506 T.indicatePessimisticFixpoint();
9507 }
9508
9509 return T.isValidState();
9510 };
9511
9512 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9513 return indicatePessimisticFixpoint();
9514
9515 // Ensure that long def-use chains can't cause circular reasoning either by
9516 // introducing a cutoff below.
9517 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9518 return ChangeStatus::UNCHANGED;
9519 if (++NumChanges > MaxNumChanges) {
9520 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
9521 << " but only " << MaxNumChanges
9522 << " are allowed to avoid cyclic reasoning.");
9523 return indicatePessimisticFixpoint();
9524 }
9525 return ChangeStatus::CHANGED;
9526 }
9527
9528 void trackStatistics() const override {
9530 }
9531
9532 /// Tracker to bail after too many widening steps of the constant range.
9533 int NumChanges = 0;
9534
9535 /// Upper bound for the number of allowed changes (=widening steps) for the
9536 /// constant range before we give up.
9537 static constexpr int MaxNumChanges = 5;
9538};
9539
9540struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9541 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9542 : AAValueConstantRangeImpl(IRP, A) {}
9543
9544 ChangeStatus updateImpl(Attributor &A) override {
9545 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
9546 "not be called");
9547 }
9548
9549 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
9550};
9551
9552struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9553 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9554 : AAValueConstantRangeFunction(IRP, A) {}
9555
9556 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
9557};
9558
9559struct AAValueConstantRangeCallSiteReturned
9560 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9561 AAValueConstantRangeImpl::StateType,
9562 /* IntroduceCallBaseContext */ true> {
9563 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9564 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9565 AAValueConstantRangeImpl::StateType,
9566 /* IntroduceCallBaseContext */ true>(IRP, A) {}
9567
9568 void initialize(Attributor &A) override {
9569 // If it is a call instruction with range attribute, use the range.
9570 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) {
9571 if (std::optional<ConstantRange> Range = CI->getRange())
9572 intersectKnown(*Range);
9573 }
9574
9575 AAValueConstantRangeImpl::initialize(A);
9576 }
9577
9578 void trackStatistics() const override {
9579 STATS_DECLTRACK_CSRET_ATTR(value_range)
9580 }
9581};
9582struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9583 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9584 : AAValueConstantRangeFloating(IRP, A) {}
9585
9586 ChangeStatus manifest(Attributor &A) override {
9587 return ChangeStatus::UNCHANGED;
9588 }
9589
9590 void trackStatistics() const override {
9591 STATS_DECLTRACK_CSARG_ATTR(value_range)
9592 }
9593};
9594} // namespace
9595
9596/// ------------------ Potential Values Attribute -------------------------
9597
9598namespace {
9599struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9600 using StateType = PotentialConstantIntValuesState;
9601
9602 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9603 : AAPotentialConstantValues(IRP, A) {}
9604
9605 void initialize(Attributor &A) override {
9606 if (A.hasSimplificationCallback(getIRPosition()))
9607 indicatePessimisticFixpoint();
9608 else
9609 AAPotentialConstantValues::initialize(A);
9610 }
9611
9612 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9613 bool &ContainsUndef, bool ForSelf) {
9615 bool UsedAssumedInformation = false;
9616 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9617 UsedAssumedInformation)) {
9618 // Avoid recursion when the caller is computing constant values for this
9619 // IRP itself.
9620 if (ForSelf)
9621 return false;
9622 if (!IRP.getAssociatedType()->isIntegerTy())
9623 return false;
9624 auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9625 *this, IRP, DepClassTy::REQUIRED);
9626 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9627 return false;
9628 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9629 S = PotentialValuesAA->getState().getAssumedSet();
9630 return true;
9631 }
9632
9633 // Copy all the constant values, except UndefValue. ContainsUndef is true
9634 // iff Values contains only UndefValue instances. If there are other known
9635 // constants, then UndefValue is dropped.
9636 ContainsUndef = false;
9637 for (auto &It : Values) {
9638 if (isa<UndefValue>(It.getValue())) {
9639 ContainsUndef = true;
9640 continue;
9641 }
9642 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9643 if (!CI)
9644 return false;
9645 S.insert(CI->getValue());
9646 }
9647 ContainsUndef &= S.empty();
9648
9649 return true;
9650 }
9651
9652 const std::string getAsStr(Attributor *A) const override {
9653 std::string Str;
9654 llvm::raw_string_ostream OS(Str);
9655 OS << getState();
9656 return Str;
9657 }
9658
9659 ChangeStatus updateImpl(Attributor &A) override {
9660 return indicatePessimisticFixpoint();
9661 }
9662};
9663
9664struct AAPotentialConstantValuesArgument final
9665 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9666 AAPotentialConstantValuesImpl,
9667 PotentialConstantIntValuesState> {
9668 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9669 AAPotentialConstantValuesImpl,
9671 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9672 : Base(IRP, A) {}
9673
9674 void trackStatistics() const override {
9675 STATS_DECLTRACK_ARG_ATTR(potential_values)
9676 }
9677};
9678
9679struct AAPotentialConstantValuesReturned
9680 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9681 AAPotentialConstantValuesImpl> {
9682 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9683 AAPotentialConstantValuesImpl>;
9684 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9685 : Base(IRP, A) {}
9686
9687 void initialize(Attributor &A) override {
9688 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9689 indicatePessimisticFixpoint();
9690 Base::initialize(A);
9691 }
9692
9693 void trackStatistics() const override {
9694 STATS_DECLTRACK_FNRET_ATTR(potential_values)
9695 }
9696};
9697
9698struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9699 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9700 : AAPotentialConstantValuesImpl(IRP, A) {}
9701
9702 void initialize(Attributor &A) override {
9703 AAPotentialConstantValuesImpl::initialize(A);
9704 if (isAtFixpoint())
9705 return;
9706
9707 Value &V = getAssociatedValue();
9708
9709 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9710 unionAssumed(C->getValue());
9711 indicateOptimisticFixpoint();
9712 return;
9713 }
9714
9715 if (isa<UndefValue>(&V)) {
9716 unionAssumedWithUndef();
9717 indicateOptimisticFixpoint();
9718 return;
9719 }
9720
9722 return;
9723
9725 return;
9726
9727 indicatePessimisticFixpoint();
9728
9729 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
9730 << getAssociatedValue() << "\n");
9731 }
9732
9733 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9734 const APInt &RHS) {
9735 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9736 }
9737
9738 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9739 uint32_t ResultBitWidth) {
9740 Instruction::CastOps CastOp = CI->getOpcode();
9741 switch (CastOp) {
9742 default:
9743 llvm_unreachable("unsupported or not integer cast");
9744 case Instruction::Trunc:
9745 return Src.trunc(ResultBitWidth);
9746 case Instruction::SExt:
9747 return Src.sext(ResultBitWidth);
9748 case Instruction::ZExt:
9749 return Src.zext(ResultBitWidth);
9750 case Instruction::BitCast:
9751 return Src;
9752 }
9753 }
9754
9755 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9756 const APInt &LHS, const APInt &RHS,
9757 bool &SkipOperation, bool &Unsupported) {
9758 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9759 // Unsupported is set to true when the binary operator is not supported.
9760 // SkipOperation is set to true when UB occur with the given operand pair
9761 // (LHS, RHS).
9762 // TODO: we should look at nsw and nuw keywords to handle operations
9763 // that create poison or undef value.
9764 switch (BinOpcode) {
9765 default:
9766 Unsupported = true;
9767 return LHS;
9768 case Instruction::Add:
9769 return LHS + RHS;
9770 case Instruction::Sub:
9771 return LHS - RHS;
9772 case Instruction::Mul:
9773 return LHS * RHS;
9774 case Instruction::UDiv:
9775 if (RHS.isZero()) {
9776 SkipOperation = true;
9777 return LHS;
9778 }
9779 return LHS.udiv(RHS);
9780 case Instruction::SDiv:
9781 if (RHS.isZero()) {
9782 SkipOperation = true;
9783 return LHS;
9784 }
9785 return LHS.sdiv(RHS);
9786 case Instruction::URem:
9787 if (RHS.isZero()) {
9788 SkipOperation = true;
9789 return LHS;
9790 }
9791 return LHS.urem(RHS);
9792 case Instruction::SRem:
9793 if (RHS.isZero()) {
9794 SkipOperation = true;
9795 return LHS;
9796 }
9797 return LHS.srem(RHS);
9798 case Instruction::Shl:
9799 return LHS.shl(RHS);
9800 case Instruction::LShr:
9801 return LHS.lshr(RHS);
9802 case Instruction::AShr:
9803 return LHS.ashr(RHS);
9804 case Instruction::And:
9805 return LHS & RHS;
9806 case Instruction::Or:
9807 return LHS | RHS;
9808 case Instruction::Xor:
9809 return LHS ^ RHS;
9810 }
9811 }
9812
9813 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9814 const APInt &LHS, const APInt &RHS) {
9815 bool SkipOperation = false;
9816 bool Unsupported = false;
9817 APInt Result =
9818 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9819 if (Unsupported)
9820 return false;
9821 // If SkipOperation is true, we can ignore this operand pair (L, R).
9822 if (!SkipOperation)
9823 unionAssumed(Result);
9824 return isValidState();
9825 }
9826
9827 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9828 auto AssumedBefore = getAssumed();
9829 Value *LHS = ICI->getOperand(0);
9830 Value *RHS = ICI->getOperand(1);
9831
9832 bool LHSContainsUndef = false, RHSContainsUndef = false;
9833 SetTy LHSAAPVS, RHSAAPVS;
9834 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9835 LHSContainsUndef, /* ForSelf */ false) ||
9836 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9837 RHSContainsUndef, /* ForSelf */ false))
9838 return indicatePessimisticFixpoint();
9839
9840 // TODO: make use of undef flag to limit potential values aggressively.
9841 bool MaybeTrue = false, MaybeFalse = false;
9842 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
9843 if (LHSContainsUndef && RHSContainsUndef) {
9844 // The result of any comparison between undefs can be soundly replaced
9845 // with undef.
9846 unionAssumedWithUndef();
9847 } else if (LHSContainsUndef) {
9848 for (const APInt &R : RHSAAPVS) {
9849 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9850 MaybeTrue |= CmpResult;
9851 MaybeFalse |= !CmpResult;
9852 if (MaybeTrue & MaybeFalse)
9853 return indicatePessimisticFixpoint();
9854 }
9855 } else if (RHSContainsUndef) {
9856 for (const APInt &L : LHSAAPVS) {
9857 bool CmpResult = calculateICmpInst(ICI, L, Zero);
9858 MaybeTrue |= CmpResult;
9859 MaybeFalse |= !CmpResult;
9860 if (MaybeTrue & MaybeFalse)
9861 return indicatePessimisticFixpoint();
9862 }
9863 } else {
9864 for (const APInt &L : LHSAAPVS) {
9865 for (const APInt &R : RHSAAPVS) {
9866 bool CmpResult = calculateICmpInst(ICI, L, R);
9867 MaybeTrue |= CmpResult;
9868 MaybeFalse |= !CmpResult;
9869 if (MaybeTrue & MaybeFalse)
9870 return indicatePessimisticFixpoint();
9871 }
9872 }
9873 }
9874 if (MaybeTrue)
9875 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
9876 if (MaybeFalse)
9877 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
9878 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9879 : ChangeStatus::CHANGED;
9880 }
9881
9882 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
9883 auto AssumedBefore = getAssumed();
9884 Value *LHS = SI->getTrueValue();
9885 Value *RHS = SI->getFalseValue();
9886
9887 bool UsedAssumedInformation = false;
9888 std::optional<Constant *> C = A.getAssumedConstant(
9889 *SI->getCondition(), *this, UsedAssumedInformation);
9890
9891 // Check if we only need one operand.
9892 bool OnlyLeft = false, OnlyRight = false;
9893 if (C && *C && (*C)->isOneValue())
9894 OnlyLeft = true;
9895 else if (C && *C && (*C)->isNullValue())
9896 OnlyRight = true;
9897
9898 bool LHSContainsUndef = false, RHSContainsUndef = false;
9899 SetTy LHSAAPVS, RHSAAPVS;
9900 if (!OnlyRight &&
9901 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9902 LHSContainsUndef, /* ForSelf */ false))
9903 return indicatePessimisticFixpoint();
9904
9905 if (!OnlyLeft &&
9906 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9907 RHSContainsUndef, /* ForSelf */ false))
9908 return indicatePessimisticFixpoint();
9909
9910 if (OnlyLeft || OnlyRight) {
9911 // select (true/false), lhs, rhs
9912 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9913 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9914
9915 if (Undef)
9916 unionAssumedWithUndef();
9917 else {
9918 for (const auto &It : *OpAA)
9919 unionAssumed(It);
9920 }
9921
9922 } else if (LHSContainsUndef && RHSContainsUndef) {
9923 // select i1 *, undef , undef => undef
9924 unionAssumedWithUndef();
9925 } else {
9926 for (const auto &It : LHSAAPVS)
9927 unionAssumed(It);
9928 for (const auto &It : RHSAAPVS)
9929 unionAssumed(It);
9930 }
9931 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9932 : ChangeStatus::CHANGED;
9933 }
9934
9935 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
9936 auto AssumedBefore = getAssumed();
9937 if (!CI->isIntegerCast())
9938 return indicatePessimisticFixpoint();
9939 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
9940 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
9941 Value *Src = CI->getOperand(0);
9942
9943 bool SrcContainsUndef = false;
9944 SetTy SrcPVS;
9945 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
9946 SrcContainsUndef, /* ForSelf */ false))
9947 return indicatePessimisticFixpoint();
9948
9949 if (SrcContainsUndef)
9950 unionAssumedWithUndef();
9951 else {
9952 for (const APInt &S : SrcPVS) {
9953 APInt T = calculateCastInst(CI, S, ResultBitWidth);
9954 unionAssumed(T);
9955 }
9956 }
9957 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9958 : ChangeStatus::CHANGED;
9959 }
9960
9961 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
9962 auto AssumedBefore = getAssumed();
9963 Value *LHS = BinOp->getOperand(0);
9964 Value *RHS = BinOp->getOperand(1);
9965
9966 bool LHSContainsUndef = false, RHSContainsUndef = false;
9967 SetTy LHSAAPVS, RHSAAPVS;
9968 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9969 LHSContainsUndef, /* ForSelf */ false) ||
9970 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9971 RHSContainsUndef, /* ForSelf */ false))
9972 return indicatePessimisticFixpoint();
9973
9974 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
9975
9976 // TODO: make use of undef flag to limit potential values aggressively.
9977 if (LHSContainsUndef && RHSContainsUndef) {
9978 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
9979 return indicatePessimisticFixpoint();
9980 } else if (LHSContainsUndef) {
9981 for (const APInt &R : RHSAAPVS) {
9982 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
9983 return indicatePessimisticFixpoint();
9984 }
9985 } else if (RHSContainsUndef) {
9986 for (const APInt &L : LHSAAPVS) {
9987 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
9988 return indicatePessimisticFixpoint();
9989 }
9990 } else {
9991 for (const APInt &L : LHSAAPVS) {
9992 for (const APInt &R : RHSAAPVS) {
9993 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9994 return indicatePessimisticFixpoint();
9995 }
9996 }
9997 }
9998 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9999 : ChangeStatus::CHANGED;
10000 }
10001
10002 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
10003 auto AssumedBefore = getAssumed();
10004 SetTy Incoming;
10005 bool ContainsUndef;
10006 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
10007 ContainsUndef, /* ForSelf */ true))
10008 return indicatePessimisticFixpoint();
10009 if (ContainsUndef) {
10010 unionAssumedWithUndef();
10011 } else {
10012 for (const auto &It : Incoming)
10013 unionAssumed(It);
10014 }
10015 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10016 : ChangeStatus::CHANGED;
10017 }
10018
10019 ChangeStatus updateImpl(Attributor &A) override {
10020 Value &V = getAssociatedValue();
10022
10023 if (auto *ICI = dyn_cast<ICmpInst>(I))
10024 return updateWithICmpInst(A, ICI);
10025
10026 if (auto *SI = dyn_cast<SelectInst>(I))
10027 return updateWithSelectInst(A, SI);
10028
10029 if (auto *CI = dyn_cast<CastInst>(I))
10030 return updateWithCastInst(A, CI);
10031
10032 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
10033 return updateWithBinaryOperator(A, BinOp);
10034
10035 if (isa<PHINode>(I) || isa<LoadInst>(I))
10036 return updateWithInstruction(A, I);
10037
10038 return indicatePessimisticFixpoint();
10039 }
10040
10041 void trackStatistics() const override {
10042 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
10043 }
10044};
10045
10046struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10047 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
10048 : AAPotentialConstantValuesImpl(IRP, A) {}
10049
10050 ChangeStatus updateImpl(Attributor &A) override {
10052 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10053 "not be called");
10054 }
10055
10056 void trackStatistics() const override {
10057 STATS_DECLTRACK_FN_ATTR(potential_values)
10058 }
10059};
10060
10061struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10062 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
10063 : AAPotentialConstantValuesFunction(IRP, A) {}
10064
10065 void trackStatistics() const override {
10066 STATS_DECLTRACK_CS_ATTR(potential_values)
10067 }
10068};
10069
10070struct AAPotentialConstantValuesCallSiteReturned
10071 : AACalleeToCallSite<AAPotentialConstantValues,
10072 AAPotentialConstantValuesImpl> {
10073 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
10074 Attributor &A)
10075 : AACalleeToCallSite<AAPotentialConstantValues,
10076 AAPotentialConstantValuesImpl>(IRP, A) {}
10077
10078 void trackStatistics() const override {
10079 STATS_DECLTRACK_CSRET_ATTR(potential_values)
10080 }
10081};
10082
10083struct AAPotentialConstantValuesCallSiteArgument
10084 : AAPotentialConstantValuesFloating {
10085 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
10086 Attributor &A)
10087 : AAPotentialConstantValuesFloating(IRP, A) {}
10088
10089 void initialize(Attributor &A) override {
10090 AAPotentialConstantValuesImpl::initialize(A);
10091 if (isAtFixpoint())
10092 return;
10093
10094 Value &V = getAssociatedValue();
10095
10096 if (auto *C = dyn_cast<ConstantInt>(&V)) {
10097 unionAssumed(C->getValue());
10098 indicateOptimisticFixpoint();
10099 return;
10100 }
10101
10102 if (isa<UndefValue>(&V)) {
10103 unionAssumedWithUndef();
10104 indicateOptimisticFixpoint();
10105 return;
10106 }
10107 }
10108
10109 ChangeStatus updateImpl(Attributor &A) override {
10110 Value &V = getAssociatedValue();
10111 auto AssumedBefore = getAssumed();
10112 auto *AA = A.getAAFor<AAPotentialConstantValues>(
10113 *this, IRPosition::value(V), DepClassTy::REQUIRED);
10114 if (!AA)
10115 return indicatePessimisticFixpoint();
10116 const auto &S = AA->getAssumed();
10117 unionAssumed(S);
10118 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10119 : ChangeStatus::CHANGED;
10120 }
10121
10122 void trackStatistics() const override {
10123 STATS_DECLTRACK_CSARG_ATTR(potential_values)
10124 }
10125};
10126} // namespace
10127
10128/// ------------------------ NoUndef Attribute ---------------------------------
10130 Attribute::AttrKind ImpliedAttributeKind,
10131 bool IgnoreSubsumingPositions) {
10132 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10133 "Unexpected attribute kind");
10134 if (A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10135 Attribute::NoUndef))
10136 return true;
10137
10138 Value &Val = IRP.getAssociatedValue();
10141 LLVMContext &Ctx = Val.getContext();
10142 A.manifestAttrs(IRP, Attribute::get(Ctx, Attribute::NoUndef));
10143 return true;
10144 }
10145
10146 return false;
10147}
10148
10149namespace {
10150struct AANoUndefImpl : AANoUndef {
10151 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
10152
10153 void initialize(Attributor &A) override {
10154 Value &V = getAssociatedValue();
10155 if (isa<UndefValue>(V))
10156 indicatePessimisticFixpoint();
10157 assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));
10158 }
10159
10160 /// See followUsesInMBEC
10161 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10162 AANoUndef::StateType &State) {
10163 const Value *UseV = U->get();
10164 const DominatorTree *DT = nullptr;
10165 AssumptionCache *AC = nullptr;
10166 InformationCache &InfoCache = A.getInfoCache();
10167 if (Function *F = getAnchorScope()) {
10168 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10169 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10170 }
10171 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10172 bool TrackUse = false;
10173 // Track use for instructions which must produce undef or poison bits when
10174 // at least one operand contains such bits.
10176 TrackUse = true;
10177 return TrackUse;
10178 }
10179
10180 const std::string getAsStr(Attributor *A) const override {
10181 return getAssumed() ? "noundef" : "may-undef-or-poison";
10182 }
10183
10184 ChangeStatus manifest(Attributor &A) override {
10185 // We don't manifest noundef attribute for dead positions because the
10186 // associated values with dead positions would be replaced with undef
10187 // values.
10188 bool UsedAssumedInformation = false;
10189 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10190 UsedAssumedInformation))
10191 return ChangeStatus::UNCHANGED;
10192 // A position whose simplified value does not have any value is
10193 // considered to be dead. We don't manifest noundef in such positions for
10194 // the same reason above.
10195 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10197 .has_value())
10198 return ChangeStatus::UNCHANGED;
10199 return AANoUndef::manifest(A);
10200 }
10201};
10202
10203struct AANoUndefFloating : public AANoUndefImpl {
10204 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10205 : AANoUndefImpl(IRP, A) {}
10206
10207 void initialize(Attributor &A) override {
10208 AANoUndefImpl::initialize(A);
10209 if (!getState().isAtFixpoint() && getAnchorScope() &&
10210 !getAnchorScope()->isDeclaration())
10211 if (Instruction *CtxI = getCtxI())
10212 followUsesInMBEC(*this, A, getState(), *CtxI);
10213 }
10214
10215 ChangeStatus updateImpl(Attributor &A) override {
10216 auto VisitValueCB = [&](const IRPosition &IRP) -> bool {
10217 bool IsKnownNoUndef;
10219 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10220 };
10221
10222 bool Stripped;
10223 bool UsedAssumedInformation = false;
10224 Value *AssociatedValue = &getAssociatedValue();
10226 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10227 AA::AnyScope, UsedAssumedInformation))
10228 Stripped = false;
10229 else
10230 Stripped =
10231 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
10232
10233 if (!Stripped) {
10234 // If we haven't stripped anything we might still be able to use a
10235 // different AA, but only if the IRP changes. Effectively when we
10236 // interpret this not as a call site value but as a floating/argument
10237 // value.
10238 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
10239 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10240 return indicatePessimisticFixpoint();
10241 return ChangeStatus::UNCHANGED;
10242 }
10243
10244 for (const auto &VAC : Values)
10245 if (!VisitValueCB(IRPosition::value(*VAC.getValue())))
10246 return indicatePessimisticFixpoint();
10247
10248 return ChangeStatus::UNCHANGED;
10249 }
10250
10251 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10252};
10253
10254struct AANoUndefReturned final
10255 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10256 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10257 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10258
10259 void initialize(Attributor &A) override {
10260 AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>::initialize(A);
10261 if (isAtFixpoint())
10262 return;
10263
10264 // Returning a value that violates a return attribute, e.g., nonnull, is
10265 // poison.
10266 AttributeMask AM = AttributeFuncs::getPoisonGeneratingAttributes();
10267 AttributeSet RetAttrs =
10268 getAssociatedFunction()->getAttributes().getRetAttrs();
10269 if (any_of(RetAttrs, [&](Attribute Attr) { return AM.contains(Attr); }))
10270 indicatePessimisticFixpoint();
10271 }
10272
10273 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10274};
10275
10276struct AANoUndefArgument final
10277 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10278 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10279 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10280
10281 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
10282};
10283
10284struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10285 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10286 : AANoUndefFloating(IRP, A) {}
10287
10288 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
10289};
10290
10291struct AANoUndefCallSiteReturned final
10292 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10293 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10294 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP, A) {}
10295
10296 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
10297};
10298
10299/// ------------------------ NoFPClass Attribute -------------------------------
10300
10301struct AANoFPClassImpl : AANoFPClass {
10302 AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}
10303
10304 void initialize(Attributor &A) override {
10305 const IRPosition &IRP = getIRPosition();
10306
10307 Value &V = IRP.getAssociatedValue();
10308 if (isa<UndefValue>(V)) {
10309 indicateOptimisticFixpoint();
10310 return;
10311 }
10312
10314 A.getAttrs(getIRPosition(), {Attribute::NoFPClass}, Attrs, false);
10315 for (const auto &Attr : Attrs) {
10316 addKnownBits(Attr.getNoFPClass());
10317 }
10318
10319 Instruction *CtxI = getCtxI();
10320
10321 if (getPositionKind() != IRPosition::IRP_RETURNED) {
10322 const DataLayout &DL = A.getDataLayout();
10323 InformationCache &InfoCache = A.getInfoCache();
10324
10325 const DominatorTree *DT = nullptr;
10326 AssumptionCache *AC = nullptr;
10327 const TargetLibraryInfo *TLI = nullptr;
10328 Function *F = getAnchorScope();
10329 if (F) {
10331 if (!F->isDeclaration()) {
10332 DT =
10333 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10334 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10335 }
10336 }
10337
10338 SimplifyQuery Q(DL, TLI, DT, AC, CtxI);
10339
10340 KnownFPClass KnownFPClass = computeKnownFPClass(&V, fcAllFlags, Q);
10341 addKnownBits(~KnownFPClass.getKnownFPClasses());
10342 }
10343
10344 if (CtxI)
10345 followUsesInMBEC(*this, A, getState(), *CtxI);
10346 }
10347
10348 /// See followUsesInMBEC
10349 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10350 AANoFPClass::StateType &State) {
10351 // TODO: Determine what instructions can be looked through.
10352 auto *CB = dyn_cast<CallBase>(I);
10353 if (!CB)
10354 return false;
10355
10356 if (!CB->isArgOperand(U))
10357 return false;
10358
10359 unsigned ArgNo = CB->getArgOperandNo(U);
10360 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
10361 if (auto *NoFPAA = A.getAAFor<AANoFPClass>(*this, IRP, DepClassTy::NONE))
10362 State.addKnownBits(NoFPAA->getState().getKnown());
10363 return false;
10364 }
10365
10366 const std::string getAsStr(Attributor *A) const override {
10367 std::string Result = "nofpclass";
10368 raw_string_ostream OS(Result);
10369 OS << getKnownNoFPClass() << '/' << getAssumedNoFPClass();
10370 return Result;
10371 }
10372
10373 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
10374 SmallVectorImpl<Attribute> &Attrs) const override {
10375 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10376 }
10377};
10378
10379struct AANoFPClassFloating : public AANoFPClassImpl {
10380 AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
10381 : AANoFPClassImpl(IRP, A) {}
10382
10383 ChangeStatus updateImpl(Attributor &A) override {
10385 bool UsedAssumedInformation = false;
10386 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10387 AA::AnyScope, UsedAssumedInformation)) {
10388 Values.push_back({getAssociatedValue(), getCtxI()});
10389 }
10390
10391 StateType T;
10392 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10393 const auto *AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),
10394 DepClassTy::REQUIRED);
10395 if (!AA || this == AA) {
10396 T.indicatePessimisticFixpoint();
10397 } else {
10398 const AANoFPClass::StateType &S =
10399 static_cast<const AANoFPClass::StateType &>(AA->getState());
10400 T ^= S;
10401 }
10402 return T.isValidState();
10403 };
10404
10405 for (const auto &VAC : Values)
10406 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10407 return indicatePessimisticFixpoint();
10408
10409 return clampStateAndIndicateChange(getState(), T);
10410 }
10411
10412 void trackStatistics() const override {
10414 }
10415};
10416
10417struct AANoFPClassReturned final
10418 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10419 AANoFPClassImpl::StateType, false,
10420 Attribute::None, false> {
10421 AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
10422 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10423 AANoFPClassImpl::StateType, false,
10424 Attribute::None, false>(IRP, A) {}
10425
10426 void trackStatistics() const override {
10428 }
10429};
10430
10431struct AANoFPClassArgument final
10432 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10433 AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
10434 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10435
10436 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }
10437};
10438
10439struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10440 AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
10441 : AANoFPClassFloating(IRP, A) {}
10442
10443 void trackStatistics() const override {
10445 }
10446};
10447
10448struct AANoFPClassCallSiteReturned final
10449 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10450 AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
10451 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10452
10453 void trackStatistics() const override {
10455 }
10456};
10457
10458struct AACallEdgesImpl : public AACallEdges {
10459 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10460
10461 const SetVector<Function *> &getOptimisticEdges() const override {
10462 return CalledFunctions;
10463 }
10464
10465 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10466
10467 bool hasNonAsmUnknownCallee() const override {
10468 return HasUnknownCalleeNonAsm;
10469 }
10470
10471 const std::string getAsStr(Attributor *A) const override {
10472 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10473 std::to_string(CalledFunctions.size()) + "]";
10474 }
10475
10476 void trackStatistics() const override {}
10477
10478protected:
10479 /// Return the callee of \p CB if it is a direct call whose callee has no
10480 /// callback metadata. Such a call only calls its callee.
10481 static Function *getOnlyCallee(const CallBase &CB) {
10483 if (Callee && !Callee->hasMetadata(LLVMContext::MD_callback))
10484 return Callee;
10485 return nullptr;
10486 }
10487
10488 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10489 if (CalledFunctions.insert(Fn)) {
10490 Change = ChangeStatus::CHANGED;
10491 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
10492 << "\n");
10493 }
10494 }
10495
10496 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10497 if (!HasUnknownCallee)
10498 Change = ChangeStatus::CHANGED;
10499 if (NonAsm && !HasUnknownCalleeNonAsm)
10500 Change = ChangeStatus::CHANGED;
10501 HasUnknownCalleeNonAsm |= NonAsm;
10502 HasUnknownCallee = true;
10503 }
10504
10505private:
10506 /// Optimistic set of functions that might be called by this position.
10507 SetVector<Function *> CalledFunctions;
10508
10509 /// Is there any call with a unknown callee.
10510 bool HasUnknownCallee = false;
10511
10512 /// Is there any call with a unknown callee, excluding any inline asm.
10513 bool HasUnknownCalleeNonAsm = false;
10514};
10515
10516struct AACallEdgesCallSite : public AACallEdgesImpl {
10517 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10518 : AACallEdgesImpl(IRP, A) {}
10519
10520 void initialize(Attributor &A) override {
10521 // The only callee of a direct call without callbacks never changes.
10522 if (Function *Callee = getOnlyCallee(cast<CallBase>(getAnchorValue()))) {
10523 ChangeStatus Change = ChangeStatus::UNCHANGED;
10524 addCalledFunction(Callee, Change);
10525 indicateOptimisticFixpoint();
10526 }
10527 }
10528
10529 ChangeStatus updateImpl(Attributor &A) override {
10530 ChangeStatus Change = ChangeStatus::UNCHANGED;
10531
10532 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10533 if (Function *Fn = dyn_cast<Function>(&V)) {
10534 addCalledFunction(Fn, Change);
10535 } else {
10536 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
10537 setHasUnknownCallee(true, Change);
10538 }
10539
10540 // Explore all values.
10541 return true;
10542 };
10543
10545 // Process any value that we might call.
10546 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10547 if (isa<Constant>(V)) {
10548 VisitValue(*V, CtxI);
10549 return;
10550 }
10551
10552 bool UsedAssumedInformation = false;
10553 Values.clear();
10554 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10555 AA::AnyScope, UsedAssumedInformation)) {
10556 Values.push_back({*V, CtxI});
10557 }
10558 for (auto &VAC : Values)
10559 VisitValue(*VAC.getValue(), VAC.getCtxI());
10560 };
10561
10562 CallBase *CB = cast<CallBase>(getCtxI());
10563
10564 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10565 if (IA->hasSideEffects() &&
10566 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10567 !hasAssumption(*CB, "ompx_no_call_asm")) {
10568 setHasUnknownCallee(false, Change);
10569 }
10570 return Change;
10571 }
10572
10573 if (CB->isIndirectCall())
10574 if (auto *IndirectCallAA = A.getAAFor<AAIndirectCallInfo>(
10575 *this, getIRPosition(), DepClassTy::OPTIONAL))
10576 if (IndirectCallAA->foreachCallee(
10577 [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10578 return Change;
10579
10580 // The most simple case.
10581 ProcessCalledOperand(CB->getCalledOperand(), CB);
10582
10583 // Process callback functions.
10584 SmallVector<const Use *, 4u> CallbackUses;
10585 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10586 for (const Use *U : CallbackUses)
10587 ProcessCalledOperand(U->get(), CB);
10588
10589 return Change;
10590 }
10591};
10592
10593struct AACallEdgesFunction : public AACallEdgesImpl {
10594 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10595 : AACallEdgesImpl(IRP, A) {}
10596
10597 ChangeStatus updateImpl(Attributor &A) override {
10598 ChangeStatus Change = ChangeStatus::UNCHANGED;
10599 bool AllCallsDirect = true;
10600
10601 auto ProcessCallInst = [&](Instruction &Inst) {
10602 CallBase &CB = cast<CallBase>(Inst);
10603
10604 // A direct call without callbacks only calls its callee; there is no
10605 // need for a call site attribute.
10606 if (Function *Callee = getOnlyCallee(CB)) {
10607 addCalledFunction(Callee, Change);
10608 return true;
10609 }
10610
10611 AllCallsDirect = false;
10612 auto *CBEdges = A.getAAFor<AACallEdges>(
10613 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10614 if (!CBEdges)
10615 return false;
10616 if (CBEdges->hasNonAsmUnknownCallee())
10617 setHasUnknownCallee(true, Change);
10618 if (CBEdges->hasUnknownCallee())
10619 setHasUnknownCallee(false, Change);
10620
10621 for (Function *F : CBEdges->getOptimisticEdges())
10622 addCalledFunction(F, Change);
10623
10624 return true;
10625 };
10626
10627 // Visit all callable instructions.
10628 bool UsedAssumedInformation = false;
10629 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10630 UsedAssumedInformation,
10631 /* CheckBBLivenessOnly */ true)) {
10632 // If we haven't looked at all call like instructions, assume that there
10633 // are unknown callees.
10634 setHasUnknownCallee(true, Change);
10635 }
10636
10637 // The callees of direct calls in code known to be live do not change.
10638 if (AllCallsDirect && !UsedAssumedInformation)
10639 indicateOptimisticFixpoint();
10640
10641 return Change;
10642 }
10643};
10644
10645/// -------------------AAInterFnReachability Attribute--------------------------
10646
10647struct AAInterFnReachabilityFunction
10648 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10649 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10650 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10651 : Base(IRP, A) {}
10652
10653 bool instructionCanReach(
10654 Attributor &A, const Instruction &From, const Function &To,
10655 const AA::InstExclusionSetTy *ExclusionSet) const override {
10656 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
10657 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10658
10659 RQITy StackRQI(A, From, To, ExclusionSet, false);
10660 RQITy::Reachable Result;
10661 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
10662 return NonConstThis->isReachableImpl(A, StackRQI,
10663 /*IsTemporaryRQI=*/true);
10664 return Result == RQITy::Reachable::Yes;
10665 }
10666
10667 bool isReachableImpl(Attributor &A, RQITy &RQI,
10668 bool IsTemporaryRQI) override {
10669 const Instruction *EntryI =
10670 &RQI.From->getFunction()->getEntryBlock().front();
10671 if (EntryI != RQI.From &&
10672 !instructionCanReach(A, *EntryI, *RQI.To, nullptr))
10673 return rememberResult(A, RQITy::Reachable::No, RQI, false,
10674 IsTemporaryRQI);
10675
10676 auto CheckReachableCallBase = [&](CallBase *CB) {
10677 auto *CBEdges = A.getAAFor<AACallEdges>(
10678 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10679 if (!CBEdges || !CBEdges->getState().isValidState())
10680 return false;
10681 // TODO Check To backwards in this case.
10682 if (CBEdges->hasUnknownCallee())
10683 return false;
10684
10685 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10686 if (Fn == RQI.To)
10687 return false;
10688
10689 if (Fn->isDeclaration()) {
10690 if (Fn->hasFnAttribute(Attribute::NoCallback))
10691 continue;
10692 // TODO Check To backwards in this case.
10693 return false;
10694 }
10695
10696 if (Fn == getAnchorScope()) {
10697 if (EntryI == RQI.From)
10698 continue;
10699 return false;
10700 }
10701
10702 const AAInterFnReachability *InterFnReachability =
10703 A.getAAFor<AAInterFnReachability>(*this, IRPosition::function(*Fn),
10704 DepClassTy::OPTIONAL);
10705
10706 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10707 if (!InterFnReachability ||
10708 InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10709 RQI.ExclusionSet))
10710 return false;
10711 }
10712 return true;
10713 };
10714
10715 const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10716 *this, IRPosition::function(*RQI.From->getFunction()),
10717 DepClassTy::OPTIONAL);
10718
10719 // Determine call like instructions that we can reach from the inst.
10720 auto CheckCallBase = [&](Instruction &CBInst) {
10721 // There are usually less nodes in the call graph, check inter function
10722 // reachability first.
10723 if (CheckReachableCallBase(cast<CallBase>(&CBInst)))
10724 return true;
10725 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10726 A, *RQI.From, CBInst, RQI.ExclusionSet);
10727 };
10728
10729 bool UsedExclusionSet = /* conservative */ true;
10730 bool UsedAssumedInformation = false;
10731 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10732 UsedAssumedInformation,
10733 /* CheckBBLivenessOnly */ true))
10734 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10735 IsTemporaryRQI);
10736
10737 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10738 IsTemporaryRQI);
10739 }
10740
10741 void trackStatistics() const override {}
10742};
10743} // namespace
10744
10745template <typename AAType>
10746static std::optional<Constant *>
10748 const IRPosition &IRP, Type &Ty) {
10749 if (!Ty.isIntegerTy())
10750 return nullptr;
10751
10752 // This will also pass the call base context.
10753 const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10754 if (!AA)
10755 return nullptr;
10756
10757 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
10758
10759 if (!COpt.has_value()) {
10760 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10761 return std::nullopt;
10762 }
10763 if (auto *C = *COpt) {
10764 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10765 return C;
10766 }
10767 return nullptr;
10768}
10769
10771 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10773 Type &Ty = *IRP.getAssociatedType();
10774 std::optional<Value *> V;
10775 for (auto &It : Values) {
10776 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10777 if (V.has_value() && !*V)
10778 break;
10779 }
10780 if (!V.has_value())
10781 return UndefValue::get(&Ty);
10782 return *V;
10783}
10784
10785namespace {
10786struct AAPotentialValuesImpl : AAPotentialValues {
10787 using StateType = PotentialLLVMValuesState;
10788
10789 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10790 : AAPotentialValues(IRP, A) {}
10791
10792 void initialize(Attributor &A) override {
10793 if (A.hasSimplificationCallback(getIRPosition())) {
10794 indicatePessimisticFixpoint();
10795 return;
10796 }
10797 Value *Stripped = getAssociatedValue().stripPointerCasts();
10798 if (isa<Constant>(Stripped) && !isa<ConstantExpr>(Stripped)) {
10799 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10800 getAnchorScope());
10801 indicateOptimisticFixpoint();
10802 return;
10803 }
10804 AAPotentialValues::initialize(A);
10805 }
10806
10807 const std::string getAsStr(Attributor *A) const override {
10808 std::string Str;
10809 llvm::raw_string_ostream OS(Str);
10810 OS << getState();
10811 return Str;
10812 }
10813
10814 template <typename AAType>
10815 static std::optional<Value *> askOtherAA(Attributor &A,
10816 const AbstractAttribute &AA,
10817 const IRPosition &IRP, Type &Ty) {
10819 return &IRP.getAssociatedValue();
10820 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10821 if (!C)
10822 return std::nullopt;
10823 if (*C)
10824 if (auto *CC = AA::getWithType(**C, Ty))
10825 return CC;
10826 return nullptr;
10827 }
10828
10829 virtual void addValue(Attributor &A, StateType &State, Value &V,
10830 const Instruction *CtxI, AA::ValueScope S,
10831 Function *AnchorScope) const {
10832
10833 IRPosition ValIRP = IRPosition::value(V);
10834 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
10835 for (const auto &U : CB->args()) {
10836 if (U.get() != &V)
10837 continue;
10838 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
10839 break;
10840 }
10841 }
10842
10843 Value *VPtr = &V;
10844 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10845 Type &Ty = *getAssociatedType();
10846 std::optional<Value *> SimpleV =
10847 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
10848 if (SimpleV.has_value() && !*SimpleV) {
10849 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10850 *this, ValIRP, DepClassTy::OPTIONAL);
10851 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10852 for (const auto &It : PotentialConstantsAA->getAssumedSet())
10853 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
10854 if (PotentialConstantsAA->undefIsContained())
10855 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
10856 return;
10857 }
10858 }
10859 if (!SimpleV.has_value())
10860 return;
10861
10862 if (*SimpleV)
10863 VPtr = *SimpleV;
10864 }
10865
10866 if (isa<ConstantInt>(VPtr))
10867 CtxI = nullptr;
10868 if (!AA::isValidInScope(*VPtr, AnchorScope))
10870
10871 State.unionAssumed({{*VPtr, CtxI}, S});
10872 }
10873
10874 /// Helper struct to tie a value+context pair together with the scope for
10875 /// which this is the simplified version.
10876 struct ItemInfo {
10877 AA::ValueAndContext I;
10879
10880 bool operator==(const ItemInfo &II) const {
10881 return II.I == I && II.S == S;
10882 };
10883 bool operator<(const ItemInfo &II) const {
10884 return std::tie(I, S) < std::tie(II.I, II.S);
10885 };
10886 };
10887
10888 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
10889 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10890 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
10891 if (!(CS & S))
10892 continue;
10893
10894 bool UsedAssumedInformation = false;
10896 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
10897 UsedAssumedInformation))
10898 return false;
10899
10900 for (auto &It : Values)
10901 ValueScopeMap[It] += CS;
10902 }
10903 for (auto &It : ValueScopeMap)
10904 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
10905 AA::ValueScope(It.second), getAnchorScope());
10906
10907 return true;
10908 }
10909
10910 void giveUpOnIntraprocedural(Attributor &A) {
10911 auto NewS = StateType::getBestState(getState());
10912 for (const auto &It : getAssumedSet()) {
10913 if (It.second == AA::Intraprocedural)
10914 continue;
10915 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
10916 AA::Interprocedural, getAnchorScope());
10917 }
10918 assert(!undefIsContained() && "Undef should be an explicit value!");
10919 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
10920 getAnchorScope());
10921 getState() = NewS;
10922 }
10923
10924 ChangeStatus indicatePessimisticFixpoint() override {
10925 getState() = StateType::getBestState(getState());
10926 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
10927 AAPotentialValues::indicateOptimisticFixpoint();
10928 return ChangeStatus::CHANGED;
10929 }
10930
10931 ChangeStatus updateImpl(Attributor &A) override {
10932 return indicatePessimisticFixpoint();
10933 }
10934
10935 ChangeStatus manifest(Attributor &A) override {
10938 Values.clear();
10939 if (!getAssumedSimplifiedValues(A, Values, S))
10940 continue;
10941 Value &OldV = getAssociatedValue();
10942 if (isa<UndefValue>(OldV))
10943 continue;
10944 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
10945 if (!NewV || NewV == &OldV)
10946 continue;
10947 if (getCtxI() &&
10948 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
10949 continue;
10950 if (A.changeAfterManifest(getIRPosition(), *NewV))
10951 return ChangeStatus::CHANGED;
10952 }
10953 return ChangeStatus::UNCHANGED;
10954 }
10955
10956 bool getAssumedSimplifiedValues(
10957 Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,
10958 AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {
10959 if (!isValidState())
10960 return false;
10961 bool UsedAssumedInformation = false;
10962 for (const auto &It : getAssumedSet())
10963 if (It.second & S) {
10964 if (RecurseForSelectAndPHI && (isa<PHINode>(It.first.getValue()) ||
10965 isa<SelectInst>(It.first.getValue()))) {
10966 if (A.getAssumedSimplifiedValues(
10967 IRPosition::inst(*cast<Instruction>(It.first.getValue())),
10968 this, Values, S, UsedAssumedInformation))
10969 continue;
10970 }
10971 Values.push_back(It.first);
10972 }
10973 assert(!undefIsContained() && "Undef should be an explicit value!");
10974 return true;
10975 }
10976};
10977
10978struct AAPotentialValuesFloating : AAPotentialValuesImpl {
10979 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
10980 : AAPotentialValuesImpl(IRP, A) {}
10981
10982 ChangeStatus updateImpl(Attributor &A) override {
10983 auto AssumedBefore = getAssumed();
10984
10985 genericValueTraversal(A, &getAssociatedValue());
10986
10987 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10988 : ChangeStatus::CHANGED;
10989 }
10990
10991 /// Helper struct to remember which AAIsDead instances we actually used.
10992 struct LivenessInfo {
10993 const AAIsDead *LivenessAA = nullptr;
10994 bool AnyDead = false;
10995 };
10996
10997 /// Check if \p Cmp is a comparison we can simplify.
10998 ///
10999 /// We handle multiple cases, one in which at least one operand is an
11000 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
11001 /// operand. Return true if successful, in that case Worklist will be updated.
11002 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
11003 CmpInst::Predicate Pred, ItemInfo II,
11004 SmallVectorImpl<ItemInfo> &Worklist) {
11005
11006 // Simplify the operands first.
11007 bool UsedAssumedInformation = false;
11008 SmallVector<AA::ValueAndContext> LHSValues, RHSValues;
11009 auto GetSimplifiedValues = [&](Value &V,
11011 if (!A.getAssumedSimplifiedValues(
11012 IRPosition::value(V, getCallBaseContext()), this, Values,
11013 AA::Intraprocedural, UsedAssumedInformation)) {
11014 Values.clear();
11015 Values.push_back(AA::ValueAndContext{V, II.I.getCtxI()});
11016 }
11017 return Values.empty();
11018 };
11019 if (GetSimplifiedValues(*LHS, LHSValues))
11020 return true;
11021 if (GetSimplifiedValues(*RHS, RHSValues))
11022 return true;
11023
11024 LLVMContext &Ctx = LHS->getContext();
11025
11026 InformationCache &InfoCache = A.getInfoCache();
11027 Instruction *CmpI = dyn_cast<Instruction>(&Cmp);
11028 Function *F = CmpI ? CmpI->getFunction() : nullptr;
11029 const auto *DT =
11030 F ? InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F)
11031 : nullptr;
11032 const auto *TLI =
11033 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
11034 auto *AC =
11035 F ? InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F)
11036 : nullptr;
11037
11038 const DataLayout &DL = A.getDataLayout();
11039 SimplifyQuery Q(DL, TLI, DT, AC, CmpI);
11040
11041 auto CheckPair = [&](Value &LHSV, Value &RHSV) {
11042 if (isa<UndefValue>(LHSV) || isa<UndefValue>(RHSV)) {
11043 addValue(A, getState(), *UndefValue::get(Cmp.getType()),
11044 /* CtxI */ nullptr, II.S, getAnchorScope());
11045 return true;
11046 }
11047
11048 // Handle the trivial case first in which we don't even need to think
11049 // about null or non-null.
11050 if (&LHSV == &RHSV &&
11052 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11054 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11055 getAnchorScope());
11056 return true;
11057 }
11058
11059 auto *TypedLHS = AA::getWithType(LHSV, *LHS->getType());
11060 auto *TypedRHS = AA::getWithType(RHSV, *RHS->getType());
11061 if (TypedLHS && TypedRHS) {
11062 Value *NewV = simplifyCmpInst(Pred, TypedLHS, TypedRHS, Q);
11063 if (NewV && NewV != &Cmp) {
11064 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11065 getAnchorScope());
11066 return true;
11067 }
11068 }
11069
11070 // From now on we only handle equalities (==, !=).
11072 return false;
11073
11074 bool LHSIsNull = isa<ConstantPointerNull>(LHSV);
11075 bool RHSIsNull = isa<ConstantPointerNull>(RHSV);
11076 if (!LHSIsNull && !RHSIsNull)
11077 return false;
11078
11079 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
11080 // non-nullptr operand and if we assume it's non-null we can conclude the
11081 // result of the comparison.
11082 assert((LHSIsNull || RHSIsNull) &&
11083 "Expected nullptr versus non-nullptr comparison at this point");
11084
11085 // The index is the operand that we assume is not null.
11086 unsigned PtrIdx = LHSIsNull;
11087 bool IsKnownNonNull;
11088 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
11089 A, this, IRPosition::value(*(PtrIdx ? &RHSV : &LHSV)),
11090 DepClassTy::REQUIRED, IsKnownNonNull);
11091 if (!IsAssumedNonNull)
11092 return false;
11093
11094 // The new value depends on the predicate, true for != and false for ==.
11095 Constant *NewV =
11096 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
11097 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11098 getAnchorScope());
11099 return true;
11100 };
11101
11102 for (auto &LHSValue : LHSValues)
11103 for (auto &RHSValue : RHSValues)
11104 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11105 return false;
11106 return true;
11107 }
11108
11109 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
11110 SmallVectorImpl<ItemInfo> &Worklist) {
11111 const Instruction *CtxI = II.I.getCtxI();
11112 bool UsedAssumedInformation = false;
11113
11114 std::optional<Constant *> C =
11115 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
11116 bool NoValueYet = !C.has_value();
11117 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
11118 return true;
11119 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
11120 if (CI->isZero())
11121 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11122 else
11123 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11124 } else if (&SI == &getAssociatedValue()) {
11125 // We could not simplify the condition, assume both values.
11126 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11127 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11128 } else {
11129 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11130 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
11131 if (!SimpleV.has_value())
11132 return true;
11133 if (*SimpleV) {
11134 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
11135 return true;
11136 }
11137 return false;
11138 }
11139 return true;
11140 }
11141
11142 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
11143 SmallVectorImpl<ItemInfo> &Worklist) {
11144 SmallSetVector<Value *, 4> PotentialCopies;
11145 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11146 bool UsedAssumedInformation = false;
11147 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
11148 PotentialValueOrigins, *this,
11149 UsedAssumedInformation,
11150 /* OnlyExact */ true)) {
11151 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
11152 "loaded values for load instruction "
11153 << LI << "\n");
11154 return false;
11155 }
11156
11157 // Do not simplify loads that are only used in llvm.assume if we cannot also
11158 // remove all stores that may feed into the load. The reason is that the
11159 // assume is probably worth something as long as the stores are around.
11160 InformationCache &InfoCache = A.getInfoCache();
11161 if (InfoCache.isOnlyUsedByAssume(LI)) {
11162 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
11163 if (!I || isa<AssumeInst>(I))
11164 return true;
11165 if (auto *SI = dyn_cast<StoreInst>(I))
11166 return A.isAssumedDead(SI->getOperandUse(0), this,
11167 /* LivenessAA */ nullptr,
11168 UsedAssumedInformation,
11169 /* CheckBBLivenessOnly */ false);
11170 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
11171 UsedAssumedInformation,
11172 /* CheckBBLivenessOnly */ false);
11173 })) {
11174 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
11175 "and we cannot delete all the stores: "
11176 << LI << "\n");
11177 return false;
11178 }
11179 }
11180
11181 // Values have to be dynamically unique or we loose the fact that a
11182 // single llvm::Value might represent two runtime values (e.g.,
11183 // stack locations in different recursive calls).
11184 const Instruction *CtxI = II.I.getCtxI();
11185 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
11186 bool AllLocal = ScopeIsLocal;
11187 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
11188 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
11189 return AA::isDynamicallyUnique(A, *this, *PC);
11190 });
11191 if (!DynamicallyUnique) {
11192 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
11193 "values are dynamically unique: "
11194 << LI << "\n");
11195 return false;
11196 }
11197
11198 for (auto *PotentialCopy : PotentialCopies) {
11199 if (AllLocal) {
11200 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
11201 } else {
11202 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
11203 }
11204 }
11205 if (!AllLocal && ScopeIsLocal)
11206 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
11207 return true;
11208 }
11209
11210 bool handlePHINode(
11211 Attributor &A, PHINode &PHI, ItemInfo II,
11212 SmallVectorImpl<ItemInfo> &Worklist,
11213 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11214 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
11215 LivenessInfo &LI = LivenessAAs[&F];
11216 if (!LI.LivenessAA)
11217 LI.LivenessAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
11218 DepClassTy::NONE);
11219 return LI;
11220 };
11221
11222 if (&PHI == &getAssociatedValue()) {
11223 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
11224 const auto *CI =
11225 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11226 *PHI.getFunction());
11227
11228 CycleRef C;
11229 bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);
11230 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
11231 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
11232 if (LI.LivenessAA &&
11233 LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
11234 LI.AnyDead = true;
11235 continue;
11236 }
11237 Value *V = PHI.getIncomingValue(u);
11238 if (V == &PHI)
11239 continue;
11240
11241 // If the incoming value is not the PHI but an instruction in the same
11242 // cycle we might have multiple versions of it flying around.
11243 if (CyclePHI && isa<Instruction>(V) &&
11244 (!C || CI->contains(C, cast<Instruction>(V)->getParent())))
11245 return false;
11246
11247 Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});
11248 }
11249 return true;
11250 }
11251
11252 bool UsedAssumedInformation = false;
11253 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11254 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
11255 if (!SimpleV.has_value())
11256 return true;
11257 if (!(*SimpleV))
11258 return false;
11259 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
11260 return true;
11261 }
11262
11263 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
11264 /// simplify any operand of the instruction \p I. Return true if successful,
11265 /// in that case Worklist will be updated.
11266 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
11267 SmallVectorImpl<ItemInfo> &Worklist) {
11268 bool SomeSimplified = false;
11269 bool UsedAssumedInformation = false;
11270
11271 SmallVector<Value *, 8> NewOps(I.getNumOperands());
11272 int Idx = 0;
11273 for (Value *Op : I.operands()) {
11274 const auto &SimplifiedOp = A.getAssumedSimplified(
11275 IRPosition::value(*Op, getCallBaseContext()), *this,
11276 UsedAssumedInformation, AA::Intraprocedural);
11277 // If we are not sure about any operand we are not sure about the entire
11278 // instruction, we'll wait.
11279 if (!SimplifiedOp.has_value())
11280 return true;
11281
11282 if (*SimplifiedOp)
11283 NewOps[Idx] = *SimplifiedOp;
11284 else
11285 NewOps[Idx] = Op;
11286
11287 SomeSimplified |= (NewOps[Idx] != Op);
11288 ++Idx;
11289 }
11290
11291 // We won't bother with the InstSimplify interface if we didn't simplify any
11292 // operand ourselves.
11293 if (!SomeSimplified)
11294 return false;
11295
11296 InformationCache &InfoCache = A.getInfoCache();
11297 Function *F = I.getFunction();
11298 const auto *DT =
11299 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
11300 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
11301 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
11302
11303 const DataLayout &DL = I.getDataLayout();
11304 SimplifyQuery Q(DL, TLI, DT, AC, &I);
11305 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);
11306 if (!NewV || NewV == &I)
11307 return false;
11308
11309 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
11310 << *NewV << "\n");
11311 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
11312 return true;
11313 }
11314
11316 Attributor &A, Instruction &I, ItemInfo II,
11317 SmallVectorImpl<ItemInfo> &Worklist,
11318 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11319 if (auto *CI = dyn_cast<CmpInst>(&I))
11320 return handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
11321 CI->getPredicate(), II, Worklist);
11322
11323 switch (I.getOpcode()) {
11324 case Instruction::Select:
11325 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
11326 case Instruction::PHI:
11327 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
11328 case Instruction::Load:
11329 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
11330 default:
11331 return handleGenericInst(A, I, II, Worklist);
11332 };
11333 return false;
11334 }
11335
11336 void genericValueTraversal(Attributor &A, Value *InitialV) {
11337 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11338
11339 SmallSet<ItemInfo, 16> Visited;
11341 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
11342
11343 int Iteration = 0;
11344 do {
11345 ItemInfo II = Worklist.pop_back_val();
11346 Value *V = II.I.getValue();
11347 assert(V);
11348 const Instruction *CtxI = II.I.getCtxI();
11349 AA::ValueScope S = II.S;
11350
11351 // Check if we should process the current value. To prevent endless
11352 // recursion keep a record of the values we followed!
11353 if (!Visited.insert(II).second)
11354 continue;
11355
11356 // Make sure we limit the compile time for complex expressions.
11357 if (Iteration++ >= MaxPotentialValuesIterations) {
11358 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
11359 << Iteration << "!\n");
11360 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11361 continue;
11362 }
11363
11364 // Explicitly look through calls with a "returned" attribute if we do
11365 // not have a pointer as stripPointerCasts only works on them.
11366 Value *NewV = nullptr;
11367 if (V->getType()->isPointerTy()) {
11368 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
11369 } else {
11370 if (auto *CB = dyn_cast<CallBase>(V))
11371 if (auto *Callee =
11373 for (Argument &Arg : Callee->args())
11374 if (Arg.hasReturnedAttr()) {
11375 NewV = CB->getArgOperand(Arg.getArgNo());
11376 break;
11377 }
11378 }
11379 }
11380 if (NewV && NewV != V) {
11381 Worklist.push_back({{*NewV, CtxI}, S});
11382 continue;
11383 }
11384
11385 if (auto *I = dyn_cast<Instruction>(V)) {
11386 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
11387 continue;
11388 }
11389
11390 if (V != InitialV || isa<Argument>(V))
11391 if (recurseForValue(A, IRPosition::value(*V), II.S))
11392 continue;
11393
11394 // If we haven't stripped anything we give up.
11395 if (V == InitialV && CtxI == getCtxI()) {
11396 indicatePessimisticFixpoint();
11397 return;
11398 }
11399
11400 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11401 } while (!Worklist.empty());
11402
11403 // If we actually used liveness information so we have to record a
11404 // dependence.
11405 for (auto &It : LivenessAAs)
11406 if (It.second.AnyDead)
11407 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
11408 }
11409
11410 void trackStatistics() const override {
11411 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
11412 }
11413};
11414
11415struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11416 using Base = AAPotentialValuesImpl;
11417 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11418 : Base(IRP, A) {}
11419
11420 void initialize(Attributor &A) override {
11421 auto &Arg = cast<Argument>(getAssociatedValue());
11423 indicatePessimisticFixpoint();
11424 }
11425
11426 ChangeStatus updateImpl(Attributor &A) override {
11427 auto AssumedBefore = getAssumed();
11428
11429 unsigned ArgNo = getCalleeArgNo();
11430
11431 bool UsedAssumedInformation = false;
11433 auto CallSitePred = [&](AbstractCallSite ACS) {
11434 const auto CSArgIRP = IRPosition::callsite_argument(ACS, ArgNo);
11435 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11436 return false;
11437
11438 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11440 UsedAssumedInformation))
11441 return false;
11442
11443 return isValidState();
11444 };
11445
11446 if (!A.checkForAllCallSites(CallSitePred, *this,
11447 /* RequireAllCallSites */ true,
11448 UsedAssumedInformation))
11449 return indicatePessimisticFixpoint();
11450
11451 Function *Fn = getAssociatedFunction();
11452 bool AnyNonLocal = false;
11453 for (auto &It : Values) {
11454 if (isa<Constant>(It.getValue())) {
11455 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11456 getAnchorScope());
11457 continue;
11458 }
11459 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11460 return indicatePessimisticFixpoint();
11461
11462 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11463 if (Arg->getParent() == Fn) {
11464 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11465 getAnchorScope());
11466 continue;
11467 }
11468 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11469 getAnchorScope());
11470 AnyNonLocal = true;
11471 }
11472 assert(!undefIsContained() && "Undef should be an explicit value!");
11473 if (AnyNonLocal)
11474 giveUpOnIntraprocedural(A);
11475
11476 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11477 : ChangeStatus::CHANGED;
11478 }
11479
11480 void trackStatistics() const override {
11481 STATS_DECLTRACK_ARG_ATTR(potential_values)
11482 }
11483};
11484
11485struct AAPotentialValuesReturned : public AAPotentialValuesFloating {
11486 using Base = AAPotentialValuesFloating;
11487 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11488 : Base(IRP, A) {}
11489
11490 void initialize(Attributor &A) override {
11491 Function *F = getAssociatedFunction();
11492 if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {
11493 indicatePessimisticFixpoint();
11494 return;
11495 }
11496
11497 for (Argument &Arg : F->args())
11498 if (Arg.hasReturnedAttr()) {
11499 addValue(A, getState(), Arg, nullptr, AA::AnyScope, F);
11500 ReturnedArg = &Arg;
11501 break;
11502 }
11503 if (!A.isFunctionIPOAmendable(*F) ||
11504 A.hasSimplificationCallback(getIRPosition())) {
11505 if (!ReturnedArg)
11506 indicatePessimisticFixpoint();
11507 else
11508 indicateOptimisticFixpoint();
11509 }
11510 }
11511
11512 ChangeStatus updateImpl(Attributor &A) override {
11513 auto AssumedBefore = getAssumed();
11514 bool UsedAssumedInformation = false;
11515
11517 Function *AnchorScope = getAnchorScope();
11518 auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,
11519 bool AddValues) {
11521 Values.clear();
11522 if (!A.getAssumedSimplifiedValues(IRPosition::value(V), this, Values, S,
11523 UsedAssumedInformation,
11524 /* RecurseForSelectAndPHI */ true))
11525 return false;
11526 if (!AddValues)
11527 continue;
11528
11529 bool AllInterAreIntra = false;
11530 if (S == AA::Interprocedural)
11531 AllInterAreIntra =
11532 llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) {
11533 return AA::isValidInScope(*VAC.getValue(), AnchorScope);
11534 });
11535
11536 for (const AA::ValueAndContext &VAC : Values) {
11537 addValue(A, getState(), *VAC.getValue(),
11538 VAC.getCtxI() ? VAC.getCtxI() : CtxI,
11539 AllInterAreIntra ? AA::AnyScope : S, AnchorScope);
11540 }
11541 if (AllInterAreIntra)
11542 break;
11543 }
11544 return true;
11545 };
11546
11547 if (ReturnedArg) {
11548 HandleReturnedValue(*ReturnedArg, nullptr, true);
11549 } else {
11550 auto RetInstPred = [&](Instruction &RetI) {
11551 bool AddValues = true;
11552 if (isa<PHINode>(RetI.getOperand(0)) ||
11553 isa<SelectInst>(RetI.getOperand(0))) {
11554 addValue(A, getState(), *RetI.getOperand(0), &RetI, AA::AnyScope,
11555 AnchorScope);
11556 AddValues = false;
11557 }
11558 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11559 };
11560
11561 if (!A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11562 UsedAssumedInformation,
11563 /* CheckBBLivenessOnly */ true))
11564 return indicatePessimisticFixpoint();
11565 }
11566
11567 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11568 : ChangeStatus::CHANGED;
11569 }
11570
11571 ChangeStatus manifest(Attributor &A) override {
11572 if (ReturnedArg)
11573 return ChangeStatus::UNCHANGED;
11575 if (!getAssumedSimplifiedValues(A, Values, AA::ValueScope::Intraprocedural,
11576 /* RecurseForSelectAndPHI */ true))
11577 return ChangeStatus::UNCHANGED;
11578 Value *NewVal = getSingleValue(A, *this, getIRPosition(), Values);
11579 if (!NewVal)
11580 return ChangeStatus::UNCHANGED;
11581
11582 ChangeStatus Changed = ChangeStatus::UNCHANGED;
11583 if (auto *Arg = dyn_cast<Argument>(NewVal)) {
11584 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
11585 "Number of function with unique return");
11586 Changed |= A.manifestAttrs(
11588 {Attribute::get(Arg->getContext(), Attribute::Returned)});
11589 STATS_DECLTRACK_ARG_ATTR(returned);
11590 }
11591
11592 auto RetInstPred = [&](Instruction &RetI) {
11593 Value *RetOp = RetI.getOperand(0);
11594 if (isa<UndefValue>(RetOp) || RetOp == NewVal)
11595 return true;
11596 if (AA::isValidAtPosition({*NewVal, RetI}, A.getInfoCache()))
11597 if (A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11598 Changed = ChangeStatus::CHANGED;
11599 return true;
11600 };
11601 bool UsedAssumedInformation = false;
11602 (void)A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11603 UsedAssumedInformation,
11604 /* CheckBBLivenessOnly */ true);
11605 return Changed;
11606 }
11607
11608 ChangeStatus indicatePessimisticFixpoint() override {
11609 return AAPotentialValues::indicatePessimisticFixpoint();
11610 }
11611
11612 void trackStatistics() const override{
11613 STATS_DECLTRACK_FNRET_ATTR(potential_values)}
11614
11615 /// The argumented with an existing `returned` attribute.
11616 Argument *ReturnedArg = nullptr;
11617};
11618
11619struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11620 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11621 : AAPotentialValuesImpl(IRP, A) {}
11622
11623 ChangeStatus updateImpl(Attributor &A) override {
11624 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
11625 "not be called");
11626 }
11627
11628 void trackStatistics() const override {
11629 STATS_DECLTRACK_FN_ATTR(potential_values)
11630 }
11631};
11632
11633struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11634 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11635 : AAPotentialValuesFunction(IRP, A) {}
11636
11637 void trackStatistics() const override {
11638 STATS_DECLTRACK_CS_ATTR(potential_values)
11639 }
11640};
11641
11642struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11643 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11644 : AAPotentialValuesImpl(IRP, A) {}
11645
11646 ChangeStatus updateImpl(Attributor &A) override {
11647 auto AssumedBefore = getAssumed();
11648
11649 Function *Callee = getAssociatedFunction();
11650 if (!Callee)
11651 return indicatePessimisticFixpoint();
11652
11653 bool UsedAssumedInformation = false;
11654 auto *CB = cast<CallBase>(getCtxI());
11655 if (CB->isMustTailCall() &&
11656 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11657 UsedAssumedInformation))
11658 return indicatePessimisticFixpoint();
11659
11660 Function *Caller = CB->getCaller();
11661
11662 auto AddScope = [&](AA::ValueScope S) {
11664 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11665 Values, S, UsedAssumedInformation))
11666 return false;
11667
11668 for (auto &It : Values) {
11669 Value *V = It.getValue();
11670 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11671 V, *CB, *this, UsedAssumedInformation);
11672 if (!CallerV.has_value()) {
11673 // Nothing to do as long as no value was determined.
11674 continue;
11675 }
11676 V = *CallerV ? *CallerV : V;
11677 if (*CallerV && AA::isDynamicallyUnique(A, *this, *V)) {
11678 if (recurseForValue(A, IRPosition::value(*V), S))
11679 continue;
11680 }
11681 if (S == AA::Intraprocedural && !AA::isValidInScope(*V, Caller)) {
11682 giveUpOnIntraprocedural(A);
11683 return true;
11684 }
11685 addValue(A, getState(), *V, CB, S, getAnchorScope());
11686 }
11687 return true;
11688 };
11689 if (!AddScope(AA::Intraprocedural))
11690 return indicatePessimisticFixpoint();
11691 if (!AddScope(AA::Interprocedural))
11692 return indicatePessimisticFixpoint();
11693 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11694 : ChangeStatus::CHANGED;
11695 }
11696
11697 ChangeStatus indicatePessimisticFixpoint() override {
11698 return AAPotentialValues::indicatePessimisticFixpoint();
11699 }
11700
11701 void trackStatistics() const override {
11702 STATS_DECLTRACK_CSRET_ATTR(potential_values)
11703 }
11704};
11705
11706struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11707 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11708 : AAPotentialValuesFloating(IRP, A) {}
11709
11710 void trackStatistics() const override {
11711 STATS_DECLTRACK_CSARG_ATTR(potential_values)
11712 }
11713};
11714} // namespace
11715
11716/// ---------------------- Assumption Propagation ------------------------------
11717namespace {
11718struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11719 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11720 const DenseSet<StringRef> &Known)
11721 : AAAssumptionInfo(IRP, A, Known) {}
11722
11723 ChangeStatus manifest(Attributor &A) override {
11724 // Don't manifest a universal set if it somehow made it here.
11725 if (getKnown().isUniversal())
11726 return ChangeStatus::UNCHANGED;
11727
11728 const IRPosition &IRP = getIRPosition();
11729 SmallVector<StringRef, 0> Set(getAssumed().getSet().begin(),
11730 getAssumed().getSet().end());
11731 llvm::sort(Set);
11732 return A.manifestAttrs(IRP,
11733 Attribute::get(IRP.getAnchorValue().getContext(),
11735 llvm::join(Set, ",")),
11736 /*ForceReplace=*/true);
11737 }
11738
11739 bool hasAssumption(const StringRef Assumption) const override {
11740 return isValidState() && setContains(Assumption);
11741 }
11742
11743 const std::string getAsStr(Attributor *A) const override {
11744 const SetContents &Known = getKnown();
11745 const SetContents &Assumed = getAssumed();
11746
11747 SmallVector<StringRef, 0> Set(Known.getSet().begin(), Known.getSet().end());
11748 llvm::sort(Set);
11749 const std::string KnownStr = llvm::join(Set, ",");
11750
11751 std::string AssumedStr = "Universal";
11752 if (!Assumed.isUniversal()) {
11753 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11754 AssumedStr = llvm::join(Set, ",");
11755 }
11756 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11757 }
11758};
11759
11760/// Propagates assumption information from parent functions to all of their
11761/// successors. An assumption can be propagated if the containing function
11762/// dominates the called function.
11763///
11764/// We start with a "known" set of assumptions already valid for the associated
11765/// function and an "assumed" set that initially contains all possible
11766/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11767/// contents as concrete values are known. The concrete values are seeded by the
11768/// first nodes that are either entries into the call graph, or contains no
11769/// assumptions. Each node is updated as the intersection of the assumed state
11770/// with all of its predecessors.
11771struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11772 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11773 : AAAssumptionInfoImpl(IRP, A,
11774 getAssumptions(*IRP.getAssociatedFunction())) {}
11775
11776 ChangeStatus updateImpl(Attributor &A) override {
11777 bool Changed = false;
11778
11779 auto CallSitePred = [&](AbstractCallSite ACS) {
11780 const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11781 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11782 DepClassTy::REQUIRED);
11783 if (!AssumptionAA)
11784 return false;
11785 // Get the set of assumptions shared by all of this function's callers.
11786 Changed |= getIntersection(AssumptionAA->getAssumed());
11787 return !getAssumed().empty() || !getKnown().empty();
11788 };
11789
11790 bool UsedAssumedInformation = false;
11791 // Get the intersection of all assumptions held by this node's predecessors.
11792 // If we don't know all the call sites then this is either an entry into the
11793 // call graph or an empty node. This node is known to only contain its own
11794 // assumptions and can be propagated to its successors.
11795 if (!A.checkForAllCallSites(CallSitePred, *this, true,
11796 UsedAssumedInformation))
11797 return indicatePessimisticFixpoint();
11798
11799 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11800 }
11801
11802 void trackStatistics() const override {}
11803};
11804
11805/// Assumption Info defined for call sites.
11806struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11807
11808 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11809 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11810
11811 void initialize(Attributor &A) override {
11812 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11813 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11814 }
11815
11816 ChangeStatus updateImpl(Attributor &A) override {
11817 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11818 auto *AssumptionAA =
11819 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11820 if (!AssumptionAA)
11821 return indicatePessimisticFixpoint();
11822 bool Changed = getIntersection(AssumptionAA->getAssumed());
11823 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11824 }
11825
11826 void trackStatistics() const override {}
11827
11828private:
11829 /// Helper to initialized the known set as all the assumptions this call and
11830 /// the callee contain.
11831 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11832 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
11833 auto Assumptions = getAssumptions(CB);
11834 if (const Function *F = CB.getCaller())
11835 set_union(Assumptions, getAssumptions(*F));
11836 if (Function *F = IRP.getAssociatedFunction())
11837 set_union(Assumptions, getAssumptions(*F));
11838 return Assumptions;
11839 }
11840};
11841} // namespace
11842
11844 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11845 A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
11846}
11847
11849
11850/// ------------------------ UnderlyingObjects ---------------------------------
11851
11852namespace {
11853struct AAUnderlyingObjectsImpl
11854 : StateWrapper<BooleanState, AAUnderlyingObjects> {
11856 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
11857
11858 const std::string getAsStr(Attributor *A) const override {
11859 if (!isValidState())
11860 return "<invalid>";
11861 std::string Str;
11863 OS << "underlying objects: inter " << InterAssumedUnderlyingObjects.size()
11864 << " objects, intra " << IntraAssumedUnderlyingObjects.size()
11865 << " objects.\n";
11866 if (!InterAssumedUnderlyingObjects.empty()) {
11867 OS << "inter objects:\n";
11868 for (auto *Obj : InterAssumedUnderlyingObjects)
11869 OS << *Obj << '\n';
11870 }
11871 if (!IntraAssumedUnderlyingObjects.empty()) {
11872 OS << "intra objects:\n";
11873 for (auto *Obj : IntraAssumedUnderlyingObjects)
11874 OS << *Obj << '\n';
11875 }
11876 return Str;
11877 }
11878
11879 void trackStatistics() const override {}
11880
11881 ChangeStatus updateImpl(Attributor &A) override {
11882 auto &Ptr = getAssociatedValue();
11883
11884 bool UsedAssumedInformation = false;
11885 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11887 SmallPtrSet<Value *, 8> SeenObjects;
11889
11890 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
11891 Scope, UsedAssumedInformation))
11892 return UnderlyingObjects.insert(&Ptr);
11893
11894 bool Changed = false;
11895
11896 for (unsigned I = 0; I < Values.size(); ++I) {
11897 auto &VAC = Values[I];
11898 auto *Obj = VAC.getValue();
11899 Value *UO = getUnderlyingObject(Obj);
11900 if (!SeenObjects.insert(UO ? UO : Obj).second)
11901 continue;
11902 if (UO && UO != Obj) {
11903 if (isa<AllocaInst>(UO) || isa<GlobalValue>(UO)) {
11904 Changed |= UnderlyingObjects.insert(UO);
11905 continue;
11906 }
11907
11908 const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(
11909 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
11910 auto Pred = [&](Value &V) {
11911 if (&V == UO)
11912 Changed |= UnderlyingObjects.insert(UO);
11913 else
11914 Values.emplace_back(V, nullptr);
11915 return true;
11916 };
11917
11918 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
11920 "The forall call should not return false at this position");
11921 UsedAssumedInformation |= !OtherAA->getState().isAtFixpoint();
11922 continue;
11923 }
11924
11925 if (isa<SelectInst>(Obj)) {
11926 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope,
11927 UsedAssumedInformation);
11928 continue;
11929 }
11930 if (auto *PHI = dyn_cast<PHINode>(Obj)) {
11931 // Explicitly look through PHIs as we do not care about dynamically
11932 // uniqueness.
11933 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
11934 Changed |=
11935 handleIndirect(A, *PHI->getIncomingValue(u), UnderlyingObjects,
11936 Scope, UsedAssumedInformation);
11937 }
11938 continue;
11939 }
11940
11941 Changed |= UnderlyingObjects.insert(Obj);
11942 }
11943
11944 return Changed;
11945 };
11946
11947 bool Changed = false;
11948 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
11949 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
11950 if (!UsedAssumedInformation)
11951 indicateOptimisticFixpoint();
11952 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11953 }
11954
11955 bool forallUnderlyingObjects(
11956 function_ref<bool(Value &)> Pred,
11957 AA::ValueScope Scope = AA::Interprocedural) const override {
11958 if (!isValidState())
11959 return Pred(getAssociatedValue());
11960
11961 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
11962 ? IntraAssumedUnderlyingObjects
11963 : InterAssumedUnderlyingObjects;
11964 for (Value *Obj : AssumedUnderlyingObjects)
11965 if (!Pred(*Obj))
11966 return false;
11967
11968 return true;
11969 }
11970
11971private:
11972 /// Handle the case where the value is not the actual underlying value, such
11973 /// as a phi node or a select instruction.
11974 bool handleIndirect(Attributor &A, Value &V,
11975 SmallSetVector<Value *, 8> &UnderlyingObjects,
11976 AA::ValueScope Scope, bool &UsedAssumedInformation) {
11977 bool Changed = false;
11978 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
11979 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
11980 auto Pred = [&](Value &V) {
11981 Changed |= UnderlyingObjects.insert(&V);
11982 return true;
11983 };
11984 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
11986 "The forall call should not return false at this position");
11987 UsedAssumedInformation |= !AA->getState().isAtFixpoint();
11988 return Changed;
11989 }
11990
11991 /// All the underlying objects collected so far via intra procedural scope.
11992 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11993 /// All the underlying objects collected so far via inter procedural scope.
11994 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11995};
11996
11997struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
11998 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
11999 : AAUnderlyingObjectsImpl(IRP, A) {}
12000};
12001
12002struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12003 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
12004 : AAUnderlyingObjectsImpl(IRP, A) {}
12005};
12006
12007struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12008 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
12009 : AAUnderlyingObjectsImpl(IRP, A) {}
12010};
12011
12012struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12013 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
12014 : AAUnderlyingObjectsImpl(IRP, A) {}
12015};
12016
12017struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12018 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
12019 : AAUnderlyingObjectsImpl(IRP, A) {}
12020};
12021
12022struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12023 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
12024 : AAUnderlyingObjectsImpl(IRP, A) {}
12025};
12026
12027struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12028 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
12029 : AAUnderlyingObjectsImpl(IRP, A) {}
12030};
12031} // namespace
12032
12033/// ------------------------ Global Value Info -------------------------------
12034namespace {
12035struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
12036 AAGlobalValueInfoFloating(const IRPosition &IRP, Attributor &A)
12037 : AAGlobalValueInfo(IRP, A) {}
12038
12039 void initialize(Attributor &A) override {}
12040
12041 bool checkUse(Attributor &A, const Use &U, bool &Follow,
12042 SmallVectorImpl<const Value *> &Worklist) {
12043 Instruction *UInst = dyn_cast<Instruction>(U.getUser());
12044 if (!UInst) {
12045 // Outside a closed world, code outside the module can read an
12046 // externally visible global, so the value escapes through it.
12047 if (auto *GV = dyn_cast<GlobalValue>(U.getUser()))
12048 if (!GV->hasLocalLinkage() && !A.isClosedWorldModule())
12049 return false;
12050 Follow = true;
12051 return true;
12052 }
12053
12054 LLVM_DEBUG(dbgs() << "[AAGlobalValueInfo] Check use: " << *U.get() << " in "
12055 << *UInst << "\n");
12056
12057 if (auto *Cmp = dyn_cast<ICmpInst>(U.getUser())) {
12058 int Idx = &Cmp->getOperandUse(0) == &U;
12059 if (isa<Constant>(Cmp->getOperand(Idx)))
12060 return true;
12061 return U == &getAnchorValue();
12062 }
12063
12064 // Explicitly catch return instructions.
12065 if (isa<ReturnInst>(UInst)) {
12066 auto CallSitePred = [&](AbstractCallSite ACS) {
12067 Worklist.push_back(ACS.getInstruction());
12068 return true;
12069 };
12070 bool UsedAssumedInformation = false;
12071 // TODO: We should traverse the uses or add a "non-call-site" CB.
12072 if (!A.checkForAllCallSites(CallSitePred, *UInst->getFunction(),
12073 /*RequireAllCallSites=*/true, this,
12074 UsedAssumedInformation))
12075 return false;
12076 return true;
12077 }
12078
12079 // For now we only use special logic for call sites. However, the tracker
12080 // itself knows about a lot of other non-capturing cases already.
12081 auto *CB = dyn_cast<CallBase>(UInst);
12082 if (!CB)
12083 return false;
12084 // Direct calls are OK uses.
12085 if (CB->isCallee(&U))
12086 return true;
12087 // Non-argument uses are scary.
12088 if (!CB->isArgOperand(&U))
12089 return false;
12090 // TODO: Iterate callees.
12091 auto *Fn = dyn_cast<Function>(CB->getCalledOperand());
12092 if (!Fn || !A.isFunctionIPOAmendable(*Fn))
12093 return false;
12094
12095 unsigned ArgNo = CB->getArgOperandNo(&U);
12096 Worklist.push_back(Fn->getArg(ArgNo));
12097 return true;
12098 }
12099
12100 ChangeStatus updateImpl(Attributor &A) override {
12101 unsigned NumUsesBefore = Uses.size();
12102
12103 SmallPtrSet<const Value *, 8> Visited;
12105 Worklist.push_back(&getAnchorValue());
12106
12107 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
12108 Uses.insert(&U);
12109 // TODO(captures): Make this more precise.
12110 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
12111 if (CI.isPassthrough()) {
12112 Follow = true;
12113 return true;
12114 }
12115 return checkUse(A, U, Follow, Worklist);
12116 };
12117 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
12118 Uses.insert(&OldU);
12119 return true;
12120 };
12121
12122 while (!Worklist.empty()) {
12123 const Value *V = Worklist.pop_back_val();
12124 if (!Visited.insert(V).second)
12125 continue;
12126 if (!A.checkForAllUses(UsePred, *this, *V,
12127 /* CheckBBLivenessOnly */ true,
12128 DepClassTy::OPTIONAL,
12129 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
12130 return indicatePessimisticFixpoint();
12131 }
12132 }
12133
12134 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12135 : ChangeStatus::CHANGED;
12136 }
12137
12138 bool isPotentialUse(const Use &U) const override {
12139 return !isValidState() || Uses.contains(&U);
12140 }
12141
12142 ChangeStatus manifest(Attributor &A) override {
12143 return ChangeStatus::UNCHANGED;
12144 }
12145
12146 const std::string getAsStr(Attributor *A) const override {
12147 return "[" + std::to_string(Uses.size()) + " uses]";
12148 }
12149
12150 void trackStatistics() const override {
12151 STATS_DECLTRACK_FLOATING_ATTR(GlobalValuesTracked);
12152 }
12153
12154private:
12155 /// Set of (transitive) uses of this GlobalValue.
12156 SmallPtrSet<const Use *, 8> Uses;
12157};
12158} // namespace
12159
12160/// ------------------------ Indirect Call Info -------------------------------
12161namespace {
12162struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12163 AAIndirectCallInfoCallSite(const IRPosition &IRP, Attributor &A)
12164 : AAIndirectCallInfo(IRP, A) {}
12165
12166 void initialize(Attributor &A) override {
12167 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12168 if (!MD && !A.isClosedWorldModule())
12169 return;
12170
12171 if (MD) {
12172 for (const auto &Op : MD->operands())
12174 PotentialCallees.insert(Callee);
12175 } else if (A.isClosedWorldModule()) {
12176 ArrayRef<Function *> IndirectlyCallableFunctions =
12177 A.getInfoCache().getIndirectlyCallableFunctions(A);
12178 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12179 }
12180
12181 if (PotentialCallees.empty())
12182 indicateOptimisticFixpoint();
12183 }
12184
12185 ChangeStatus updateImpl(Attributor &A) override {
12186 CallBase *CB = cast<CallBase>(getCtxI());
12187 const Use &CalleeUse = CB->getCalledOperandUse();
12188 Value *FP = CB->getCalledOperand();
12189
12190 SmallSetVector<Function *, 4> AssumedCalleesNow;
12191 bool AllCalleesKnownNow = AllCalleesKnown;
12192
12193 auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,
12194 bool &UsedAssumedInformation) {
12195 const auto *GIAA = A.getAAFor<AAGlobalValueInfo>(
12196 *this, IRPosition::value(PotentialCallee), DepClassTy::OPTIONAL);
12197 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12198 return true;
12199 UsedAssumedInformation = !GIAA->isAtFixpoint();
12200 return false;
12201 };
12202
12203 auto AddPotentialCallees = [&]() {
12204 for (auto *PotentialCallee : PotentialCallees) {
12205 bool UsedAssumedInformation = false;
12206 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12207 AssumedCalleesNow.insert(PotentialCallee);
12208 }
12209 };
12210
12211 // Use simplification to find potential callees, if !callees was present,
12212 // fallback to that set if necessary.
12213 bool UsedAssumedInformation = false;
12215 if (!A.getAssumedSimplifiedValues(IRPosition::value(*FP), this, Values,
12216 AA::ValueScope::AnyScope,
12217 UsedAssumedInformation)) {
12218 if (PotentialCallees.empty())
12219 return indicatePessimisticFixpoint();
12220 AddPotentialCallees();
12221 }
12222
12223 // Try to find a reason for \p Fn not to be a potential callee. If none was
12224 // found, add it to the assumed callees set.
12225 auto CheckPotentialCallee = [&](Function &Fn) {
12226 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12227 return false;
12228
12229 auto &CachedResult = FilterResults[&Fn];
12230 if (CachedResult.has_value())
12231 return CachedResult.value();
12232
12233 bool UsedAssumedInformation = false;
12234 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12235 if (!UsedAssumedInformation)
12236 CachedResult = false;
12237 return false;
12238 }
12239
12240 int NumFnArgs = Fn.arg_size();
12241 int NumCBArgs = CB->arg_size();
12242
12243 // Check if any excess argument (which we fill up with poison) is known to
12244 // be UB on undef.
12245 for (int I = NumCBArgs; I < NumFnArgs; ++I) {
12246 bool IsKnown = false;
12248 A, this, IRPosition::argument(*Fn.getArg(I)),
12249 DepClassTy::OPTIONAL, IsKnown)) {
12250 if (IsKnown)
12251 CachedResult = false;
12252 return false;
12253 }
12254 }
12255
12256 CachedResult = true;
12257 return true;
12258 };
12259
12260 // Check simplification result, prune known UB callees, also restrict it to
12261 // the !callees set, if present.
12262 for (auto &VAC : Values) {
12263 if (isa<UndefValue>(VAC.getValue()))
12264 continue;
12266 VAC.getValue()->getType()->getPointerAddressSpace() == 0)
12267 continue;
12268 // TODO: Check for known UB, e.g., poison + noundef.
12269 if (auto *VACFn = dyn_cast<Function>(VAC.getValue())) {
12270 if (CheckPotentialCallee(*VACFn))
12271 AssumedCalleesNow.insert(VACFn);
12272 continue;
12273 }
12274 if (!PotentialCallees.empty()) {
12275 AddPotentialCallees();
12276 break;
12277 }
12278 AllCalleesKnownNow = false;
12279 }
12280
12281 if (AssumedCalleesNow == AssumedCallees &&
12282 AllCalleesKnown == AllCalleesKnownNow)
12283 return ChangeStatus::UNCHANGED;
12284
12285 std::swap(AssumedCallees, AssumedCalleesNow);
12286 AllCalleesKnown = AllCalleesKnownNow;
12287 return ChangeStatus::CHANGED;
12288 }
12289
12290 ChangeStatus manifest(Attributor &A) override {
12291 // If we can't specialize at all, give up now.
12292 if (!AllCalleesKnown && AssumedCallees.empty())
12293 return ChangeStatus::UNCHANGED;
12294
12295 CallBase *CB = cast<CallBase>(getCtxI());
12296 bool UsedAssumedInformation = false;
12297 if (A.isAssumedDead(*CB, this, /*LivenessAA=*/nullptr,
12298 UsedAssumedInformation))
12299 return ChangeStatus::UNCHANGED;
12300
12301 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12302 unsigned ProgramAS = CB->getDataLayout().getProgramAddressSpace();
12303 Value *FP = CB->getCalledOperand();
12304 if (FP->getType()->getPointerAddressSpace() != ProgramAS)
12305 FP = new AddrSpaceCastInst(
12306 FP, PointerType::get(FP->getContext(), ProgramAS),
12307 FP->getName() + ".as" + Twine(ProgramAS), CB->getIterator());
12308
12309 bool CBIsVoid = CB->getType()->isVoidTy();
12311 FunctionType *CSFT = CB->getFunctionType();
12312 SmallVector<Value *> CSArgs(CB->args());
12313
12314 // If we know all callees and there are none, the call site is (effectively)
12315 // dead (or UB).
12316 if (AssumedCallees.empty()) {
12317 assert(AllCalleesKnown &&
12318 "Expected all callees to be known if there are none.");
12319 A.changeToUnreachableAfterManifest(CB);
12320 return ChangeStatus::CHANGED;
12321 }
12322
12323 // Special handling for the single callee case.
12324 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12325 auto *NewCallee = AssumedCallees.front();
12326 if (isLegalToPromote(*CB, NewCallee)) {
12327 promoteCall(*CB, NewCallee, nullptr);
12328 NumIndirectCallsPromoted++;
12329 return ChangeStatus::CHANGED;
12330 }
12331 Instruction *NewCall =
12332 CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12333 CB->getName(), CB->getIterator());
12334 if (!CBIsVoid)
12335 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *NewCall);
12336 A.deleteAfterManifest(*CB);
12337 return ChangeStatus::CHANGED;
12338 }
12339
12340 // For each potential value we create a conditional
12341 //
12342 // ```
12343 // if (ptr == value) value(args);
12344 // else ...
12345 // ```
12346 //
12347 bool SpecializedForAnyCallees = false;
12348 bool SpecializedForAllCallees = AllCalleesKnown;
12349 ICmpInst *LastCmp = nullptr;
12350 SmallVector<Function *, 8> SkippedAssumedCallees;
12352 for (Function *NewCallee : AssumedCallees) {
12353 if (!A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,
12354 AssumedCallees.size())) {
12355 SkippedAssumedCallees.push_back(NewCallee);
12356 SpecializedForAllCallees = false;
12357 continue;
12358 }
12359 SpecializedForAnyCallees = true;
12360
12361 LastCmp = new ICmpInst(IP, llvm::CmpInst::ICMP_EQ, FP, NewCallee);
12362 Instruction *ThenTI =
12363 SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false);
12364 BasicBlock *CBBB = CB->getParent();
12365 A.registerManifestAddedBasicBlock(*ThenTI->getParent());
12366 A.registerManifestAddedBasicBlock(*IP->getParent());
12367 auto *SplitTI = cast<CondBrInst>(LastCmp->getNextNode());
12368 BasicBlock *ElseBB;
12369 if (&*IP == CB) {
12370 ElseBB = BasicBlock::Create(ThenTI->getContext(), "",
12371 ThenTI->getFunction(), CBBB);
12372 A.registerManifestAddedBasicBlock(*ElseBB);
12373 IP = UncondBrInst::Create(CBBB, ElseBB)->getIterator();
12374 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12375 } else {
12376 ElseBB = IP->getParent();
12377 ThenTI->replaceUsesOfWith(ElseBB, CBBB);
12378 }
12379 CastInst *RetBC = nullptr;
12380 CallInst *NewCall = nullptr;
12381 if (isLegalToPromote(*CB, NewCallee)) {
12382 auto *CBClone = cast<CallBase>(CB->clone());
12383 CBClone->insertBefore(ThenTI->getIterator());
12384 NewCall = &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));
12385 NumIndirectCallsPromoted++;
12386 } else {
12387 NewCall = CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12388 CB->getName(), ThenTI->getIterator());
12389 }
12390 NewCalls.push_back({NewCall, RetBC});
12391 }
12392
12393 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12394 if (!AllCalleesKnown)
12395 return ChangeStatus::UNCHANGED;
12396 MDBuilder MDB(IndirectCB.getContext());
12397 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12398 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12399 return ChangeStatus::CHANGED;
12400 };
12401
12402 if (!SpecializedForAnyCallees)
12403 return AttachCalleeMetadata(*CB);
12404
12405 // Check if we need the fallback indirect call still.
12406 if (SpecializedForAllCallees) {
12408 LastCmp->eraseFromParent();
12409 new UnreachableInst(IP->getContext(), IP);
12410 IP->eraseFromParent();
12411 } else {
12412 auto *CBClone = cast<CallInst>(CB->clone());
12413 CBClone->setName(CB->getName());
12414 CBClone->insertBefore(*IP->getParent(), IP);
12415 NewCalls.push_back({CBClone, nullptr});
12416 AttachCalleeMetadata(*CBClone);
12417 }
12418
12419 // Check if we need a PHI to merge the results.
12420 if (!CBIsVoid) {
12421 auto *PHI = PHINode::Create(CB->getType(), NewCalls.size(),
12422 CB->getName() + ".phi",
12423 CB->getParent()->getFirstInsertionPt());
12424 for (auto &It : NewCalls) {
12425 CallBase *NewCall = It.first;
12426 Instruction *CallRet = It.second ? It.second : It.first;
12427 if (CallRet->getType() == CB->getType())
12428 PHI->addIncoming(CallRet, CallRet->getParent());
12429 else if (NewCall->getType()->isVoidTy())
12430 PHI->addIncoming(PoisonValue::get(CB->getType()),
12431 NewCall->getParent());
12432 else
12433 llvm_unreachable("Call return should match or be void!");
12434 }
12435 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *PHI);
12436 }
12437
12438 A.deleteAfterManifest(*CB);
12439 Changed = ChangeStatus::CHANGED;
12440
12441 return Changed;
12442 }
12443
12444 const std::string getAsStr(Attributor *A) const override {
12445 return std::string(AllCalleesKnown ? "eliminate" : "specialize") +
12446 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12447 " functions";
12448 }
12449
12450 void trackStatistics() const override {
12451 if (AllCalleesKnown) {
12453 Eliminated, CallSites,
12454 "Number of indirect call sites eliminated via specialization")
12455 } else {
12456 STATS_DECLTRACK(Specialized, CallSites,
12457 "Number of indirect call sites specialized")
12458 }
12459 }
12460
12461 bool foreachCallee(function_ref<bool(Function *)> CB) const override {
12462 return isValidState() && AllCalleesKnown && all_of(AssumedCallees, CB);
12463 }
12464
12465private:
12466 /// Map to remember filter results.
12467 DenseMap<Function *, std::optional<bool>> FilterResults;
12468
12469 /// If the !callee metadata was present, this set will contain all potential
12470 /// callees (superset).
12471 SmallSetVector<Function *, 4> PotentialCallees;
12472
12473 /// This set contains all currently assumed calllees, which might grow over
12474 /// time.
12475 SmallSetVector<Function *, 4> AssumedCallees;
12476
12477 /// Flag to indicate if all possible callees are in the AssumedCallees set or
12478 /// if there could be others.
12479 bool AllCalleesKnown = true;
12480};
12481} // namespace
12482
12483/// --------------------- Invariant Load Pointer -------------------------------
12484namespace {
12485
12486struct AAInvariantLoadPointerImpl
12487 : public StateWrapper<BitIntegerState<uint8_t, 15>,
12488 AAInvariantLoadPointer> {
12489
12490 enum {
12491 // pointer does not alias within the bounds of the function
12492 IS_NOALIAS = 1 << 0,
12493 // pointer is not involved in any effectful instructions within the bounds
12494 // of the function
12495 IS_NOEFFECT = 1 << 1,
12496 // loads are invariant within the bounds of the function
12497 IS_LOCALLY_INVARIANT = 1 << 2,
12498 // memory lifetime is constrained within the bounds of the function
12499 IS_LOCALLY_CONSTRAINED = 1 << 3,
12500
12501 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12502 IS_LOCALLY_CONSTRAINED,
12503 };
12504 static_assert(getBestState() == IS_BEST_STATE, "Unexpected best state");
12505
12506 using Base =
12507 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12508
12509 // the BitIntegerState is optimistic about IS_NOALIAS and IS_NOEFFECT, but
12510 // pessimistic about IS_KNOWN_INVARIANT
12511 AAInvariantLoadPointerImpl(const IRPosition &IRP, Attributor &A)
12512 : Base(IRP) {}
12513
12514 bool isKnownInvariant() const final {
12515 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12516 }
12517
12518 bool isKnownLocallyInvariant() const final {
12519 if (isKnown(IS_LOCALLY_INVARIANT))
12520 return true;
12521 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12522 }
12523
12524 bool isAssumedInvariant() const final {
12525 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12526 }
12527
12528 bool isAssumedLocallyInvariant() const final {
12529 if (isAssumed(IS_LOCALLY_INVARIANT))
12530 return true;
12531 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12532 }
12533
12534 ChangeStatus updateImpl(Attributor &A) override {
12535 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12536
12537 Changed |= updateNoAlias(A);
12538 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12539 return indicatePessimisticFixpoint();
12540
12541 Changed |= updateNoEffect(A);
12542
12543 Changed |= updateLocalInvariance(A);
12544
12545 return Changed;
12546 }
12547
12548 ChangeStatus manifest(Attributor &A) override {
12549 if (!isKnownInvariant())
12550 return ChangeStatus::UNCHANGED;
12551
12552 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12553 const Value *Ptr = &getAssociatedValue();
12554 const auto TagInvariantLoads = [&](const Use &U, bool &) {
12555 if (U.get() != Ptr)
12556 return true;
12557 auto *I = dyn_cast<Instruction>(U.getUser());
12558 if (!I)
12559 return true;
12560
12561 // Ensure that we are only changing uses from the corresponding callgraph
12562 // SSC in the case that the AA isn't run on the entire module
12563 if (!A.isRunOn(I->getFunction()))
12564 return true;
12565
12566 if (I->hasMetadata(LLVMContext::MD_invariant_load))
12567 return true;
12568
12569 if (auto *LI = dyn_cast<LoadInst>(I)) {
12570 LI->setMetadata(LLVMContext::MD_invariant_load,
12571 MDNode::get(LI->getContext(), {}));
12572 Changed = ChangeStatus::CHANGED;
12573 }
12574 return true;
12575 };
12576
12577 (void)A.checkForAllUses(TagInvariantLoads, *this, *Ptr);
12578 return Changed;
12579 }
12580
12581 const std::string getAsStr(Attributor *) const override {
12582 if (isKnownInvariant())
12583 return "load-invariant pointer";
12584 return "non-invariant pointer";
12585 }
12586
12587 void trackStatistics() const override {}
12588
12589private:
12590 /// Indicate that noalias is required for the pointer to be invariant.
12591 bool requiresNoAlias() const {
12592 switch (getPositionKind()) {
12593 default:
12594 // Conservatively default to require noalias.
12595 return true;
12596 case IRP_FLOAT:
12597 case IRP_RETURNED:
12598 case IRP_CALL_SITE:
12599 return false;
12600 case IRP_CALL_SITE_RETURNED: {
12601 const auto &CB = cast<CallBase>(getAnchorValue());
12603 &CB, /*MustPreserveOffset=*/false);
12604 }
12605 case IRP_ARGUMENT: {
12606 const Function *F = getAssociatedFunction();
12607 assert(F && "no associated function for argument");
12608 return !isCallableCC(F->getCallingConv());
12609 }
12610 }
12611 }
12612
12613 bool isExternal() const {
12614 const Function *F = getAssociatedFunction();
12615 if (!F)
12616 return true;
12617 return isCallableCC(F->getCallingConv()) &&
12618 getPositionKind() != IRP_CALL_SITE_RETURNED;
12619 }
12620
12621 ChangeStatus updateNoAlias(Attributor &A) {
12622 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12623 return ChangeStatus::UNCHANGED;
12624
12625 // Try to use AANoAlias.
12626 if (const auto *ANoAlias = A.getOrCreateAAFor<AANoAlias>(
12627 getIRPosition(), this, DepClassTy::REQUIRED)) {
12628 if (ANoAlias->isKnownNoAlias()) {
12629 addKnownBits(IS_NOALIAS);
12630 return ChangeStatus::CHANGED;
12631 }
12632
12633 if (!ANoAlias->isAssumedNoAlias()) {
12634 removeAssumedBits(IS_NOALIAS);
12635 return ChangeStatus::CHANGED;
12636 }
12637
12638 return ChangeStatus::UNCHANGED;
12639 }
12640
12641 // Try to infer noalias from argument attribute, since it is applicable for
12642 // the duration of the function.
12643 if (const Argument *Arg = getAssociatedArgument()) {
12644 if (Arg->hasNoAliasAttr()) {
12645 addKnownBits(IS_NOALIAS);
12646 return ChangeStatus::UNCHANGED;
12647 }
12648
12649 // Noalias information is not provided, and cannot be inferred,
12650 // so we conservatively assume the pointer aliases.
12651 removeAssumedBits(IS_NOALIAS);
12652 return ChangeStatus::CHANGED;
12653 }
12654
12655 return ChangeStatus::UNCHANGED;
12656 }
12657
12658 ChangeStatus updateNoEffect(Attributor &A) {
12659 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12660 return ChangeStatus::UNCHANGED;
12661
12662 if (!getAssociatedFunction())
12663 return indicatePessimisticFixpoint();
12664
12665 if (isa<AllocaInst>(&getAssociatedValue()))
12666 return indicatePessimisticFixpoint();
12667
12668 const auto HasNoEffectLoads = [&](const Use &U, bool &) {
12669 const auto *LI = dyn_cast<LoadInst>(U.getUser());
12670 return !LI || !LI->mayHaveSideEffects();
12671 };
12672 if (!A.checkForAllUses(HasNoEffectLoads, *this, getAssociatedValue()))
12673 return indicatePessimisticFixpoint();
12674
12675 if (const auto *AMemoryBehavior = A.getOrCreateAAFor<AAMemoryBehavior>(
12676 getIRPosition(), this, DepClassTy::REQUIRED)) {
12677 // For non-instructions, try to use AAMemoryBehavior to infer the readonly
12678 // attribute
12679 if (!AMemoryBehavior->isAssumedReadOnly())
12680 return indicatePessimisticFixpoint();
12681
12682 if (AMemoryBehavior->isKnownReadOnly()) {
12683 addKnownBits(IS_NOEFFECT);
12684 return ChangeStatus::UNCHANGED;
12685 }
12686
12687 return ChangeStatus::UNCHANGED;
12688 }
12689
12690 if (const Argument *Arg = getAssociatedArgument()) {
12691 if (Arg->onlyReadsMemory()) {
12692 addKnownBits(IS_NOEFFECT);
12693 return ChangeStatus::UNCHANGED;
12694 }
12695
12696 // Readonly information is not provided, and cannot be inferred from
12697 // AAMemoryBehavior.
12698 return indicatePessimisticFixpoint();
12699 }
12700
12701 return ChangeStatus::UNCHANGED;
12702 }
12703
12704 ChangeStatus updateLocalInvariance(Attributor &A) {
12705 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12706 return ChangeStatus::UNCHANGED;
12707
12708 // try to infer invariance from underlying objects
12709 const auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
12710 getIRPosition(), this, DepClassTy::REQUIRED);
12711 if (!AUO)
12712 return ChangeStatus::UNCHANGED;
12713
12714 bool UsedAssumedInformation = false;
12715 const auto IsLocallyInvariantLoadIfPointer = [&](const Value &V) {
12716 if (!V.getType()->isPointerTy())
12717 return true;
12718 const auto *IsInvariantLoadPointer =
12719 A.getOrCreateAAFor<AAInvariantLoadPointer>(IRPosition::value(V), this,
12720 DepClassTy::REQUIRED);
12721 // Conservatively fail if invariance cannot be inferred.
12722 if (!IsInvariantLoadPointer)
12723 return false;
12724
12725 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12726 return true;
12727 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12728 return false;
12729
12730 UsedAssumedInformation = true;
12731 return true;
12732 };
12733 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12734 return indicatePessimisticFixpoint();
12735
12736 if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue())) {
12738 CB, /*MustPreserveOffset=*/false)) {
12739 for (const Value *Arg : CB->args()) {
12740 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12741 return indicatePessimisticFixpoint();
12742 }
12743 }
12744 }
12745
12746 if (!UsedAssumedInformation) {
12747 // Pointer is known and not just assumed to be locally invariant.
12748 addKnownBits(IS_LOCALLY_INVARIANT);
12749 return ChangeStatus::CHANGED;
12750 }
12751
12752 return ChangeStatus::UNCHANGED;
12753 }
12754};
12755
12756struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12757 AAInvariantLoadPointerFloating(const IRPosition &IRP, Attributor &A)
12758 : AAInvariantLoadPointerImpl(IRP, A) {}
12759};
12760
12761struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12762 AAInvariantLoadPointerReturned(const IRPosition &IRP, Attributor &A)
12763 : AAInvariantLoadPointerImpl(IRP, A) {}
12764
12765 void initialize(Attributor &) override {
12766 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12767 }
12768};
12769
12770struct AAInvariantLoadPointerCallSiteReturned final
12771 : AAInvariantLoadPointerImpl {
12772 AAInvariantLoadPointerCallSiteReturned(const IRPosition &IRP, Attributor &A)
12773 : AAInvariantLoadPointerImpl(IRP, A) {}
12774
12775 void initialize(Attributor &A) override {
12776 // Nothing is known about the result of an indirect call.
12777 const Function *F = getAssociatedFunction();
12778 if (!F) {
12779 indicatePessimisticFixpoint();
12780 return;
12781 }
12782
12783 if (!F->isDeclaration() && !F->isIntrinsic())
12784 return AAInvariantLoadPointerImpl::initialize(A);
12785
12786 const auto &CB = cast<CallBase>(getAnchorValue());
12788 &CB, /*MustPreserveOffset=*/false))
12789 return AAInvariantLoadPointerImpl::initialize(A);
12790
12791 if (F->onlyReadsMemory() && F->hasNoSync())
12792 return AAInvariantLoadPointerImpl::initialize(A);
12793
12794 // At this point, the function is opaque, so we conservatively assume
12795 // non-invariance.
12796 indicatePessimisticFixpoint();
12797 }
12798};
12799
12800struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12801 AAInvariantLoadPointerArgument(const IRPosition &IRP, Attributor &A)
12802 : AAInvariantLoadPointerImpl(IRP, A) {}
12803
12804 void initialize(Attributor &) override {
12805 const Function *F = getAssociatedFunction();
12806 assert(F && "no associated function for argument");
12807
12808 if (!isCallableCC(F->getCallingConv())) {
12809 addKnownBits(IS_LOCALLY_CONSTRAINED);
12810 return;
12811 }
12812
12813 if (!F->hasLocalLinkage())
12814 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12815 }
12816};
12817
12818struct AAInvariantLoadPointerCallSiteArgument final
12819 : AAInvariantLoadPointerImpl {
12820 AAInvariantLoadPointerCallSiteArgument(const IRPosition &IRP, Attributor &A)
12821 : AAInvariantLoadPointerImpl(IRP, A) {}
12822};
12823} // namespace
12824
12825/// ------------------------ Address Space ------------------------------------
12826namespace {
12827
12828template <typename InstType>
12829static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,
12830 Value *OriginalValue, PointerType *NewPtrTy,
12831 bool UseOriginalValue) {
12832 if (U.getOperandNo() != InstType::getPointerOperandIndex())
12833 return false;
12834
12835 if (MemInst->isVolatile()) {
12836 auto *TTI = A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12837 *MemInst->getFunction());
12838 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12839 if (!TTI || !TTI->hasVolatileVariant(MemInst, NewAS))
12840 return false;
12841 }
12842
12843 if (UseOriginalValue) {
12844 A.changeUseAfterManifest(const_cast<Use &>(U), *OriginalValue);
12845 return true;
12846 }
12847
12848 Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12849 CastInst->insertBefore(MemInst->getIterator());
12850 A.changeUseAfterManifest(const_cast<Use &>(U), *CastInst);
12851 return true;
12852}
12853
12854struct AAAddressSpaceImpl : public AAAddressSpace {
12855 AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)
12856 : AAAddressSpace(IRP, A) {}
12857
12858 uint32_t getAddressSpace() const override {
12859 assert(isValidState() && "the AA is invalid");
12860 return AssumedAddressSpace;
12861 }
12862
12863 void initialize(Attributor &A) override {
12864 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
12865 "Associated value is not a pointer");
12866
12867 if (!A.getInfoCache().getFlatAddressSpace().has_value()) {
12868 indicatePessimisticFixpoint();
12869 return;
12870 }
12871
12872 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12873 unsigned AS = getAssociatedType()->getPointerAddressSpace();
12874 if (AS != FlatAS) {
12875 [[maybe_unused]] bool R = takeAddressSpace(AS);
12876 assert(R && "The take should happen");
12877 indicateOptimisticFixpoint();
12878 }
12879 }
12880
12881 ChangeStatus updateImpl(Attributor &A) override {
12882 uint32_t OldAddressSpace = AssumedAddressSpace;
12883 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12884
12885 auto CheckAddressSpace = [&](Value &Obj) {
12886 // Ignore undef.
12887 if (isa<UndefValue>(&Obj))
12888 return true;
12889
12890 // If the object already has a non-flat address space, we simply take it.
12891 unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
12892 if (ObjAS != FlatAS)
12893 return takeAddressSpace(ObjAS);
12894
12895 // At this point, we know Obj is in the flat address space. For a final
12896 // attempt, we want to use getAssumedAddrSpace, but first we must get the
12897 // associated function, if possible.
12898 Function *F = nullptr;
12899 if (auto *Arg = dyn_cast<Argument>(&Obj))
12900 F = Arg->getParent();
12901 else if (auto *I = dyn_cast<Instruction>(&Obj))
12902 F = I->getFunction();
12903
12904 // Use getAssumedAddrSpace if the associated function exists.
12905 if (F) {
12906 auto *TTI =
12907 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
12908 unsigned AssumedAS = TTI->getAssumedAddrSpace(&Obj);
12909 if (AssumedAS != ~0U)
12910 return takeAddressSpace(AssumedAS);
12911 }
12912
12913 // Now we can't do anything else but to take the flat AS.
12914 return takeAddressSpace(FlatAS);
12915 };
12916
12917 auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this,
12918 DepClassTy::REQUIRED);
12919 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
12920 return indicatePessimisticFixpoint();
12921
12922 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
12923 : ChangeStatus::CHANGED;
12924 }
12925
12926 ChangeStatus manifest(Attributor &A) override {
12927 unsigned NewAS = getAddressSpace();
12928
12929 if (NewAS == InvalidAddressSpace ||
12930 NewAS == getAssociatedType()->getPointerAddressSpace())
12931 return ChangeStatus::UNCHANGED;
12932
12933 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12934
12935 Value *AssociatedValue = &getAssociatedValue();
12936 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
12937
12938 PointerType *NewPtrTy =
12939 PointerType::get(getAssociatedType()->getContext(), NewAS);
12940 bool UseOriginalValue =
12941 OriginalValue->getType()->getPointerAddressSpace() == NewAS;
12942
12943 bool Changed = false;
12944
12945 auto Pred = [&](const Use &U, bool &) {
12946 if (U.get() != AssociatedValue)
12947 return true;
12948 auto *Inst = dyn_cast<Instruction>(U.getUser());
12949 if (!Inst)
12950 return true;
12951 // This is a WA to make sure we only change uses from the corresponding
12952 // CGSCC if the AA is run on CGSCC instead of the entire module.
12953 if (!A.isRunOn(Inst->getFunction()))
12954 return true;
12955 if (auto *LI = dyn_cast<LoadInst>(Inst)) {
12956 Changed |=
12957 makeChange(A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12958 } else if (auto *SI = dyn_cast<StoreInst>(Inst)) {
12959 Changed |=
12960 makeChange(A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12961 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Inst)) {
12962 Changed |=
12963 makeChange(A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
12964 } else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Inst)) {
12965 Changed |=
12966 makeChange(A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
12967 }
12968 return true;
12969 };
12970
12971 // It doesn't matter if we can't check all uses as we can simply
12972 // conservatively ignore those that can not be visited.
12973 (void)A.checkForAllUses(Pred, *this, getAssociatedValue(),
12974 /* CheckBBLivenessOnly */ true);
12975
12976 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12977 }
12978
12979 const std::string getAsStr(Attributor *A) const override {
12980 if (!isValidState())
12981 return "addrspace(<invalid>)";
12982 return "addrspace(" +
12983 (AssumedAddressSpace == InvalidAddressSpace
12984 ? "none"
12985 : std::to_string(AssumedAddressSpace)) +
12986 ")";
12987 }
12988
12989private:
12990 uint32_t AssumedAddressSpace = InvalidAddressSpace;
12991
12992 bool takeAddressSpace(uint32_t AS) {
12993 if (AssumedAddressSpace == InvalidAddressSpace) {
12994 AssumedAddressSpace = AS;
12995 return true;
12996 }
12997 return AssumedAddressSpace == AS;
12998 }
12999
13000 static Value *peelAddrspacecast(Value *V, unsigned FlatAS) {
13001 if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) {
13002 assert(I->getSrcAddressSpace() != FlatAS &&
13003 "there should not be flat AS -> non-flat AS");
13004 return I->getPointerOperand();
13005 }
13006 if (auto *C = dyn_cast<ConstantExpr>(V))
13007 if (C->getOpcode() == Instruction::AddrSpaceCast) {
13008 assert(C->getOperand(0)->getType()->getPointerAddressSpace() !=
13009 FlatAS &&
13010 "there should not be flat AS -> non-flat AS X");
13011 return C->getOperand(0);
13012 }
13013 return V;
13014 }
13015};
13016
13017struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13018 AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)
13019 : AAAddressSpaceImpl(IRP, A) {}
13020
13021 void trackStatistics() const override {
13023 }
13024};
13025
13026struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13027 AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)
13028 : AAAddressSpaceImpl(IRP, A) {}
13029
13030 void initialize(Attributor &A) override {
13031 // TODO: we don't rewrite function argument for now because it will need to
13032 // rewrite the function signature and all call sites.
13033 (void)indicatePessimisticFixpoint();
13034 }
13035
13036 void trackStatistics() const override {
13037 STATS_DECLTRACK_FNRET_ATTR(addrspace);
13038 }
13039};
13040
13041struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13042 AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13043 : AAAddressSpaceImpl(IRP, A) {}
13044
13045 void trackStatistics() const override {
13046 STATS_DECLTRACK_CSRET_ATTR(addrspace);
13047 }
13048};
13049
13050struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13051 AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)
13052 : AAAddressSpaceImpl(IRP, A) {}
13053
13054 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }
13055};
13056
13057struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13058 AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13059 : AAAddressSpaceImpl(IRP, A) {}
13060
13061 void initialize(Attributor &A) override {
13062 // TODO: we don't rewrite call site argument for now because it will need to
13063 // rewrite the function signature of the callee.
13064 (void)indicatePessimisticFixpoint();
13065 }
13066
13067 void trackStatistics() const override {
13068 STATS_DECLTRACK_CSARG_ATTR(addrspace);
13069 }
13070};
13071} // namespace
13072
13073/// ------------------------ No Alias Address Space ---------------------------
13074// This attribute assumes flat address space can alias all other address space
13075
13076// TODO: this is similar to AAAddressSpace, most of the code should be merged.
13077// But merging it created failing cased on gateway test that cannot be
13078// reproduced locally. So should open a separated PR to handle the merge of
13079// AANoAliasAddrSpace and AAAddressSpace attribute
13080
13081namespace {
13082struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {
13083 AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)
13084 : AANoAliasAddrSpace(IRP, A) {}
13085
13086 void initialize(Attributor &A) override {
13087 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13088 "Associated value is not a pointer");
13089
13090 resetASRanges(A);
13091
13092 std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();
13093 if (!FlatAS.has_value()) {
13094 indicatePessimisticFixpoint();
13095 return;
13096 }
13097
13098 removeAS(*FlatAS);
13099
13100 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13101 if (AS != *FlatAS) {
13102 removeAS(AS);
13103 indicateOptimisticFixpoint();
13104 }
13105 }
13106
13107 ChangeStatus updateImpl(Attributor &A) override {
13108 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13109 uint32_t OldAssumed = getAssumed();
13110
13111 auto CheckAddressSpace = [&](Value &Obj) {
13112 if (isa<PoisonValue>(&Obj))
13113 return true;
13114
13115 unsigned AS = Obj.getType()->getPointerAddressSpace();
13116 if (AS == FlatAS)
13117 return false;
13118
13119 removeAS(Obj.getType()->getPointerAddressSpace());
13120 return true;
13121 };
13122
13123 const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
13124 getIRPosition(), this, DepClassTy::REQUIRED);
13125 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13126 return indicatePessimisticFixpoint();
13127
13128 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13129 : ChangeStatus::CHANGED;
13130 }
13131
13132 ChangeStatus manifest(Attributor &A) override {
13133 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13134
13135 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13136 if (AS != FlatAS || Map.empty())
13137 return ChangeStatus::UNCHANGED;
13138
13139 LLVMContext &Ctx = getAssociatedValue().getContext();
13140 MDNode *NoAliasASNode = nullptr;
13141 MDBuilder MDB(Ctx);
13142 // Has to use iterator to get the range info.
13143 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13144 if (!I.value())
13145 continue;
13146 unsigned Upper = I.stop();
13147 unsigned Lower = I.start();
13148 if (!NoAliasASNode) {
13149 NoAliasASNode = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13150 continue;
13151 }
13152 MDNode *ASRange = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13153 NoAliasASNode = MDNode::getMostGenericRange(NoAliasASNode, ASRange);
13154 }
13155
13156 Value *AssociatedValue = &getAssociatedValue();
13157 bool Changed = false;
13158
13159 auto AddNoAliasAttr = [&](const Use &U, bool &) {
13160 if (U.get() != AssociatedValue)
13161 return true;
13162 Instruction *Inst = dyn_cast<Instruction>(U.getUser());
13163 if (!Inst || Inst->hasMetadata(LLVMContext::MD_noalias_addrspace))
13164 return true;
13165 if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst) &&
13167 return true;
13168 if (!A.isRunOn(Inst->getFunction()))
13169 return true;
13170 Inst->setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13171 Changed = true;
13172 return true;
13173 };
13174 (void)A.checkForAllUses(AddNoAliasAttr, *this, *AssociatedValue,
13175 /*CheckBBLivenessOnly=*/true);
13176 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13177 }
13178
13179 const std::string getAsStr(Attributor *A) const override {
13180 if (!isValidState())
13181 return "<invalid>";
13182 std::string Str;
13183 raw_string_ostream OS(Str);
13184 OS << "CanNotBeAddrSpace(";
13185 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13186 unsigned Upper = I.stop();
13187 unsigned Lower = I.start();
13188 OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';
13189 }
13190 OS << " )";
13191 return OS.str();
13192 }
13193
13194private:
13195 void removeAS(unsigned AS) {
13196 RangeMap::iterator I = Map.find(AS);
13197
13198 if (I != Map.end()) {
13199 unsigned Upper = I.stop();
13200 unsigned Lower = I.start();
13201 I.erase();
13202 if (Upper == Lower)
13203 return;
13204 if (AS != ~((unsigned)0) && AS + 1 <= Upper)
13205 Map.insert(AS + 1, Upper, /*what ever this variable name is=*/true);
13206 if (AS != 0 && Lower <= AS - 1)
13207 Map.insert(Lower, AS - 1, true);
13208 }
13209 }
13210
13211 void resetASRanges(Attributor &A) {
13212 Map.clear();
13213 Map.insert(0, A.getInfoCache().getMaxAddrSpace(), true);
13214 }
13215};
13216
13217struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13218 AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)
13219 : AANoAliasAddrSpaceImpl(IRP, A) {}
13220
13221 void trackStatistics() const override {
13222 STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);
13223 }
13224};
13225
13226struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13227 AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)
13228 : AANoAliasAddrSpaceImpl(IRP, A) {}
13229
13230 void trackStatistics() const override {
13231 STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);
13232 }
13233};
13234
13235struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13236 AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13237 : AANoAliasAddrSpaceImpl(IRP, A) {}
13238
13239 void trackStatistics() const override {
13240 STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);
13241 }
13242};
13243
13244struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13245 AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)
13246 : AANoAliasAddrSpaceImpl(IRP, A) {}
13247
13248 void trackStatistics() const override {
13249 STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);
13250 }
13251};
13252
13253struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13254 AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13255 : AANoAliasAddrSpaceImpl(IRP, A) {}
13256
13257 void trackStatistics() const override {
13258 STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);
13259 }
13260};
13261} // namespace
13262/// ----------- Allocation Info ----------
13263namespace {
13264struct AAAllocationInfoImpl : public AAAllocationInfo {
13265 AAAllocationInfoImpl(const IRPosition &IRP, Attributor &A)
13266 : AAAllocationInfo(IRP, A) {}
13267
13268 std::optional<TypeSize> getAllocatedSize() const override {
13269 assert(isValidState() && "the AA is invalid");
13270 return AssumedAllocatedSize;
13271 }
13272
13273 std::optional<TypeSize> findInitialAllocationSize(Instruction *I,
13274 const DataLayout &DL) {
13275
13276 // TODO: implement case for malloc like instructions
13277 switch (I->getOpcode()) {
13278 case Instruction::Alloca: {
13279 AllocaInst *AI = cast<AllocaInst>(I);
13280 return AI->getAllocationSize(DL);
13281 }
13282 default:
13283 return std::nullopt;
13284 }
13285 }
13286
13287 ChangeStatus updateImpl(Attributor &A) override {
13288
13289 const IRPosition &IRP = getIRPosition();
13290 Instruction *I = IRP.getCtxI();
13291
13292 // TODO: update check for malloc like calls
13293 if (!isa<AllocaInst>(I))
13294 return indicatePessimisticFixpoint();
13295
13296 bool IsKnownNoCapture;
13298 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13299 return indicatePessimisticFixpoint();
13300
13301 const AAPointerInfo *PI =
13302 A.getOrCreateAAFor<AAPointerInfo>(IRP, *this, DepClassTy::REQUIRED);
13303
13304 if (!PI)
13305 return indicatePessimisticFixpoint();
13306
13307 if (!PI->getState().isValidState() || PI->reachesReturn())
13308 return indicatePessimisticFixpoint();
13309
13310 const DataLayout &DL = A.getDataLayout();
13311 const auto AllocationSize = findInitialAllocationSize(I, DL);
13312
13313 // If allocation size is nullopt, we give up.
13314 if (!AllocationSize)
13315 return indicatePessimisticFixpoint();
13316
13317 // For zero sized allocations, we give up.
13318 // Since we can't reduce further
13319 if (*AllocationSize == 0)
13320 return indicatePessimisticFixpoint();
13321
13322 int64_t BinSize = PI->numOffsetBins();
13323
13324 // TODO: implement for multiple bins
13325 if (BinSize > 1)
13326 return indicatePessimisticFixpoint();
13327
13328 if (BinSize == 0) {
13329 auto NewAllocationSize = std::make_optional<TypeSize>(0, false);
13330 if (!changeAllocationSize(NewAllocationSize))
13331 return ChangeStatus::UNCHANGED;
13332 return ChangeStatus::CHANGED;
13333 }
13334
13335 // TODO: refactor this to be part of multiple bin case
13336 const auto &It = PI->begin();
13337
13338 // TODO: handle if Offset is not zero
13339 if (It->first.Offset != 0)
13340 return indicatePessimisticFixpoint();
13341
13342 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13343
13344 if (SizeOfBin >= *AllocationSize)
13345 return indicatePessimisticFixpoint();
13346
13347 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8, false);
13348
13349 if (!changeAllocationSize(NewAllocationSize))
13350 return ChangeStatus::UNCHANGED;
13351
13352 return ChangeStatus::CHANGED;
13353 }
13354
13355 ChangeStatus manifest(Attributor &A) override {
13356
13357 assert(isValidState() &&
13358 "Manifest should only be called if the state is valid.");
13359
13360 Instruction *I = getIRPosition().getCtxI();
13361
13362 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13363
13364 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13365
13366 switch (I->getOpcode()) {
13367 // TODO: add case for malloc like calls
13368 case Instruction::Alloca: {
13369
13370 AllocaInst *AI = cast<AllocaInst>(I);
13371
13372 Type *CharType = Type::getInt8Ty(I->getContext());
13373
13374 auto *NumBytesToValue =
13375 ConstantInt::get(I->getContext(), APInt(32, NumBytesToAllocate));
13376
13377 BasicBlock::iterator insertPt = AI->getIterator();
13378 insertPt = std::next(insertPt);
13379 AllocaInst *NewAllocaInst =
13380 new AllocaInst(CharType, AI->getAddressSpace(), NumBytesToValue,
13381 AI->getAlign(), AI->getName(), insertPt);
13382
13383 if (A.changeAfterManifest(IRPosition::inst(*AI), *NewAllocaInst))
13384 return ChangeStatus::CHANGED;
13385
13386 break;
13387 }
13388 default:
13389 break;
13390 }
13391
13392 return ChangeStatus::UNCHANGED;
13393 }
13394
13395 const std::string getAsStr(Attributor *A) const override {
13396 if (!isValidState())
13397 return "allocationinfo(<invalid>)";
13398 return "allocationinfo(" +
13399 (AssumedAllocatedSize == HasNoAllocationSize
13400 ? "none"
13401 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13402 ")";
13403 }
13404
13405private:
13406 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13407
13408 // Maintain the computed allocation size of the object.
13409 // Returns (bool) weather the size of the allocation was modified or not.
13410 bool changeAllocationSize(std::optional<TypeSize> Size) {
13411 if (AssumedAllocatedSize == HasNoAllocationSize ||
13412 AssumedAllocatedSize != Size) {
13413 AssumedAllocatedSize = Size;
13414 return true;
13415 }
13416 return false;
13417 }
13418};
13419
13420struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13421 AAAllocationInfoFloating(const IRPosition &IRP, Attributor &A)
13422 : AAAllocationInfoImpl(IRP, A) {}
13423
13424 void trackStatistics() const override {
13425 STATS_DECLTRACK_FLOATING_ATTR(allocationinfo);
13426 }
13427};
13428
13429struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13430 AAAllocationInfoReturned(const IRPosition &IRP, Attributor &A)
13431 : AAAllocationInfoImpl(IRP, A) {}
13432
13433 void initialize(Attributor &A) override {
13434 // TODO: we don't rewrite function argument for now because it will need to
13435 // rewrite the function signature and all call sites
13436 (void)indicatePessimisticFixpoint();
13437 }
13438
13439 void trackStatistics() const override {
13440 STATS_DECLTRACK_FNRET_ATTR(allocationinfo);
13441 }
13442};
13443
13444struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13445 AAAllocationInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
13446 : AAAllocationInfoImpl(IRP, A) {}
13447
13448 void trackStatistics() const override {
13449 STATS_DECLTRACK_CSRET_ATTR(allocationinfo);
13450 }
13451};
13452
13453struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13454 AAAllocationInfoArgument(const IRPosition &IRP, Attributor &A)
13455 : AAAllocationInfoImpl(IRP, A) {}
13456
13457 void trackStatistics() const override {
13458 STATS_DECLTRACK_ARG_ATTR(allocationinfo);
13459 }
13460};
13461
13462struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13463 AAAllocationInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
13464 : AAAllocationInfoImpl(IRP, A) {}
13465
13466 void initialize(Attributor &A) override {
13467
13468 (void)indicatePessimisticFixpoint();
13469 }
13470
13471 void trackStatistics() const override {
13472 STATS_DECLTRACK_CSARG_ATTR(allocationinfo);
13473 }
13474};
13475} // namespace
13476
13477const char AANoUnwind::ID = 0;
13478const char AANoSync::ID = 0;
13479const char AANoFree::ID = 0;
13480const char AANonNull::ID = 0;
13481const char AAMustProgress::ID = 0;
13482const char AANoRecurse::ID = 0;
13483const char AANonConvergent::ID = 0;
13484const char AAWillReturn::ID = 0;
13485const char AAUndefinedBehavior::ID = 0;
13486const char AANoAlias::ID = 0;
13487const char AAIntraFnReachability::ID = 0;
13488const char AANoReturn::ID = 0;
13489const char AAIsDead::ID = 0;
13490const char AADereferenceable::ID = 0;
13491const char AAAlign::ID = 0;
13492const char AAInstanceInfo::ID = 0;
13493const char AANoCapture::ID = 0;
13494const char AAValueSimplify::ID = 0;
13495const char AAHeapToStack::ID = 0;
13496const char AAPrivatizablePtr::ID = 0;
13497const char AAMemoryBehavior::ID = 0;
13498const char AAMemoryLocation::ID = 0;
13499const char AAValueConstantRange::ID = 0;
13500const char AAPotentialConstantValues::ID = 0;
13501const char AAPotentialValues::ID = 0;
13502const char AANoUndef::ID = 0;
13503const char AANoFPClass::ID = 0;
13504const char AACallEdges::ID = 0;
13505const char AAInterFnReachability::ID = 0;
13506const char AAPointerInfo::ID = 0;
13507const char AAAssumptionInfo::ID = 0;
13508const char AAUnderlyingObjects::ID = 0;
13509const char AAInvariantLoadPointer::ID = 0;
13510const char AAAddressSpace::ID = 0;
13511const char AANoAliasAddrSpace::ID = 0;
13512const char AAAllocationInfo::ID = 0;
13513const char AAIndirectCallInfo::ID = 0;
13514const char AAGlobalValueInfo::ID = 0;
13515const char AADenormalFPMath::ID = 0;
13516
13517// Macro magic to create the static generator function for attributes that
13518// follow the naming scheme.
13519
13520#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13521 case IRPosition::PK: \
13522 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13523
13524#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13525 case IRPosition::PK: \
13526 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13527 ++NumAAs; \
13528 break;
13529
13530#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13531 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13532 CLASS *AA = nullptr; \
13533 switch (IRP.getPositionKind()) { \
13534 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13535 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13536 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13537 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13538 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13539 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13540 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13541 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13542 } \
13543 return *AA; \
13544 }
13545
13546#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13547 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13548 CLASS *AA = nullptr; \
13549 switch (IRP.getPositionKind()) { \
13550 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13551 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13552 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13553 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13554 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13555 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13556 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13557 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13558 } \
13559 return *AA; \
13560 }
13561
13562#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13563 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13564 CLASS *AA = nullptr; \
13565 switch (IRP.getPositionKind()) { \
13566 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13567 default: \
13568 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13569 " position!"); \
13570 } \
13571 return *AA; \
13572 }
13573
13574#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13575 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13576 CLASS *AA = nullptr; \
13577 switch (IRP.getPositionKind()) { \
13578 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13579 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13580 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13581 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13582 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13583 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13584 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13585 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13586 } \
13587 return *AA; \
13588 }
13589
13590#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13591 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13592 CLASS *AA = nullptr; \
13593 switch (IRP.getPositionKind()) { \
13594 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13595 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13596 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13597 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13598 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13599 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13600 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13601 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13602 } \
13603 return *AA; \
13604 }
13605
13606#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13607 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13608 CLASS *AA = nullptr; \
13609 switch (IRP.getPositionKind()) { \
13610 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13611 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13612 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13613 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13614 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13615 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13616 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13617 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13618 } \
13619 return *AA; \
13620 }
13621
13631
13649
13654
13659
13666
13668
13669#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13670#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13671#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13672#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13673#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13674#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13675#undef SWITCH_PK_CREATE
13676#undef SWITCH_PK_INV
#define Success
const TargetLowering & TLI
SDValue Pred
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
uint64_t uint64_t
AMDGPU Register Bank Select
Rewrite undef for PHI
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
#define STATS_DECLTRACK(NAME, TYPE, MSG)
static std::optional< Constant * > askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA, const IRPosition &IRP, Type &Ty)
static cl::opt< unsigned, true > MaxPotentialValues("attributor-max-potential-values", cl::Hidden, cl::desc("Maximum number of potential values to be " "tracked for each position."), cl::location(llvm::PotentialConstantIntValuesState::MaxPotentialValues), cl::init(7))
static bool collectTailCalls(Attributor &A, const AbstractAttribute &QueryingAA, SmallVectorImpl< CallInst * > &TailCalls)
Collect the non-musttail tail calls in the function of QueryingAA.
static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA, StateType &S, const IRPosition::CallBaseContext *CBContext=nullptr)
Clamp the information known for all returned values of a function (identified by QueryingAA) into S.
#define STATS_DECLTRACK_FN_ATTR(NAME)
#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxPotentialValuesIterations("attributor-max-potential-values-iterations", cl::Hidden, cl::desc("Maximum number of iterations we keep dismantling potential values."), cl::init(64))
#define STATS_DECLTRACK_CS_ATTR(NAME)
#define PIPE_OPERATOR(CLASS)
#define STATS_DECLTRACK_ARG_ATTR(NAME)
static const Value * stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Val, const DataLayout &DL, APInt &Offset, bool GetMinOffset, bool AllowNonInbounds, bool UseAssumed=false)
#define STATS_DECLTRACK_CSRET_ATTR(NAME)
static cl::opt< bool > ManifestInternal("attributor-manifest-internal", cl::Hidden, cl::desc("Manifest Attributor internal string attributes."), cl::init(false))
static Value * constructPointer(Value *Ptr, int64_t Offset, IRBuilder< NoFolder > &IRB)
Helper function to create a pointer based on Ptr, and advanced by Offset bytes.
#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define BUILD_STAT_NAME(NAME, TYPE)
static bool isDenselyPacked(Type *Ty, const DataLayout &DL)
Checks if a type could have padding bytes.
#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static const Value * getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Ptr, int64_t &BytesOffset, const DataLayout &DL, bool AllowNonInbounds=false)
static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I, bool HeaderOnly, CycleRef *CPtr=nullptr)
#define STATS_DECLTRACK_FNRET_ATTR(NAME)
#define STATS_DECLTRACK_CSARG_ATTR(NAME)
#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS)
#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128), cl::Hidden)
#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define STATS_DECLTRACK_FLOATING_ATTR(NAME)
#define STATS_DECL(NAME, TYPE, MSG)
bpf unwind BPF Unwind Lower
basic Basic Alias true
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isReachableImpl(SmallVectorImpl< BasicBlock * > &Worklist, const StopSetT &StopSet, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT, const LoopInfo *LI, const CycleInfo *CI)
Definition CFG.cpp:145
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
static uint64_t align(uint64_t Size)
DXIL Forward Handle Accesses
DXIL Resource Access
dxil translate DXIL Translate Metadata
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
#define Check(C,...)
static Value * getCondition(Instruction *I)
Hexagon Common GEP
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
#define T
#define T1
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
if(PassOpts->AAPipeline)
static StringRef getName(Value *V)
RISCVCC::CondCode CC
Basic Register Allocator
dot regions Print regions of function to dot true view regions View regions of function(with no function bodies)"
Remove Loads Into Fake Uses
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
bool IsDead
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
std::pair< BasicBlock *, BasicBlock * > Edge
This file contains some templates that are useful if you are working with the STL at all.
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines generic set operations that may be used on set's of different types,...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
This pass exposes codegen information to IR-level passes.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Value * RHS
Value * LHS
static unsigned getSize(unsigned Kind)
LLVM_ABI AACallGraphNode * operator*() const
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias.
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
CallBase * getInstruction() const
Return the underlying instruction.
bool isCallbackCall() const
Return true if this ACS represents a callback call.
bool isDirectCall() const
Return true if this ACS represents a direct call.
static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)
Add operand uses of CB that represent callback uses into CallbackUses.
int getCallArgOperandNo(Argument &Arg) const
Return the operand index of the underlying instruction associated with Arg.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
LLVM_ABI bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute.
Definition Function.cpp:266
LLVM_ABI bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
Definition Function.cpp:302
LLVM_ABI bool hasPointeeInMemoryValueAttr() const
Return true if this argument has the byval, sret, inalloca, preallocated, or byref attribute.
Definition Function.cpp:169
LLVM_ABI bool hasReturnedAttr() const
Return true if this argument has the returned attribute.
Definition Function.cpp:290
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
Definition Function.cpp:126
const Function * getParent() const
Definition Argument.h:44
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Definition Argument.h:50
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static bool isEnumAttrKind(AttrKind Kind)
Definition Attributes.h:139
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:262
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:125
LLVM_ABI CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
const Instruction & front() const
Definition BasicBlock.h:463
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
BinaryOps getOpcode() const
Definition InstrTypes.h:409
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI MemoryEffects getMemoryEffects() const
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
Value * getCalledOperand() const
const Use & getCalledOperandUse() const
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
const Use & getArgOperandUse(unsigned i) const
Wrappers for getting the Use of a call argument.
OperandBundleUse getOperandBundleForOperand(unsigned OpIdx) const
Return the operand bundle for the operand at index OpIdx.
LLVM_ABI std::optional< ConstantRange > getRange() const
If this return value has a range attribute, return the value range of the argument.
Value * getArgOperand(unsigned i) const
bool isBundleOperand(unsigned Idx) const
Return true if the operand at index Idx is a bundle operand.
bool isConvergent() const
Determine if the invoke is convergent.
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
Definition ModRef.h:427
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
Definition InstrTypes.h:674
LLVM_ABI bool isIntegerCast() const
There are several places where we need to know if a cast instruction only deals with integer source a...
Type * getDestTy() const
Return the destination type, as a convenience.
Definition InstrTypes.h:681
bool isEquality() const
Determine if this is an equals/not equals predicate.
Definition InstrTypes.h:978
bool isFalseWhenEqual() const
This is just a convenience.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_NE
not equal
Definition InstrTypes.h:762
bool isTrueWhenEqual() const
This is just a convenience.
Predicate getPredicate() const
Return the predicate for this instruction.
Definition InstrTypes.h:828
Conditional Branch instruction.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:548
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
unsigned getProgramAddressSpace() const
Definition DataLayout.h:269
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:757
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:762
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
iterator end()
Definition DenseMap.h:686
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:827
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
const BasicBlock & getEntryBlock() const
Definition Function.h:803
Argument * arg_iterator
Definition Function.h:73
iterator_range< arg_iterator > args()
Definition Function.h:886
const Function & getFunction() const
Definition Function.h:167
size_t arg_size() const
Definition Function.h:895
Argument * getArg(unsigned i) const
Definition Function.h:880
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:731
BlockT * getHeader(CycleRef C) const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
bool hasLocalLinkage() const
PointerType * getType() const
Global values are always pointers.
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
Value * CreatePtrAddWithSignedOffset(Value *Ptr, int64_t Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Create a ptradd with a signed constant offset.
Definition IRBuilder.h:2123
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2987
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI bool mayReadOrWriteMemory() const LLVM_READONLY
Return true if this instruction may read or write memory.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
FPClassTest getKnownFPClasses() const
Floating-point classes the value could be one of.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LLVM_ABI ConstantRange getConstantRange(Value *V, Instruction *CtxI, bool UndefAllowed)
Return the ConstantRange constraint that is known to hold for the specified value at the specified in...
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
static LLVM_ABI MDNode * getMostGenericRange(MDNode *A, MDNode *B)
bool empty() const
Definition MapVector.h:80
static MemoryEffectsBase readOnly()
Definition ModRef.h:133
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:246
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:143
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:149
bool onlyAccessesInaccessibleMem() const
Whether this function only (at most) accesses inaccessible memory.
Definition ModRef.h:265
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:219
bool onlyAccessesArgPointees() const
Whether this function only (at most) accesses argument memory.
Definition ModRef.h:255
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
Definition ModRef.h:249
static MemoryEffectsBase writeOnly()
Definition ModRef.h:138
static MemoryEffectsBase inaccessibleOrArgMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:166
static MemoryEffectsBase none()
Definition ModRef.h:128
bool onlyAccessesInaccessibleOrArgMem() const
Whether this function only (at most) accesses argument and inaccessible memory.
Definition ModRef.h:305
static MemoryEffectsBase unknown()
Definition ModRef.h:123
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static SizeOffsetValue unknown()
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
LLVM_ABI SCEVUse getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
A vector that has set insertion semantics.
Definition SetVector.h:57
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
Definition DataLayout.h:743
TypeSize getElementOffset(unsigned Idx) const
Definition DataLayout.h:774
TypeSize getSizeInBits() const
Definition DataLayout.h:754
TypeSize getElementOffsetInBits(unsigned Idx) const
Definition DataLayout.h:779
Class to represent struct types.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
LLVM_ABI bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const
LLVM_ABI unsigned getAssumedAddrSpace(const Value *V) const
LLVM_ABI bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) const
Return true if the given instruction (assumed to be a memory access instruction) has a volatile varia...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
Definition Type.h:280
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i=0) const
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
User * getUser() const
Returns the User that contains this Use.
Definition Use.h:61
Value * get() const
Definition Use.h:55
const Use & getOperandUse(unsigned i) const
Definition User.h:220
LLVM_ABI bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
Definition User.cpp:113
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition User.cpp:25
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition ValueMap.h:167
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
static constexpr uint64_t MaximumAlignment
Definition Value.h:801
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:548
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
bool use_empty() const
Definition Value.h:348
static constexpr unsigned MaxAlignmentExponent
The maximum alignment for instructions.
Definition Value.h:800
iterator_range< use_iterator > uses()
Definition Value.h:382
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:314
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:210
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:169
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
LLVM_ABI bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
LLVM_ABI bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
raw_ostream & operator<<(raw_ostream &OS, const RangeTy &R)
Definition Attributor.h:327
LLVM_ABI std::optional< Value * > combineOptionalValuesInAAValueLatice(const std::optional< Value * > &A, const std::optional< Value * > &B, Type *Ty)
Return the combination of A and B such that the result is a possible value of both.
LLVM_ABI bool isValidAtPosition(const ValueAndContext &VAC, InformationCache &InfoCache)
Return true if the value of VAC is a valid at the position of VAC, that is a constant,...
LLVM_ABI bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)
Return true if Obj is assumed to be a thread local object.
LLVM_ABI bool isGPUConstantAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU constant address space for the target triple...
LLVM_ABI bool isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA, const Value &V, bool ForAnalysisOnly=true)
Return true if V is dynamically unique, that is, there are no two "instances" of V at runtime with di...
LLVM_ABI bool getPotentialCopiesOfStoredValue(Attributor &A, StoreInst &SI, SmallSetVector< Value *, 4 > &PotentialCopies, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values of the one stored by SI into PotentialCopies.
LLVM_ABI bool isGPUSharedAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU shared address space for the target triple i...
LLVM_ABI bool isGPULocalAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU local/private address space for the target t...
SmallPtrSet< Instruction *, 4 > InstExclusionSetTy
Definition Attributor.h:166
LLVM_ABI bool isGPU(const Module &M)
Return true iff M target a GPU (and we can use GPU AS reasoning).
ValueScope
Flags to distinguish intra-procedural queries from potentially inter-procedural queries.
Definition Attributor.h:186
@ Intraprocedural
Definition Attributor.h:187
@ Interprocedural
Definition Attributor.h:188
LLVM_ABI bool isValidInScope(const Value &V, const Function *Scope)
Return true if V is a valid value in Scope, that is a constant or an instruction/argument of Scope.
LLVM_ABI bool isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction &ToI, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet=nullptr, std::function< bool(const Function &F)> GoBackwardsCB=nullptr)
Return true if ToI is potentially reachable from FromI without running into any instruction in Exclus...
LLVM_ABI bool isNoSyncInst(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is a nosync instruction.
bool hasAssumedIRAttr(Attributor &A, const AbstractAttribute *QueryingAA, const IRPosition &IRP, DepClassTy DepClass, bool &IsKnown, bool IgnoreSubsumingPositions=false, const AAType **AAPtr=nullptr)
Helper to avoid creating an AA for IR Attributes that might already be set.
LLVM_ABI bool getPotentiallyLoadedValues(Attributor &A, LoadInst &LI, SmallSetVector< Value *, 4 > &PotentialValues, SmallSetVector< Instruction *, 4 > &PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values LI could read into PotentialValues.
LLVM_ABI Value * getWithType(Value &V, Type &Ty)
Try to convert V to type Ty without introducing new instructions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
@ Unsupported
This operation is completely unsupported on the target.
Offsets
Offsets in bytes from the start of the input buffer.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Definition LLVMContext.h:63
@ Valid
The data is already valid.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
unsigned combineHashValue(unsigned a, unsigned b)
Simplistic combination of 32-bit hash values into 32-bit hash values.
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:68
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:720
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:679
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
iterator end() const
Definition BasicBlock.h:89
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
@ Length
Definition DWP.cpp:577
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt gcd(const DynamicAPInt &A, const DynamicAPInt &B)
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI bool isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason=nullptr)
Return true if the given indirect call site can be made to call Callee.
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
BundleAttr getBundleAttrFromOBU(OperandBundleUse OBU)
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
auto pred_end(const MachineBasicBlock *BB)
unsigned getPointerAddressSpace(const Type *T)
Definition SPIRVUtils.h:385
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto successors(const MachineBasicBlock *BB)
LLVM_ABI bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition APFloat.h:1736
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
LLVM_ABI Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
LLVM_ABI Value * simplifyInstructionWithOperands(Instruction *I, ArrayRef< Value * > NewOps, const SimplifyQuery &Q)
Like simplifyInstruction but the operands of I are replaced with NewOps.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:366
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
bool isModSet(const ModRefInfo MRI)
Definition ModRef.h:49
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isPointerTy(const Type *T)
Definition SPIRVUtils.h:373
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool wouldInstructionBeTriviallyDead(const Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction would have no side effects if it was not used.
Definition Local.cpp:415
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI CallBase & promoteCall(CallBase &CB, Function *Callee, CastInst **RetBitCast=nullptr)
Promote the given indirect call site to unconditionally call Callee.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI bool hasAssumption(const Function &F, const KnownAssumptionString &AssumptionStr)
Return true if F has the assumption AssumptionStr attached.
@ Success
The lock was released successfully.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition ModRef.h:28
@ Other
Any other memory.
Definition ModRef.h:68
PotentialValuesState< APInt > PotentialConstantIntValuesState
TargetTransformInfo TTI
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
InterleavedRange< Range > interleaved_array(const Range &R, StringRef Separator=", ")
Output range R as an array of interleaved elements.
ChangeStatus clampStateAndIndicateChange< DerefState >(DerefState &S, const DerefState &R)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset, bool MustPreserveProvenance=false)
launder.invariant.group and similar intrinsics return a pointer that aliases their argument,...
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R)
Helper function to clamp a state S of type StateType with the information in R and indicate/return if...
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
ChangeStatus
{
Definition Attributor.h:477
LLVM_ABI std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
LLVM_ABI DenseSet< StringRef > getAssumptions(const Function &F)
Return the set of all assumptions for the function F.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
Definition Alignment.h:105
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
@ OPTIONAL
The target may be valid if the source is not.
Definition Attributor.h:489
@ NONE
Do not track a dependence between source and target.
Definition Attributor.h:490
@ REQUIRED
The target cannot be valid if the source is not.
Definition Attributor.h:488
LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)
Determine what kind of capture behaviour U may exhibit.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
LLVM_ABI bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:391
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
bool capturesNothing(CaptureComponents CC)
Definition ModRef.h:375
LLVM_ABI AssumeDereferenceableInfo getAssumeDereferenceableInfo(OperandBundleUse)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
Definition ModRef.h:400
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
Definition Assumptions.h:29
constexpr bool isCallableCC(CallingConv::ID CC)
bool isRefSet(const ModRefInfo MRI)
Definition ModRef.h:52
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:881
A type to track pointer/struct usage and accesses for AAPointerInfo.
bool forallInterferingAccesses(AA::RangeTy Range, F CB) const
See AAPointerInfo::forallInterferingAccesses.
AAPointerInfo::const_bin_iterator end() const
ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I, std::optional< Value * > Content, AAPointerInfo::AccessKind Kind, Type *Ty, Instruction *RemoteI=nullptr)
Add a new Access to the state at offset Offset and with size Size.
DenseMap< const Instruction *, SmallVector< unsigned > > RemoteIMap
AAPointerInfo::const_bin_iterator begin() const
AAPointerInfo::OffsetInfo ReturnedOffsets
Flag to determine if the underlying pointer is reaching a return statement in the associated function...
State(State &&SIS)=default
const AAPointerInfo::Access & getAccess(unsigned Index) const
SmallVector< AAPointerInfo::Access > AccessList
bool isAtFixpoint() const override
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
bool forallInterferingAccesses(Instruction &I, F CB, AA::RangeTy &Range) const
See AAPointerInfo::forallInterferingAccesses.
static State getWorstState(const State &SIS)
Return the worst possible representable state.
AAPointerInfo::OffsetBinsTy OffsetBins
ChangeStatus indicateOptimisticFixpoint() override
Indicate that the abstract state should converge to the optimistic state.
ChangeStatus indicatePessimisticFixpoint() override
Indicate that the abstract state should converge to the pessimistic state.
static State getBestState(const State &SIS)
Return the best possible representable state.
bool isValidState() const override
Return if this abstract state is in a valid state.
----------------—AAIntraFnReachability Attribute-----------------------—
ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
unsigned Hash
Precomputed hash for this RQI.
const Instruction * From
Start here,.
Reachable Result
and remember if it worked:
ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To, const AA::InstExclusionSetTy *ES, bool MakeUnique)
Constructor replacement to ensure unique and stable sets are used for the cache.
const ToTy * To
reach this place,
const AA::InstExclusionSetTy * ExclusionSet
without going through any of these instructions,
An abstract interface for address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all align attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Align getKnownAlign() const
Return known alignment.
static LLVM_ABI const char ID
An abstract attribute for getting assumption information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract state for querying live call edges.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for specializing "dynamic" components of denormal_fpenv to a known denormal mod...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all dereferenceable attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for llvm::GlobalValue information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for indirect call information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to track if a value leaves it's defining function instance.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool canReach(Attributor &A, const Function &Fn) const
If the function represented by this possition can reach Fn.
virtual bool instructionCanReach(Attributor &A, const Instruction &Inst, const Function &Fn, const AA::InstExclusionSetTy *ExclusionSet=nullptr) const =0
Can Inst reach Fn.
An abstract interface to determine reachability of point A to B.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for identifying pointers from which loads can be marked invariant.
static LLVM_ABI const char ID
Unique ID (due to the unique address).
An abstract interface for liveness abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
bool isAssumedReadOnly() const
Return true if we assume that the underlying value is not accessed (=written) in its respective scope...
bool isKnownReadNone() const
Return true if we know that the underlying value is not read or accessed in its respective scope.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedReadNone() const
Return true if we assume that the underlying value is not read or accessed in its respective scope.
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI std::string getMemoryLocationsAsStr(MemoryLocationsKind MLK)
Return the locations encoded by MLK as a readable string.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
StateType::base_t MemoryLocationsKind
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for potential address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all noalias attributes.
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
---------------------— NoAlias Argument Attribute ---------------------—
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nocapture attributes.
@ NO_CAPTURE_MAYBE_RETURNED
If we do not capture the value in memory or through integers we can only communicate it back as a der...
@ NO_CAPTURE
If we do not capture the value in memory, through integers, or as a derived pointer we know it is not...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedNoCaptureMaybeReturned() const
Return true if we assume that the underlying value is not captured in its respective scope but we all...
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
--------------------— Variable Capturing ------------------------------—
static LLVM_ABI void determineFunctionCaptureCapabilities(const IRPosition &IRP, const Function &F, BitIntegerState &State)
Update State according to the capture capabilities of F for position IRP.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for nofree.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for norecurse.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for noreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isAlignedBarrier(const CallBase &CB, bool ExecutedAligned)
Helper function to determine if CB is an aligned (GPU) barrier.
static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
An abstract interface for all noundef attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
---------------------— NoUndef Attribute ------------------------------—
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for determining the necessity of the convergent attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
---------------------— NonNull Argument Attribute ---------------------—
An access description.
A helper containing a list of offsets computed for a Use.
A container for a list of ranges.
static void set_difference(const RangeList &L, const RangeList &R, RangeList &D)
Copy ranges from L that are not in R, into D.
An abstract interface for struct information.
virtual bool reachesReturn() const =0
OffsetBinsTy::const_iterator const_bin_iterator
virtual const_bin_iterator begin() const =0
DenseMap< AA::RangeTy, SmallSet< unsigned, 4 > > OffsetBinsTy
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual int64_t numOffsetBins() const =0
An abstract interface for potential values analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
friend struct Attributor
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract interface for privatizability.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for undefined behavior.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for getting all assumption underlying objects.
virtual bool forallUnderlyingObjects(function_ref< bool(Value &)> Pred, AA::ValueScope Scope=AA::Interprocedural) const =0
Check Pred on all underlying objects in Scope collected so far.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for range value analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for value simplify abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for willreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...
Definition Attributor.h:245
static constexpr int64_t Unknown
Definition Attributor.h:324
static RangeTy getUnknown()
Definition Attributor.h:251
Value * getValue() const
Definition Attributor.h:198
const Instruction * getCtxI() const
Definition Attributor.h:199
Base struct for all "concrete attribute" deductions.
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
AbstractState StateType
An interface to query the internal state of an abstract attribute.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:82
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
Definition Alignment.h:73
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
const Argument & getReplacedArg() const
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
std::function< std::optional< Value * >( const IRPosition &, const AbstractAttribute *, bool &)> SimplifictionCallbackTy
Register CB as a simplification callback.
Specialization of the integer state for a bit-wise encoding.
BitIntegerState & addKnownBits(base_t Bits)
Add the bits in BitsEncoding to the "known bits".
Simple wrapper for a single bit (boolean) state.
static constexpr DenormalFPEnv getDefault()
static unsigned getHashValue(const Access &A)
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static unsigned getHashValue(const AA::RangeTy &Range)
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static bool isEqual(const ReachabilityQueryInfo< ToTy > *LHS, const ReachabilityQueryInfo< ToTy > *RHS)
DenseMapInfo< const AA::InstExclusionSetTy * > InstSetDMI
static unsigned getHashValue(const ReachabilityQueryInfo< ToTy > *RQI)
An information struct used to provide DenseMap with the various necessary components for a given valu...
State for dereferenceable attribute.
IncIntegerState DerefBytesState
State representing for dereferenceable bytes.
ChangeStatus manifest(Attributor &A) override
Helper to describe and deal with positions in the LLVM-IR.
Definition Attributor.h:573
Function * getAssociatedFunction() const
Return the associated function, if any.
Definition Attributor.h:704
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
Definition Attributor.h:641
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
Definition Attributor.h:623
LLVM_ABI Argument * getAssociatedArgument() const
Return the associated argument, if any.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
Definition Attributor.h:597
CallBase CallBaseContext
Definition Attributor.h:576
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
Definition Attributor.h:790
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
Definition Attributor.h:609
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
Definition Attributor.h:646
Kind
The positions we distinguish in the IR.
Definition Attributor.h:579
@ IRP_ARGUMENT
An attribute for a function argument.
Definition Attributor.h:587
@ IRP_RETURNED
An attribute for the function return value.
Definition Attributor.h:583
@ IRP_CALL_SITE
An attribute for a call site (function scope).
Definition Attributor.h:586
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
Definition Attributor.h:584
@ IRP_FUNCTION
An attribute for a function (scope).
Definition Attributor.h:585
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
Definition Attributor.h:588
@ IRP_INVALID
An invalid position.
Definition Attributor.h:580
Instruction * getCtxI() const
Return the context instruction, if any.
Definition Attributor.h:757
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
Definition Attributor.h:630
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
Definition Attributor.h:779
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
Definition Attributor.h:616
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Definition Attributor.h:896
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Definition Attributor.h:771
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
Definition Attributor.h:690
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
Definition Attributor.h:799
static const IRPosition function_scope(const IRPosition &IRP, const CallBaseContext *CBContext=nullptr)
Create a position with function scope matching the "context" of IRP.
Definition Attributor.h:669
Kind getPositionKind() const
Return the associated position kind.
Definition Attributor.h:846
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
Definition Attributor.h:878
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Definition Attributor.h:636
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
Definition Attributor.h:745
Data structure to hold cached (LLVM-IR) information.
bool isOnlyUsedByAssume(const Instruction &I)
TargetLibraryInfo * getTargetLibraryInfoForFunction(const Function &F)
Return TargetLibraryInfo for function F.
AP::Result * getAnalysisResultForFunction(const Function &F, bool CachedOnly=false)
Return the analysis result from a pass AP for function F.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
base_t getAssumed() const
Return the assumed state encoding.
Helper that allows to insert a new assumption string in the known assumption set by creating a (stati...
Definition Assumptions.h:37
A "must be executed context" for a given program point PP is the set of instructions,...
iterator & end()
Return an universal end iterator.
bool findInContextOf(const Instruction *I, const Instruction *PP)
Helper to look for I in the context of PP.
iterator & begin(const Instruction *PP)
Return an iterator to explore the context around PP.
bool checkForAllContext(const Instruction *PP, function_ref< bool(const Instruction *)> Pred)
}
Helper to tie a abstract state implementation to an abstract attribute.
StateType & getState() override
CaptureComponents ResultCC
Components captured by the return value of the user of this Use.
LLVM_ABI bool unionAssumed(std::optional< Value * > Other)
Merge Other into the currently assumed simplified value.
std::optional< Value * > SimplifiedAssociatedValue
An assumed simplified value.
Type * Ty
The type of the original value.