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 *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
7826 if (!I->mayReadFromMemory())
7827 State.addKnownBits(NO_READS);
7828 if (!I->mayWriteToMemory())
7829 State.addKnownBits(NO_WRITES);
7830 }
7831 }
7832 }
7833
7834 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
7835 SmallVectorImpl<Attribute> &Attrs) const override {
7836 assert(Attrs.size() == 0);
7837 if (isAssumedReadNone())
7838 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7839 else if (isAssumedReadOnly())
7840 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7841 else if (isAssumedWriteOnly())
7842 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7843 assert(Attrs.size() <= 1);
7844 }
7845
7846 ChangeStatus manifest(Attributor &A) override {
7847 const IRPosition &IRP = getIRPosition();
7848
7849 if (A.hasAttr(IRP, Attribute::ReadNone,
7850 /* IgnoreSubsumingPositions */ true))
7851 return ChangeStatus::UNCHANGED;
7852
7853 // Check if we would improve the existing attributes first.
7854 SmallVector<Attribute, 4> DeducedAttrs;
7855 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
7856 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
7857 return A.hasAttr(IRP, Attr.getKindAsEnum(),
7858 /* IgnoreSubsumingPositions */ true);
7859 }))
7860 return ChangeStatus::UNCHANGED;
7861
7862 // Clear existing attributes.
7863 A.removeAttrs(IRP, AttrKinds);
7864 // Clear conflicting writable attribute.
7865 if (isAssumedReadOnly())
7866 A.removeAttrs(IRP, Attribute::Writable);
7867
7868 // Use the generic manifest method.
7869 return IRAttribute::manifest(A);
7870 }
7871
7872 const std::string getAsStr(Attributor *A) const override {
7873 if (isAssumedReadNone())
7874 return "readnone";
7875 if (isAssumedReadOnly())
7876 return "readonly";
7877 if (isAssumedWriteOnly())
7878 return "writeonly";
7879 return "may-read/write";
7880 }
7881
7882 /// The set of IR attributes AAMemoryBehavior deals with.
7883 static const Attribute::AttrKind AttrKinds[3];
7884};
7885
7886const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7887 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7888
7889/// Memory behavior attribute for a floating value.
7890struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7891 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7892 : AAMemoryBehaviorImpl(IRP, A) {}
7893
7894 ChangeStatus updateImpl(Attributor &A) override;
7895
7896 void trackStatistics() const override {
7897 if (isAssumedReadNone())
7899 else if (isAssumedReadOnly())
7901 else if (isAssumedWriteOnly())
7903 }
7904
7905private:
7906 /// Return true if users of \p UserI might access the underlying
7907 /// variable/location described by \p U and should therefore be analyzed.
7908 bool followUsersOfUseIn(Attributor &A, const Use &U,
7909 const Instruction *UserI);
7910
7911 /// Update the state according to the effect of use \p U in \p UserI.
7912 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
7913};
7914
7915/// Memory behavior attribute for function argument.
7916struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
7917 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
7918 : AAMemoryBehaviorFloating(IRP, A) {}
7919
7920 void initialize(Attributor &A) override {
7921 intersectAssumedBits(BEST_STATE);
7922 const IRPosition &IRP = getIRPosition();
7923 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
7924 // can query it when we use has/getAttr. That would allow us to reuse the
7925 // initialize of the base class here.
7926 bool HasByVal = A.hasAttr(IRP, {Attribute::ByVal},
7927 /* IgnoreSubsumingPositions */ true);
7928 getKnownStateFromValue(A, IRP, getState(),
7929 /* IgnoreSubsumingPositions */ HasByVal);
7930 }
7931
7932 ChangeStatus manifest(Attributor &A) override {
7933 // TODO: Pointer arguments are not supported on vectors of pointers yet.
7934 if (!getAssociatedValue().getType()->isPointerTy())
7935 return ChangeStatus::UNCHANGED;
7936
7937 // TODO: From readattrs.ll: "inalloca parameters are always
7938 // considered written"
7939 if (A.hasAttr(getIRPosition(),
7940 {Attribute::InAlloca, Attribute::Preallocated})) {
7941 removeKnownBits(NO_WRITES);
7942 removeAssumedBits(NO_WRITES);
7943 }
7944 A.removeAttrs(getIRPosition(), AttrKinds);
7945 return AAMemoryBehaviorFloating::manifest(A);
7946 }
7947
7948 void trackStatistics() const override {
7949 if (isAssumedReadNone())
7950 STATS_DECLTRACK_ARG_ATTR(readnone)
7951 else if (isAssumedReadOnly())
7952 STATS_DECLTRACK_ARG_ATTR(readonly)
7953 else if (isAssumedWriteOnly())
7954 STATS_DECLTRACK_ARG_ATTR(writeonly)
7955 }
7956};
7957
7958struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
7959 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
7960 : AAMemoryBehaviorArgument(IRP, A) {}
7961
7962 void initialize(Attributor &A) override {
7963 // If we don't have an associated attribute this is either a variadic call
7964 // or an indirect call, either way, nothing to do here.
7965 Argument *Arg = getAssociatedArgument();
7966 if (!Arg) {
7967 indicatePessimisticFixpoint();
7968 return;
7969 }
7970 if (Arg->hasByValAttr()) {
7971 addKnownBits(NO_WRITES);
7972 removeKnownBits(NO_READS);
7973 removeAssumedBits(NO_READS);
7974 }
7975 AAMemoryBehaviorArgument::initialize(A);
7976 if (getAssociatedFunction()->isDeclaration())
7977 indicatePessimisticFixpoint();
7978 }
7979
7980 ChangeStatus updateImpl(Attributor &A) override {
7981 // TODO: Once we have call site specific value information we can provide
7982 // call site specific liveness liveness information and then it makes
7983 // sense to specialize attributes for call sites arguments instead of
7984 // redirecting requests to the callee argument.
7985 Argument *Arg = getAssociatedArgument();
7986 const IRPosition &ArgPos = IRPosition::argument(*Arg);
7987 auto *ArgAA =
7988 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
7989 if (!ArgAA)
7990 return indicatePessimisticFixpoint();
7991 return clampStateAndIndicateChange(getState(), ArgAA->getState());
7992 }
7993
7994 void trackStatistics() const override {
7995 if (isAssumedReadNone())
7997 else if (isAssumedReadOnly())
7999 else if (isAssumedWriteOnly())
8001 }
8002};
8003
8004/// Memory behavior attribute for a call site return position.
8005struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8006 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
8007 : AAMemoryBehaviorFloating(IRP, A) {}
8008
8009 void initialize(Attributor &A) override {
8010 AAMemoryBehaviorImpl::initialize(A);
8011 }
8012 ChangeStatus manifest(Attributor &A) override {
8013 // We do not annotate returned values.
8014 return ChangeStatus::UNCHANGED;
8015 }
8016
8017 void trackStatistics() const override {}
8018};
8019
8020/// An AA to represent the memory behavior function attributes.
8021struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
8022 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
8023 : AAMemoryBehaviorImpl(IRP, A) {}
8024
8025 ChangeStatus updateImpl(Attributor &A) override;
8026
8027 ChangeStatus manifest(Attributor &A) override {
8028 // TODO: It would be better to merge this with AAMemoryLocation, so that
8029 // we could determine read/write per location. This would also have the
8030 // benefit of only one place trying to manifest the memory attribute.
8031 Function &F = cast<Function>(getAnchorValue());
8033 if (isAssumedReadNone())
8034 ME = MemoryEffects::none();
8035 else if (isAssumedReadOnly())
8037 else if (isAssumedWriteOnly())
8039
8040 A.removeAttrs(getIRPosition(), AttrKinds);
8041 // Clear conflicting writable attribute.
8042 if (ME.onlyReadsMemory())
8043 for (Argument &Arg : F.args())
8044 A.removeAttrs(IRPosition::argument(Arg), Attribute::Writable);
8045 return A.manifestAttrs(getIRPosition(),
8046 Attribute::getWithMemoryEffects(F.getContext(), ME));
8047 }
8048
8049 void trackStatistics() const override {
8050 if (isAssumedReadNone())
8051 STATS_DECLTRACK_FN_ATTR(readnone)
8052 else if (isAssumedReadOnly())
8053 STATS_DECLTRACK_FN_ATTR(readonly)
8054 else if (isAssumedWriteOnly())
8055 STATS_DECLTRACK_FN_ATTR(writeonly)
8056 }
8057};
8058
8059/// AAMemoryBehavior attribute for call sites.
8060struct AAMemoryBehaviorCallSite final
8061 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8062 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
8063 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP, A) {}
8064
8065 ChangeStatus manifest(Attributor &A) override {
8066 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8067 CallBase &CB = cast<CallBase>(getAnchorValue());
8069 if (isAssumedReadNone())
8070 ME = MemoryEffects::none();
8071 else if (isAssumedReadOnly())
8073 else if (isAssumedWriteOnly())
8075
8076 A.removeAttrs(getIRPosition(), AttrKinds);
8077 // Clear conflicting writable attribute.
8078 if (ME.onlyReadsMemory())
8079 for (Use &U : CB.args())
8080 A.removeAttrs(IRPosition::callsite_argument(CB, U.getOperandNo()),
8081 Attribute::Writable);
8082 return A.manifestAttrs(
8083 getIRPosition(), Attribute::getWithMemoryEffects(CB.getContext(), ME));
8084 }
8085
8086 void trackStatistics() const override {
8087 if (isAssumedReadNone())
8088 STATS_DECLTRACK_CS_ATTR(readnone)
8089 else if (isAssumedReadOnly())
8090 STATS_DECLTRACK_CS_ATTR(readonly)
8091 else if (isAssumedWriteOnly())
8092 STATS_DECLTRACK_CS_ATTR(writeonly)
8093 }
8094};
8095
8096ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8097
8098 // The current assumed state used to determine a change.
8099 auto AssumedState = getAssumed();
8100
8101 auto CheckRWInst = [&](Instruction &I) {
8102 // If the instruction has an own memory behavior state, use it to restrict
8103 // the local state. No further analysis is required as the other memory
8104 // state is as optimistic as it gets.
8105 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8106 const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8108 if (MemBehaviorAA) {
8109 intersectAssumedBits(MemBehaviorAA->getAssumed());
8110 return !isAtFixpoint();
8111 }
8112 }
8113
8114 // Remove access kind modifiers if necessary.
8115 if (I.mayReadFromMemory())
8116 removeAssumedBits(NO_READS);
8117 if (I.mayWriteToMemory())
8118 removeAssumedBits(NO_WRITES);
8119 return !isAtFixpoint();
8120 };
8121
8122 bool UsedAssumedInformation = false;
8123 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8124 UsedAssumedInformation))
8125 return indicatePessimisticFixpoint();
8126
8127 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8129}
8130
8131ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8132
8133 const IRPosition &IRP = getIRPosition();
8134 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8135 AAMemoryBehavior::StateType &S = getState();
8136
8137 // First, check the function scope. We take the known information and we avoid
8138 // work if the assumed information implies the current assumed information for
8139 // this attribute. This is a valid for all but byval arguments.
8140 Argument *Arg = IRP.getAssociatedArgument();
8141 AAMemoryBehavior::base_t FnMemAssumedState =
8143 if (!Arg || !Arg->hasByValAttr()) {
8144 const auto *FnMemAA =
8145 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8146 if (FnMemAA) {
8147 FnMemAssumedState = FnMemAA->getAssumed();
8148 S.addKnownBits(FnMemAA->getKnown());
8149 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8151 }
8152 }
8153
8154 // The current assumed state used to determine a change.
8155 auto AssumedState = S.getAssumed();
8156
8157 // Make sure the value is not captured (except through "return"), if
8158 // it is, any information derived would be irrelevant anyway as we cannot
8159 // check the potential aliases introduced by the capture. However, no need
8160 // to fall back to anythign less optimistic than the function state.
8161 bool IsKnownNoCapture;
8162 const AANoCapture *ArgNoCaptureAA = nullptr;
8163 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
8164 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture, false,
8165 &ArgNoCaptureAA);
8166
8167 if (!IsAssumedNoCapture &&
8168 (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
8169 S.intersectAssumedBits(FnMemAssumedState);
8170 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8172 }
8173
8174 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8175 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8176 Instruction *UserI = cast<Instruction>(U.getUser());
8177 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
8178 << " \n");
8179
8180 // Droppable users, e.g., llvm::assume does not actually perform any action.
8181 if (UserI->isDroppable())
8182 return true;
8183
8184 // Check if the users of UserI should also be visited.
8185 Follow = followUsersOfUseIn(A, U, UserI);
8186
8187 // If UserI might touch memory we analyze the use in detail.
8188 if (UserI->mayReadOrWriteMemory())
8189 analyzeUseIn(A, U, UserI);
8190
8191 return !isAtFixpoint();
8192 };
8193
8194 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8195 return indicatePessimisticFixpoint();
8196
8197 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8199}
8200
8201bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8202 const Instruction *UserI) {
8203 // The loaded value is unrelated to the pointer argument, no need to
8204 // follow the users of the load.
8205 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8206 return false;
8207
8208 // By default we follow all uses assuming UserI might leak information on U,
8209 // we have special handling for call sites operands though.
8210 const auto *CB = dyn_cast<CallBase>(UserI);
8211 if (!CB || !CB->isArgOperand(&U))
8212 return true;
8213
8214 // If the use is a call argument known not to be captured, the users of
8215 // the call do not need to be visited because they have to be unrelated to
8216 // the input. Note that this check is not trivial even though we disallow
8217 // general capturing of the underlying argument. The reason is that the
8218 // call might the argument "through return", which we allow and for which we
8219 // need to check call users.
8220 if (U.get()->getType()->isPointerTy()) {
8221 unsigned ArgNo = CB->getArgOperandNo(&U);
8222 bool IsKnownNoCapture;
8224 A, this, IRPosition::callsite_argument(*CB, ArgNo),
8225 DepClassTy::OPTIONAL, IsKnownNoCapture);
8226 }
8227
8228 return true;
8229}
8230
8231void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8232 const Instruction *UserI) {
8233 assert(UserI->mayReadOrWriteMemory());
8234
8235 switch (UserI->getOpcode()) {
8236 default:
8237 // TODO: Handle all atomics and other side-effect operations we know of.
8238 break;
8239 case Instruction::Load:
8240 // Loads cause the NO_READS property to disappear.
8241 removeAssumedBits(NO_READS);
8242 return;
8243
8244 case Instruction::Store:
8245 // Stores cause the NO_WRITES property to disappear if the use is the
8246 // pointer operand. Note that while capturing was taken care of somewhere
8247 // else we need to deal with stores of the value that is not looked through.
8248 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8249 removeAssumedBits(NO_WRITES);
8250 else
8251 indicatePessimisticFixpoint();
8252 return;
8253
8254 case Instruction::Call:
8255 case Instruction::CallBr:
8256 case Instruction::Invoke: {
8257 // For call sites we look at the argument memory behavior attribute (this
8258 // could be recursive!) in order to restrict our own state.
8259 const auto *CB = cast<CallBase>(UserI);
8260
8261 // Give up on operand bundles.
8262 if (CB->isBundleOperand(&U)) {
8263 indicatePessimisticFixpoint();
8264 return;
8265 }
8266
8267 // Calling a function does read the function pointer, maybe write it if the
8268 // function is self-modifying.
8269 if (CB->isCallee(&U)) {
8270 removeAssumedBits(NO_READS);
8271 break;
8272 }
8273
8274 // Adjust the possible access behavior based on the information on the
8275 // argument.
8276 IRPosition Pos;
8277 if (U.get()->getType()->isPointerTy())
8279 else
8281 const auto *MemBehaviorAA =
8282 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8283 if (!MemBehaviorAA)
8284 break;
8285 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8286 // and at least "known".
8287 intersectAssumedBits(MemBehaviorAA->getAssumed());
8288 return;
8289 }
8290 };
8291
8292 // Generally, look at the "may-properties" and adjust the assumed state if we
8293 // did not trigger special handling before.
8294 if (UserI->mayReadFromMemory())
8295 removeAssumedBits(NO_READS);
8296 if (UserI->mayWriteToMemory())
8297 removeAssumedBits(NO_WRITES);
8298}
8299} // namespace
8300
8301/// -------------------- Memory Locations Attributes ---------------------------
8302/// Includes read-none, argmemonly, inaccessiblememonly,
8303/// inaccessiblememorargmemonly
8304/// ----------------------------------------------------------------------------
8305
8308 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8309 return "all memory";
8311 return "no memory";
8312 std::string S = "memory:";
8313 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8314 S += "stack,";
8315 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8316 S += "constant,";
8318 S += "internal global,";
8320 S += "external global,";
8321 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8322 S += "argument,";
8324 S += "inaccessible,";
8325 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8326 S += "malloced,";
8327 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8328 S += "unknown,";
8329 S.pop_back();
8330 return S;
8331}
8332
8333namespace {
8334struct AAMemoryLocationImpl : public AAMemoryLocation {
8335
8336 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8337 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8338 AccessKind2Accesses.fill(nullptr);
8339 }
8340
8341 ~AAMemoryLocationImpl() override {
8342 // The AccessSets are allocated via a BumpPtrAllocator, we call
8343 // the destructor manually.
8344 for (AccessSet *AS : AccessKind2Accesses)
8345 if (AS)
8346 AS->~AccessSet();
8347 }
8348
8349 void initialize(Attributor &A) override {
8350 intersectAssumedBits(BEST_STATE);
8351 getKnownStateFromValue(A, getIRPosition(), getState());
8352 AAMemoryLocation::initialize(A);
8353 }
8354
8355 /// Return the memory behavior information encoded in the IR for \p IRP.
8356 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8357 BitIntegerState &State,
8358 bool IgnoreSubsumingPositions = false) {
8359 // For internal functions we ignore `argmemonly` and
8360 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8361 // constant propagation. It is unclear if this is the best way but it is
8362 // unlikely this will cause real performance problems. If we are deriving
8363 // attributes for the anchor function we even remove the attribute in
8364 // addition to ignoring it.
8365 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8366 // MemoryEffects::Other as a possible location.
8367 bool UseArgMemOnly = true;
8368 Function *AnchorFn = IRP.getAnchorScope();
8369 if (AnchorFn && A.isRunOn(*AnchorFn))
8370 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8371
8373 A.getAttrs(IRP, {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8374 for (const Attribute &Attr : Attrs) {
8375 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8376 MemoryEffects ME = Attr.getMemoryEffects();
8377 if (ME.doesNotAccessMemory()) {
8378 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8379 continue;
8380 }
8381 if (ME.onlyAccessesInaccessibleMem()) {
8382 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8383 continue;
8384 }
8385 if (ME.onlyAccessesArgPointees()) {
8386 if (UseArgMemOnly)
8387 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8388 else {
8389 // Remove location information, only keep read/write info.
8390 ME = MemoryEffects(ME.getModRef());
8391 A.manifestAttrs(IRP,
8392 Attribute::getWithMemoryEffects(
8393 IRP.getAnchorValue().getContext(), ME),
8394 /*ForceReplace*/ true);
8395 }
8396 continue;
8397 }
8399 if (UseArgMemOnly)
8400 State.addKnownBits(inverseLocation(
8401 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8402 else {
8403 // Remove location information, only keep read/write info.
8404 ME = MemoryEffects(ME.getModRef());
8405 A.manifestAttrs(IRP,
8406 Attribute::getWithMemoryEffects(
8407 IRP.getAnchorValue().getContext(), ME),
8408 /*ForceReplace*/ true);
8409 }
8410 continue;
8411 }
8412 }
8413 }
8414
8415 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
8416 SmallVectorImpl<Attribute> &Attrs) const override {
8417 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8418 assert(Attrs.size() == 0);
8419 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8420 if (isAssumedReadNone())
8421 Attrs.push_back(
8422 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8423 else if (isAssumedInaccessibleMemOnly())
8424 Attrs.push_back(Attribute::getWithMemoryEffects(
8426 else if (isAssumedArgMemOnly())
8427 Attrs.push_back(
8428 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8429 else if (isAssumedInaccessibleOrArgMemOnly())
8430 Attrs.push_back(Attribute::getWithMemoryEffects(
8432 }
8433 assert(Attrs.size() <= 1);
8434 }
8435
8436 ChangeStatus manifest(Attributor &A) override {
8437 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8438 // provide per-location modref information here.
8439 const IRPosition &IRP = getIRPosition();
8440
8441 SmallVector<Attribute, 1> DeducedAttrs;
8442 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
8443 if (DeducedAttrs.size() != 1)
8444 return ChangeStatus::UNCHANGED;
8445 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8446
8447 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8448 IRP.getAnchorValue().getContext(), ME));
8449 }
8450
8451 bool checkForAllAccessesToMemoryKind(
8452 function_ref<bool(const Instruction *, const Value *, AccessKind,
8453 MemoryLocationsKind)>
8454 Pred,
8455 MemoryLocationsKind RequestedMLK) const override {
8456 if (!isValidState())
8457 return false;
8458
8459 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8460 if (AssumedMLK == NO_LOCATIONS)
8461 return true;
8462
8463 unsigned Idx = 0;
8464 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8465 CurMLK *= 2, ++Idx) {
8466 if (CurMLK & RequestedMLK)
8467 continue;
8468
8469 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8470 for (const AccessInfo &AI : *Accesses)
8471 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8472 return false;
8473 }
8474
8475 return true;
8476 }
8477
8478 ChangeStatus indicatePessimisticFixpoint() override {
8479 // If we give up and indicate a pessimistic fixpoint this instruction will
8480 // become an access for all potential access kinds:
8481 // TODO: Add pointers for argmemonly and globals to improve the results of
8482 // checkForAllAccessesToMemoryKind.
8483 bool Changed = false;
8484 MemoryLocationsKind KnownMLK = getKnown();
8485 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8486 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8487 if (!(CurMLK & KnownMLK))
8488 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8489 getAccessKindFromInst(I));
8490 return AAMemoryLocation::indicatePessimisticFixpoint();
8491 }
8492
8493protected:
8494 /// Helper struct to tie together an instruction that has a read or write
8495 /// effect with the pointer it accesses (if any).
8496 struct AccessInfo {
8497
8498 /// The instruction that caused the access.
8499 const Instruction *I;
8500
8501 /// The base pointer that is accessed, or null if unknown.
8502 const Value *Ptr;
8503
8504 /// The kind of access (read/write/read+write).
8506
8507 bool operator==(const AccessInfo &RHS) const {
8508 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8509 }
8510 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8511 if (LHS.I != RHS.I)
8512 return LHS.I < RHS.I;
8513 if (LHS.Ptr != RHS.Ptr)
8514 return LHS.Ptr < RHS.Ptr;
8515 if (LHS.Kind != RHS.Kind)
8516 return LHS.Kind < RHS.Kind;
8517 return false;
8518 }
8519 };
8520
8521 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8522 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8523 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8524 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8525 AccessKind2Accesses;
8526
8527 /// Categorize the pointer arguments of CB that might access memory in
8528 /// AccessedLoc and update the state and access map accordingly.
8529 void
8530 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8531 AAMemoryLocation::StateType &AccessedLocs,
8532 bool &Changed);
8533
8534 /// Return the kind(s) of location that may be accessed by \p V.
8536 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8537
8538 /// Return the access kind as determined by \p I.
8539 AccessKind getAccessKindFromInst(const Instruction *I) {
8540 AccessKind AK = READ_WRITE;
8541 if (I) {
8542 AK = I->mayReadFromMemory() ? READ : NONE;
8543 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8544 }
8545 return AK;
8546 }
8547
8548 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8549 /// an access of kind \p AK to a \p MLK memory location with the access
8550 /// pointer \p Ptr.
8551 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8552 MemoryLocationsKind MLK, const Instruction *I,
8553 const Value *Ptr, bool &Changed,
8554 AccessKind AK = READ_WRITE) {
8555
8556 assert(isPowerOf2_32(MLK) && "Expected a single location set!");
8557 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8558 if (!Accesses)
8559 Accesses = new (Allocator) AccessSet();
8560 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8561 if (MLK == NO_UNKOWN_MEM)
8562 MLK = NO_LOCATIONS;
8563 State.removeAssumedBits(MLK);
8564 }
8565
8566 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8567 /// arguments, and update the state and access map accordingly.
8568 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8569 AAMemoryLocation::StateType &State, bool &Changed,
8570 unsigned AccessAS = 0);
8571
8572 /// Used to allocate access sets.
8574};
8575
8576void AAMemoryLocationImpl::categorizePtrValue(
8577 Attributor &A, const Instruction &I, const Value &Ptr,
8578 AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {
8579 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
8580 << Ptr << " ["
8581 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");
8582
8583 auto Pred = [&](Value &Obj) {
8584 unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();
8585 // TODO: recognize the TBAA used for constant accesses.
8586 MemoryLocationsKind MLK = NO_LOCATIONS;
8587
8588 // Filter accesses to constant (GPU) memory if we have an AS at the access
8589 // site or the object is known to actually have the associated AS.
8590 if (AA::isGPU(A.getModule())) {
8591 if (AA::isGPUConstantAddressSpace(A.getModule(), AccessAS) ||
8592 (AA::isGPUConstantAddressSpace(A.getModule(), ObjectAS) &&
8593 isIdentifiedObject(&Obj)))
8594 return true;
8595 }
8596
8597 if (isa<UndefValue>(&Obj))
8598 return true;
8599 if (isa<Argument>(&Obj)) {
8600 // TODO: For now we do not treat byval arguments as local copies performed
8601 // on the call edge, though, we should. To make that happen we need to
8602 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8603 // would also allow us to mark functions only accessing byval arguments as
8604 // readnone again, arguably their accesses have no effect outside of the
8605 // function, like accesses to allocas.
8606 MLK = NO_ARGUMENT_MEM;
8607 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8608 // Reading constant memory is not treated as a read "effect" by the
8609 // function attr pass so we won't neither. Constants defined by TBAA are
8610 // similar. (We know we do not write it because it is constant.)
8611 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8612 if (GVar->isConstant())
8613 return true;
8614
8615 if (GV->hasLocalLinkage())
8616 MLK = NO_GLOBAL_INTERNAL_MEM;
8617 else
8618 MLK = NO_GLOBAL_EXTERNAL_MEM;
8619 } else if (isa<ConstantPointerNull>(&Obj) && ObjectAS == AccessAS &&
8620 !NullPointerIsDefined(getAssociatedFunction(), AccessAS)) {
8621 // Accessing null is undefined, but not accessing a null pointer cast to
8622 // another address space, which may be a valid address there.
8623 return true;
8624 } else if (isa<AllocaInst>(&Obj)) {
8625 MLK = NO_LOCAL_MEM;
8626 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8627 bool IsKnownNoAlias;
8630 IsKnownNoAlias))
8631 MLK = NO_MALLOCED_MEM;
8632 else
8633 MLK = NO_UNKOWN_MEM;
8634 } else {
8635 MLK = NO_UNKOWN_MEM;
8636 }
8637
8638 assert(MLK != NO_LOCATIONS && "No location specified!");
8639 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
8640 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
8641 updateStateAndAccessesMap(State, MLK, &I, &Obj, Changed,
8642 getAccessKindFromInst(&I));
8643
8644 return true;
8645 };
8646
8647 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
8649 if (!AA || !AA->forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8650 LLVM_DEBUG(
8651 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
8652 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8653 getAccessKindFromInst(&I));
8654 return;
8655 }
8656
8657 LLVM_DEBUG(
8658 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
8659 << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
8660}
8661
8662void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8663 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8664 bool &Changed) {
8665 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8666
8667 // Skip non-pointer arguments.
8668 const Value *ArgOp = CB.getArgOperand(ArgNo);
8669 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8670 continue;
8671
8672 // Skip readnone arguments.
8673 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8674 const auto *ArgOpMemLocationAA =
8675 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8676
8677 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8678 continue;
8679
8680 // Categorize potentially accessed pointer arguments as if there was an
8681 // access instruction with them as pointer.
8682 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8683 }
8684}
8685
8687AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8688 bool &Changed) {
8689 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
8690 << I << "\n");
8691
8692 AAMemoryLocation::StateType AccessedLocs;
8693 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8694
8695 if (auto *CB = dyn_cast<CallBase>(&I)) {
8696
8697 // First check if we assume any memory is access is visible.
8698 const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8700 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
8701 << " [" << CBMemLocationAA << "]\n");
8702 if (!CBMemLocationAA) {
8703 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr,
8704 Changed, getAccessKindFromInst(&I));
8705 return NO_UNKOWN_MEM;
8706 }
8707
8708 if (CBMemLocationAA->isAssumedReadNone())
8709 return NO_LOCATIONS;
8710
8711 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8712 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8713 Changed, getAccessKindFromInst(&I));
8714 return AccessedLocs.getAssumed();
8715 }
8716
8717 uint32_t CBAssumedNotAccessedLocs =
8718 CBMemLocationAA->getAssumedNotAccessedLocation();
8719
8720 // Set the argmemonly and global bit as we handle them separately below.
8721 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8722 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8723
8724 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8725 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8726 continue;
8727 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8728 getAccessKindFromInst(&I));
8729 }
8730
8731 // Now handle global memory if it might be accessed. This is slightly tricky
8732 // as NO_GLOBAL_MEM has multiple bits set.
8733 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8734 if (HasGlobalAccesses) {
8735 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8736 AccessKind Kind, MemoryLocationsKind MLK) {
8737 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8738 getAccessKindFromInst(&I));
8739 return true;
8740 };
8741 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8742 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8743 return AccessedLocs.getWorstState();
8744 }
8745
8746 LLVM_DEBUG(
8747 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
8748 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8749
8750 // Now handle argument memory if it might be accessed.
8751 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8752 if (HasArgAccesses)
8753 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8754
8755 LLVM_DEBUG(
8756 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
8757 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8758
8759 return AccessedLocs.getAssumed();
8760 }
8761
8762 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8763 LLVM_DEBUG(
8764 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
8765 << I << " [" << *Ptr << "]\n");
8766 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed,
8767 Ptr->getType()->getPointerAddressSpace());
8768 return AccessedLocs.getAssumed();
8769 }
8770
8771 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
8772 << I << "\n");
8773 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8774 getAccessKindFromInst(&I));
8775 return AccessedLocs.getAssumed();
8776}
8777
8778/// An AA to represent the memory behavior function attributes.
8779struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8780 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8781 : AAMemoryLocationImpl(IRP, A) {}
8782
8783 ChangeStatus updateImpl(Attributor &A) override {
8784
8785 const auto *MemBehaviorAA =
8786 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8787 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
8788 if (MemBehaviorAA->isKnownReadNone())
8789 return indicateOptimisticFixpoint();
8791 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8792 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8793 return ChangeStatus::UNCHANGED;
8794 }
8795
8796 // The current assumed state used to determine a change.
8797 auto AssumedState = getAssumed();
8798 bool Changed = false;
8799
8800 auto CheckRWInst = [&](Instruction &I) {
8801 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8802 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
8803 << ": " << getMemoryLocationsAsStr(MLK) << "\n");
8804 removeAssumedBits(inverseLocation(MLK, false, false));
8805 // Stop once only the valid bit set in the *not assumed location*, thus
8806 // once we don't actually exclude any memory locations in the state.
8807 return getAssumedNotAccessedLocation() != VALID_STATE;
8808 };
8809
8810 bool UsedAssumedInformation = false;
8811 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8812 UsedAssumedInformation))
8813 return indicatePessimisticFixpoint();
8814
8815 Changed |= AssumedState != getAssumed();
8816 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8817 }
8818
8819 void trackStatistics() const override {
8820 if (isAssumedReadNone())
8821 STATS_DECLTRACK_FN_ATTR(readnone)
8822 else if (isAssumedArgMemOnly())
8823 STATS_DECLTRACK_FN_ATTR(argmemonly)
8824 else if (isAssumedInaccessibleMemOnly())
8825 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
8826 else if (isAssumedInaccessibleOrArgMemOnly())
8827 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
8828 }
8829};
8830
8831/// AAMemoryLocation attribute for call sites.
8832struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8833 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8834 : AAMemoryLocationImpl(IRP, A) {}
8835
8836 ChangeStatus updateImpl(Attributor &A) override {
8837 // TODO: Once we have call site specific value information we can provide
8838 // call site specific liveness liveness information and then it makes
8839 // sense to specialize attributes for call sites arguments instead of
8840 // redirecting requests to the callee argument.
8841 Function *F = getAssociatedFunction();
8842 const IRPosition &FnPos = IRPosition::function(*F);
8843 auto *FnAA =
8844 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
8845 if (!FnAA)
8846 return indicatePessimisticFixpoint();
8847 bool Changed = false;
8848 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8849 AccessKind Kind, MemoryLocationsKind MLK) {
8850 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
8851 getAccessKindFromInst(I));
8852 return true;
8853 };
8854 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8855 return indicatePessimisticFixpoint();
8856 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8857 }
8858
8859 void trackStatistics() const override {
8860 if (isAssumedReadNone())
8861 STATS_DECLTRACK_CS_ATTR(readnone)
8862 }
8863};
8864} // namespace
8865
8866/// ------------------ denormal-fp-math Attribute -------------------------
8867
8868namespace {
8869struct AADenormalFPMathImpl : public AADenormalFPMath {
8870 AADenormalFPMathImpl(const IRPosition &IRP, Attributor &A)
8871 : AADenormalFPMath(IRP, A) {}
8872
8873 const std::string getAsStr(Attributor *A) const override {
8874 std::string Str("AADenormalFPMath[");
8875 raw_string_ostream OS(Str);
8876
8877 DenormalState Known = getKnown();
8878 if (Known.Mode.isValid())
8879 OS << "denormal-fp-math=" << Known.Mode;
8880 else
8881 OS << "invalid";
8882
8883 if (Known.ModeF32.isValid())
8884 OS << " denormal-fp-math-f32=" << Known.ModeF32;
8885 OS << ']';
8886 return Str;
8887 }
8888};
8889
8890struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
8891 AADenormalFPMathFunction(const IRPosition &IRP, Attributor &A)
8892 : AADenormalFPMathImpl(IRP, A) {}
8893
8894 void initialize(Attributor &A) override {
8895 const Function *F = getAnchorScope();
8896 DenormalFPEnv DenormEnv = F->getDenormalFPEnv();
8897
8898 Known = DenormalState{DenormEnv.DefaultMode, DenormEnv.F32Mode};
8899 if (isModeFixed())
8900 indicateFixpoint();
8901 }
8902
8903 ChangeStatus updateImpl(Attributor &A) override {
8904 ChangeStatus Change = ChangeStatus::UNCHANGED;
8905
8906 auto CheckCallSite = [=, &Change, &A](AbstractCallSite CS) {
8907 Function *Caller = CS.getInstruction()->getFunction();
8908 LLVM_DEBUG(dbgs() << "[AADenormalFPMath] Call " << Caller->getName()
8909 << "->" << getAssociatedFunction()->getName() << '\n');
8910
8911 const auto *CallerInfo = A.getAAFor<AADenormalFPMath>(
8912 *this, IRPosition::function(*Caller), DepClassTy::REQUIRED);
8913 if (!CallerInfo)
8914 return false;
8915
8916 Change = Change | clampStateAndIndicateChange(this->getState(),
8917 CallerInfo->getState());
8918 return true;
8919 };
8920
8921 bool AllCallSitesKnown = true;
8922 if (!A.checkForAllCallSites(CheckCallSite, *this, true, AllCallSitesKnown))
8923 return indicatePessimisticFixpoint();
8924
8925 if (Change == ChangeStatus::CHANGED && isModeFixed())
8926 indicateFixpoint();
8927 return Change;
8928 }
8929
8930 ChangeStatus manifest(Attributor &A) override {
8931 LLVMContext &Ctx = getAssociatedFunction()->getContext();
8932
8933 SmallVector<Attribute, 2> AttrToAdd;
8935
8936 // TODO: Change to use DenormalFPEnv everywhere.
8937 DenormalFPEnv KnownEnv(Known.Mode, Known.ModeF32);
8938
8939 if (KnownEnv == DenormalFPEnv::getDefault()) {
8940 AttrToRemove.push_back(Attribute::DenormalFPEnv);
8941 } else {
8942 AttrToAdd.push_back(Attribute::get(
8943 Ctx, Attribute::DenormalFPEnv,
8944 DenormalFPEnv(Known.Mode, Known.ModeF32).toIntValue()));
8945 }
8946
8947 auto &IRP = getIRPosition();
8948
8949 // TODO: There should be a combined add and remove API.
8950 return A.removeAttrs(IRP, AttrToRemove) |
8951 A.manifestAttrs(IRP, AttrToAdd, /*ForceReplace=*/true);
8952 }
8953
8954 void trackStatistics() const override {
8955 STATS_DECLTRACK_FN_ATTR(denormal_fpenv)
8956 }
8957};
8958} // namespace
8959
8960/// ------------------ Value Constant Range Attribute -------------------------
8961
8962namespace {
8963struct AAValueConstantRangeImpl : AAValueConstantRange {
8964 using StateType = IntegerRangeState;
8965 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
8966 : AAValueConstantRange(IRP, A) {}
8967
8968 void initialize(Attributor &A) override {
8969 if (A.hasSimplificationCallback(getIRPosition())) {
8970 indicatePessimisticFixpoint();
8971 return;
8972 }
8973
8974 // Intersect a range given by SCEV.
8975 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
8976
8977 // Intersect a range given by LVI.
8978 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
8979 }
8980
8981 const std::string getAsStr(Attributor *A) const override {
8982 std::string Str;
8983 llvm::raw_string_ostream OS(Str);
8984 OS << "range(" << getBitWidth() << ")<";
8985 getKnown().print(OS);
8986 OS << " / ";
8987 getAssumed().print(OS);
8988 OS << ">";
8989 return Str;
8990 }
8991
8992 /// Helper function to get a SCEV expr for the associated value at program
8993 /// point \p I.
8994 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
8995 if (!getAnchorScope())
8996 return nullptr;
8997
8998 ScalarEvolution *SE =
8999 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9000 *getAnchorScope());
9001
9002 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9003 *getAnchorScope());
9004
9005 if (!SE || !LI)
9006 return nullptr;
9007
9008 const SCEV *S = SE->getSCEV(&getAssociatedValue());
9009 if (!I)
9010 return S;
9011
9012 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
9013 }
9014
9015 /// Helper function to get a range from SCEV for the associated value at
9016 /// program point \p I.
9017 ConstantRange getConstantRangeFromSCEV(Attributor &A,
9018 const Instruction *I = nullptr) const {
9019 if (!getAnchorScope())
9020 return getWorstState(getBitWidth());
9021
9022 ScalarEvolution *SE =
9023 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9024 *getAnchorScope());
9025
9026 const SCEV *S = getSCEV(A, I);
9027 if (!SE || !S)
9028 return getWorstState(getBitWidth());
9029
9030 return SE->getUnsignedRange(S);
9031 }
9032
9033 /// Helper function to get a range from LVI for the associated value at
9034 /// program point \p I.
9035 ConstantRange
9036 getConstantRangeFromLVI(Attributor &A,
9037 const Instruction *CtxI = nullptr) const {
9038 if (!getAnchorScope())
9039 return getWorstState(getBitWidth());
9040
9041 LazyValueInfo *LVI =
9042 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9043 *getAnchorScope());
9044
9045 if (!LVI || !CtxI)
9046 return getWorstState(getBitWidth());
9047 return LVI->getConstantRange(&getAssociatedValue(),
9048 const_cast<Instruction *>(CtxI),
9049 /*UndefAllowed*/ false);
9050 }
9051
9052 /// Return true if \p CtxI is valid for querying outside analyses.
9053 /// This basically makes sure we do not ask intra-procedural analysis
9054 /// about a context in the wrong function or a context that violates
9055 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
9056 /// if the original context of this AA is OK or should be considered invalid.
9057 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
9058 const Instruction *CtxI,
9059 bool AllowAACtxI) const {
9060 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9061 return false;
9062
9063 // Our context might be in a different function, neither intra-procedural
9064 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
9065 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
9066 return false;
9067
9068 // If the context is not dominated by the value there are paths to the
9069 // context that do not define the value. This cannot be handled by
9070 // LazyValueInfo so we need to bail.
9071 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
9072 InformationCache &InfoCache = A.getInfoCache();
9073 const DominatorTree *DT =
9074 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
9075 *I->getFunction());
9076 return DT && DT->dominates(I, CtxI);
9077 }
9078
9079 return true;
9080 }
9081
9082 ConstantRange
9083 getAssumedConstantRange(Attributor &A,
9084 const Instruction *CtxI = nullptr) const override {
9085 // TODO: Make SCEV use Attributor assumption.
9086 // We may be able to bound a variable range via assumptions in
9087 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
9088 // evolve to x^2 + x, then we can say that y is in [2, 12].
9089 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9090 /* AllowAACtxI */ false))
9091 return getAssumed();
9092
9093 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9094 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9095 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9096 }
9097
9098 /// Helper function to create MDNode for range metadata.
9099 static MDNode *
9100 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
9101 const ConstantRange &AssumedConstantRange) {
9102 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
9103 Ty, AssumedConstantRange.getLower())),
9104 ConstantAsMetadata::get(ConstantInt::get(
9105 Ty, AssumedConstantRange.getUpper()))};
9106 return MDNode::get(Ctx, LowAndHigh);
9107 }
9108
9109 /// Return true if \p Assumed is included in ranges from instruction \p I.
9110 static bool isBetterRange(const ConstantRange &Assumed,
9111 const Instruction &I) {
9112 if (Assumed.isFullSet())
9113 return false;
9114
9115 std::optional<ConstantRange> Known;
9116
9117 if (const auto *CB = dyn_cast<CallBase>(&I)) {
9118 Known = CB->getRange();
9119 } else if (MDNode *KnownRanges = I.getMetadata(LLVMContext::MD_range)) {
9120 // If multiple ranges are annotated in IR, we give up to annotate assumed
9121 // range for now.
9122
9123 // TODO: If there exists a known range which containts assumed range, we
9124 // can say assumed range is better.
9125 if (KnownRanges->getNumOperands() > 2)
9126 return false;
9127
9128 ConstantInt *Lower =
9129 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
9130 ConstantInt *Upper =
9131 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
9132
9133 Known.emplace(Lower->getValue(), Upper->getValue());
9134 }
9135 return !Known || (*Known != Assumed && Known->contains(Assumed));
9136 }
9137
9138 /// Helper function to set range metadata.
9139 static bool
9140 setRangeMetadataIfisBetterRange(Instruction *I,
9141 const ConstantRange &AssumedConstantRange) {
9142 if (isBetterRange(AssumedConstantRange, *I)) {
9143 I->setMetadata(LLVMContext::MD_range,
9144 getMDNodeForConstantRange(I->getType(), I->getContext(),
9145 AssumedConstantRange));
9146 return true;
9147 }
9148 return false;
9149 }
9150 /// Helper function to set range return attribute.
9151 static bool
9152 setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,
9153 Instruction *I,
9154 const ConstantRange &AssumedConstantRange) {
9155 if (isBetterRange(AssumedConstantRange, *I)) {
9156 A.manifestAttrs(IRP,
9157 Attribute::get(I->getContext(), Attribute::Range,
9158 AssumedConstantRange),
9159 /*ForceReplace*/ true);
9160 return true;
9161 }
9162 return false;
9163 }
9164
9165 ChangeStatus manifest(Attributor &A) override {
9166 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9167 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9168 assert(!AssumedConstantRange.isFullSet() && "Invalid state");
9169
9170 auto &V = getAssociatedValue();
9171 if (!AssumedConstantRange.isEmptySet() &&
9172 !AssumedConstantRange.isSingleElement()) {
9173 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9174 assert(I == getCtxI() && "Should not annotate an instruction which is "
9175 "not the context instruction");
9176 if (isa<LoadInst>(I))
9177 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9178 Changed = ChangeStatus::CHANGED;
9179 if (isa<CallInst>(I))
9180 if (setRangeRetAttrIfisBetterRange(A, getIRPosition(), I,
9181 AssumedConstantRange))
9182 Changed = ChangeStatus::CHANGED;
9183 }
9184 }
9185
9186 return Changed;
9187 }
9188};
9189
9190struct AAValueConstantRangeArgument final
9191 : AAArgumentFromCallSiteArguments<
9192 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9193 true /* BridgeCallBaseContext */> {
9194 using Base = AAArgumentFromCallSiteArguments<
9195 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9196 true /* BridgeCallBaseContext */>;
9197 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9198 : Base(IRP, A) {}
9199
9200 void trackStatistics() const override {
9201 STATS_DECLTRACK_ARG_ATTR(value_range)
9202 }
9203};
9204
9205struct AAValueConstantRangeReturned
9206 : AAReturnedFromReturnedValues<AAValueConstantRange,
9207 AAValueConstantRangeImpl,
9208 AAValueConstantRangeImpl::StateType,
9209 /* PropagateCallBaseContext */ true> {
9210 using Base =
9211 AAReturnedFromReturnedValues<AAValueConstantRange,
9212 AAValueConstantRangeImpl,
9213 AAValueConstantRangeImpl::StateType,
9214 /* PropagateCallBaseContext */ true>;
9215 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9216 : Base(IRP, A) {}
9217
9218 void initialize(Attributor &A) override {
9219 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9220 indicatePessimisticFixpoint();
9221 }
9222
9223 void trackStatistics() const override {
9224 STATS_DECLTRACK_FNRET_ATTR(value_range)
9225 }
9226};
9227
9228struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9229 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9230 : AAValueConstantRangeImpl(IRP, A) {}
9231
9232 void initialize(Attributor &A) override {
9233 AAValueConstantRangeImpl::initialize(A);
9234 if (isAtFixpoint())
9235 return;
9236
9237 Value &V = getAssociatedValue();
9238
9239 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9240 unionAssumed(ConstantRange(C->getValue()));
9241 indicateOptimisticFixpoint();
9242 return;
9243 }
9244
9245 if (isa<UndefValue>(&V)) {
9246 // Collapse the undef state to 0.
9247 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9248 indicateOptimisticFixpoint();
9249 return;
9250 }
9251
9252 if (isa<CallBase>(&V))
9253 return;
9254
9256 return;
9257
9258 // If it is a load instruction with range metadata, use it.
9259 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9260 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9261 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9262 return;
9263 }
9264
9265 // We can work with PHI and select instruction as we traverse their operands
9266 // during update.
9268 return;
9269
9270 // Otherwise we give up.
9271 indicatePessimisticFixpoint();
9272
9273 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
9274 << getAssociatedValue() << "\n");
9275 }
9276
9277 bool calculateBinaryOperator(
9278 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9279 const Instruction *CtxI,
9280 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9281 Value *LHS = BinOp->getOperand(0);
9282 Value *RHS = BinOp->getOperand(1);
9283
9284 // Simplify the operands first.
9285 bool UsedAssumedInformation = false;
9286 const auto &SimplifiedLHS = A.getAssumedSimplified(
9287 IRPosition::value(*LHS, getCallBaseContext()), *this,
9288 UsedAssumedInformation, AA::Interprocedural);
9289 if (!SimplifiedLHS.has_value())
9290 return true;
9291 if (!*SimplifiedLHS)
9292 return false;
9293 LHS = *SimplifiedLHS;
9294
9295 const auto &SimplifiedRHS = A.getAssumedSimplified(
9296 IRPosition::value(*RHS, getCallBaseContext()), *this,
9297 UsedAssumedInformation, AA::Interprocedural);
9298 if (!SimplifiedRHS.has_value())
9299 return true;
9300 if (!*SimplifiedRHS)
9301 return false;
9302 RHS = *SimplifiedRHS;
9303
9304 // TODO: Allow non integers as well.
9305 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9306 return false;
9307
9308 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9309 *this, IRPosition::value(*LHS, getCallBaseContext()),
9310 DepClassTy::REQUIRED);
9311 if (!LHSAA)
9312 return false;
9313 QuerriedAAs.push_back(LHSAA);
9314 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9315
9316 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9317 *this, IRPosition::value(*RHS, getCallBaseContext()),
9318 DepClassTy::REQUIRED);
9319 if (!RHSAA)
9320 return false;
9321 QuerriedAAs.push_back(RHSAA);
9322 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9323
9324 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9325
9326 T.unionAssumed(AssumedRange);
9327
9328 // TODO: Track a known state too.
9329
9330 return T.isValidState();
9331 }
9332
9333 bool calculateCastInst(
9334 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9335 const Instruction *CtxI,
9336 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9337 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
9338 // TODO: Allow non integers as well.
9339 Value *OpV = CastI->getOperand(0);
9340
9341 // Simplify the operand first.
9342 bool UsedAssumedInformation = false;
9343 const auto &SimplifiedOpV = A.getAssumedSimplified(
9344 IRPosition::value(*OpV, getCallBaseContext()), *this,
9345 UsedAssumedInformation, AA::Interprocedural);
9346 if (!SimplifiedOpV.has_value())
9347 return true;
9348 if (!*SimplifiedOpV)
9349 return false;
9350 OpV = *SimplifiedOpV;
9351
9352 if (!OpV->getType()->isIntegerTy())
9353 return false;
9354
9355 auto *OpAA = A.getAAFor<AAValueConstantRange>(
9356 *this, IRPosition::value(*OpV, getCallBaseContext()),
9357 DepClassTy::REQUIRED);
9358 if (!OpAA)
9359 return false;
9360 QuerriedAAs.push_back(OpAA);
9361 T.unionAssumed(OpAA->getAssumed().castOp(CastI->getOpcode(),
9362 getState().getBitWidth()));
9363 return T.isValidState();
9364 }
9365
9366 bool
9367 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9368 const Instruction *CtxI,
9369 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9370 Value *LHS = CmpI->getOperand(0);
9371 Value *RHS = CmpI->getOperand(1);
9372
9373 // Simplify the operands first.
9374 bool UsedAssumedInformation = false;
9375 const auto &SimplifiedLHS = A.getAssumedSimplified(
9376 IRPosition::value(*LHS, getCallBaseContext()), *this,
9377 UsedAssumedInformation, AA::Interprocedural);
9378 if (!SimplifiedLHS.has_value())
9379 return true;
9380 if (!*SimplifiedLHS)
9381 return false;
9382 LHS = *SimplifiedLHS;
9383
9384 const auto &SimplifiedRHS = A.getAssumedSimplified(
9385 IRPosition::value(*RHS, getCallBaseContext()), *this,
9386 UsedAssumedInformation, AA::Interprocedural);
9387 if (!SimplifiedRHS.has_value())
9388 return true;
9389 if (!*SimplifiedRHS)
9390 return false;
9391 RHS = *SimplifiedRHS;
9392
9393 // TODO: Allow non integers as well.
9394 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9395 return false;
9396
9397 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9398 *this, IRPosition::value(*LHS, getCallBaseContext()),
9399 DepClassTy::REQUIRED);
9400 if (!LHSAA)
9401 return false;
9402 QuerriedAAs.push_back(LHSAA);
9403 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9404 *this, IRPosition::value(*RHS, getCallBaseContext()),
9405 DepClassTy::REQUIRED);
9406 if (!RHSAA)
9407 return false;
9408 QuerriedAAs.push_back(RHSAA);
9409 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9410 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9411
9412 // If one of them is empty set, we can't decide.
9413 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9414 return true;
9415
9416 bool MustTrue = false, MustFalse = false;
9417
9418 auto AllowedRegion =
9420
9421 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9422 MustFalse = true;
9423
9424 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9425 MustTrue = true;
9426
9427 assert((!MustTrue || !MustFalse) &&
9428 "Either MustTrue or MustFalse should be false!");
9429
9430 if (MustTrue)
9431 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9432 else if (MustFalse)
9433 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9434 else
9435 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9436
9437 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "
9438 << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))
9439 << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"
9440 << *RHSAA);
9441
9442 // TODO: Track a known state too.
9443 return T.isValidState();
9444 }
9445
9446 ChangeStatus updateImpl(Attributor &A) override {
9447
9448 IntegerRangeState T(getBitWidth());
9449 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9451 if (!I || isa<CallBase>(I)) {
9452
9453 // Simplify the operand first.
9454 bool UsedAssumedInformation = false;
9455 const auto &SimplifiedOpV = A.getAssumedSimplified(
9456 IRPosition::value(V, getCallBaseContext()), *this,
9457 UsedAssumedInformation, AA::Interprocedural);
9458 if (!SimplifiedOpV.has_value())
9459 return true;
9460 if (!*SimplifiedOpV)
9461 return false;
9462 Value *VPtr = *SimplifiedOpV;
9463
9464 // If the value is not instruction, we query AA to Attributor.
9465 const auto *AA = A.getAAFor<AAValueConstantRange>(
9466 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9467 DepClassTy::REQUIRED);
9468
9469 // Clamp operator is not used to utilize a program point CtxI.
9470 if (AA)
9471 T.unionAssumed(AA->getAssumedConstantRange(A, CtxI));
9472 else
9473 return false;
9474
9475 return T.isValidState();
9476 }
9477
9479 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9480 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9481 return false;
9482 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9483 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9484 return false;
9485 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9486 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9487 return false;
9488 } else {
9489 // Give up with other instructions.
9490 // TODO: Add other instructions
9491
9492 T.indicatePessimisticFixpoint();
9493 return false;
9494 }
9495
9496 // Catch circular reasoning in a pessimistic way for now.
9497 // TODO: Check how the range evolves and if we stripped anything, see also
9498 // AADereferenceable or AAAlign for similar situations.
9499 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9500 if (QueriedAA != this)
9501 continue;
9502 // If we are in a stady state we do not need to worry.
9503 if (T.getAssumed() == getState().getAssumed())
9504 continue;
9505 T.indicatePessimisticFixpoint();
9506 }
9507
9508 return T.isValidState();
9509 };
9510
9511 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9512 return indicatePessimisticFixpoint();
9513
9514 // Ensure that long def-use chains can't cause circular reasoning either by
9515 // introducing a cutoff below.
9516 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9517 return ChangeStatus::UNCHANGED;
9518 if (++NumChanges > MaxNumChanges) {
9519 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
9520 << " but only " << MaxNumChanges
9521 << " are allowed to avoid cyclic reasoning.");
9522 return indicatePessimisticFixpoint();
9523 }
9524 return ChangeStatus::CHANGED;
9525 }
9526
9527 void trackStatistics() const override {
9529 }
9530
9531 /// Tracker to bail after too many widening steps of the constant range.
9532 int NumChanges = 0;
9533
9534 /// Upper bound for the number of allowed changes (=widening steps) for the
9535 /// constant range before we give up.
9536 static constexpr int MaxNumChanges = 5;
9537};
9538
9539struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9540 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9541 : AAValueConstantRangeImpl(IRP, A) {}
9542
9543 ChangeStatus updateImpl(Attributor &A) override {
9544 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
9545 "not be called");
9546 }
9547
9548 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
9549};
9550
9551struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9552 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9553 : AAValueConstantRangeFunction(IRP, A) {}
9554
9555 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
9556};
9557
9558struct AAValueConstantRangeCallSiteReturned
9559 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9560 AAValueConstantRangeImpl::StateType,
9561 /* IntroduceCallBaseContext */ true> {
9562 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9563 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9564 AAValueConstantRangeImpl::StateType,
9565 /* IntroduceCallBaseContext */ true>(IRP, A) {}
9566
9567 void initialize(Attributor &A) override {
9568 // If it is a call instruction with range attribute, use the range.
9569 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) {
9570 if (std::optional<ConstantRange> Range = CI->getRange())
9571 intersectKnown(*Range);
9572 }
9573
9574 AAValueConstantRangeImpl::initialize(A);
9575 }
9576
9577 void trackStatistics() const override {
9578 STATS_DECLTRACK_CSRET_ATTR(value_range)
9579 }
9580};
9581struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9582 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9583 : AAValueConstantRangeFloating(IRP, A) {}
9584
9585 ChangeStatus manifest(Attributor &A) override {
9586 return ChangeStatus::UNCHANGED;
9587 }
9588
9589 void trackStatistics() const override {
9590 STATS_DECLTRACK_CSARG_ATTR(value_range)
9591 }
9592};
9593} // namespace
9594
9595/// ------------------ Potential Values Attribute -------------------------
9596
9597namespace {
9598struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9599 using StateType = PotentialConstantIntValuesState;
9600
9601 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9602 : AAPotentialConstantValues(IRP, A) {}
9603
9604 void initialize(Attributor &A) override {
9605 if (A.hasSimplificationCallback(getIRPosition()))
9606 indicatePessimisticFixpoint();
9607 else
9608 AAPotentialConstantValues::initialize(A);
9609 }
9610
9611 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9612 bool &ContainsUndef, bool ForSelf) {
9614 bool UsedAssumedInformation = false;
9615 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9616 UsedAssumedInformation)) {
9617 // Avoid recursion when the caller is computing constant values for this
9618 // IRP itself.
9619 if (ForSelf)
9620 return false;
9621 if (!IRP.getAssociatedType()->isIntegerTy())
9622 return false;
9623 auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9624 *this, IRP, DepClassTy::REQUIRED);
9625 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9626 return false;
9627 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9628 S = PotentialValuesAA->getState().getAssumedSet();
9629 return true;
9630 }
9631
9632 // Copy all the constant values, except UndefValue. ContainsUndef is true
9633 // iff Values contains only UndefValue instances. If there are other known
9634 // constants, then UndefValue is dropped.
9635 ContainsUndef = false;
9636 for (auto &It : Values) {
9637 if (isa<UndefValue>(It.getValue())) {
9638 ContainsUndef = true;
9639 continue;
9640 }
9641 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9642 if (!CI)
9643 return false;
9644 S.insert(CI->getValue());
9645 }
9646 ContainsUndef &= S.empty();
9647
9648 return true;
9649 }
9650
9651 const std::string getAsStr(Attributor *A) const override {
9652 std::string Str;
9653 llvm::raw_string_ostream OS(Str);
9654 OS << getState();
9655 return Str;
9656 }
9657
9658 ChangeStatus updateImpl(Attributor &A) override {
9659 return indicatePessimisticFixpoint();
9660 }
9661};
9662
9663struct AAPotentialConstantValuesArgument final
9664 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9665 AAPotentialConstantValuesImpl,
9666 PotentialConstantIntValuesState> {
9667 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9668 AAPotentialConstantValuesImpl,
9670 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9671 : Base(IRP, A) {}
9672
9673 void trackStatistics() const override {
9674 STATS_DECLTRACK_ARG_ATTR(potential_values)
9675 }
9676};
9677
9678struct AAPotentialConstantValuesReturned
9679 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9680 AAPotentialConstantValuesImpl> {
9681 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9682 AAPotentialConstantValuesImpl>;
9683 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9684 : Base(IRP, A) {}
9685
9686 void initialize(Attributor &A) override {
9687 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9688 indicatePessimisticFixpoint();
9689 Base::initialize(A);
9690 }
9691
9692 void trackStatistics() const override {
9693 STATS_DECLTRACK_FNRET_ATTR(potential_values)
9694 }
9695};
9696
9697struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9698 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9699 : AAPotentialConstantValuesImpl(IRP, A) {}
9700
9701 void initialize(Attributor &A) override {
9702 AAPotentialConstantValuesImpl::initialize(A);
9703 if (isAtFixpoint())
9704 return;
9705
9706 Value &V = getAssociatedValue();
9707
9708 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9709 unionAssumed(C->getValue());
9710 indicateOptimisticFixpoint();
9711 return;
9712 }
9713
9714 if (isa<UndefValue>(&V)) {
9715 unionAssumedWithUndef();
9716 indicateOptimisticFixpoint();
9717 return;
9718 }
9719
9721 return;
9722
9724 return;
9725
9726 indicatePessimisticFixpoint();
9727
9728 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
9729 << getAssociatedValue() << "\n");
9730 }
9731
9732 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9733 const APInt &RHS) {
9734 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9735 }
9736
9737 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9738 uint32_t ResultBitWidth) {
9739 Instruction::CastOps CastOp = CI->getOpcode();
9740 switch (CastOp) {
9741 default:
9742 llvm_unreachable("unsupported or not integer cast");
9743 case Instruction::Trunc:
9744 return Src.trunc(ResultBitWidth);
9745 case Instruction::SExt:
9746 return Src.sext(ResultBitWidth);
9747 case Instruction::ZExt:
9748 return Src.zext(ResultBitWidth);
9749 case Instruction::BitCast:
9750 return Src;
9751 }
9752 }
9753
9754 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9755 const APInt &LHS, const APInt &RHS,
9756 bool &SkipOperation, bool &Unsupported) {
9757 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9758 // Unsupported is set to true when the binary operator is not supported.
9759 // SkipOperation is set to true when UB occur with the given operand pair
9760 // (LHS, RHS).
9761 // TODO: we should look at nsw and nuw keywords to handle operations
9762 // that create poison or undef value.
9763 switch (BinOpcode) {
9764 default:
9765 Unsupported = true;
9766 return LHS;
9767 case Instruction::Add:
9768 return LHS + RHS;
9769 case Instruction::Sub:
9770 return LHS - RHS;
9771 case Instruction::Mul:
9772 return LHS * RHS;
9773 case Instruction::UDiv:
9774 if (RHS.isZero()) {
9775 SkipOperation = true;
9776 return LHS;
9777 }
9778 return LHS.udiv(RHS);
9779 case Instruction::SDiv:
9780 if (RHS.isZero()) {
9781 SkipOperation = true;
9782 return LHS;
9783 }
9784 return LHS.sdiv(RHS);
9785 case Instruction::URem:
9786 if (RHS.isZero()) {
9787 SkipOperation = true;
9788 return LHS;
9789 }
9790 return LHS.urem(RHS);
9791 case Instruction::SRem:
9792 if (RHS.isZero()) {
9793 SkipOperation = true;
9794 return LHS;
9795 }
9796 return LHS.srem(RHS);
9797 case Instruction::Shl:
9798 return LHS.shl(RHS);
9799 case Instruction::LShr:
9800 return LHS.lshr(RHS);
9801 case Instruction::AShr:
9802 return LHS.ashr(RHS);
9803 case Instruction::And:
9804 return LHS & RHS;
9805 case Instruction::Or:
9806 return LHS | RHS;
9807 case Instruction::Xor:
9808 return LHS ^ RHS;
9809 }
9810 }
9811
9812 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9813 const APInt &LHS, const APInt &RHS) {
9814 bool SkipOperation = false;
9815 bool Unsupported = false;
9816 APInt Result =
9817 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9818 if (Unsupported)
9819 return false;
9820 // If SkipOperation is true, we can ignore this operand pair (L, R).
9821 if (!SkipOperation)
9822 unionAssumed(Result);
9823 return isValidState();
9824 }
9825
9826 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9827 auto AssumedBefore = getAssumed();
9828 Value *LHS = ICI->getOperand(0);
9829 Value *RHS = ICI->getOperand(1);
9830
9831 bool LHSContainsUndef = false, RHSContainsUndef = false;
9832 SetTy LHSAAPVS, RHSAAPVS;
9833 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9834 LHSContainsUndef, /* ForSelf */ false) ||
9835 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9836 RHSContainsUndef, /* ForSelf */ false))
9837 return indicatePessimisticFixpoint();
9838
9839 // TODO: make use of undef flag to limit potential values aggressively.
9840 bool MaybeTrue = false, MaybeFalse = false;
9841 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
9842 if (LHSContainsUndef && RHSContainsUndef) {
9843 // The result of any comparison between undefs can be soundly replaced
9844 // with undef.
9845 unionAssumedWithUndef();
9846 } else if (LHSContainsUndef) {
9847 for (const APInt &R : RHSAAPVS) {
9848 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9849 MaybeTrue |= CmpResult;
9850 MaybeFalse |= !CmpResult;
9851 if (MaybeTrue & MaybeFalse)
9852 return indicatePessimisticFixpoint();
9853 }
9854 } else if (RHSContainsUndef) {
9855 for (const APInt &L : LHSAAPVS) {
9856 bool CmpResult = calculateICmpInst(ICI, L, Zero);
9857 MaybeTrue |= CmpResult;
9858 MaybeFalse |= !CmpResult;
9859 if (MaybeTrue & MaybeFalse)
9860 return indicatePessimisticFixpoint();
9861 }
9862 } else {
9863 for (const APInt &L : LHSAAPVS) {
9864 for (const APInt &R : RHSAAPVS) {
9865 bool CmpResult = calculateICmpInst(ICI, L, R);
9866 MaybeTrue |= CmpResult;
9867 MaybeFalse |= !CmpResult;
9868 if (MaybeTrue & MaybeFalse)
9869 return indicatePessimisticFixpoint();
9870 }
9871 }
9872 }
9873 if (MaybeTrue)
9874 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
9875 if (MaybeFalse)
9876 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
9877 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9878 : ChangeStatus::CHANGED;
9879 }
9880
9881 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
9882 auto AssumedBefore = getAssumed();
9883 Value *LHS = SI->getTrueValue();
9884 Value *RHS = SI->getFalseValue();
9885
9886 bool UsedAssumedInformation = false;
9887 std::optional<Constant *> C = A.getAssumedConstant(
9888 *SI->getCondition(), *this, UsedAssumedInformation);
9889
9890 // Check if we only need one operand.
9891 bool OnlyLeft = false, OnlyRight = false;
9892 if (C && *C && (*C)->isOneValue())
9893 OnlyLeft = true;
9894 else if (C && *C && (*C)->isNullValue())
9895 OnlyRight = true;
9896
9897 bool LHSContainsUndef = false, RHSContainsUndef = false;
9898 SetTy LHSAAPVS, RHSAAPVS;
9899 if (!OnlyRight &&
9900 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9901 LHSContainsUndef, /* ForSelf */ false))
9902 return indicatePessimisticFixpoint();
9903
9904 if (!OnlyLeft &&
9905 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9906 RHSContainsUndef, /* ForSelf */ false))
9907 return indicatePessimisticFixpoint();
9908
9909 if (OnlyLeft || OnlyRight) {
9910 // select (true/false), lhs, rhs
9911 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9912 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9913
9914 if (Undef)
9915 unionAssumedWithUndef();
9916 else {
9917 for (const auto &It : *OpAA)
9918 unionAssumed(It);
9919 }
9920
9921 } else if (LHSContainsUndef && RHSContainsUndef) {
9922 // select i1 *, undef , undef => undef
9923 unionAssumedWithUndef();
9924 } else {
9925 for (const auto &It : LHSAAPVS)
9926 unionAssumed(It);
9927 for (const auto &It : RHSAAPVS)
9928 unionAssumed(It);
9929 }
9930 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9931 : ChangeStatus::CHANGED;
9932 }
9933
9934 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
9935 auto AssumedBefore = getAssumed();
9936 if (!CI->isIntegerCast())
9937 return indicatePessimisticFixpoint();
9938 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
9939 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
9940 Value *Src = CI->getOperand(0);
9941
9942 bool SrcContainsUndef = false;
9943 SetTy SrcPVS;
9944 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
9945 SrcContainsUndef, /* ForSelf */ false))
9946 return indicatePessimisticFixpoint();
9947
9948 if (SrcContainsUndef)
9949 unionAssumedWithUndef();
9950 else {
9951 for (const APInt &S : SrcPVS) {
9952 APInt T = calculateCastInst(CI, S, ResultBitWidth);
9953 unionAssumed(T);
9954 }
9955 }
9956 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9957 : ChangeStatus::CHANGED;
9958 }
9959
9960 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
9961 auto AssumedBefore = getAssumed();
9962 Value *LHS = BinOp->getOperand(0);
9963 Value *RHS = BinOp->getOperand(1);
9964
9965 bool LHSContainsUndef = false, RHSContainsUndef = false;
9966 SetTy LHSAAPVS, RHSAAPVS;
9967 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9968 LHSContainsUndef, /* ForSelf */ false) ||
9969 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9970 RHSContainsUndef, /* ForSelf */ false))
9971 return indicatePessimisticFixpoint();
9972
9973 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
9974
9975 // TODO: make use of undef flag to limit potential values aggressively.
9976 if (LHSContainsUndef && RHSContainsUndef) {
9977 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
9978 return indicatePessimisticFixpoint();
9979 } else if (LHSContainsUndef) {
9980 for (const APInt &R : RHSAAPVS) {
9981 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
9982 return indicatePessimisticFixpoint();
9983 }
9984 } else if (RHSContainsUndef) {
9985 for (const APInt &L : LHSAAPVS) {
9986 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
9987 return indicatePessimisticFixpoint();
9988 }
9989 } else {
9990 for (const APInt &L : LHSAAPVS) {
9991 for (const APInt &R : RHSAAPVS) {
9992 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9993 return indicatePessimisticFixpoint();
9994 }
9995 }
9996 }
9997 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9998 : ChangeStatus::CHANGED;
9999 }
10000
10001 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
10002 auto AssumedBefore = getAssumed();
10003 SetTy Incoming;
10004 bool ContainsUndef;
10005 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
10006 ContainsUndef, /* ForSelf */ true))
10007 return indicatePessimisticFixpoint();
10008 if (ContainsUndef) {
10009 unionAssumedWithUndef();
10010 } else {
10011 for (const auto &It : Incoming)
10012 unionAssumed(It);
10013 }
10014 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10015 : ChangeStatus::CHANGED;
10016 }
10017
10018 ChangeStatus updateImpl(Attributor &A) override {
10019 Value &V = getAssociatedValue();
10021
10022 if (auto *ICI = dyn_cast<ICmpInst>(I))
10023 return updateWithICmpInst(A, ICI);
10024
10025 if (auto *SI = dyn_cast<SelectInst>(I))
10026 return updateWithSelectInst(A, SI);
10027
10028 if (auto *CI = dyn_cast<CastInst>(I))
10029 return updateWithCastInst(A, CI);
10030
10031 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
10032 return updateWithBinaryOperator(A, BinOp);
10033
10034 if (isa<PHINode>(I) || isa<LoadInst>(I))
10035 return updateWithInstruction(A, I);
10036
10037 return indicatePessimisticFixpoint();
10038 }
10039
10040 void trackStatistics() const override {
10041 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
10042 }
10043};
10044
10045struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10046 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
10047 : AAPotentialConstantValuesImpl(IRP, A) {}
10048
10049 ChangeStatus updateImpl(Attributor &A) override {
10051 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10052 "not be called");
10053 }
10054
10055 void trackStatistics() const override {
10056 STATS_DECLTRACK_FN_ATTR(potential_values)
10057 }
10058};
10059
10060struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10061 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
10062 : AAPotentialConstantValuesFunction(IRP, A) {}
10063
10064 void trackStatistics() const override {
10065 STATS_DECLTRACK_CS_ATTR(potential_values)
10066 }
10067};
10068
10069struct AAPotentialConstantValuesCallSiteReturned
10070 : AACalleeToCallSite<AAPotentialConstantValues,
10071 AAPotentialConstantValuesImpl> {
10072 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
10073 Attributor &A)
10074 : AACalleeToCallSite<AAPotentialConstantValues,
10075 AAPotentialConstantValuesImpl>(IRP, A) {}
10076
10077 void trackStatistics() const override {
10078 STATS_DECLTRACK_CSRET_ATTR(potential_values)
10079 }
10080};
10081
10082struct AAPotentialConstantValuesCallSiteArgument
10083 : AAPotentialConstantValuesFloating {
10084 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
10085 Attributor &A)
10086 : AAPotentialConstantValuesFloating(IRP, A) {}
10087
10088 void initialize(Attributor &A) override {
10089 AAPotentialConstantValuesImpl::initialize(A);
10090 if (isAtFixpoint())
10091 return;
10092
10093 Value &V = getAssociatedValue();
10094
10095 if (auto *C = dyn_cast<ConstantInt>(&V)) {
10096 unionAssumed(C->getValue());
10097 indicateOptimisticFixpoint();
10098 return;
10099 }
10100
10101 if (isa<UndefValue>(&V)) {
10102 unionAssumedWithUndef();
10103 indicateOptimisticFixpoint();
10104 return;
10105 }
10106 }
10107
10108 ChangeStatus updateImpl(Attributor &A) override {
10109 Value &V = getAssociatedValue();
10110 auto AssumedBefore = getAssumed();
10111 auto *AA = A.getAAFor<AAPotentialConstantValues>(
10112 *this, IRPosition::value(V), DepClassTy::REQUIRED);
10113 if (!AA)
10114 return indicatePessimisticFixpoint();
10115 const auto &S = AA->getAssumed();
10116 unionAssumed(S);
10117 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10118 : ChangeStatus::CHANGED;
10119 }
10120
10121 void trackStatistics() const override {
10122 STATS_DECLTRACK_CSARG_ATTR(potential_values)
10123 }
10124};
10125} // namespace
10126
10127/// ------------------------ NoUndef Attribute ---------------------------------
10129 Attribute::AttrKind ImpliedAttributeKind,
10130 bool IgnoreSubsumingPositions) {
10131 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10132 "Unexpected attribute kind");
10133 if (A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10134 Attribute::NoUndef))
10135 return true;
10136
10137 Value &Val = IRP.getAssociatedValue();
10140 LLVMContext &Ctx = Val.getContext();
10141 A.manifestAttrs(IRP, Attribute::get(Ctx, Attribute::NoUndef));
10142 return true;
10143 }
10144
10145 return false;
10146}
10147
10148namespace {
10149struct AANoUndefImpl : AANoUndef {
10150 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
10151
10152 void initialize(Attributor &A) override {
10153 Value &V = getAssociatedValue();
10154 if (isa<UndefValue>(V))
10155 indicatePessimisticFixpoint();
10156 assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));
10157 }
10158
10159 /// See followUsesInMBEC
10160 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10161 AANoUndef::StateType &State) {
10162 const Value *UseV = U->get();
10163 const DominatorTree *DT = nullptr;
10164 AssumptionCache *AC = nullptr;
10165 InformationCache &InfoCache = A.getInfoCache();
10166 if (Function *F = getAnchorScope()) {
10167 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10168 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10169 }
10170 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10171 bool TrackUse = false;
10172 // Track use for instructions which must produce undef or poison bits when
10173 // at least one operand contains such bits.
10175 TrackUse = true;
10176 return TrackUse;
10177 }
10178
10179 const std::string getAsStr(Attributor *A) const override {
10180 return getAssumed() ? "noundef" : "may-undef-or-poison";
10181 }
10182
10183 ChangeStatus manifest(Attributor &A) override {
10184 // We don't manifest noundef attribute for dead positions because the
10185 // associated values with dead positions would be replaced with undef
10186 // values.
10187 bool UsedAssumedInformation = false;
10188 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10189 UsedAssumedInformation))
10190 return ChangeStatus::UNCHANGED;
10191 // A position whose simplified value does not have any value is
10192 // considered to be dead. We don't manifest noundef in such positions for
10193 // the same reason above.
10194 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10196 .has_value())
10197 return ChangeStatus::UNCHANGED;
10198 return AANoUndef::manifest(A);
10199 }
10200};
10201
10202struct AANoUndefFloating : public AANoUndefImpl {
10203 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10204 : AANoUndefImpl(IRP, A) {}
10205
10206 void initialize(Attributor &A) override {
10207 AANoUndefImpl::initialize(A);
10208 if (!getState().isAtFixpoint() && getAnchorScope() &&
10209 !getAnchorScope()->isDeclaration())
10210 if (Instruction *CtxI = getCtxI())
10211 followUsesInMBEC(*this, A, getState(), *CtxI);
10212 }
10213
10214 ChangeStatus updateImpl(Attributor &A) override {
10215 auto VisitValueCB = [&](const IRPosition &IRP) -> bool {
10216 bool IsKnownNoUndef;
10218 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10219 };
10220
10221 bool Stripped;
10222 bool UsedAssumedInformation = false;
10223 Value *AssociatedValue = &getAssociatedValue();
10225 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10226 AA::AnyScope, UsedAssumedInformation))
10227 Stripped = false;
10228 else
10229 Stripped =
10230 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
10231
10232 if (!Stripped) {
10233 // If we haven't stripped anything we might still be able to use a
10234 // different AA, but only if the IRP changes. Effectively when we
10235 // interpret this not as a call site value but as a floating/argument
10236 // value.
10237 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
10238 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10239 return indicatePessimisticFixpoint();
10240 return ChangeStatus::UNCHANGED;
10241 }
10242
10243 for (const auto &VAC : Values)
10244 if (!VisitValueCB(IRPosition::value(*VAC.getValue())))
10245 return indicatePessimisticFixpoint();
10246
10247 return ChangeStatus::UNCHANGED;
10248 }
10249
10250 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10251};
10252
10253struct AANoUndefReturned final
10254 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10255 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10256 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10257
10258 void initialize(Attributor &A) override {
10259 AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>::initialize(A);
10260 if (isAtFixpoint())
10261 return;
10262
10263 // Returning a value that violates a return attribute, e.g., nonnull, is
10264 // poison.
10265 AttributeMask AM = AttributeFuncs::getPoisonGeneratingAttributes();
10266 AttributeSet RetAttrs =
10267 getAssociatedFunction()->getAttributes().getRetAttrs();
10268 if (any_of(RetAttrs, [&](Attribute Attr) { return AM.contains(Attr); }))
10269 indicatePessimisticFixpoint();
10270 }
10271
10272 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10273};
10274
10275struct AANoUndefArgument final
10276 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10277 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10278 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10279
10280 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
10281};
10282
10283struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10284 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10285 : AANoUndefFloating(IRP, A) {}
10286
10287 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
10288};
10289
10290struct AANoUndefCallSiteReturned final
10291 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10292 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10293 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP, A) {}
10294
10295 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
10296};
10297
10298/// ------------------------ NoFPClass Attribute -------------------------------
10299
10300struct AANoFPClassImpl : AANoFPClass {
10301 AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}
10302
10303 void initialize(Attributor &A) override {
10304 const IRPosition &IRP = getIRPosition();
10305
10306 Value &V = IRP.getAssociatedValue();
10307 if (isa<UndefValue>(V)) {
10308 indicateOptimisticFixpoint();
10309 return;
10310 }
10311
10313 A.getAttrs(getIRPosition(), {Attribute::NoFPClass}, Attrs, false);
10314 for (const auto &Attr : Attrs) {
10315 addKnownBits(Attr.getNoFPClass());
10316 }
10317
10318 Instruction *CtxI = getCtxI();
10319
10320 if (getPositionKind() != IRPosition::IRP_RETURNED) {
10321 const DataLayout &DL = A.getDataLayout();
10322 InformationCache &InfoCache = A.getInfoCache();
10323
10324 const DominatorTree *DT = nullptr;
10325 AssumptionCache *AC = nullptr;
10326 const TargetLibraryInfo *TLI = nullptr;
10327 Function *F = getAnchorScope();
10328 if (F) {
10330 if (!F->isDeclaration()) {
10331 DT =
10332 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10333 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10334 }
10335 }
10336
10337 SimplifyQuery Q(DL, TLI, DT, AC, CtxI);
10338
10339 KnownFPClass KnownFPClass = computeKnownFPClass(&V, fcAllFlags, Q);
10340 addKnownBits(~KnownFPClass.getKnownFPClasses());
10341 }
10342
10343 if (CtxI)
10344 followUsesInMBEC(*this, A, getState(), *CtxI);
10345 }
10346
10347 /// See followUsesInMBEC
10348 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10349 AANoFPClass::StateType &State) {
10350 // TODO: Determine what instructions can be looked through.
10351 auto *CB = dyn_cast<CallBase>(I);
10352 if (!CB)
10353 return false;
10354
10355 if (!CB->isArgOperand(U))
10356 return false;
10357
10358 unsigned ArgNo = CB->getArgOperandNo(U);
10359 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
10360 if (auto *NoFPAA = A.getAAFor<AANoFPClass>(*this, IRP, DepClassTy::NONE))
10361 State.addKnownBits(NoFPAA->getState().getKnown());
10362 return false;
10363 }
10364
10365 const std::string getAsStr(Attributor *A) const override {
10366 std::string Result = "nofpclass";
10367 raw_string_ostream OS(Result);
10368 OS << getKnownNoFPClass() << '/' << getAssumedNoFPClass();
10369 return Result;
10370 }
10371
10372 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
10373 SmallVectorImpl<Attribute> &Attrs) const override {
10374 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10375 }
10376};
10377
10378struct AANoFPClassFloating : public AANoFPClassImpl {
10379 AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
10380 : AANoFPClassImpl(IRP, A) {}
10381
10382 ChangeStatus updateImpl(Attributor &A) override {
10384 bool UsedAssumedInformation = false;
10385 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10386 AA::AnyScope, UsedAssumedInformation)) {
10387 Values.push_back({getAssociatedValue(), getCtxI()});
10388 }
10389
10390 StateType T;
10391 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10392 const auto *AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),
10393 DepClassTy::REQUIRED);
10394 if (!AA || this == AA) {
10395 T.indicatePessimisticFixpoint();
10396 } else {
10397 const AANoFPClass::StateType &S =
10398 static_cast<const AANoFPClass::StateType &>(AA->getState());
10399 T ^= S;
10400 }
10401 return T.isValidState();
10402 };
10403
10404 for (const auto &VAC : Values)
10405 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10406 return indicatePessimisticFixpoint();
10407
10408 return clampStateAndIndicateChange(getState(), T);
10409 }
10410
10411 void trackStatistics() const override {
10413 }
10414};
10415
10416struct AANoFPClassReturned final
10417 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10418 AANoFPClassImpl::StateType, false,
10419 Attribute::None, false> {
10420 AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
10421 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10422 AANoFPClassImpl::StateType, false,
10423 Attribute::None, false>(IRP, A) {}
10424
10425 void trackStatistics() const override {
10427 }
10428};
10429
10430struct AANoFPClassArgument final
10431 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10432 AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
10433 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10434
10435 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }
10436};
10437
10438struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10439 AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
10440 : AANoFPClassFloating(IRP, A) {}
10441
10442 void trackStatistics() const override {
10444 }
10445};
10446
10447struct AANoFPClassCallSiteReturned final
10448 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10449 AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
10450 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10451
10452 void trackStatistics() const override {
10454 }
10455};
10456
10457struct AACallEdgesImpl : public AACallEdges {
10458 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10459
10460 const SetVector<Function *> &getOptimisticEdges() const override {
10461 return CalledFunctions;
10462 }
10463
10464 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10465
10466 bool hasNonAsmUnknownCallee() const override {
10467 return HasUnknownCalleeNonAsm;
10468 }
10469
10470 const std::string getAsStr(Attributor *A) const override {
10471 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10472 std::to_string(CalledFunctions.size()) + "]";
10473 }
10474
10475 void trackStatistics() const override {}
10476
10477protected:
10478 /// Return the callee of \p CB if it is a direct call whose callee has no
10479 /// callback metadata. Such a call only calls its callee.
10480 static Function *getOnlyCallee(const CallBase &CB) {
10482 if (Callee && !Callee->hasMetadata(LLVMContext::MD_callback))
10483 return Callee;
10484 return nullptr;
10485 }
10486
10487 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10488 if (CalledFunctions.insert(Fn)) {
10489 Change = ChangeStatus::CHANGED;
10490 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
10491 << "\n");
10492 }
10493 }
10494
10495 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10496 if (!HasUnknownCallee)
10497 Change = ChangeStatus::CHANGED;
10498 if (NonAsm && !HasUnknownCalleeNonAsm)
10499 Change = ChangeStatus::CHANGED;
10500 HasUnknownCalleeNonAsm |= NonAsm;
10501 HasUnknownCallee = true;
10502 }
10503
10504private:
10505 /// Optimistic set of functions that might be called by this position.
10506 SetVector<Function *> CalledFunctions;
10507
10508 /// Is there any call with a unknown callee.
10509 bool HasUnknownCallee = false;
10510
10511 /// Is there any call with a unknown callee, excluding any inline asm.
10512 bool HasUnknownCalleeNonAsm = false;
10513};
10514
10515struct AACallEdgesCallSite : public AACallEdgesImpl {
10516 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10517 : AACallEdgesImpl(IRP, A) {}
10518
10519 void initialize(Attributor &A) override {
10520 // The only callee of a direct call without callbacks never changes.
10521 if (Function *Callee = getOnlyCallee(cast<CallBase>(getAnchorValue()))) {
10522 ChangeStatus Change = ChangeStatus::UNCHANGED;
10523 addCalledFunction(Callee, Change);
10524 indicateOptimisticFixpoint();
10525 }
10526 }
10527
10528 ChangeStatus updateImpl(Attributor &A) override {
10529 ChangeStatus Change = ChangeStatus::UNCHANGED;
10530
10531 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10532 if (Function *Fn = dyn_cast<Function>(&V)) {
10533 addCalledFunction(Fn, Change);
10534 } else {
10535 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
10536 setHasUnknownCallee(true, Change);
10537 }
10538
10539 // Explore all values.
10540 return true;
10541 };
10542
10544 // Process any value that we might call.
10545 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10546 if (isa<Constant>(V)) {
10547 VisitValue(*V, CtxI);
10548 return;
10549 }
10550
10551 bool UsedAssumedInformation = false;
10552 Values.clear();
10553 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10554 AA::AnyScope, UsedAssumedInformation)) {
10555 Values.push_back({*V, CtxI});
10556 }
10557 for (auto &VAC : Values)
10558 VisitValue(*VAC.getValue(), VAC.getCtxI());
10559 };
10560
10561 CallBase *CB = cast<CallBase>(getCtxI());
10562
10563 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10564 if (IA->hasSideEffects() &&
10565 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10566 !hasAssumption(*CB, "ompx_no_call_asm")) {
10567 setHasUnknownCallee(false, Change);
10568 }
10569 return Change;
10570 }
10571
10572 if (CB->isIndirectCall())
10573 if (auto *IndirectCallAA = A.getAAFor<AAIndirectCallInfo>(
10574 *this, getIRPosition(), DepClassTy::OPTIONAL))
10575 if (IndirectCallAA->foreachCallee(
10576 [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10577 return Change;
10578
10579 // The most simple case.
10580 ProcessCalledOperand(CB->getCalledOperand(), CB);
10581
10582 // Process callback functions.
10583 SmallVector<const Use *, 4u> CallbackUses;
10584 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10585 for (const Use *U : CallbackUses)
10586 ProcessCalledOperand(U->get(), CB);
10587
10588 return Change;
10589 }
10590};
10591
10592struct AACallEdgesFunction : public AACallEdgesImpl {
10593 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10594 : AACallEdgesImpl(IRP, A) {}
10595
10596 ChangeStatus updateImpl(Attributor &A) override {
10597 ChangeStatus Change = ChangeStatus::UNCHANGED;
10598 bool AllCallsDirect = true;
10599
10600 auto ProcessCallInst = [&](Instruction &Inst) {
10601 CallBase &CB = cast<CallBase>(Inst);
10602
10603 // A direct call without callbacks only calls its callee; there is no
10604 // need for a call site attribute.
10605 if (Function *Callee = getOnlyCallee(CB)) {
10606 addCalledFunction(Callee, Change);
10607 return true;
10608 }
10609
10610 AllCallsDirect = false;
10611 auto *CBEdges = A.getAAFor<AACallEdges>(
10612 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10613 if (!CBEdges)
10614 return false;
10615 if (CBEdges->hasNonAsmUnknownCallee())
10616 setHasUnknownCallee(true, Change);
10617 if (CBEdges->hasUnknownCallee())
10618 setHasUnknownCallee(false, Change);
10619
10620 for (Function *F : CBEdges->getOptimisticEdges())
10621 addCalledFunction(F, Change);
10622
10623 return true;
10624 };
10625
10626 // Visit all callable instructions.
10627 bool UsedAssumedInformation = false;
10628 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10629 UsedAssumedInformation,
10630 /* CheckBBLivenessOnly */ true)) {
10631 // If we haven't looked at all call like instructions, assume that there
10632 // are unknown callees.
10633 setHasUnknownCallee(true, Change);
10634 }
10635
10636 // The callees of direct calls in code known to be live do not change.
10637 if (AllCallsDirect && !UsedAssumedInformation)
10638 indicateOptimisticFixpoint();
10639
10640 return Change;
10641 }
10642};
10643
10644/// -------------------AAInterFnReachability Attribute--------------------------
10645
10646struct AAInterFnReachabilityFunction
10647 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10648 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10649 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10650 : Base(IRP, A) {}
10651
10652 bool instructionCanReach(
10653 Attributor &A, const Instruction &From, const Function &To,
10654 const AA::InstExclusionSetTy *ExclusionSet) const override {
10655 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
10656 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10657
10658 RQITy StackRQI(A, From, To, ExclusionSet, false);
10659 RQITy::Reachable Result;
10660 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
10661 return NonConstThis->isReachableImpl(A, StackRQI,
10662 /*IsTemporaryRQI=*/true);
10663 return Result == RQITy::Reachable::Yes;
10664 }
10665
10666 bool isReachableImpl(Attributor &A, RQITy &RQI,
10667 bool IsTemporaryRQI) override {
10668 const Instruction *EntryI =
10669 &RQI.From->getFunction()->getEntryBlock().front();
10670 if (EntryI != RQI.From &&
10671 !instructionCanReach(A, *EntryI, *RQI.To, nullptr))
10672 return rememberResult(A, RQITy::Reachable::No, RQI, false,
10673 IsTemporaryRQI);
10674
10675 auto CheckReachableCallBase = [&](CallBase *CB) {
10676 auto *CBEdges = A.getAAFor<AACallEdges>(
10677 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10678 if (!CBEdges || !CBEdges->getState().isValidState())
10679 return false;
10680 // TODO Check To backwards in this case.
10681 if (CBEdges->hasUnknownCallee())
10682 return false;
10683
10684 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10685 if (Fn == RQI.To)
10686 return false;
10687
10688 if (Fn->isDeclaration()) {
10689 if (Fn->hasFnAttribute(Attribute::NoCallback))
10690 continue;
10691 // TODO Check To backwards in this case.
10692 return false;
10693 }
10694
10695 if (Fn == getAnchorScope()) {
10696 if (EntryI == RQI.From)
10697 continue;
10698 return false;
10699 }
10700
10701 const AAInterFnReachability *InterFnReachability =
10702 A.getAAFor<AAInterFnReachability>(*this, IRPosition::function(*Fn),
10703 DepClassTy::OPTIONAL);
10704
10705 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10706 if (!InterFnReachability ||
10707 InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10708 RQI.ExclusionSet))
10709 return false;
10710 }
10711 return true;
10712 };
10713
10714 const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10715 *this, IRPosition::function(*RQI.From->getFunction()),
10716 DepClassTy::OPTIONAL);
10717
10718 // Determine call like instructions that we can reach from the inst.
10719 auto CheckCallBase = [&](Instruction &CBInst) {
10720 // There are usually less nodes in the call graph, check inter function
10721 // reachability first.
10722 if (CheckReachableCallBase(cast<CallBase>(&CBInst)))
10723 return true;
10724 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10725 A, *RQI.From, CBInst, RQI.ExclusionSet);
10726 };
10727
10728 bool UsedExclusionSet = /* conservative */ true;
10729 bool UsedAssumedInformation = false;
10730 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10731 UsedAssumedInformation,
10732 /* CheckBBLivenessOnly */ true))
10733 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10734 IsTemporaryRQI);
10735
10736 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10737 IsTemporaryRQI);
10738 }
10739
10740 void trackStatistics() const override {}
10741};
10742} // namespace
10743
10744template <typename AAType>
10745static std::optional<Constant *>
10747 const IRPosition &IRP, Type &Ty) {
10748 if (!Ty.isIntegerTy())
10749 return nullptr;
10750
10751 // This will also pass the call base context.
10752 const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10753 if (!AA)
10754 return nullptr;
10755
10756 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
10757
10758 if (!COpt.has_value()) {
10759 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10760 return std::nullopt;
10761 }
10762 if (auto *C = *COpt) {
10763 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10764 return C;
10765 }
10766 return nullptr;
10767}
10768
10770 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10772 Type &Ty = *IRP.getAssociatedType();
10773 std::optional<Value *> V;
10774 for (auto &It : Values) {
10775 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10776 if (V.has_value() && !*V)
10777 break;
10778 }
10779 if (!V.has_value())
10780 return UndefValue::get(&Ty);
10781 return *V;
10782}
10783
10784namespace {
10785struct AAPotentialValuesImpl : AAPotentialValues {
10786 using StateType = PotentialLLVMValuesState;
10787
10788 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10789 : AAPotentialValues(IRP, A) {}
10790
10791 void initialize(Attributor &A) override {
10792 if (A.hasSimplificationCallback(getIRPosition())) {
10793 indicatePessimisticFixpoint();
10794 return;
10795 }
10796 Value *Stripped = getAssociatedValue().stripPointerCasts();
10797 if (isa<Constant>(Stripped) && !isa<ConstantExpr>(Stripped)) {
10798 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10799 getAnchorScope());
10800 indicateOptimisticFixpoint();
10801 return;
10802 }
10803 AAPotentialValues::initialize(A);
10804 }
10805
10806 const std::string getAsStr(Attributor *A) const override {
10807 std::string Str;
10808 llvm::raw_string_ostream OS(Str);
10809 OS << getState();
10810 return Str;
10811 }
10812
10813 template <typename AAType>
10814 static std::optional<Value *> askOtherAA(Attributor &A,
10815 const AbstractAttribute &AA,
10816 const IRPosition &IRP, Type &Ty) {
10818 return &IRP.getAssociatedValue();
10819 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10820 if (!C)
10821 return std::nullopt;
10822 if (*C)
10823 if (auto *CC = AA::getWithType(**C, Ty))
10824 return CC;
10825 return nullptr;
10826 }
10827
10828 virtual void addValue(Attributor &A, StateType &State, Value &V,
10829 const Instruction *CtxI, AA::ValueScope S,
10830 Function *AnchorScope) const {
10831
10832 IRPosition ValIRP = IRPosition::value(V);
10833 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
10834 for (const auto &U : CB->args()) {
10835 if (U.get() != &V)
10836 continue;
10837 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
10838 break;
10839 }
10840 }
10841
10842 Value *VPtr = &V;
10843 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10844 Type &Ty = *getAssociatedType();
10845 std::optional<Value *> SimpleV =
10846 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
10847 if (SimpleV.has_value() && !*SimpleV) {
10848 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10849 *this, ValIRP, DepClassTy::OPTIONAL);
10850 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10851 for (const auto &It : PotentialConstantsAA->getAssumedSet())
10852 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
10853 if (PotentialConstantsAA->undefIsContained())
10854 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
10855 return;
10856 }
10857 }
10858 if (!SimpleV.has_value())
10859 return;
10860
10861 if (*SimpleV)
10862 VPtr = *SimpleV;
10863 }
10864
10865 if (isa<ConstantInt>(VPtr))
10866 CtxI = nullptr;
10867 if (!AA::isValidInScope(*VPtr, AnchorScope))
10869
10870 State.unionAssumed({{*VPtr, CtxI}, S});
10871 }
10872
10873 /// Helper struct to tie a value+context pair together with the scope for
10874 /// which this is the simplified version.
10875 struct ItemInfo {
10876 AA::ValueAndContext I;
10878
10879 bool operator==(const ItemInfo &II) const {
10880 return II.I == I && II.S == S;
10881 };
10882 bool operator<(const ItemInfo &II) const {
10883 return std::tie(I, S) < std::tie(II.I, II.S);
10884 };
10885 };
10886
10887 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
10888 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10889 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
10890 if (!(CS & S))
10891 continue;
10892
10893 bool UsedAssumedInformation = false;
10895 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
10896 UsedAssumedInformation))
10897 return false;
10898
10899 for (auto &It : Values)
10900 ValueScopeMap[It] += CS;
10901 }
10902 for (auto &It : ValueScopeMap)
10903 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
10904 AA::ValueScope(It.second), getAnchorScope());
10905
10906 return true;
10907 }
10908
10909 void giveUpOnIntraprocedural(Attributor &A) {
10910 auto NewS = StateType::getBestState(getState());
10911 for (const auto &It : getAssumedSet()) {
10912 if (It.second == AA::Intraprocedural)
10913 continue;
10914 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
10915 AA::Interprocedural, getAnchorScope());
10916 }
10917 assert(!undefIsContained() && "Undef should be an explicit value!");
10918 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
10919 getAnchorScope());
10920 getState() = NewS;
10921 }
10922
10923 ChangeStatus indicatePessimisticFixpoint() override {
10924 getState() = StateType::getBestState(getState());
10925 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
10926 AAPotentialValues::indicateOptimisticFixpoint();
10927 return ChangeStatus::CHANGED;
10928 }
10929
10930 ChangeStatus updateImpl(Attributor &A) override {
10931 return indicatePessimisticFixpoint();
10932 }
10933
10934 ChangeStatus manifest(Attributor &A) override {
10937 Values.clear();
10938 if (!getAssumedSimplifiedValues(A, Values, S))
10939 continue;
10940 Value &OldV = getAssociatedValue();
10941 if (isa<UndefValue>(OldV))
10942 continue;
10943 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
10944 if (!NewV || NewV == &OldV)
10945 continue;
10946 if (getCtxI() &&
10947 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
10948 continue;
10949 if (A.changeAfterManifest(getIRPosition(), *NewV))
10950 return ChangeStatus::CHANGED;
10951 }
10952 return ChangeStatus::UNCHANGED;
10953 }
10954
10955 bool getAssumedSimplifiedValues(
10956 Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,
10957 AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {
10958 if (!isValidState())
10959 return false;
10960 bool UsedAssumedInformation = false;
10961 for (const auto &It : getAssumedSet())
10962 if (It.second & S) {
10963 if (RecurseForSelectAndPHI && (isa<PHINode>(It.first.getValue()) ||
10964 isa<SelectInst>(It.first.getValue()))) {
10965 if (A.getAssumedSimplifiedValues(
10966 IRPosition::inst(*cast<Instruction>(It.first.getValue())),
10967 this, Values, S, UsedAssumedInformation))
10968 continue;
10969 }
10970 Values.push_back(It.first);
10971 }
10972 assert(!undefIsContained() && "Undef should be an explicit value!");
10973 return true;
10974 }
10975};
10976
10977struct AAPotentialValuesFloating : AAPotentialValuesImpl {
10978 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
10979 : AAPotentialValuesImpl(IRP, A) {}
10980
10981 ChangeStatus updateImpl(Attributor &A) override {
10982 auto AssumedBefore = getAssumed();
10983
10984 genericValueTraversal(A, &getAssociatedValue());
10985
10986 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10987 : ChangeStatus::CHANGED;
10988 }
10989
10990 /// Helper struct to remember which AAIsDead instances we actually used.
10991 struct LivenessInfo {
10992 const AAIsDead *LivenessAA = nullptr;
10993 bool AnyDead = false;
10994 };
10995
10996 /// Check if \p Cmp is a comparison we can simplify.
10997 ///
10998 /// We handle multiple cases, one in which at least one operand is an
10999 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
11000 /// operand. Return true if successful, in that case Worklist will be updated.
11001 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
11002 CmpInst::Predicate Pred, ItemInfo II,
11003 SmallVectorImpl<ItemInfo> &Worklist) {
11004
11005 // Simplify the operands first.
11006 bool UsedAssumedInformation = false;
11007 SmallVector<AA::ValueAndContext> LHSValues, RHSValues;
11008 auto GetSimplifiedValues = [&](Value &V,
11010 if (!A.getAssumedSimplifiedValues(
11011 IRPosition::value(V, getCallBaseContext()), this, Values,
11012 AA::Intraprocedural, UsedAssumedInformation)) {
11013 Values.clear();
11014 Values.push_back(AA::ValueAndContext{V, II.I.getCtxI()});
11015 }
11016 return Values.empty();
11017 };
11018 if (GetSimplifiedValues(*LHS, LHSValues))
11019 return true;
11020 if (GetSimplifiedValues(*RHS, RHSValues))
11021 return true;
11022
11023 LLVMContext &Ctx = LHS->getContext();
11024
11025 InformationCache &InfoCache = A.getInfoCache();
11026 Instruction *CmpI = dyn_cast<Instruction>(&Cmp);
11027 Function *F = CmpI ? CmpI->getFunction() : nullptr;
11028 const auto *DT =
11029 F ? InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F)
11030 : nullptr;
11031 const auto *TLI =
11032 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
11033 auto *AC =
11034 F ? InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F)
11035 : nullptr;
11036
11037 const DataLayout &DL = A.getDataLayout();
11038 SimplifyQuery Q(DL, TLI, DT, AC, CmpI);
11039
11040 auto CheckPair = [&](Value &LHSV, Value &RHSV) {
11041 if (isa<UndefValue>(LHSV) || isa<UndefValue>(RHSV)) {
11042 addValue(A, getState(), *UndefValue::get(Cmp.getType()),
11043 /* CtxI */ nullptr, II.S, getAnchorScope());
11044 return true;
11045 }
11046
11047 // Handle the trivial case first in which we don't even need to think
11048 // about null or non-null.
11049 if (&LHSV == &RHSV &&
11051 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11053 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11054 getAnchorScope());
11055 return true;
11056 }
11057
11058 auto *TypedLHS = AA::getWithType(LHSV, *LHS->getType());
11059 auto *TypedRHS = AA::getWithType(RHSV, *RHS->getType());
11060 if (TypedLHS && TypedRHS) {
11061 Value *NewV = simplifyCmpInst(Pred, TypedLHS, TypedRHS, Q);
11062 if (NewV && NewV != &Cmp) {
11063 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11064 getAnchorScope());
11065 return true;
11066 }
11067 }
11068
11069 // From now on we only handle equalities (==, !=).
11071 return false;
11072
11073 bool LHSIsNull = isa<ConstantPointerNull>(LHSV);
11074 bool RHSIsNull = isa<ConstantPointerNull>(RHSV);
11075 if (!LHSIsNull && !RHSIsNull)
11076 return false;
11077
11078 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
11079 // non-nullptr operand and if we assume it's non-null we can conclude the
11080 // result of the comparison.
11081 assert((LHSIsNull || RHSIsNull) &&
11082 "Expected nullptr versus non-nullptr comparison at this point");
11083
11084 // The index is the operand that we assume is not null.
11085 unsigned PtrIdx = LHSIsNull;
11086 bool IsKnownNonNull;
11087 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
11088 A, this, IRPosition::value(*(PtrIdx ? &RHSV : &LHSV)),
11089 DepClassTy::REQUIRED, IsKnownNonNull);
11090 if (!IsAssumedNonNull)
11091 return false;
11092
11093 // The new value depends on the predicate, true for != and false for ==.
11094 Constant *NewV =
11095 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
11096 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11097 getAnchorScope());
11098 return true;
11099 };
11100
11101 for (auto &LHSValue : LHSValues)
11102 for (auto &RHSValue : RHSValues)
11103 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11104 return false;
11105 return true;
11106 }
11107
11108 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
11109 SmallVectorImpl<ItemInfo> &Worklist) {
11110 const Instruction *CtxI = II.I.getCtxI();
11111 bool UsedAssumedInformation = false;
11112
11113 std::optional<Constant *> C =
11114 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
11115 bool NoValueYet = !C.has_value();
11116 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
11117 return true;
11118 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
11119 if (CI->isZero())
11120 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11121 else
11122 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11123 } else if (&SI == &getAssociatedValue()) {
11124 // We could not simplify the condition, assume both values.
11125 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11126 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11127 } else {
11128 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11129 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
11130 if (!SimpleV.has_value())
11131 return true;
11132 if (*SimpleV) {
11133 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
11134 return true;
11135 }
11136 return false;
11137 }
11138 return true;
11139 }
11140
11141 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
11142 SmallVectorImpl<ItemInfo> &Worklist) {
11143 SmallSetVector<Value *, 4> PotentialCopies;
11144 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11145 bool UsedAssumedInformation = false;
11146 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
11147 PotentialValueOrigins, *this,
11148 UsedAssumedInformation,
11149 /* OnlyExact */ true)) {
11150 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
11151 "loaded values for load instruction "
11152 << LI << "\n");
11153 return false;
11154 }
11155
11156 // Do not simplify loads that are only used in llvm.assume if we cannot also
11157 // remove all stores that may feed into the load. The reason is that the
11158 // assume is probably worth something as long as the stores are around.
11159 InformationCache &InfoCache = A.getInfoCache();
11160 if (InfoCache.isOnlyUsedByAssume(LI)) {
11161 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
11162 if (!I || isa<AssumeInst>(I))
11163 return true;
11164 if (auto *SI = dyn_cast<StoreInst>(I))
11165 return A.isAssumedDead(SI->getOperandUse(0), this,
11166 /* LivenessAA */ nullptr,
11167 UsedAssumedInformation,
11168 /* CheckBBLivenessOnly */ false);
11169 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
11170 UsedAssumedInformation,
11171 /* CheckBBLivenessOnly */ false);
11172 })) {
11173 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
11174 "and we cannot delete all the stores: "
11175 << LI << "\n");
11176 return false;
11177 }
11178 }
11179
11180 // Values have to be dynamically unique or we loose the fact that a
11181 // single llvm::Value might represent two runtime values (e.g.,
11182 // stack locations in different recursive calls).
11183 const Instruction *CtxI = II.I.getCtxI();
11184 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
11185 bool AllLocal = ScopeIsLocal;
11186 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
11187 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
11188 return AA::isDynamicallyUnique(A, *this, *PC);
11189 });
11190 if (!DynamicallyUnique) {
11191 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
11192 "values are dynamically unique: "
11193 << LI << "\n");
11194 return false;
11195 }
11196
11197 for (auto *PotentialCopy : PotentialCopies) {
11198 if (AllLocal) {
11199 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
11200 } else {
11201 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
11202 }
11203 }
11204 if (!AllLocal && ScopeIsLocal)
11205 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
11206 return true;
11207 }
11208
11209 bool handlePHINode(
11210 Attributor &A, PHINode &PHI, ItemInfo II,
11211 SmallVectorImpl<ItemInfo> &Worklist,
11212 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11213 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
11214 LivenessInfo &LI = LivenessAAs[&F];
11215 if (!LI.LivenessAA)
11216 LI.LivenessAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
11217 DepClassTy::NONE);
11218 return LI;
11219 };
11220
11221 if (&PHI == &getAssociatedValue()) {
11222 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
11223 const auto *CI =
11224 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11225 *PHI.getFunction());
11226
11227 CycleRef C;
11228 bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);
11229 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
11230 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
11231 if (LI.LivenessAA &&
11232 LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
11233 LI.AnyDead = true;
11234 continue;
11235 }
11236 Value *V = PHI.getIncomingValue(u);
11237 if (V == &PHI)
11238 continue;
11239
11240 // If the incoming value is not the PHI but an instruction in the same
11241 // cycle we might have multiple versions of it flying around.
11242 if (CyclePHI && isa<Instruction>(V) &&
11243 (!C || CI->contains(C, cast<Instruction>(V)->getParent())))
11244 return false;
11245
11246 Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});
11247 }
11248 return true;
11249 }
11250
11251 bool UsedAssumedInformation = false;
11252 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11253 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
11254 if (!SimpleV.has_value())
11255 return true;
11256 if (!(*SimpleV))
11257 return false;
11258 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
11259 return true;
11260 }
11261
11262 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
11263 /// simplify any operand of the instruction \p I. Return true if successful,
11264 /// in that case Worklist will be updated.
11265 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
11266 SmallVectorImpl<ItemInfo> &Worklist) {
11267 bool SomeSimplified = false;
11268 bool UsedAssumedInformation = false;
11269
11270 SmallVector<Value *, 8> NewOps(I.getNumOperands());
11271 int Idx = 0;
11272 for (Value *Op : I.operands()) {
11273 const auto &SimplifiedOp = A.getAssumedSimplified(
11274 IRPosition::value(*Op, getCallBaseContext()), *this,
11275 UsedAssumedInformation, AA::Intraprocedural);
11276 // If we are not sure about any operand we are not sure about the entire
11277 // instruction, we'll wait.
11278 if (!SimplifiedOp.has_value())
11279 return true;
11280
11281 if (*SimplifiedOp)
11282 NewOps[Idx] = *SimplifiedOp;
11283 else
11284 NewOps[Idx] = Op;
11285
11286 SomeSimplified |= (NewOps[Idx] != Op);
11287 ++Idx;
11288 }
11289
11290 // We won't bother with the InstSimplify interface if we didn't simplify any
11291 // operand ourselves.
11292 if (!SomeSimplified)
11293 return false;
11294
11295 InformationCache &InfoCache = A.getInfoCache();
11296 Function *F = I.getFunction();
11297 const auto *DT =
11298 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
11299 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
11300 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
11301
11302 const DataLayout &DL = I.getDataLayout();
11303 SimplifyQuery Q(DL, TLI, DT, AC, &I);
11304 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);
11305 if (!NewV || NewV == &I)
11306 return false;
11307
11308 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
11309 << *NewV << "\n");
11310 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
11311 return true;
11312 }
11313
11315 Attributor &A, Instruction &I, ItemInfo II,
11316 SmallVectorImpl<ItemInfo> &Worklist,
11317 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11318 if (auto *CI = dyn_cast<CmpInst>(&I))
11319 return handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
11320 CI->getPredicate(), II, Worklist);
11321
11322 switch (I.getOpcode()) {
11323 case Instruction::Select:
11324 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
11325 case Instruction::PHI:
11326 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
11327 case Instruction::Load:
11328 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
11329 default:
11330 return handleGenericInst(A, I, II, Worklist);
11331 };
11332 return false;
11333 }
11334
11335 void genericValueTraversal(Attributor &A, Value *InitialV) {
11336 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11337
11338 SmallSet<ItemInfo, 16> Visited;
11340 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
11341
11342 int Iteration = 0;
11343 do {
11344 ItemInfo II = Worklist.pop_back_val();
11345 Value *V = II.I.getValue();
11346 assert(V);
11347 const Instruction *CtxI = II.I.getCtxI();
11348 AA::ValueScope S = II.S;
11349
11350 // Check if we should process the current value. To prevent endless
11351 // recursion keep a record of the values we followed!
11352 if (!Visited.insert(II).second)
11353 continue;
11354
11355 // Make sure we limit the compile time for complex expressions.
11356 if (Iteration++ >= MaxPotentialValuesIterations) {
11357 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
11358 << Iteration << "!\n");
11359 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11360 continue;
11361 }
11362
11363 // Explicitly look through calls with a "returned" attribute if we do
11364 // not have a pointer as stripPointerCasts only works on them.
11365 Value *NewV = nullptr;
11366 if (V->getType()->isPointerTy()) {
11367 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
11368 } else {
11369 if (auto *CB = dyn_cast<CallBase>(V))
11370 if (auto *Callee =
11372 for (Argument &Arg : Callee->args())
11373 if (Arg.hasReturnedAttr()) {
11374 NewV = CB->getArgOperand(Arg.getArgNo());
11375 break;
11376 }
11377 }
11378 }
11379 if (NewV && NewV != V) {
11380 Worklist.push_back({{*NewV, CtxI}, S});
11381 continue;
11382 }
11383
11384 if (auto *I = dyn_cast<Instruction>(V)) {
11385 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
11386 continue;
11387 }
11388
11389 if (V != InitialV || isa<Argument>(V))
11390 if (recurseForValue(A, IRPosition::value(*V), II.S))
11391 continue;
11392
11393 // If we haven't stripped anything we give up.
11394 if (V == InitialV && CtxI == getCtxI()) {
11395 indicatePessimisticFixpoint();
11396 return;
11397 }
11398
11399 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11400 } while (!Worklist.empty());
11401
11402 // If we actually used liveness information so we have to record a
11403 // dependence.
11404 for (auto &It : LivenessAAs)
11405 if (It.second.AnyDead)
11406 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
11407 }
11408
11409 void trackStatistics() const override {
11410 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
11411 }
11412};
11413
11414struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11415 using Base = AAPotentialValuesImpl;
11416 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11417 : Base(IRP, A) {}
11418
11419 void initialize(Attributor &A) override {
11420 auto &Arg = cast<Argument>(getAssociatedValue());
11422 indicatePessimisticFixpoint();
11423 }
11424
11425 ChangeStatus updateImpl(Attributor &A) override {
11426 auto AssumedBefore = getAssumed();
11427
11428 unsigned ArgNo = getCalleeArgNo();
11429
11430 bool UsedAssumedInformation = false;
11432 auto CallSitePred = [&](AbstractCallSite ACS) {
11433 const auto CSArgIRP = IRPosition::callsite_argument(ACS, ArgNo);
11434 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11435 return false;
11436
11437 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11439 UsedAssumedInformation))
11440 return false;
11441
11442 return isValidState();
11443 };
11444
11445 if (!A.checkForAllCallSites(CallSitePred, *this,
11446 /* RequireAllCallSites */ true,
11447 UsedAssumedInformation))
11448 return indicatePessimisticFixpoint();
11449
11450 Function *Fn = getAssociatedFunction();
11451 bool AnyNonLocal = false;
11452 for (auto &It : Values) {
11453 if (isa<Constant>(It.getValue())) {
11454 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11455 getAnchorScope());
11456 continue;
11457 }
11458 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11459 return indicatePessimisticFixpoint();
11460
11461 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11462 if (Arg->getParent() == Fn) {
11463 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11464 getAnchorScope());
11465 continue;
11466 }
11467 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11468 getAnchorScope());
11469 AnyNonLocal = true;
11470 }
11471 assert(!undefIsContained() && "Undef should be an explicit value!");
11472 if (AnyNonLocal)
11473 giveUpOnIntraprocedural(A);
11474
11475 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11476 : ChangeStatus::CHANGED;
11477 }
11478
11479 void trackStatistics() const override {
11480 STATS_DECLTRACK_ARG_ATTR(potential_values)
11481 }
11482};
11483
11484struct AAPotentialValuesReturned : public AAPotentialValuesFloating {
11485 using Base = AAPotentialValuesFloating;
11486 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11487 : Base(IRP, A) {}
11488
11489 void initialize(Attributor &A) override {
11490 Function *F = getAssociatedFunction();
11491 if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {
11492 indicatePessimisticFixpoint();
11493 return;
11494 }
11495
11496 for (Argument &Arg : F->args())
11497 if (Arg.hasReturnedAttr()) {
11498 addValue(A, getState(), Arg, nullptr, AA::AnyScope, F);
11499 ReturnedArg = &Arg;
11500 break;
11501 }
11502 if (!A.isFunctionIPOAmendable(*F) ||
11503 A.hasSimplificationCallback(getIRPosition())) {
11504 if (!ReturnedArg)
11505 indicatePessimisticFixpoint();
11506 else
11507 indicateOptimisticFixpoint();
11508 }
11509 }
11510
11511 ChangeStatus updateImpl(Attributor &A) override {
11512 auto AssumedBefore = getAssumed();
11513 bool UsedAssumedInformation = false;
11514
11516 Function *AnchorScope = getAnchorScope();
11517 auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,
11518 bool AddValues) {
11520 Values.clear();
11521 if (!A.getAssumedSimplifiedValues(IRPosition::value(V), this, Values, S,
11522 UsedAssumedInformation,
11523 /* RecurseForSelectAndPHI */ true))
11524 return false;
11525 if (!AddValues)
11526 continue;
11527
11528 bool AllInterAreIntra = false;
11529 if (S == AA::Interprocedural)
11530 AllInterAreIntra =
11531 llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) {
11532 return AA::isValidInScope(*VAC.getValue(), AnchorScope);
11533 });
11534
11535 for (const AA::ValueAndContext &VAC : Values) {
11536 addValue(A, getState(), *VAC.getValue(),
11537 VAC.getCtxI() ? VAC.getCtxI() : CtxI,
11538 AllInterAreIntra ? AA::AnyScope : S, AnchorScope);
11539 }
11540 if (AllInterAreIntra)
11541 break;
11542 }
11543 return true;
11544 };
11545
11546 if (ReturnedArg) {
11547 HandleReturnedValue(*ReturnedArg, nullptr, true);
11548 } else {
11549 auto RetInstPred = [&](Instruction &RetI) {
11550 bool AddValues = true;
11551 if (isa<PHINode>(RetI.getOperand(0)) ||
11552 isa<SelectInst>(RetI.getOperand(0))) {
11553 addValue(A, getState(), *RetI.getOperand(0), &RetI, AA::AnyScope,
11554 AnchorScope);
11555 AddValues = false;
11556 }
11557 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11558 };
11559
11560 if (!A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11561 UsedAssumedInformation,
11562 /* CheckBBLivenessOnly */ true))
11563 return indicatePessimisticFixpoint();
11564 }
11565
11566 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11567 : ChangeStatus::CHANGED;
11568 }
11569
11570 ChangeStatus manifest(Attributor &A) override {
11571 if (ReturnedArg)
11572 return ChangeStatus::UNCHANGED;
11574 if (!getAssumedSimplifiedValues(A, Values, AA::ValueScope::Intraprocedural,
11575 /* RecurseForSelectAndPHI */ true))
11576 return ChangeStatus::UNCHANGED;
11577 Value *NewVal = getSingleValue(A, *this, getIRPosition(), Values);
11578 if (!NewVal)
11579 return ChangeStatus::UNCHANGED;
11580
11581 ChangeStatus Changed = ChangeStatus::UNCHANGED;
11582 if (auto *Arg = dyn_cast<Argument>(NewVal)) {
11583 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
11584 "Number of function with unique return");
11585 Changed |= A.manifestAttrs(
11587 {Attribute::get(Arg->getContext(), Attribute::Returned)});
11588 STATS_DECLTRACK_ARG_ATTR(returned);
11589 }
11590
11591 auto RetInstPred = [&](Instruction &RetI) {
11592 Value *RetOp = RetI.getOperand(0);
11593 if (isa<UndefValue>(RetOp) || RetOp == NewVal)
11594 return true;
11595 if (AA::isValidAtPosition({*NewVal, RetI}, A.getInfoCache()))
11596 if (A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11597 Changed = ChangeStatus::CHANGED;
11598 return true;
11599 };
11600 bool UsedAssumedInformation = false;
11601 (void)A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11602 UsedAssumedInformation,
11603 /* CheckBBLivenessOnly */ true);
11604 return Changed;
11605 }
11606
11607 ChangeStatus indicatePessimisticFixpoint() override {
11608 return AAPotentialValues::indicatePessimisticFixpoint();
11609 }
11610
11611 void trackStatistics() const override{
11612 STATS_DECLTRACK_FNRET_ATTR(potential_values)}
11613
11614 /// The argumented with an existing `returned` attribute.
11615 Argument *ReturnedArg = nullptr;
11616};
11617
11618struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11619 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11620 : AAPotentialValuesImpl(IRP, A) {}
11621
11622 ChangeStatus updateImpl(Attributor &A) override {
11623 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
11624 "not be called");
11625 }
11626
11627 void trackStatistics() const override {
11628 STATS_DECLTRACK_FN_ATTR(potential_values)
11629 }
11630};
11631
11632struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11633 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11634 : AAPotentialValuesFunction(IRP, A) {}
11635
11636 void trackStatistics() const override {
11637 STATS_DECLTRACK_CS_ATTR(potential_values)
11638 }
11639};
11640
11641struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11642 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11643 : AAPotentialValuesImpl(IRP, A) {}
11644
11645 ChangeStatus updateImpl(Attributor &A) override {
11646 auto AssumedBefore = getAssumed();
11647
11648 Function *Callee = getAssociatedFunction();
11649 if (!Callee)
11650 return indicatePessimisticFixpoint();
11651
11652 bool UsedAssumedInformation = false;
11653 auto *CB = cast<CallBase>(getCtxI());
11654 if (CB->isMustTailCall() &&
11655 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11656 UsedAssumedInformation))
11657 return indicatePessimisticFixpoint();
11658
11659 Function *Caller = CB->getCaller();
11660
11661 auto AddScope = [&](AA::ValueScope S) {
11663 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11664 Values, S, UsedAssumedInformation))
11665 return false;
11666
11667 for (auto &It : Values) {
11668 Value *V = It.getValue();
11669 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11670 V, *CB, *this, UsedAssumedInformation);
11671 if (!CallerV.has_value()) {
11672 // Nothing to do as long as no value was determined.
11673 continue;
11674 }
11675 V = *CallerV ? *CallerV : V;
11676 if (*CallerV && AA::isDynamicallyUnique(A, *this, *V)) {
11677 if (recurseForValue(A, IRPosition::value(*V), S))
11678 continue;
11679 }
11680 if (S == AA::Intraprocedural && !AA::isValidInScope(*V, Caller)) {
11681 giveUpOnIntraprocedural(A);
11682 return true;
11683 }
11684 addValue(A, getState(), *V, CB, S, getAnchorScope());
11685 }
11686 return true;
11687 };
11688 if (!AddScope(AA::Intraprocedural))
11689 return indicatePessimisticFixpoint();
11690 if (!AddScope(AA::Interprocedural))
11691 return indicatePessimisticFixpoint();
11692 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11693 : ChangeStatus::CHANGED;
11694 }
11695
11696 ChangeStatus indicatePessimisticFixpoint() override {
11697 return AAPotentialValues::indicatePessimisticFixpoint();
11698 }
11699
11700 void trackStatistics() const override {
11701 STATS_DECLTRACK_CSRET_ATTR(potential_values)
11702 }
11703};
11704
11705struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11706 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11707 : AAPotentialValuesFloating(IRP, A) {}
11708
11709 void trackStatistics() const override {
11710 STATS_DECLTRACK_CSARG_ATTR(potential_values)
11711 }
11712};
11713} // namespace
11714
11715/// ---------------------- Assumption Propagation ------------------------------
11716namespace {
11717struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11718 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11719 const DenseSet<StringRef> &Known)
11720 : AAAssumptionInfo(IRP, A, Known) {}
11721
11722 ChangeStatus manifest(Attributor &A) override {
11723 // Don't manifest a universal set if it somehow made it here.
11724 if (getKnown().isUniversal())
11725 return ChangeStatus::UNCHANGED;
11726
11727 const IRPosition &IRP = getIRPosition();
11728 SmallVector<StringRef, 0> Set(getAssumed().getSet().begin(),
11729 getAssumed().getSet().end());
11730 llvm::sort(Set);
11731 return A.manifestAttrs(IRP,
11732 Attribute::get(IRP.getAnchorValue().getContext(),
11734 llvm::join(Set, ",")),
11735 /*ForceReplace=*/true);
11736 }
11737
11738 bool hasAssumption(const StringRef Assumption) const override {
11739 return isValidState() && setContains(Assumption);
11740 }
11741
11742 const std::string getAsStr(Attributor *A) const override {
11743 const SetContents &Known = getKnown();
11744 const SetContents &Assumed = getAssumed();
11745
11746 SmallVector<StringRef, 0> Set(Known.getSet().begin(), Known.getSet().end());
11747 llvm::sort(Set);
11748 const std::string KnownStr = llvm::join(Set, ",");
11749
11750 std::string AssumedStr = "Universal";
11751 if (!Assumed.isUniversal()) {
11752 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11753 AssumedStr = llvm::join(Set, ",");
11754 }
11755 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11756 }
11757};
11758
11759/// Propagates assumption information from parent functions to all of their
11760/// successors. An assumption can be propagated if the containing function
11761/// dominates the called function.
11762///
11763/// We start with a "known" set of assumptions already valid for the associated
11764/// function and an "assumed" set that initially contains all possible
11765/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11766/// contents as concrete values are known. The concrete values are seeded by the
11767/// first nodes that are either entries into the call graph, or contains no
11768/// assumptions. Each node is updated as the intersection of the assumed state
11769/// with all of its predecessors.
11770struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11771 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11772 : AAAssumptionInfoImpl(IRP, A,
11773 getAssumptions(*IRP.getAssociatedFunction())) {}
11774
11775 ChangeStatus updateImpl(Attributor &A) override {
11776 bool Changed = false;
11777
11778 auto CallSitePred = [&](AbstractCallSite ACS) {
11779 const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11780 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11781 DepClassTy::REQUIRED);
11782 if (!AssumptionAA)
11783 return false;
11784 // Get the set of assumptions shared by all of this function's callers.
11785 Changed |= getIntersection(AssumptionAA->getAssumed());
11786 return !getAssumed().empty() || !getKnown().empty();
11787 };
11788
11789 bool UsedAssumedInformation = false;
11790 // Get the intersection of all assumptions held by this node's predecessors.
11791 // If we don't know all the call sites then this is either an entry into the
11792 // call graph or an empty node. This node is known to only contain its own
11793 // assumptions and can be propagated to its successors.
11794 if (!A.checkForAllCallSites(CallSitePred, *this, true,
11795 UsedAssumedInformation))
11796 return indicatePessimisticFixpoint();
11797
11798 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11799 }
11800
11801 void trackStatistics() const override {}
11802};
11803
11804/// Assumption Info defined for call sites.
11805struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11806
11807 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11808 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11809
11810 void initialize(Attributor &A) override {
11811 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11812 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11813 }
11814
11815 ChangeStatus updateImpl(Attributor &A) override {
11816 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11817 auto *AssumptionAA =
11818 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11819 if (!AssumptionAA)
11820 return indicatePessimisticFixpoint();
11821 bool Changed = getIntersection(AssumptionAA->getAssumed());
11822 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11823 }
11824
11825 void trackStatistics() const override {}
11826
11827private:
11828 /// Helper to initialized the known set as all the assumptions this call and
11829 /// the callee contain.
11830 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11831 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
11832 auto Assumptions = getAssumptions(CB);
11833 if (const Function *F = CB.getCaller())
11834 set_union(Assumptions, getAssumptions(*F));
11835 if (Function *F = IRP.getAssociatedFunction())
11836 set_union(Assumptions, getAssumptions(*F));
11837 return Assumptions;
11838 }
11839};
11840} // namespace
11841
11843 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11844 A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
11845}
11846
11848
11849/// ------------------------ UnderlyingObjects ---------------------------------
11850
11851namespace {
11852struct AAUnderlyingObjectsImpl
11853 : StateWrapper<BooleanState, AAUnderlyingObjects> {
11855 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
11856
11857 const std::string getAsStr(Attributor *A) const override {
11858 if (!isValidState())
11859 return "<invalid>";
11860 std::string Str;
11862 OS << "underlying objects: inter " << InterAssumedUnderlyingObjects.size()
11863 << " objects, intra " << IntraAssumedUnderlyingObjects.size()
11864 << " objects.\n";
11865 if (!InterAssumedUnderlyingObjects.empty()) {
11866 OS << "inter objects:\n";
11867 for (auto *Obj : InterAssumedUnderlyingObjects)
11868 OS << *Obj << '\n';
11869 }
11870 if (!IntraAssumedUnderlyingObjects.empty()) {
11871 OS << "intra objects:\n";
11872 for (auto *Obj : IntraAssumedUnderlyingObjects)
11873 OS << *Obj << '\n';
11874 }
11875 return Str;
11876 }
11877
11878 void trackStatistics() const override {}
11879
11880 ChangeStatus updateImpl(Attributor &A) override {
11881 auto &Ptr = getAssociatedValue();
11882
11883 bool UsedAssumedInformation = false;
11884 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11886 SmallPtrSet<Value *, 8> SeenObjects;
11888
11889 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
11890 Scope, UsedAssumedInformation))
11891 return UnderlyingObjects.insert(&Ptr);
11892
11893 bool Changed = false;
11894
11895 for (unsigned I = 0; I < Values.size(); ++I) {
11896 auto &VAC = Values[I];
11897 auto *Obj = VAC.getValue();
11898 Value *UO = getUnderlyingObject(Obj);
11899 if (!SeenObjects.insert(UO ? UO : Obj).second)
11900 continue;
11901 if (UO && UO != Obj) {
11902 if (isa<AllocaInst>(UO) || isa<GlobalValue>(UO)) {
11903 Changed |= UnderlyingObjects.insert(UO);
11904 continue;
11905 }
11906
11907 const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(
11908 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
11909 auto Pred = [&](Value &V) {
11910 if (&V == UO)
11911 Changed |= UnderlyingObjects.insert(UO);
11912 else
11913 Values.emplace_back(V, nullptr);
11914 return true;
11915 };
11916
11917 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
11919 "The forall call should not return false at this position");
11920 UsedAssumedInformation |= !OtherAA->getState().isAtFixpoint();
11921 continue;
11922 }
11923
11924 if (isa<SelectInst>(Obj)) {
11925 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope,
11926 UsedAssumedInformation);
11927 continue;
11928 }
11929 if (auto *PHI = dyn_cast<PHINode>(Obj)) {
11930 // Explicitly look through PHIs as we do not care about dynamically
11931 // uniqueness.
11932 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
11933 Changed |=
11934 handleIndirect(A, *PHI->getIncomingValue(u), UnderlyingObjects,
11935 Scope, UsedAssumedInformation);
11936 }
11937 continue;
11938 }
11939
11940 Changed |= UnderlyingObjects.insert(Obj);
11941 }
11942
11943 return Changed;
11944 };
11945
11946 bool Changed = false;
11947 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
11948 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
11949 if (!UsedAssumedInformation)
11950 indicateOptimisticFixpoint();
11951 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11952 }
11953
11954 bool forallUnderlyingObjects(
11955 function_ref<bool(Value &)> Pred,
11956 AA::ValueScope Scope = AA::Interprocedural) const override {
11957 if (!isValidState())
11958 return Pred(getAssociatedValue());
11959
11960 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
11961 ? IntraAssumedUnderlyingObjects
11962 : InterAssumedUnderlyingObjects;
11963 for (Value *Obj : AssumedUnderlyingObjects)
11964 if (!Pred(*Obj))
11965 return false;
11966
11967 return true;
11968 }
11969
11970private:
11971 /// Handle the case where the value is not the actual underlying value, such
11972 /// as a phi node or a select instruction.
11973 bool handleIndirect(Attributor &A, Value &V,
11974 SmallSetVector<Value *, 8> &UnderlyingObjects,
11975 AA::ValueScope Scope, bool &UsedAssumedInformation) {
11976 bool Changed = false;
11977 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
11978 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
11979 auto Pred = [&](Value &V) {
11980 Changed |= UnderlyingObjects.insert(&V);
11981 return true;
11982 };
11983 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
11985 "The forall call should not return false at this position");
11986 UsedAssumedInformation |= !AA->getState().isAtFixpoint();
11987 return Changed;
11988 }
11989
11990 /// All the underlying objects collected so far via intra procedural scope.
11991 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11992 /// All the underlying objects collected so far via inter procedural scope.
11993 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11994};
11995
11996struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
11997 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
11998 : AAUnderlyingObjectsImpl(IRP, A) {}
11999};
12000
12001struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12002 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
12003 : AAUnderlyingObjectsImpl(IRP, A) {}
12004};
12005
12006struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12007 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
12008 : AAUnderlyingObjectsImpl(IRP, A) {}
12009};
12010
12011struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12012 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
12013 : AAUnderlyingObjectsImpl(IRP, A) {}
12014};
12015
12016struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12017 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
12018 : AAUnderlyingObjectsImpl(IRP, A) {}
12019};
12020
12021struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12022 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
12023 : AAUnderlyingObjectsImpl(IRP, A) {}
12024};
12025
12026struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12027 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
12028 : AAUnderlyingObjectsImpl(IRP, A) {}
12029};
12030} // namespace
12031
12032/// ------------------------ Global Value Info -------------------------------
12033namespace {
12034struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
12035 AAGlobalValueInfoFloating(const IRPosition &IRP, Attributor &A)
12036 : AAGlobalValueInfo(IRP, A) {}
12037
12038 void initialize(Attributor &A) override {}
12039
12040 bool checkUse(Attributor &A, const Use &U, bool &Follow,
12041 SmallVectorImpl<const Value *> &Worklist) {
12042 Instruction *UInst = dyn_cast<Instruction>(U.getUser());
12043 if (!UInst) {
12044 // Outside a closed world, code outside the module can read an
12045 // externally visible global, so the value escapes through it.
12046 if (auto *GV = dyn_cast<GlobalValue>(U.getUser()))
12047 if (!GV->hasLocalLinkage() && !A.isClosedWorldModule())
12048 return false;
12049 Follow = true;
12050 return true;
12051 }
12052
12053 LLVM_DEBUG(dbgs() << "[AAGlobalValueInfo] Check use: " << *U.get() << " in "
12054 << *UInst << "\n");
12055
12056 if (auto *Cmp = dyn_cast<ICmpInst>(U.getUser())) {
12057 int Idx = &Cmp->getOperandUse(0) == &U;
12058 if (isa<Constant>(Cmp->getOperand(Idx)))
12059 return true;
12060 return U == &getAnchorValue();
12061 }
12062
12063 // Explicitly catch return instructions.
12064 if (isa<ReturnInst>(UInst)) {
12065 auto CallSitePred = [&](AbstractCallSite ACS) {
12066 Worklist.push_back(ACS.getInstruction());
12067 return true;
12068 };
12069 bool UsedAssumedInformation = false;
12070 // TODO: We should traverse the uses or add a "non-call-site" CB.
12071 if (!A.checkForAllCallSites(CallSitePred, *UInst->getFunction(),
12072 /*RequireAllCallSites=*/true, this,
12073 UsedAssumedInformation))
12074 return false;
12075 return true;
12076 }
12077
12078 // For now we only use special logic for call sites. However, the tracker
12079 // itself knows about a lot of other non-capturing cases already.
12080 auto *CB = dyn_cast<CallBase>(UInst);
12081 if (!CB)
12082 return false;
12083 // Direct calls are OK uses.
12084 if (CB->isCallee(&U))
12085 return true;
12086 // Non-argument uses are scary.
12087 if (!CB->isArgOperand(&U))
12088 return false;
12089 // TODO: Iterate callees.
12090 auto *Fn = dyn_cast<Function>(CB->getCalledOperand());
12091 if (!Fn || !A.isFunctionIPOAmendable(*Fn))
12092 return false;
12093
12094 unsigned ArgNo = CB->getArgOperandNo(&U);
12095 Worklist.push_back(Fn->getArg(ArgNo));
12096 return true;
12097 }
12098
12099 ChangeStatus updateImpl(Attributor &A) override {
12100 unsigned NumUsesBefore = Uses.size();
12101
12102 SmallPtrSet<const Value *, 8> Visited;
12104 Worklist.push_back(&getAnchorValue());
12105
12106 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
12107 Uses.insert(&U);
12108 // TODO(captures): Make this more precise.
12109 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
12110 if (CI.isPassthrough()) {
12111 Follow = true;
12112 return true;
12113 }
12114 return checkUse(A, U, Follow, Worklist);
12115 };
12116 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
12117 Uses.insert(&OldU);
12118 return true;
12119 };
12120
12121 while (!Worklist.empty()) {
12122 const Value *V = Worklist.pop_back_val();
12123 if (!Visited.insert(V).second)
12124 continue;
12125 if (!A.checkForAllUses(UsePred, *this, *V,
12126 /* CheckBBLivenessOnly */ true,
12127 DepClassTy::OPTIONAL,
12128 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
12129 return indicatePessimisticFixpoint();
12130 }
12131 }
12132
12133 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12134 : ChangeStatus::CHANGED;
12135 }
12136
12137 bool isPotentialUse(const Use &U) const override {
12138 return !isValidState() || Uses.contains(&U);
12139 }
12140
12141 ChangeStatus manifest(Attributor &A) override {
12142 return ChangeStatus::UNCHANGED;
12143 }
12144
12145 const std::string getAsStr(Attributor *A) const override {
12146 return "[" + std::to_string(Uses.size()) + " uses]";
12147 }
12148
12149 void trackStatistics() const override {
12150 STATS_DECLTRACK_FLOATING_ATTR(GlobalValuesTracked);
12151 }
12152
12153private:
12154 /// Set of (transitive) uses of this GlobalValue.
12155 SmallPtrSet<const Use *, 8> Uses;
12156};
12157} // namespace
12158
12159/// ------------------------ Indirect Call Info -------------------------------
12160namespace {
12161struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12162 AAIndirectCallInfoCallSite(const IRPosition &IRP, Attributor &A)
12163 : AAIndirectCallInfo(IRP, A) {}
12164
12165 void initialize(Attributor &A) override {
12166 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12167 if (!MD && !A.isClosedWorldModule())
12168 return;
12169
12170 if (MD) {
12171 for (const auto &Op : MD->operands())
12173 PotentialCallees.insert(Callee);
12174 } else if (A.isClosedWorldModule()) {
12175 ArrayRef<Function *> IndirectlyCallableFunctions =
12176 A.getInfoCache().getIndirectlyCallableFunctions(A);
12177 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12178 }
12179
12180 if (PotentialCallees.empty())
12181 indicateOptimisticFixpoint();
12182 }
12183
12184 ChangeStatus updateImpl(Attributor &A) override {
12185 CallBase *CB = cast<CallBase>(getCtxI());
12186 const Use &CalleeUse = CB->getCalledOperandUse();
12187 Value *FP = CB->getCalledOperand();
12188
12189 SmallSetVector<Function *, 4> AssumedCalleesNow;
12190 bool AllCalleesKnownNow = AllCalleesKnown;
12191
12192 auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,
12193 bool &UsedAssumedInformation) {
12194 const auto *GIAA = A.getAAFor<AAGlobalValueInfo>(
12195 *this, IRPosition::value(PotentialCallee), DepClassTy::OPTIONAL);
12196 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12197 return true;
12198 UsedAssumedInformation = !GIAA->isAtFixpoint();
12199 return false;
12200 };
12201
12202 auto AddPotentialCallees = [&]() {
12203 for (auto *PotentialCallee : PotentialCallees) {
12204 bool UsedAssumedInformation = false;
12205 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12206 AssumedCalleesNow.insert(PotentialCallee);
12207 }
12208 };
12209
12210 // Use simplification to find potential callees, if !callees was present,
12211 // fallback to that set if necessary.
12212 bool UsedAssumedInformation = false;
12214 if (!A.getAssumedSimplifiedValues(IRPosition::value(*FP), this, Values,
12215 AA::ValueScope::AnyScope,
12216 UsedAssumedInformation)) {
12217 if (PotentialCallees.empty())
12218 return indicatePessimisticFixpoint();
12219 AddPotentialCallees();
12220 }
12221
12222 // Try to find a reason for \p Fn not to be a potential callee. If none was
12223 // found, add it to the assumed callees set.
12224 auto CheckPotentialCallee = [&](Function &Fn) {
12225 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12226 return false;
12227
12228 auto &CachedResult = FilterResults[&Fn];
12229 if (CachedResult.has_value())
12230 return CachedResult.value();
12231
12232 bool UsedAssumedInformation = false;
12233 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12234 if (!UsedAssumedInformation)
12235 CachedResult = false;
12236 return false;
12237 }
12238
12239 int NumFnArgs = Fn.arg_size();
12240 int NumCBArgs = CB->arg_size();
12241
12242 // Check if any excess argument (which we fill up with poison) is known to
12243 // be UB on undef.
12244 for (int I = NumCBArgs; I < NumFnArgs; ++I) {
12245 bool IsKnown = false;
12247 A, this, IRPosition::argument(*Fn.getArg(I)),
12248 DepClassTy::OPTIONAL, IsKnown)) {
12249 if (IsKnown)
12250 CachedResult = false;
12251 return false;
12252 }
12253 }
12254
12255 CachedResult = true;
12256 return true;
12257 };
12258
12259 // Check simplification result, prune known UB callees, also restrict it to
12260 // the !callees set, if present.
12261 for (auto &VAC : Values) {
12262 if (isa<UndefValue>(VAC.getValue()))
12263 continue;
12265 VAC.getValue()->getType()->getPointerAddressSpace() == 0)
12266 continue;
12267 // TODO: Check for known UB, e.g., poison + noundef.
12268 if (auto *VACFn = dyn_cast<Function>(VAC.getValue())) {
12269 if (CheckPotentialCallee(*VACFn))
12270 AssumedCalleesNow.insert(VACFn);
12271 continue;
12272 }
12273 if (!PotentialCallees.empty()) {
12274 AddPotentialCallees();
12275 break;
12276 }
12277 AllCalleesKnownNow = false;
12278 }
12279
12280 if (AssumedCalleesNow == AssumedCallees &&
12281 AllCalleesKnown == AllCalleesKnownNow)
12282 return ChangeStatus::UNCHANGED;
12283
12284 std::swap(AssumedCallees, AssumedCalleesNow);
12285 AllCalleesKnown = AllCalleesKnownNow;
12286 return ChangeStatus::CHANGED;
12287 }
12288
12289 ChangeStatus manifest(Attributor &A) override {
12290 // If we can't specialize at all, give up now.
12291 if (!AllCalleesKnown && AssumedCallees.empty())
12292 return ChangeStatus::UNCHANGED;
12293
12294 CallBase *CB = cast<CallBase>(getCtxI());
12295 bool UsedAssumedInformation = false;
12296 if (A.isAssumedDead(*CB, this, /*LivenessAA=*/nullptr,
12297 UsedAssumedInformation))
12298 return ChangeStatus::UNCHANGED;
12299
12300 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12301 unsigned ProgramAS = CB->getDataLayout().getProgramAddressSpace();
12302 Value *FP = CB->getCalledOperand();
12303 if (FP->getType()->getPointerAddressSpace() != ProgramAS)
12304 FP = new AddrSpaceCastInst(
12305 FP, PointerType::get(FP->getContext(), ProgramAS),
12306 FP->getName() + ".as" + Twine(ProgramAS), CB->getIterator());
12307
12308 bool CBIsVoid = CB->getType()->isVoidTy();
12310 FunctionType *CSFT = CB->getFunctionType();
12311 SmallVector<Value *> CSArgs(CB->args());
12312
12313 // If we know all callees and there are none, the call site is (effectively)
12314 // dead (or UB).
12315 if (AssumedCallees.empty()) {
12316 assert(AllCalleesKnown &&
12317 "Expected all callees to be known if there are none.");
12318 A.changeToUnreachableAfterManifest(CB);
12319 return ChangeStatus::CHANGED;
12320 }
12321
12322 // Special handling for the single callee case.
12323 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12324 auto *NewCallee = AssumedCallees.front();
12325 if (isLegalToPromote(*CB, NewCallee)) {
12326 promoteCall(*CB, NewCallee, nullptr);
12327 NumIndirectCallsPromoted++;
12328 return ChangeStatus::CHANGED;
12329 }
12330 Instruction *NewCall =
12331 CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12332 CB->getName(), CB->getIterator());
12333 if (!CBIsVoid)
12334 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *NewCall);
12335 A.deleteAfterManifest(*CB);
12336 return ChangeStatus::CHANGED;
12337 }
12338
12339 // For each potential value we create a conditional
12340 //
12341 // ```
12342 // if (ptr == value) value(args);
12343 // else ...
12344 // ```
12345 //
12346 bool SpecializedForAnyCallees = false;
12347 bool SpecializedForAllCallees = AllCalleesKnown;
12348 ICmpInst *LastCmp = nullptr;
12349 SmallVector<Function *, 8> SkippedAssumedCallees;
12351 for (Function *NewCallee : AssumedCallees) {
12352 if (!A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,
12353 AssumedCallees.size())) {
12354 SkippedAssumedCallees.push_back(NewCallee);
12355 SpecializedForAllCallees = false;
12356 continue;
12357 }
12358 SpecializedForAnyCallees = true;
12359
12360 LastCmp = new ICmpInst(IP, llvm::CmpInst::ICMP_EQ, FP, NewCallee);
12361 Instruction *ThenTI =
12362 SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false);
12363 BasicBlock *CBBB = CB->getParent();
12364 A.registerManifestAddedBasicBlock(*ThenTI->getParent());
12365 A.registerManifestAddedBasicBlock(*IP->getParent());
12366 auto *SplitTI = cast<CondBrInst>(LastCmp->getNextNode());
12367 BasicBlock *ElseBB;
12368 if (&*IP == CB) {
12369 ElseBB = BasicBlock::Create(ThenTI->getContext(), "",
12370 ThenTI->getFunction(), CBBB);
12371 A.registerManifestAddedBasicBlock(*ElseBB);
12372 IP = UncondBrInst::Create(CBBB, ElseBB)->getIterator();
12373 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12374 } else {
12375 ElseBB = IP->getParent();
12376 ThenTI->replaceUsesOfWith(ElseBB, CBBB);
12377 }
12378 CastInst *RetBC = nullptr;
12379 CallInst *NewCall = nullptr;
12380 if (isLegalToPromote(*CB, NewCallee)) {
12381 auto *CBClone = cast<CallBase>(CB->clone());
12382 CBClone->insertBefore(ThenTI->getIterator());
12383 NewCall = &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));
12384 NumIndirectCallsPromoted++;
12385 } else {
12386 NewCall = CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12387 CB->getName(), ThenTI->getIterator());
12388 }
12389 NewCalls.push_back({NewCall, RetBC});
12390 }
12391
12392 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12393 if (!AllCalleesKnown)
12394 return ChangeStatus::UNCHANGED;
12395 MDBuilder MDB(IndirectCB.getContext());
12396 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12397 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12398 return ChangeStatus::CHANGED;
12399 };
12400
12401 if (!SpecializedForAnyCallees)
12402 return AttachCalleeMetadata(*CB);
12403
12404 // Check if we need the fallback indirect call still.
12405 if (SpecializedForAllCallees) {
12407 LastCmp->eraseFromParent();
12408 new UnreachableInst(IP->getContext(), IP);
12409 IP->eraseFromParent();
12410 } else {
12411 auto *CBClone = cast<CallInst>(CB->clone());
12412 CBClone->setName(CB->getName());
12413 CBClone->insertBefore(*IP->getParent(), IP);
12414 NewCalls.push_back({CBClone, nullptr});
12415 AttachCalleeMetadata(*CBClone);
12416 }
12417
12418 // Check if we need a PHI to merge the results.
12419 if (!CBIsVoid) {
12420 auto *PHI = PHINode::Create(CB->getType(), NewCalls.size(),
12421 CB->getName() + ".phi",
12422 CB->getParent()->getFirstInsertionPt());
12423 for (auto &It : NewCalls) {
12424 CallBase *NewCall = It.first;
12425 Instruction *CallRet = It.second ? It.second : It.first;
12426 if (CallRet->getType() == CB->getType())
12427 PHI->addIncoming(CallRet, CallRet->getParent());
12428 else if (NewCall->getType()->isVoidTy())
12429 PHI->addIncoming(PoisonValue::get(CB->getType()),
12430 NewCall->getParent());
12431 else
12432 llvm_unreachable("Call return should match or be void!");
12433 }
12434 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *PHI);
12435 }
12436
12437 A.deleteAfterManifest(*CB);
12438 Changed = ChangeStatus::CHANGED;
12439
12440 return Changed;
12441 }
12442
12443 const std::string getAsStr(Attributor *A) const override {
12444 return std::string(AllCalleesKnown ? "eliminate" : "specialize") +
12445 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12446 " functions";
12447 }
12448
12449 void trackStatistics() const override {
12450 if (AllCalleesKnown) {
12452 Eliminated, CallSites,
12453 "Number of indirect call sites eliminated via specialization")
12454 } else {
12455 STATS_DECLTRACK(Specialized, CallSites,
12456 "Number of indirect call sites specialized")
12457 }
12458 }
12459
12460 bool foreachCallee(function_ref<bool(Function *)> CB) const override {
12461 return isValidState() && AllCalleesKnown && all_of(AssumedCallees, CB);
12462 }
12463
12464private:
12465 /// Map to remember filter results.
12466 DenseMap<Function *, std::optional<bool>> FilterResults;
12467
12468 /// If the !callee metadata was present, this set will contain all potential
12469 /// callees (superset).
12470 SmallSetVector<Function *, 4> PotentialCallees;
12471
12472 /// This set contains all currently assumed calllees, which might grow over
12473 /// time.
12474 SmallSetVector<Function *, 4> AssumedCallees;
12475
12476 /// Flag to indicate if all possible callees are in the AssumedCallees set or
12477 /// if there could be others.
12478 bool AllCalleesKnown = true;
12479};
12480} // namespace
12481
12482/// --------------------- Invariant Load Pointer -------------------------------
12483namespace {
12484
12485struct AAInvariantLoadPointerImpl
12486 : public StateWrapper<BitIntegerState<uint8_t, 15>,
12487 AAInvariantLoadPointer> {
12488
12489 enum {
12490 // pointer does not alias within the bounds of the function
12491 IS_NOALIAS = 1 << 0,
12492 // pointer is not involved in any effectful instructions within the bounds
12493 // of the function
12494 IS_NOEFFECT = 1 << 1,
12495 // loads are invariant within the bounds of the function
12496 IS_LOCALLY_INVARIANT = 1 << 2,
12497 // memory lifetime is constrained within the bounds of the function
12498 IS_LOCALLY_CONSTRAINED = 1 << 3,
12499
12500 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12501 IS_LOCALLY_CONSTRAINED,
12502 };
12503 static_assert(getBestState() == IS_BEST_STATE, "Unexpected best state");
12504
12505 using Base =
12506 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12507
12508 // the BitIntegerState is optimistic about IS_NOALIAS and IS_NOEFFECT, but
12509 // pessimistic about IS_KNOWN_INVARIANT
12510 AAInvariantLoadPointerImpl(const IRPosition &IRP, Attributor &A)
12511 : Base(IRP) {}
12512
12513 bool isKnownInvariant() const final {
12514 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12515 }
12516
12517 bool isKnownLocallyInvariant() const final {
12518 if (isKnown(IS_LOCALLY_INVARIANT))
12519 return true;
12520 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12521 }
12522
12523 bool isAssumedInvariant() const final {
12524 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12525 }
12526
12527 bool isAssumedLocallyInvariant() const final {
12528 if (isAssumed(IS_LOCALLY_INVARIANT))
12529 return true;
12530 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12531 }
12532
12533 ChangeStatus updateImpl(Attributor &A) override {
12534 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12535
12536 Changed |= updateNoAlias(A);
12537 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12538 return indicatePessimisticFixpoint();
12539
12540 Changed |= updateNoEffect(A);
12541
12542 Changed |= updateLocalInvariance(A);
12543
12544 return Changed;
12545 }
12546
12547 ChangeStatus manifest(Attributor &A) override {
12548 if (!isKnownInvariant())
12549 return ChangeStatus::UNCHANGED;
12550
12551 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12552 const Value *Ptr = &getAssociatedValue();
12553 const auto TagInvariantLoads = [&](const Use &U, bool &) {
12554 if (U.get() != Ptr)
12555 return true;
12556 auto *I = dyn_cast<Instruction>(U.getUser());
12557 if (!I)
12558 return true;
12559
12560 // Ensure that we are only changing uses from the corresponding callgraph
12561 // SSC in the case that the AA isn't run on the entire module
12562 if (!A.isRunOn(I->getFunction()))
12563 return true;
12564
12565 if (I->hasMetadata(LLVMContext::MD_invariant_load))
12566 return true;
12567
12568 if (auto *LI = dyn_cast<LoadInst>(I)) {
12569 LI->setMetadata(LLVMContext::MD_invariant_load,
12570 MDNode::get(LI->getContext(), {}));
12571 Changed = ChangeStatus::CHANGED;
12572 }
12573 return true;
12574 };
12575
12576 (void)A.checkForAllUses(TagInvariantLoads, *this, *Ptr);
12577 return Changed;
12578 }
12579
12580 const std::string getAsStr(Attributor *) const override {
12581 if (isKnownInvariant())
12582 return "load-invariant pointer";
12583 return "non-invariant pointer";
12584 }
12585
12586 void trackStatistics() const override {}
12587
12588private:
12589 /// Indicate that noalias is required for the pointer to be invariant.
12590 bool requiresNoAlias() const {
12591 switch (getPositionKind()) {
12592 default:
12593 // Conservatively default to require noalias.
12594 return true;
12595 case IRP_FLOAT:
12596 case IRP_RETURNED:
12597 case IRP_CALL_SITE:
12598 return false;
12599 case IRP_CALL_SITE_RETURNED: {
12600 const auto &CB = cast<CallBase>(getAnchorValue());
12602 &CB, /*MustPreserveOffset=*/false);
12603 }
12604 case IRP_ARGUMENT: {
12605 const Function *F = getAssociatedFunction();
12606 assert(F && "no associated function for argument");
12607 return !isCallableCC(F->getCallingConv());
12608 }
12609 }
12610 }
12611
12612 bool isExternal() const {
12613 const Function *F = getAssociatedFunction();
12614 if (!F)
12615 return true;
12616 return isCallableCC(F->getCallingConv()) &&
12617 getPositionKind() != IRP_CALL_SITE_RETURNED;
12618 }
12619
12620 ChangeStatus updateNoAlias(Attributor &A) {
12621 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12622 return ChangeStatus::UNCHANGED;
12623
12624 // Try to use AANoAlias.
12625 if (const auto *ANoAlias = A.getOrCreateAAFor<AANoAlias>(
12626 getIRPosition(), this, DepClassTy::REQUIRED)) {
12627 if (ANoAlias->isKnownNoAlias()) {
12628 addKnownBits(IS_NOALIAS);
12629 return ChangeStatus::CHANGED;
12630 }
12631
12632 if (!ANoAlias->isAssumedNoAlias()) {
12633 removeAssumedBits(IS_NOALIAS);
12634 return ChangeStatus::CHANGED;
12635 }
12636
12637 return ChangeStatus::UNCHANGED;
12638 }
12639
12640 // Try to infer noalias from argument attribute, since it is applicable for
12641 // the duration of the function.
12642 if (const Argument *Arg = getAssociatedArgument()) {
12643 if (Arg->hasNoAliasAttr()) {
12644 addKnownBits(IS_NOALIAS);
12645 return ChangeStatus::UNCHANGED;
12646 }
12647
12648 // Noalias information is not provided, and cannot be inferred,
12649 // so we conservatively assume the pointer aliases.
12650 removeAssumedBits(IS_NOALIAS);
12651 return ChangeStatus::CHANGED;
12652 }
12653
12654 return ChangeStatus::UNCHANGED;
12655 }
12656
12657 ChangeStatus updateNoEffect(Attributor &A) {
12658 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12659 return ChangeStatus::UNCHANGED;
12660
12661 if (!getAssociatedFunction())
12662 return indicatePessimisticFixpoint();
12663
12664 if (isa<AllocaInst>(&getAssociatedValue()))
12665 return indicatePessimisticFixpoint();
12666
12667 const auto HasNoEffectLoads = [&](const Use &U, bool &) {
12668 const auto *LI = dyn_cast<LoadInst>(U.getUser());
12669 return !LI || !LI->mayHaveSideEffects();
12670 };
12671 if (!A.checkForAllUses(HasNoEffectLoads, *this, getAssociatedValue()))
12672 return indicatePessimisticFixpoint();
12673
12674 if (const auto *AMemoryBehavior = A.getOrCreateAAFor<AAMemoryBehavior>(
12675 getIRPosition(), this, DepClassTy::REQUIRED)) {
12676 // For non-instructions, try to use AAMemoryBehavior to infer the readonly
12677 // attribute
12678 if (!AMemoryBehavior->isAssumedReadOnly())
12679 return indicatePessimisticFixpoint();
12680
12681 if (AMemoryBehavior->isKnownReadOnly()) {
12682 addKnownBits(IS_NOEFFECT);
12683 return ChangeStatus::UNCHANGED;
12684 }
12685
12686 return ChangeStatus::UNCHANGED;
12687 }
12688
12689 if (const Argument *Arg = getAssociatedArgument()) {
12690 if (Arg->onlyReadsMemory()) {
12691 addKnownBits(IS_NOEFFECT);
12692 return ChangeStatus::UNCHANGED;
12693 }
12694
12695 // Readonly information is not provided, and cannot be inferred from
12696 // AAMemoryBehavior.
12697 return indicatePessimisticFixpoint();
12698 }
12699
12700 return ChangeStatus::UNCHANGED;
12701 }
12702
12703 ChangeStatus updateLocalInvariance(Attributor &A) {
12704 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12705 return ChangeStatus::UNCHANGED;
12706
12707 // try to infer invariance from underlying objects
12708 const auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
12709 getIRPosition(), this, DepClassTy::REQUIRED);
12710 if (!AUO)
12711 return ChangeStatus::UNCHANGED;
12712
12713 bool UsedAssumedInformation = false;
12714 const auto IsLocallyInvariantLoadIfPointer = [&](const Value &V) {
12715 if (!V.getType()->isPointerTy())
12716 return true;
12717 const auto *IsInvariantLoadPointer =
12718 A.getOrCreateAAFor<AAInvariantLoadPointer>(IRPosition::value(V), this,
12719 DepClassTy::REQUIRED);
12720 // Conservatively fail if invariance cannot be inferred.
12721 if (!IsInvariantLoadPointer)
12722 return false;
12723
12724 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12725 return true;
12726 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12727 return false;
12728
12729 UsedAssumedInformation = true;
12730 return true;
12731 };
12732 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12733 return indicatePessimisticFixpoint();
12734
12735 if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue())) {
12737 CB, /*MustPreserveOffset=*/false)) {
12738 for (const Value *Arg : CB->args()) {
12739 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12740 return indicatePessimisticFixpoint();
12741 }
12742 }
12743 }
12744
12745 if (!UsedAssumedInformation) {
12746 // Pointer is known and not just assumed to be locally invariant.
12747 addKnownBits(IS_LOCALLY_INVARIANT);
12748 return ChangeStatus::CHANGED;
12749 }
12750
12751 return ChangeStatus::UNCHANGED;
12752 }
12753};
12754
12755struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12756 AAInvariantLoadPointerFloating(const IRPosition &IRP, Attributor &A)
12757 : AAInvariantLoadPointerImpl(IRP, A) {}
12758};
12759
12760struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12761 AAInvariantLoadPointerReturned(const IRPosition &IRP, Attributor &A)
12762 : AAInvariantLoadPointerImpl(IRP, A) {}
12763
12764 void initialize(Attributor &) override {
12765 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12766 }
12767};
12768
12769struct AAInvariantLoadPointerCallSiteReturned final
12770 : AAInvariantLoadPointerImpl {
12771 AAInvariantLoadPointerCallSiteReturned(const IRPosition &IRP, Attributor &A)
12772 : AAInvariantLoadPointerImpl(IRP, A) {}
12773
12774 void initialize(Attributor &A) override {
12775 // Nothing is known about the result of an indirect call.
12776 const Function *F = getAssociatedFunction();
12777 if (!F) {
12778 indicatePessimisticFixpoint();
12779 return;
12780 }
12781
12782 if (!F->isDeclaration() && !F->isIntrinsic())
12783 return AAInvariantLoadPointerImpl::initialize(A);
12784
12785 const auto &CB = cast<CallBase>(getAnchorValue());
12787 &CB, /*MustPreserveOffset=*/false))
12788 return AAInvariantLoadPointerImpl::initialize(A);
12789
12790 if (F->onlyReadsMemory() && F->hasNoSync())
12791 return AAInvariantLoadPointerImpl::initialize(A);
12792
12793 // At this point, the function is opaque, so we conservatively assume
12794 // non-invariance.
12795 indicatePessimisticFixpoint();
12796 }
12797};
12798
12799struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12800 AAInvariantLoadPointerArgument(const IRPosition &IRP, Attributor &A)
12801 : AAInvariantLoadPointerImpl(IRP, A) {}
12802
12803 void initialize(Attributor &) override {
12804 const Function *F = getAssociatedFunction();
12805 assert(F && "no associated function for argument");
12806
12807 if (!isCallableCC(F->getCallingConv())) {
12808 addKnownBits(IS_LOCALLY_CONSTRAINED);
12809 return;
12810 }
12811
12812 if (!F->hasLocalLinkage())
12813 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12814 }
12815};
12816
12817struct AAInvariantLoadPointerCallSiteArgument final
12818 : AAInvariantLoadPointerImpl {
12819 AAInvariantLoadPointerCallSiteArgument(const IRPosition &IRP, Attributor &A)
12820 : AAInvariantLoadPointerImpl(IRP, A) {}
12821};
12822} // namespace
12823
12824/// ------------------------ Address Space ------------------------------------
12825namespace {
12826
12827template <typename InstType>
12828static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,
12829 Value *OriginalValue, PointerType *NewPtrTy,
12830 bool UseOriginalValue) {
12831 if (U.getOperandNo() != InstType::getPointerOperandIndex())
12832 return false;
12833
12834 if (MemInst->isVolatile()) {
12835 auto *TTI = A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12836 *MemInst->getFunction());
12837 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12838 if (!TTI || !TTI->hasVolatileVariant(MemInst, NewAS))
12839 return false;
12840 }
12841
12842 if (UseOriginalValue) {
12843 A.changeUseAfterManifest(const_cast<Use &>(U), *OriginalValue);
12844 return true;
12845 }
12846
12847 Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12848 CastInst->insertBefore(MemInst->getIterator());
12849 A.changeUseAfterManifest(const_cast<Use &>(U), *CastInst);
12850 return true;
12851}
12852
12853struct AAAddressSpaceImpl : public AAAddressSpace {
12854 AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)
12855 : AAAddressSpace(IRP, A) {}
12856
12857 uint32_t getAddressSpace() const override {
12858 assert(isValidState() && "the AA is invalid");
12859 return AssumedAddressSpace;
12860 }
12861
12862 void initialize(Attributor &A) override {
12863 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
12864 "Associated value is not a pointer");
12865
12866 if (!A.getInfoCache().getFlatAddressSpace().has_value()) {
12867 indicatePessimisticFixpoint();
12868 return;
12869 }
12870
12871 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12872 unsigned AS = getAssociatedType()->getPointerAddressSpace();
12873 if (AS != FlatAS) {
12874 [[maybe_unused]] bool R = takeAddressSpace(AS);
12875 assert(R && "The take should happen");
12876 indicateOptimisticFixpoint();
12877 }
12878 }
12879
12880 ChangeStatus updateImpl(Attributor &A) override {
12881 uint32_t OldAddressSpace = AssumedAddressSpace;
12882 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12883
12884 auto CheckAddressSpace = [&](Value &Obj) {
12885 // Ignore undef.
12886 if (isa<UndefValue>(&Obj))
12887 return true;
12888
12889 // If the object already has a non-flat address space, we simply take it.
12890 unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
12891 if (ObjAS != FlatAS)
12892 return takeAddressSpace(ObjAS);
12893
12894 // At this point, we know Obj is in the flat address space. For a final
12895 // attempt, we want to use getAssumedAddrSpace, but first we must get the
12896 // associated function, if possible.
12897 Function *F = nullptr;
12898 if (auto *Arg = dyn_cast<Argument>(&Obj))
12899 F = Arg->getParent();
12900 else if (auto *I = dyn_cast<Instruction>(&Obj))
12901 F = I->getFunction();
12902
12903 // Use getAssumedAddrSpace if the associated function exists.
12904 if (F) {
12905 auto *TTI =
12906 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
12907 unsigned AssumedAS = TTI->getAssumedAddrSpace(&Obj);
12908 if (AssumedAS != ~0U)
12909 return takeAddressSpace(AssumedAS);
12910 }
12911
12912 // Now we can't do anything else but to take the flat AS.
12913 return takeAddressSpace(FlatAS);
12914 };
12915
12916 auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this,
12917 DepClassTy::REQUIRED);
12918 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
12919 return indicatePessimisticFixpoint();
12920
12921 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
12922 : ChangeStatus::CHANGED;
12923 }
12924
12925 ChangeStatus manifest(Attributor &A) override {
12926 unsigned NewAS = getAddressSpace();
12927
12928 if (NewAS == InvalidAddressSpace ||
12929 NewAS == getAssociatedType()->getPointerAddressSpace())
12930 return ChangeStatus::UNCHANGED;
12931
12932 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12933
12934 Value *AssociatedValue = &getAssociatedValue();
12935 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
12936
12937 PointerType *NewPtrTy =
12938 PointerType::get(getAssociatedType()->getContext(), NewAS);
12939 bool UseOriginalValue =
12940 OriginalValue->getType()->getPointerAddressSpace() == NewAS;
12941
12942 bool Changed = false;
12943
12944 auto Pred = [&](const Use &U, bool &) {
12945 if (U.get() != AssociatedValue)
12946 return true;
12947 auto *Inst = dyn_cast<Instruction>(U.getUser());
12948 if (!Inst)
12949 return true;
12950 // This is a WA to make sure we only change uses from the corresponding
12951 // CGSCC if the AA is run on CGSCC instead of the entire module.
12952 if (!A.isRunOn(Inst->getFunction()))
12953 return true;
12954 if (auto *LI = dyn_cast<LoadInst>(Inst)) {
12955 Changed |=
12956 makeChange(A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12957 } else if (auto *SI = dyn_cast<StoreInst>(Inst)) {
12958 Changed |=
12959 makeChange(A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12960 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Inst)) {
12961 Changed |=
12962 makeChange(A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
12963 } else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Inst)) {
12964 Changed |=
12965 makeChange(A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
12966 }
12967 return true;
12968 };
12969
12970 // It doesn't matter if we can't check all uses as we can simply
12971 // conservatively ignore those that can not be visited.
12972 (void)A.checkForAllUses(Pred, *this, getAssociatedValue(),
12973 /* CheckBBLivenessOnly */ true);
12974
12975 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12976 }
12977
12978 const std::string getAsStr(Attributor *A) const override {
12979 if (!isValidState())
12980 return "addrspace(<invalid>)";
12981 return "addrspace(" +
12982 (AssumedAddressSpace == InvalidAddressSpace
12983 ? "none"
12984 : std::to_string(AssumedAddressSpace)) +
12985 ")";
12986 }
12987
12988private:
12989 uint32_t AssumedAddressSpace = InvalidAddressSpace;
12990
12991 bool takeAddressSpace(uint32_t AS) {
12992 if (AssumedAddressSpace == InvalidAddressSpace) {
12993 AssumedAddressSpace = AS;
12994 return true;
12995 }
12996 return AssumedAddressSpace == AS;
12997 }
12998
12999 static Value *peelAddrspacecast(Value *V, unsigned FlatAS) {
13000 if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) {
13001 assert(I->getSrcAddressSpace() != FlatAS &&
13002 "there should not be flat AS -> non-flat AS");
13003 return I->getPointerOperand();
13004 }
13005 if (auto *C = dyn_cast<ConstantExpr>(V))
13006 if (C->getOpcode() == Instruction::AddrSpaceCast) {
13007 assert(C->getOperand(0)->getType()->getPointerAddressSpace() !=
13008 FlatAS &&
13009 "there should not be flat AS -> non-flat AS X");
13010 return C->getOperand(0);
13011 }
13012 return V;
13013 }
13014};
13015
13016struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13017 AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)
13018 : AAAddressSpaceImpl(IRP, A) {}
13019
13020 void trackStatistics() const override {
13022 }
13023};
13024
13025struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13026 AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)
13027 : AAAddressSpaceImpl(IRP, A) {}
13028
13029 void initialize(Attributor &A) override {
13030 // TODO: we don't rewrite function argument for now because it will need to
13031 // rewrite the function signature and all call sites.
13032 (void)indicatePessimisticFixpoint();
13033 }
13034
13035 void trackStatistics() const override {
13036 STATS_DECLTRACK_FNRET_ATTR(addrspace);
13037 }
13038};
13039
13040struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13041 AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13042 : AAAddressSpaceImpl(IRP, A) {}
13043
13044 void trackStatistics() const override {
13045 STATS_DECLTRACK_CSRET_ATTR(addrspace);
13046 }
13047};
13048
13049struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13050 AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)
13051 : AAAddressSpaceImpl(IRP, A) {}
13052
13053 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }
13054};
13055
13056struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13057 AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13058 : AAAddressSpaceImpl(IRP, A) {}
13059
13060 void initialize(Attributor &A) override {
13061 // TODO: we don't rewrite call site argument for now because it will need to
13062 // rewrite the function signature of the callee.
13063 (void)indicatePessimisticFixpoint();
13064 }
13065
13066 void trackStatistics() const override {
13067 STATS_DECLTRACK_CSARG_ATTR(addrspace);
13068 }
13069};
13070} // namespace
13071
13072/// ------------------------ No Alias Address Space ---------------------------
13073// This attribute assumes flat address space can alias all other address space
13074
13075// TODO: this is similar to AAAddressSpace, most of the code should be merged.
13076// But merging it created failing cased on gateway test that cannot be
13077// reproduced locally. So should open a separated PR to handle the merge of
13078// AANoAliasAddrSpace and AAAddressSpace attribute
13079
13080namespace {
13081struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {
13082 AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)
13083 : AANoAliasAddrSpace(IRP, A) {}
13084
13085 void initialize(Attributor &A) override {
13086 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13087 "Associated value is not a pointer");
13088
13089 resetASRanges(A);
13090
13091 std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();
13092 if (!FlatAS.has_value()) {
13093 indicatePessimisticFixpoint();
13094 return;
13095 }
13096
13097 removeAS(*FlatAS);
13098
13099 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13100 if (AS != *FlatAS) {
13101 removeAS(AS);
13102 indicateOptimisticFixpoint();
13103 }
13104 }
13105
13106 ChangeStatus updateImpl(Attributor &A) override {
13107 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13108 uint32_t OldAssumed = getAssumed();
13109
13110 auto CheckAddressSpace = [&](Value &Obj) {
13111 if (isa<PoisonValue>(&Obj))
13112 return true;
13113
13114 unsigned AS = Obj.getType()->getPointerAddressSpace();
13115 if (AS == FlatAS)
13116 return false;
13117
13118 removeAS(Obj.getType()->getPointerAddressSpace());
13119 return true;
13120 };
13121
13122 const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
13123 getIRPosition(), this, DepClassTy::REQUIRED);
13124 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13125 return indicatePessimisticFixpoint();
13126
13127 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13128 : ChangeStatus::CHANGED;
13129 }
13130
13131 ChangeStatus manifest(Attributor &A) override {
13132 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13133
13134 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13135 if (AS != FlatAS || Map.empty())
13136 return ChangeStatus::UNCHANGED;
13137
13138 LLVMContext &Ctx = getAssociatedValue().getContext();
13139 MDNode *NoAliasASNode = nullptr;
13140 MDBuilder MDB(Ctx);
13141 // Has to use iterator to get the range info.
13142 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13143 if (!I.value())
13144 continue;
13145 unsigned Upper = I.stop();
13146 unsigned Lower = I.start();
13147 if (!NoAliasASNode) {
13148 NoAliasASNode = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13149 continue;
13150 }
13151 MDNode *ASRange = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13152 NoAliasASNode = MDNode::getMostGenericRange(NoAliasASNode, ASRange);
13153 }
13154
13155 Value *AssociatedValue = &getAssociatedValue();
13156 bool Changed = false;
13157
13158 auto AddNoAliasAttr = [&](const Use &U, bool &) {
13159 if (U.get() != AssociatedValue)
13160 return true;
13161 Instruction *Inst = dyn_cast<Instruction>(U.getUser());
13162 if (!Inst || Inst->hasMetadata(LLVMContext::MD_noalias_addrspace))
13163 return true;
13164 if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst) &&
13166 return true;
13167 if (!A.isRunOn(Inst->getFunction()))
13168 return true;
13169 Inst->setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13170 Changed = true;
13171 return true;
13172 };
13173 (void)A.checkForAllUses(AddNoAliasAttr, *this, *AssociatedValue,
13174 /*CheckBBLivenessOnly=*/true);
13175 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13176 }
13177
13178 const std::string getAsStr(Attributor *A) const override {
13179 if (!isValidState())
13180 return "<invalid>";
13181 std::string Str;
13182 raw_string_ostream OS(Str);
13183 OS << "CanNotBeAddrSpace(";
13184 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13185 unsigned Upper = I.stop();
13186 unsigned Lower = I.start();
13187 OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';
13188 }
13189 OS << " )";
13190 return OS.str();
13191 }
13192
13193private:
13194 void removeAS(unsigned AS) {
13195 RangeMap::iterator I = Map.find(AS);
13196
13197 if (I != Map.end()) {
13198 unsigned Upper = I.stop();
13199 unsigned Lower = I.start();
13200 I.erase();
13201 if (Upper == Lower)
13202 return;
13203 if (AS != ~((unsigned)0) && AS + 1 <= Upper)
13204 Map.insert(AS + 1, Upper, /*what ever this variable name is=*/true);
13205 if (AS != 0 && Lower <= AS - 1)
13206 Map.insert(Lower, AS - 1, true);
13207 }
13208 }
13209
13210 void resetASRanges(Attributor &A) {
13211 Map.clear();
13212 Map.insert(0, A.getInfoCache().getMaxAddrSpace(), true);
13213 }
13214};
13215
13216struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13217 AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)
13218 : AANoAliasAddrSpaceImpl(IRP, A) {}
13219
13220 void trackStatistics() const override {
13221 STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);
13222 }
13223};
13224
13225struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13226 AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)
13227 : AANoAliasAddrSpaceImpl(IRP, A) {}
13228
13229 void trackStatistics() const override {
13230 STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);
13231 }
13232};
13233
13234struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13235 AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13236 : AANoAliasAddrSpaceImpl(IRP, A) {}
13237
13238 void trackStatistics() const override {
13239 STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);
13240 }
13241};
13242
13243struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13244 AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)
13245 : AANoAliasAddrSpaceImpl(IRP, A) {}
13246
13247 void trackStatistics() const override {
13248 STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);
13249 }
13250};
13251
13252struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13253 AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13254 : AANoAliasAddrSpaceImpl(IRP, A) {}
13255
13256 void trackStatistics() const override {
13257 STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);
13258 }
13259};
13260} // namespace
13261/// ----------- Allocation Info ----------
13262namespace {
13263struct AAAllocationInfoImpl : public AAAllocationInfo {
13264 AAAllocationInfoImpl(const IRPosition &IRP, Attributor &A)
13265 : AAAllocationInfo(IRP, A) {}
13266
13267 std::optional<TypeSize> getAllocatedSize() const override {
13268 assert(isValidState() && "the AA is invalid");
13269 return AssumedAllocatedSize;
13270 }
13271
13272 std::optional<TypeSize> findInitialAllocationSize(Instruction *I,
13273 const DataLayout &DL) {
13274
13275 // TODO: implement case for malloc like instructions
13276 switch (I->getOpcode()) {
13277 case Instruction::Alloca: {
13278 AllocaInst *AI = cast<AllocaInst>(I);
13279 return AI->getAllocationSize(DL);
13280 }
13281 default:
13282 return std::nullopt;
13283 }
13284 }
13285
13286 ChangeStatus updateImpl(Attributor &A) override {
13287
13288 const IRPosition &IRP = getIRPosition();
13289 Instruction *I = IRP.getCtxI();
13290
13291 // TODO: update check for malloc like calls
13292 if (!isa<AllocaInst>(I))
13293 return indicatePessimisticFixpoint();
13294
13295 bool IsKnownNoCapture;
13297 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13298 return indicatePessimisticFixpoint();
13299
13300 const AAPointerInfo *PI =
13301 A.getOrCreateAAFor<AAPointerInfo>(IRP, *this, DepClassTy::REQUIRED);
13302
13303 if (!PI)
13304 return indicatePessimisticFixpoint();
13305
13306 if (!PI->getState().isValidState() || PI->reachesReturn())
13307 return indicatePessimisticFixpoint();
13308
13309 const DataLayout &DL = A.getDataLayout();
13310 const auto AllocationSize = findInitialAllocationSize(I, DL);
13311
13312 // If allocation size is nullopt, we give up.
13313 if (!AllocationSize)
13314 return indicatePessimisticFixpoint();
13315
13316 // For zero sized allocations, we give up.
13317 // Since we can't reduce further
13318 if (*AllocationSize == 0)
13319 return indicatePessimisticFixpoint();
13320
13321 int64_t BinSize = PI->numOffsetBins();
13322
13323 // TODO: implement for multiple bins
13324 if (BinSize > 1)
13325 return indicatePessimisticFixpoint();
13326
13327 if (BinSize == 0) {
13328 auto NewAllocationSize = std::make_optional<TypeSize>(0, false);
13329 if (!changeAllocationSize(NewAllocationSize))
13330 return ChangeStatus::UNCHANGED;
13331 return ChangeStatus::CHANGED;
13332 }
13333
13334 // TODO: refactor this to be part of multiple bin case
13335 const auto &It = PI->begin();
13336
13337 // TODO: handle if Offset is not zero
13338 if (It->first.Offset != 0)
13339 return indicatePessimisticFixpoint();
13340
13341 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13342
13343 if (SizeOfBin >= *AllocationSize)
13344 return indicatePessimisticFixpoint();
13345
13346 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8, false);
13347
13348 if (!changeAllocationSize(NewAllocationSize))
13349 return ChangeStatus::UNCHANGED;
13350
13351 return ChangeStatus::CHANGED;
13352 }
13353
13354 ChangeStatus manifest(Attributor &A) override {
13355
13356 assert(isValidState() &&
13357 "Manifest should only be called if the state is valid.");
13358
13359 Instruction *I = getIRPosition().getCtxI();
13360
13361 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13362
13363 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13364
13365 switch (I->getOpcode()) {
13366 // TODO: add case for malloc like calls
13367 case Instruction::Alloca: {
13368
13369 AllocaInst *AI = cast<AllocaInst>(I);
13370
13371 Type *CharType = Type::getInt8Ty(I->getContext());
13372
13373 auto *NumBytesToValue =
13374 ConstantInt::get(I->getContext(), APInt(32, NumBytesToAllocate));
13375
13376 BasicBlock::iterator insertPt = AI->getIterator();
13377 insertPt = std::next(insertPt);
13378 AllocaInst *NewAllocaInst =
13379 new AllocaInst(CharType, AI->getAddressSpace(), NumBytesToValue,
13380 AI->getAlign(), AI->getName(), insertPt);
13381
13382 if (A.changeAfterManifest(IRPosition::inst(*AI), *NewAllocaInst))
13383 return ChangeStatus::CHANGED;
13384
13385 break;
13386 }
13387 default:
13388 break;
13389 }
13390
13391 return ChangeStatus::UNCHANGED;
13392 }
13393
13394 const std::string getAsStr(Attributor *A) const override {
13395 if (!isValidState())
13396 return "allocationinfo(<invalid>)";
13397 return "allocationinfo(" +
13398 (AssumedAllocatedSize == HasNoAllocationSize
13399 ? "none"
13400 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13401 ")";
13402 }
13403
13404private:
13405 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13406
13407 // Maintain the computed allocation size of the object.
13408 // Returns (bool) weather the size of the allocation was modified or not.
13409 bool changeAllocationSize(std::optional<TypeSize> Size) {
13410 if (AssumedAllocatedSize == HasNoAllocationSize ||
13411 AssumedAllocatedSize != Size) {
13412 AssumedAllocatedSize = Size;
13413 return true;
13414 }
13415 return false;
13416 }
13417};
13418
13419struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13420 AAAllocationInfoFloating(const IRPosition &IRP, Attributor &A)
13421 : AAAllocationInfoImpl(IRP, A) {}
13422
13423 void trackStatistics() const override {
13424 STATS_DECLTRACK_FLOATING_ATTR(allocationinfo);
13425 }
13426};
13427
13428struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13429 AAAllocationInfoReturned(const IRPosition &IRP, Attributor &A)
13430 : AAAllocationInfoImpl(IRP, A) {}
13431
13432 void initialize(Attributor &A) override {
13433 // TODO: we don't rewrite function argument for now because it will need to
13434 // rewrite the function signature and all call sites
13435 (void)indicatePessimisticFixpoint();
13436 }
13437
13438 void trackStatistics() const override {
13439 STATS_DECLTRACK_FNRET_ATTR(allocationinfo);
13440 }
13441};
13442
13443struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13444 AAAllocationInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
13445 : AAAllocationInfoImpl(IRP, A) {}
13446
13447 void trackStatistics() const override {
13448 STATS_DECLTRACK_CSRET_ATTR(allocationinfo);
13449 }
13450};
13451
13452struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13453 AAAllocationInfoArgument(const IRPosition &IRP, Attributor &A)
13454 : AAAllocationInfoImpl(IRP, A) {}
13455
13456 void trackStatistics() const override {
13457 STATS_DECLTRACK_ARG_ATTR(allocationinfo);
13458 }
13459};
13460
13461struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13462 AAAllocationInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
13463 : AAAllocationInfoImpl(IRP, A) {}
13464
13465 void initialize(Attributor &A) override {
13466
13467 (void)indicatePessimisticFixpoint();
13468 }
13469
13470 void trackStatistics() const override {
13471 STATS_DECLTRACK_CSARG_ATTR(allocationinfo);
13472 }
13473};
13474} // namespace
13475
13476const char AANoUnwind::ID = 0;
13477const char AANoSync::ID = 0;
13478const char AANoFree::ID = 0;
13479const char AANonNull::ID = 0;
13480const char AAMustProgress::ID = 0;
13481const char AANoRecurse::ID = 0;
13482const char AANonConvergent::ID = 0;
13483const char AAWillReturn::ID = 0;
13484const char AAUndefinedBehavior::ID = 0;
13485const char AANoAlias::ID = 0;
13486const char AAIntraFnReachability::ID = 0;
13487const char AANoReturn::ID = 0;
13488const char AAIsDead::ID = 0;
13489const char AADereferenceable::ID = 0;
13490const char AAAlign::ID = 0;
13491const char AAInstanceInfo::ID = 0;
13492const char AANoCapture::ID = 0;
13493const char AAValueSimplify::ID = 0;
13494const char AAHeapToStack::ID = 0;
13495const char AAPrivatizablePtr::ID = 0;
13496const char AAMemoryBehavior::ID = 0;
13497const char AAMemoryLocation::ID = 0;
13498const char AAValueConstantRange::ID = 0;
13499const char AAPotentialConstantValues::ID = 0;
13500const char AAPotentialValues::ID = 0;
13501const char AANoUndef::ID = 0;
13502const char AANoFPClass::ID = 0;
13503const char AACallEdges::ID = 0;
13504const char AAInterFnReachability::ID = 0;
13505const char AAPointerInfo::ID = 0;
13506const char AAAssumptionInfo::ID = 0;
13507const char AAUnderlyingObjects::ID = 0;
13508const char AAInvariantLoadPointer::ID = 0;
13509const char AAAddressSpace::ID = 0;
13510const char AANoAliasAddrSpace::ID = 0;
13511const char AAAllocationInfo::ID = 0;
13512const char AAIndirectCallInfo::ID = 0;
13513const char AAGlobalValueInfo::ID = 0;
13514const char AADenormalFPMath::ID = 0;
13515
13516// Macro magic to create the static generator function for attributes that
13517// follow the naming scheme.
13518
13519#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13520 case IRPosition::PK: \
13521 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13522
13523#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13524 case IRPosition::PK: \
13525 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13526 ++NumAAs; \
13527 break;
13528
13529#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13530 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13531 CLASS *AA = nullptr; \
13532 switch (IRP.getPositionKind()) { \
13533 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13534 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13535 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13536 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13537 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13538 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13539 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13540 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13541 } \
13542 return *AA; \
13543 }
13544
13545#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13546 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13547 CLASS *AA = nullptr; \
13548 switch (IRP.getPositionKind()) { \
13549 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13550 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13551 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13552 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13553 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13554 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13555 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13556 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13557 } \
13558 return *AA; \
13559 }
13560
13561#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13562 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13563 CLASS *AA = nullptr; \
13564 switch (IRP.getPositionKind()) { \
13565 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13566 default: \
13567 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13568 " position!"); \
13569 } \
13570 return *AA; \
13571 }
13572
13573#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13574 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13575 CLASS *AA = nullptr; \
13576 switch (IRP.getPositionKind()) { \
13577 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13578 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13579 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13580 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13581 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13582 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13583 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13584 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13585 } \
13586 return *AA; \
13587 }
13588
13589#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13590 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13591 CLASS *AA = nullptr; \
13592 switch (IRP.getPositionKind()) { \
13593 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13594 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13595 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13596 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13597 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13598 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13599 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13600 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13601 } \
13602 return *AA; \
13603 }
13604
13605#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13606 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13607 CLASS *AA = nullptr; \
13608 switch (IRP.getPositionKind()) { \
13609 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13610 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13611 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13612 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13613 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13614 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13615 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13616 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13617 } \
13618 return *AA; \
13619 }
13620
13630
13648
13653
13658
13665
13667
13668#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13669#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13670#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13671#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13672#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13673#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13674#undef SWITCH_PK_CREATE
13675#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.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:125
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
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...
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:794
Argument * arg_iterator
Definition Function.h:73
iterator_range< arg_iterator > args()
Definition Function.h:877
const Function & getFunction() const
Definition Function.h:167
size_t arg_size() const
Definition Function.h:886
Argument * getArg(unsigned i) const
Definition Function.h:871
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:2118
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2949
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
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.
@ 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)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
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:791
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:780
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:897
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:800
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:847
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
Definition Attributor.h:879
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.
TargetLibraryInfo * getTargetLibraryInfoForFunction(const Function &F)
Return TargetLibraryInfo for function F.
bool isOnlyUsedByAssume(const Instruction &I) const
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.