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)
306 Ptr = IRB.CreatePtrAdd(Ptr, IRB.getInt64(Offset),
307 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();
2560 if (isa<ConstantPointerNull>(V)) {
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.
5799 bool ReadOnly = F.onlyReadsMemory();
5800 bool NoThrow = F.doesNotThrow();
5801 bool IsVoidReturn = F.getReturnType()->isVoidTy();
5802 if (ReadOnly && NoThrow && IsVoidReturn) {
5803 State.addKnownBits(NO_CAPTURE);
5804 return;
5805 }
5806
5807 // A function cannot capture state in memory if it only reads memory, it can
5808 // however return/throw state and the state might be influenced by the
5809 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5810 if (ReadOnly)
5811 State.addKnownBits(NOT_CAPTURED_IN_MEM);
5812
5813 // A function cannot communicate state back if it does not through
5814 // exceptions and doesn not return values.
5815 if (NoThrow && IsVoidReturn)
5816 State.addKnownBits(NOT_CAPTURED_IN_RET);
5817
5818 // Check existing "returned" attributes.
5819 int ArgNo = IRP.getCalleeArgNo();
5820 if (!NoThrow || ArgNo < 0 ||
5821 !F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5822 return;
5823
5824 for (unsigned U = 0, E = F.arg_size(); U < E; ++U)
5825 if (F.hasParamAttribute(U, Attribute::Returned)) {
5826 if (U == unsigned(ArgNo))
5827 State.removeAssumedBits(NOT_CAPTURED_IN_RET);
5828 else if (ReadOnly)
5829 State.addKnownBits(NO_CAPTURE);
5830 else
5831 State.addKnownBits(NOT_CAPTURED_IN_RET);
5832 break;
5833 }
5834}
5835
5836namespace {
5837/// A class to hold the state of for no-capture attributes.
5838struct AANoCaptureImpl : public AANoCapture {
5839 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5840
5841 void initialize(Attributor &A) override {
5842 bool IsKnown;
5844 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5845 (void)IsKnown;
5846 }
5847
5848 ChangeStatus updateImpl(Attributor &A) override;
5849
5850 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5851 SmallVectorImpl<Attribute> &Attrs) const override {
5852 if (!isAssumedNoCaptureMaybeReturned())
5853 return;
5854
5855 if (isArgumentPosition()) {
5856 if (isAssumedNoCapture())
5857 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
5858 else if (ManifestInternal)
5859 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
5860 }
5861 }
5862
5863 const std::string getAsStr(Attributor *A) const override {
5864 if (isKnownNoCapture())
5865 return "known not-captured";
5866 if (isAssumedNoCapture())
5867 return "assumed not-captured";
5868 if (isKnownNoCaptureMaybeReturned())
5869 return "known not-captured-maybe-returned";
5870 if (isAssumedNoCaptureMaybeReturned())
5871 return "assumed not-captured-maybe-returned";
5872 return "assumed-captured";
5873 }
5874
5875 /// Check the use \p U and update \p State accordingly. Return true if we
5876 /// should continue to update the state.
5877 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
5878 bool &Follow) {
5879 Instruction *UInst = cast<Instruction>(U.getUser());
5880 LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "
5881 << *UInst << "\n");
5882
5883 // Deal with ptr2int by following uses.
5884 if (isa<PtrToIntInst>(UInst)) {
5885 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
5886 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5887 /* Return */ true);
5888 }
5889
5890 // For stores we already checked if we can follow them, if they make it
5891 // here we give up.
5892 if (isa<StoreInst>(UInst))
5893 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5894 /* Return */ true);
5895
5896 // Explicitly catch return instructions.
5897 if (isa<ReturnInst>(UInst)) {
5898 if (UInst->getFunction() == getAnchorScope())
5899 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5900 /* Return */ true);
5901 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5902 /* Return */ true);
5903 }
5904
5905 // For now we only use special logic for call sites. However, the tracker
5906 // itself knows about a lot of other non-capturing cases already.
5907 auto *CB = dyn_cast<CallBase>(UInst);
5908 if (!CB || !CB->isArgOperand(&U))
5909 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5910 /* Return */ true);
5911
5912 unsigned ArgNo = CB->getArgOperandNo(&U);
5913 const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
5914 // If we have a abstract no-capture attribute for the argument we can use
5915 // it to justify a non-capture attribute here. This allows recursion!
5916 bool IsKnownNoCapture;
5917 const AANoCapture *ArgNoCaptureAA = nullptr;
5918 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
5919 A, this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
5920 &ArgNoCaptureAA);
5921 if (IsAssumedNoCapture)
5922 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5923 /* Return */ false);
5924 if (ArgNoCaptureAA && ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
5925 Follow = true;
5926 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5927 /* Return */ false);
5928 }
5929
5930 // Lastly, we could not find a reason no-capture can be assumed so we don't.
5931 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5932 /* Return */ true);
5933 }
5934
5935 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
5936 /// \p CapturedInRet, then return true if we should continue updating the
5937 /// state.
5938 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
5939 bool CapturedInInt, bool CapturedInRet) {
5940 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
5941 << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
5942 if (CapturedInMem)
5943 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
5944 if (CapturedInInt)
5945 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
5946 if (CapturedInRet)
5947 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
5948 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
5949 }
5950};
5951
5952ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
5953 const IRPosition &IRP = getIRPosition();
5954 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
5955 : &IRP.getAssociatedValue();
5956 if (!V)
5957 return indicatePessimisticFixpoint();
5958
5959 const Function *F =
5960 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
5961
5962 // TODO: Is the checkForAllUses below useful for constants?
5963 if (!F)
5964 return indicatePessimisticFixpoint();
5965
5967 const IRPosition &FnPos = IRPosition::function(*F);
5968
5969 // Readonly means we cannot capture through memory.
5970 bool IsKnown;
5971 if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
5972 T.addKnownBits(NOT_CAPTURED_IN_MEM);
5973 if (IsKnown)
5974 addKnownBits(NOT_CAPTURED_IN_MEM);
5975 }
5976
5977 // Make sure all returned values are different than the underlying value.
5978 // TODO: we could do this in a more sophisticated way inside
5979 // AAReturnedValues, e.g., track all values that escape through returns
5980 // directly somehow.
5981 auto CheckReturnedArgs = [&](bool &UsedAssumedInformation) {
5983 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*F), this, Values,
5985 UsedAssumedInformation))
5986 return false;
5987 bool SeenConstant = false;
5988 for (const AA::ValueAndContext &VAC : Values) {
5989 if (isa<Constant>(VAC.getValue())) {
5990 if (SeenConstant)
5991 return false;
5992 SeenConstant = true;
5993 } else if (!isa<Argument>(VAC.getValue()) ||
5994 VAC.getValue() == getAssociatedArgument())
5995 return false;
5996 }
5997 return true;
5998 };
5999
6000 bool IsKnownNoUnwind;
6002 A, this, FnPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
6003 bool IsVoidTy = F->getReturnType()->isVoidTy();
6004 bool UsedAssumedInformation = false;
6005 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6006 T.addKnownBits(NOT_CAPTURED_IN_RET);
6007 if (T.isKnown(NOT_CAPTURED_IN_MEM))
6009 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6010 addKnownBits(NOT_CAPTURED_IN_RET);
6011 if (isKnown(NOT_CAPTURED_IN_MEM))
6012 return indicateOptimisticFixpoint();
6013 }
6014 }
6015 }
6016
6017 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
6018 // TODO(captures): Make this more precise.
6019 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
6020 if (capturesNothing(CI))
6021 return true;
6022 if (CI.isPassthrough()) {
6023 Follow = true;
6024 return true;
6025 }
6026 return checkUse(A, T, U, Follow);
6027 };
6028
6029 if (!A.checkForAllUses(UseCheck, *this, *V))
6030 return indicatePessimisticFixpoint();
6031
6032 AANoCapture::StateType &S = getState();
6033 auto Assumed = S.getAssumed();
6034 S.intersectAssumedBits(T.getAssumed());
6035 if (!isAssumedNoCaptureMaybeReturned())
6036 return indicatePessimisticFixpoint();
6037 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
6039}
6040
6041/// NoCapture attribute for function arguments.
6042struct AANoCaptureArgument final : AANoCaptureImpl {
6043 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
6044 : AANoCaptureImpl(IRP, A) {}
6045
6046 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
6047};
6048
6049/// NoCapture attribute for call site arguments.
6050struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6051 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
6052 : AANoCaptureImpl(IRP, A) {}
6053
6054 ChangeStatus updateImpl(Attributor &A) override {
6055 // TODO: Once we have call site specific value information we can provide
6056 // call site specific liveness information and then it makes
6057 // sense to specialize attributes for call sites arguments instead of
6058 // redirecting requests to the callee argument.
6059 Argument *Arg = getAssociatedArgument();
6060 if (!Arg)
6061 return indicatePessimisticFixpoint();
6062 const IRPosition &ArgPos = IRPosition::argument(*Arg);
6063 bool IsKnownNoCapture;
6064 const AANoCapture *ArgAA = nullptr;
6066 A, this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
6067 &ArgAA))
6068 return ChangeStatus::UNCHANGED;
6069 if (!ArgAA || !ArgAA->isAssumedNoCaptureMaybeReturned())
6070 return indicatePessimisticFixpoint();
6071 return clampStateAndIndicateChange(getState(), ArgAA->getState());
6072 }
6073
6074 void trackStatistics() const override {
6076 };
6077};
6078
6079/// NoCapture attribute for floating values.
6080struct AANoCaptureFloating final : AANoCaptureImpl {
6081 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
6082 : AANoCaptureImpl(IRP, A) {}
6083
6084 void trackStatistics() const override {
6086 }
6087};
6088
6089/// NoCapture attribute for function return value.
6090struct AANoCaptureReturned final : AANoCaptureImpl {
6091 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
6092 : AANoCaptureImpl(IRP, A) {
6093 llvm_unreachable("NoCapture is not applicable to function returns!");
6094 }
6095
6096 void initialize(Attributor &A) override {
6097 llvm_unreachable("NoCapture is not applicable to function returns!");
6098 }
6099
6100 ChangeStatus updateImpl(Attributor &A) override {
6101 llvm_unreachable("NoCapture is not applicable to function returns!");
6102 }
6103
6104 void trackStatistics() const override {}
6105};
6106
6107/// NoCapture attribute deduction for a call site return value.
6108struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6109 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
6110 : AANoCaptureImpl(IRP, A) {}
6111
6112 void initialize(Attributor &A) override {
6113 const Function *F = getAnchorScope();
6114 // Check what state the associated function can actually capture.
6115 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
6116 }
6117
6118 void trackStatistics() const override {
6120 }
6121};
6122} // namespace
6123
6124/// ------------------ Value Simplify Attribute ----------------------------
6125
6126bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6127 // FIXME: Add a typecast support.
6130 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6131 return false;
6132
6133 LLVM_DEBUG({
6135 dbgs() << "[ValueSimplify] is assumed to be "
6136 << **SimplifiedAssociatedValue << "\n";
6137 else
6138 dbgs() << "[ValueSimplify] is assumed to be <none>\n";
6139 });
6140 return true;
6141}
6142
6143namespace {
6144struct AAValueSimplifyImpl : AAValueSimplify {
6145 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6146 : AAValueSimplify(IRP, A) {}
6147
6148 void initialize(Attributor &A) override {
6149 if (getAssociatedValue().getType()->isVoidTy())
6150 indicatePessimisticFixpoint();
6151 if (A.hasSimplificationCallback(getIRPosition()))
6152 indicatePessimisticFixpoint();
6153 }
6154
6155 const std::string getAsStr(Attributor *A) const override {
6156 LLVM_DEBUG({
6157 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";
6158 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6159 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";
6160 });
6161 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6162 : "not-simple";
6163 }
6164
6165 void trackStatistics() const override {}
6166
6167 std::optional<Value *>
6168 getAssumedSimplifiedValue(Attributor &A) const override {
6169 return SimplifiedAssociatedValue;
6170 }
6171
6172 /// Ensure the return value is \p V with type \p Ty, if not possible return
6173 /// nullptr. If \p Check is true we will only verify such an operation would
6174 /// suceed and return a non-nullptr value if that is the case. No IR is
6175 /// generated or modified.
6176 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6177 bool Check) {
6178 if (auto *TypedV = AA::getWithType(V, Ty))
6179 return TypedV;
6180 if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
6181 return Check ? &V
6182 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6183 &V, &Ty, "", CtxI->getIterator());
6184 return nullptr;
6185 }
6186
6187 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6188 /// If \p Check is true we will only verify such an operation would suceed and
6189 /// return a non-nullptr value if that is the case. No IR is generated or
6190 /// modified.
6191 static Value *reproduceInst(Attributor &A,
6192 const AbstractAttribute &QueryingAA,
6193 Instruction &I, Type &Ty, Instruction *CtxI,
6194 bool Check, ValueToValueMapTy &VMap) {
6195 assert(CtxI && "Cannot reproduce an instruction without context!");
6196 if (Check && (I.mayReadFromMemory() ||
6197 !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
6198 /* TLI */ nullptr)))
6199 return nullptr;
6200 for (Value *Op : I.operands()) {
6201 Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
6202 if (!NewOp) {
6203 assert(Check && "Manifest of new value unexpectedly failed!");
6204 return nullptr;
6205 }
6206 if (!Check)
6207 VMap[Op] = NewOp;
6208 }
6209 if (Check)
6210 return &I;
6211
6212 Instruction *CloneI = I.clone();
6213 // TODO: Try to salvage debug information here.
6214 CloneI->setDebugLoc(DebugLoc());
6215 VMap[&I] = CloneI;
6216 CloneI->insertBefore(CtxI->getIterator());
6217 RemapInstruction(CloneI, VMap);
6218 return CloneI;
6219 }
6220
6221 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6222 /// If \p Check is true we will only verify such an operation would suceed and
6223 /// return a non-nullptr value if that is the case. No IR is generated or
6224 /// modified.
6225 static Value *reproduceValue(Attributor &A,
6226 const AbstractAttribute &QueryingAA, Value &V,
6227 Type &Ty, Instruction *CtxI, bool Check,
6228 ValueToValueMapTy &VMap) {
6229 if (const auto &NewV = VMap.lookup(&V))
6230 return NewV;
6231 bool UsedAssumedInformation = false;
6232 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6233 V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6234 if (!SimpleV.has_value())
6235 return PoisonValue::get(&Ty);
6236 Value *EffectiveV = &V;
6237 if (*SimpleV)
6238 EffectiveV = *SimpleV;
6239 if (auto *C = dyn_cast<Constant>(EffectiveV))
6240 return C;
6241 if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
6242 A.getInfoCache()))
6243 return ensureType(A, *EffectiveV, Ty, CtxI, Check);
6244 if (auto *I = dyn_cast<Instruction>(EffectiveV))
6245 if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
6246 return ensureType(A, *NewV, Ty, CtxI, Check);
6247 return nullptr;
6248 }
6249
6250 /// Return a value we can use as replacement for the associated one, or
6251 /// nullptr if we don't have one that makes sense.
6252 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6253 Value *NewV = SimplifiedAssociatedValue
6254 ? *SimplifiedAssociatedValue
6255 : UndefValue::get(getAssociatedType());
6256 if (NewV && NewV != &getAssociatedValue()) {
6257 ValueToValueMapTy VMap;
6258 // First verify we can reprduce the value with the required type at the
6259 // context location before we actually start modifying the IR.
6260 if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6261 /* CheckOnly */ true, VMap))
6262 return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6263 /* CheckOnly */ false, VMap);
6264 }
6265 return nullptr;
6266 }
6267
6268 /// Helper function for querying AAValueSimplify and updating candidate.
6269 /// \param IRP The value position we are trying to unify with SimplifiedValue
6270 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6271 const IRPosition &IRP, bool Simplify = true) {
6272 bool UsedAssumedInformation = false;
6273 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6274 if (Simplify)
6275 QueryingValueSimplified = A.getAssumedSimplified(
6276 IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6277 return unionAssumed(QueryingValueSimplified);
6278 }
6279
6280 /// Returns a candidate is found or not
6281 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6282 if (!getAssociatedValue().getType()->isIntegerTy())
6283 return false;
6284
6285 // This will also pass the call base context.
6286 const auto *AA =
6287 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6288 if (!AA)
6289 return false;
6290
6291 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
6292
6293 if (!COpt) {
6294 SimplifiedAssociatedValue = std::nullopt;
6295 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6296 return true;
6297 }
6298 if (auto *C = *COpt) {
6299 SimplifiedAssociatedValue = C;
6300 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6301 return true;
6302 }
6303 return false;
6304 }
6305
6306 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6307 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6308 return true;
6309 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6310 return true;
6311 return false;
6312 }
6313
6314 ChangeStatus manifest(Attributor &A) override {
6315 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6316 for (auto &U : getAssociatedValue().uses()) {
6317 // Check if we need to adjust the insertion point to make sure the IR is
6318 // valid.
6319 Instruction *IP = dyn_cast<Instruction>(U.getUser());
6320 if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
6321 IP = PHI->getIncomingBlock(U)->getTerminator();
6322 if (auto *NewV = manifestReplacementValue(A, IP)) {
6323 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()
6324 << " -> " << *NewV << " :: " << *this << "\n");
6325 if (A.changeUseAfterManifest(U, *NewV))
6326 Changed = ChangeStatus::CHANGED;
6327 }
6328 }
6329
6330 return Changed | AAValueSimplify::manifest(A);
6331 }
6332
6333 ChangeStatus indicatePessimisticFixpoint() override {
6334 SimplifiedAssociatedValue = &getAssociatedValue();
6335 return AAValueSimplify::indicatePessimisticFixpoint();
6336 }
6337};
6338
6339struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6340 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6341 : AAValueSimplifyImpl(IRP, A) {}
6342
6343 void initialize(Attributor &A) override {
6344 AAValueSimplifyImpl::initialize(A);
6345 if (A.hasAttr(getIRPosition(),
6346 {Attribute::InAlloca, Attribute::Preallocated,
6347 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6348 /* IgnoreSubsumingPositions */ true))
6349 indicatePessimisticFixpoint();
6350 }
6351
6352 ChangeStatus updateImpl(Attributor &A) override {
6353 // Byval is only replacable if it is readonly otherwise we would write into
6354 // the replaced value and not the copy that byval creates implicitly.
6355 Argument *Arg = getAssociatedArgument();
6356 if (Arg->hasByValAttr()) {
6357 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6358 // there is no race by not copying a constant byval.
6359 bool IsKnown;
6360 if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
6361 return indicatePessimisticFixpoint();
6362 }
6363
6364 auto Before = SimplifiedAssociatedValue;
6365
6366 auto PredForCallSite = [&](AbstractCallSite ACS) {
6367 const IRPosition &ACSArgPos =
6368 IRPosition::callsite_argument(ACS, getCallSiteArgNo());
6369 // Check if a coresponding argument was found or if it is on not
6370 // associated (which can happen for callback calls).
6371 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6372 return false;
6373
6374 // Simplify the argument operand explicitly and check if the result is
6375 // valid in the current scope. This avoids refering to simplified values
6376 // in other functions, e.g., we don't want to say a an argument in a
6377 // static function is actually an argument in a different function.
6378 bool UsedAssumedInformation = false;
6379 std::optional<Constant *> SimpleArgOp =
6380 A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
6381 if (!SimpleArgOp)
6382 return true;
6383 if (!*SimpleArgOp)
6384 return false;
6385 if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
6386 return false;
6387 return unionAssumed(*SimpleArgOp);
6388 };
6389
6390 // Generate a answer specific to a call site context.
6391 bool Success;
6392 bool UsedAssumedInformation = false;
6393 if (hasCallBaseContext() &&
6394 getCallBaseContext()->getCalledOperand() == Arg->getParent())
6395 Success = PredForCallSite(
6396 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6397 else
6398 Success = A.checkForAllCallSites(PredForCallSite, *this, true,
6399 UsedAssumedInformation);
6400
6401 if (!Success)
6402 if (!askSimplifiedValueForOtherAAs(A))
6403 return indicatePessimisticFixpoint();
6404
6405 // If a candidate was found in this update, return CHANGED.
6406 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6407 : ChangeStatus ::CHANGED;
6408 }
6409
6410 void trackStatistics() const override {
6411 STATS_DECLTRACK_ARG_ATTR(value_simplify)
6412 }
6413};
6414
6415struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6416 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6417 : AAValueSimplifyImpl(IRP, A) {}
6418
6419 std::optional<Value *>
6420 getAssumedSimplifiedValue(Attributor &A) const override {
6421 if (!isValidState())
6422 return nullptr;
6423 return SimplifiedAssociatedValue;
6424 }
6425
6426 ChangeStatus updateImpl(Attributor &A) override {
6427 auto Before = SimplifiedAssociatedValue;
6428
6429 auto ReturnInstCB = [&](Instruction &I) {
6430 auto &RI = cast<ReturnInst>(I);
6431 return checkAndUpdate(
6432 A, *this,
6433 IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
6434 };
6435
6436 bool UsedAssumedInformation = false;
6437 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
6438 UsedAssumedInformation))
6439 if (!askSimplifiedValueForOtherAAs(A))
6440 return indicatePessimisticFixpoint();
6441
6442 // If a candidate was found in this update, return CHANGED.
6443 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6444 : ChangeStatus ::CHANGED;
6445 }
6446
6447 ChangeStatus manifest(Attributor &A) override {
6448 // We queried AAValueSimplify for the returned values so they will be
6449 // replaced if a simplified form was found. Nothing to do here.
6450 return ChangeStatus::UNCHANGED;
6451 }
6452
6453 void trackStatistics() const override {
6454 STATS_DECLTRACK_FNRET_ATTR(value_simplify)
6455 }
6456};
6457
6458struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6459 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6460 : AAValueSimplifyImpl(IRP, A) {}
6461
6462 void initialize(Attributor &A) override {
6463 AAValueSimplifyImpl::initialize(A);
6464 Value &V = getAnchorValue();
6465
6466 // TODO: add other stuffs
6467 if (isa<Constant>(V))
6468 indicatePessimisticFixpoint();
6469 }
6470
6471 ChangeStatus updateImpl(Attributor &A) override {
6472 auto Before = SimplifiedAssociatedValue;
6473 if (!askSimplifiedValueForOtherAAs(A))
6474 return indicatePessimisticFixpoint();
6475
6476 // If a candidate was found in this update, return CHANGED.
6477 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6478 : ChangeStatus ::CHANGED;
6479 }
6480
6481 void trackStatistics() const override {
6482 STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
6483 }
6484};
6485
6486struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6487 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6488 : AAValueSimplifyImpl(IRP, A) {}
6489
6490 void initialize(Attributor &A) override {
6491 SimplifiedAssociatedValue = nullptr;
6492 indicateOptimisticFixpoint();
6493 }
6494 ChangeStatus updateImpl(Attributor &A) override {
6496 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6497 }
6498 void trackStatistics() const override {
6499 STATS_DECLTRACK_FN_ATTR(value_simplify)
6500 }
6501};
6502
6503struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6504 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6505 : AAValueSimplifyFunction(IRP, A) {}
6506 void trackStatistics() const override {
6507 STATS_DECLTRACK_CS_ATTR(value_simplify)
6508 }
6509};
6510
6511struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6512 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6513 : AAValueSimplifyImpl(IRP, A) {}
6514
6515 void initialize(Attributor &A) override {
6516 AAValueSimplifyImpl::initialize(A);
6517 Function *Fn = getAssociatedFunction();
6518 assert(Fn && "Did expect an associted function");
6519 for (Argument &Arg : Fn->args()) {
6520 if (Arg.hasReturnedAttr()) {
6521 auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
6522 Arg.getArgNo());
6524 checkAndUpdate(A, *this, IRP))
6525 indicateOptimisticFixpoint();
6526 else
6527 indicatePessimisticFixpoint();
6528 return;
6529 }
6530 }
6531 }
6532
6533 ChangeStatus updateImpl(Attributor &A) override {
6534 return indicatePessimisticFixpoint();
6535 }
6536
6537 void trackStatistics() const override {
6538 STATS_DECLTRACK_CSRET_ATTR(value_simplify)
6539 }
6540};
6541
6542struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6543 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6544 : AAValueSimplifyFloating(IRP, A) {}
6545
6546 ChangeStatus manifest(Attributor &A) override {
6547 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6548 // TODO: We should avoid simplification duplication to begin with.
6549 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6550 IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
6551 if (FloatAA && FloatAA->getState().isValidState())
6552 return Changed;
6553
6554 if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
6555 Use &U = cast<CallBase>(&getAnchorValue())
6556 ->getArgOperandUse(getCallSiteArgNo());
6557 if (A.changeUseAfterManifest(U, *NewV))
6558 Changed = ChangeStatus::CHANGED;
6559 }
6560
6561 return Changed | AAValueSimplify::manifest(A);
6562 }
6563
6564 void trackStatistics() const override {
6565 STATS_DECLTRACK_CSARG_ATTR(value_simplify)
6566 }
6567};
6568} // namespace
6569
6570/// ----------------------- Heap-To-Stack Conversion ---------------------------
6571namespace {
6572struct AAHeapToStackFunction final : public AAHeapToStack {
6573
6574 static bool isGlobalizedLocal(const CallBase &CB) {
6575 Attribute A = CB.getFnAttr("alloc-family");
6576 return A.isValid() && A.getValueAsString() == "__kmpc_alloc_shared";
6577 }
6578
6579 struct AllocationInfo {
6580 /// The call that allocates the memory.
6581 CallBase *const CB;
6582
6583 /// Whether this allocation is an OpenMP globalized local variable.
6584 bool IsGlobalizedLocal = false;
6585
6586 /// The status wrt. a rewrite.
6587 enum {
6588 STACK_DUE_TO_USE,
6589 STACK_DUE_TO_FREE,
6590 INVALID,
6591 } Status = STACK_DUE_TO_USE;
6592
6593 /// Flag to indicate if we encountered a use that might free this allocation
6594 /// but which is not in the deallocation infos.
6595 bool HasPotentiallyFreeingUnknownUses = false;
6596
6597 /// Flag to indicate that we should place the new alloca in the function
6598 /// entry block rather than where the call site (CB) is.
6599 bool MoveAllocaIntoEntry = true;
6600
6601 /// The set of free calls that use this allocation.
6602 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6603 };
6604
6605 struct DeallocationInfo {
6606 /// The call that deallocates the memory.
6607 CallBase *const CB;
6608 /// The value freed by the call.
6609 Value *FreedOp;
6610
6611 /// Flag to indicate if we don't know all objects this deallocation might
6612 /// free.
6613 bool MightFreeUnknownObjects = false;
6614
6615 /// The set of allocation calls that are potentially freed.
6616 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6617 };
6618
6619 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6620 : AAHeapToStack(IRP, A) {}
6621
6622 ~AAHeapToStackFunction() override {
6623 // Ensure we call the destructor so we release any memory allocated in the
6624 // sets.
6625 for (auto &It : AllocationInfos)
6626 It.second->~AllocationInfo();
6627 for (auto &It : DeallocationInfos)
6628 It.second->~DeallocationInfo();
6629 }
6630
6631 void initialize(Attributor &A) override {
6632 AAHeapToStack::initialize(A);
6633
6634 const Function *F = getAnchorScope();
6635 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6636
6637 auto AllocationIdentifierCB = [&](Instruction &I) {
6638 CallBase *CB = dyn_cast<CallBase>(&I);
6639 if (!CB)
6640 return true;
6641 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6642 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
6643 return true;
6644 }
6645 // To do heap to stack, we need to know that the allocation itself is
6646 // removable once uses are rewritten, and that we can initialize the
6647 // alloca to the same pattern as the original allocation result.
6648 if (isRemovableAlloc(CB, TLI)) {
6649 auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
6650 if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
6651 AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
6652 AllocationInfos[CB] = AI;
6653 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6654 }
6655 }
6656 return true;
6657 };
6658
6659 bool UsedAssumedInformation = false;
6660 bool Success = A.checkForAllCallLikeInstructions(
6661 AllocationIdentifierCB, *this, UsedAssumedInformation,
6662 /* CheckBBLivenessOnly */ false,
6663 /* CheckPotentiallyDead */ true);
6664 (void)Success;
6665 assert(Success && "Did not expect the call base visit callback to fail!");
6666
6668 [](const IRPosition &, const AbstractAttribute *,
6669 bool &) -> std::optional<Value *> { return nullptr; };
6670 for (const auto &It : AllocationInfos)
6671 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6672 SCB);
6673 for (const auto &It : DeallocationInfos)
6674 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6675 SCB);
6676 }
6677
6678 const std::string getAsStr(Attributor *A) const override {
6679 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6680 for (const auto &It : AllocationInfos) {
6681 if (It.second->Status == AllocationInfo::INVALID)
6682 ++NumInvalidMallocs;
6683 else
6684 ++NumH2SMallocs;
6685 }
6686 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
6687 std::to_string(NumInvalidMallocs);
6688 }
6689
6690 void trackStatistics() const override {
6691 STATS_DECL(
6692 MallocCalls, Function,
6693 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6694 for (const auto &It : AllocationInfos)
6695 if (It.second->Status != AllocationInfo::INVALID)
6696 ++BUILD_STAT_NAME(MallocCalls, Function);
6697 }
6698
6699 bool isAssumedHeapToStack(const CallBase &CB) const override {
6700 if (isValidState())
6701 if (AllocationInfo *AI =
6702 AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
6703 return AI->Status != AllocationInfo::INVALID;
6704 return false;
6705 }
6706
6707 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6708 if (!isValidState())
6709 return false;
6710
6711 for (const auto &It : AllocationInfos) {
6712 AllocationInfo &AI = *It.second;
6713 if (AI.Status == AllocationInfo::INVALID)
6714 continue;
6715
6716 if (AI.PotentialFreeCalls.count(&CB))
6717 return true;
6718 }
6719
6720 return false;
6721 }
6722
6723 ChangeStatus manifest(Attributor &A) override {
6724 assert(getState().isValidState() &&
6725 "Attempted to manifest an invalid state!");
6726
6727 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6728 Function *F = getAnchorScope();
6729 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6730
6731 for (auto &It : AllocationInfos) {
6732 AllocationInfo &AI = *It.second;
6733 if (AI.Status == AllocationInfo::INVALID)
6734 continue;
6735
6736 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6737 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
6738 A.deleteAfterManifest(*FreeCall);
6739 HasChanged = ChangeStatus::CHANGED;
6740 }
6741
6742 LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB
6743 << "\n");
6744
6745 auto Remark = [&](OptimizationRemark OR) {
6746 if (AI.IsGlobalizedLocal)
6747 return OR << "Moving globalized variable to the stack.";
6748 return OR << "Moving memory allocation from the heap to the stack.";
6749 };
6750 if (AI.IsGlobalizedLocal)
6751 A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
6752 else
6753 A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);
6754
6755 const DataLayout &DL = A.getInfoCache().getDL();
6756 Value *Size;
6757 std::optional<APInt> SizeAPI = getSize(A, *this, AI);
6758 if (SizeAPI) {
6759 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6760 } else {
6761 ObjectSizeOpts Opts;
6762 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6763 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6764 assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&
6765 cast<ConstantInt>(SizeOffsetPair.Offset)->isZero());
6766 Size = SizeOffsetPair.Size;
6767 }
6768
6769 BasicBlock::iterator IP = AI.MoveAllocaIntoEntry
6770 ? F->getEntryBlock().begin()
6771 : AI.CB->getIterator();
6772
6773 Align Alignment(1);
6774 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6775 Alignment = std::max(Alignment, *RetAlign);
6776 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
6777 std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
6778 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6779 "Expected an alignment during manifest!");
6780 Alignment =
6781 std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
6782 }
6783
6784 // TODO: Hoist the alloca towards the function entry.
6785 unsigned AS = DL.getAllocaAddrSpace();
6786 Instruction *Alloca =
6787 new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
6788 AI.CB->getName() + ".h2s", IP);
6789
6790 if (Alloca->getType() != AI.CB->getType())
6791 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6792 Alloca, AI.CB->getType(), "malloc_cast", AI.CB->getIterator());
6793
6794 auto *I8Ty = Type::getInt8Ty(F->getContext());
6795 auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
6796 assert(InitVal &&
6797 "Must be able to materialize initial memory state of allocation");
6798
6799 A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);
6800
6801 if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
6802 auto *NBB = II->getNormalDest();
6803 UncondBrInst::Create(NBB, AI.CB->getParent());
6804 A.deleteAfterManifest(*AI.CB);
6805 } else {
6806 A.deleteAfterManifest(*AI.CB);
6807 }
6808
6809 // Initialize the alloca with the same value as used by the allocation
6810 // function. We can skip undef as the initial value of an alloc is
6811 // undef, and the memset would simply end up being DSEd.
6812 if (!isa<UndefValue>(InitVal)) {
6813 IRBuilder<> Builder(Alloca->getNextNode());
6814 // TODO: Use alignment above if align!=1
6815 Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
6816 }
6817 HasChanged = ChangeStatus::CHANGED;
6818 }
6819
6820 return HasChanged;
6821 }
6822
6823 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
6824 Value &V) {
6825 bool UsedAssumedInformation = false;
6826 std::optional<Constant *> SimpleV =
6827 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6828 if (!SimpleV)
6829 return APInt(64, 0);
6830 if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
6831 return CI->getValue();
6832 return std::nullopt;
6833 }
6834
6835 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
6836 AllocationInfo &AI) {
6837 auto Mapper = [&](const Value *V) -> const Value * {
6838 bool UsedAssumedInformation = false;
6839 if (std::optional<Constant *> SimpleV =
6840 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6841 if (*SimpleV)
6842 return *SimpleV;
6843 return V;
6844 };
6845
6846 const Function *F = getAnchorScope();
6847 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6848 return getAllocSize(AI.CB, TLI, Mapper);
6849 }
6850
6851 /// Collection of all malloc-like calls in a function with associated
6852 /// information.
6853 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6854
6855 /// Collection of all free-like calls in a function with associated
6856 /// information.
6857 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6858
6859 ChangeStatus updateImpl(Attributor &A) override;
6860};
6861
6862ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
6864 const Function *F = getAnchorScope();
6865 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6866
6867 const auto *LivenessAA =
6868 A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);
6869
6870 MustBeExecutedContextExplorer *Explorer =
6871 A.getInfoCache().getMustBeExecutedContextExplorer();
6872
6873 bool StackIsAccessibleByOtherThreads =
6874 A.getInfoCache().stackIsAccessibleByOtherThreads();
6875
6876 LoopInfo *LI =
6877 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6878 std::optional<bool> MayContainIrreducibleControl;
6879 auto IsInLoop = [&](BasicBlock &BB) {
6880 if (&F->getEntryBlock() == &BB)
6881 return false;
6882 if (!MayContainIrreducibleControl.has_value())
6883 MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
6884 if (*MayContainIrreducibleControl)
6885 return true;
6886 if (!LI)
6887 return true;
6888 return LI->getLoopFor(&BB) != nullptr;
6889 };
6890
6891 // Flag to ensure we update our deallocation information at most once per
6892 // updateImpl call and only if we use the free check reasoning.
6893 bool HasUpdatedFrees = false;
6894
6895 auto UpdateFrees = [&]() {
6896 HasUpdatedFrees = true;
6897
6898 for (auto &It : DeallocationInfos) {
6899 DeallocationInfo &DI = *It.second;
6900 // For now we cannot use deallocations that have unknown inputs, skip
6901 // them.
6902 if (DI.MightFreeUnknownObjects)
6903 continue;
6904
6905 // No need to analyze dead calls, ignore them instead.
6906 bool UsedAssumedInformation = false;
6907 if (A.isAssumedDead(*DI.CB, this, LivenessAA, UsedAssumedInformation,
6908 /* CheckBBLivenessOnly */ true))
6909 continue;
6910
6911 // Use the non-optimistic version to get the freed object.
6912 Value *Obj = getUnderlyingObject(DI.FreedOp);
6913 if (!Obj) {
6914 LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");
6915 DI.MightFreeUnknownObjects = true;
6916 continue;
6917 }
6918
6919 // Free of null and undef can be ignored as no-ops (or UB in the latter
6920 // case).
6922 continue;
6923
6924 CallBase *ObjCB = dyn_cast<CallBase>(Obj);
6925 if (!ObjCB) {
6926 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj
6927 << "\n");
6928 DI.MightFreeUnknownObjects = true;
6929 continue;
6930 }
6931
6932 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
6933 if (!AI) {
6934 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj
6935 << "\n");
6936 DI.MightFreeUnknownObjects = true;
6937 continue;
6938 }
6939
6940 DI.PotentialAllocationCalls.insert(ObjCB);
6941 }
6942 };
6943
6944 auto FreeCheck = [&](AllocationInfo &AI) {
6945 // If the stack is not accessible by other threads, the "must-free" logic
6946 // doesn't apply as the pointer could be shared and needs to be places in
6947 // "shareable" memory.
6948 if (!StackIsAccessibleByOtherThreads) {
6949 bool IsKnownNoSycn;
6951 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoSycn)) {
6952 LLVM_DEBUG(
6953 dbgs() << "[H2S] found an escaping use, stack is not accessible by "
6954 "other threads and function is not nosync:\n");
6955 return false;
6956 }
6957 }
6958 if (!HasUpdatedFrees)
6959 UpdateFrees();
6960
6961 // TODO: Allow multi exit functions that have different free calls.
6962 if (AI.PotentialFreeCalls.size() != 1) {
6963 LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "
6964 << AI.PotentialFreeCalls.size() << "\n");
6965 return false;
6966 }
6967 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
6968 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
6969 if (!DI) {
6970 LLVM_DEBUG(
6971 dbgs() << "[H2S] unique free call was not known as deallocation call "
6972 << *UniqueFree << "\n");
6973 return false;
6974 }
6975 if (DI->MightFreeUnknownObjects) {
6976 LLVM_DEBUG(
6977 dbgs() << "[H2S] unique free call might free unknown allocations\n");
6978 return false;
6979 }
6980 if (DI->PotentialAllocationCalls.empty())
6981 return true;
6982 if (DI->PotentialAllocationCalls.size() > 1) {
6983 LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "
6984 << DI->PotentialAllocationCalls.size()
6985 << " different allocations\n");
6986 return false;
6987 }
6988 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
6989 LLVM_DEBUG(
6990 dbgs()
6991 << "[H2S] unique free call not known to free this allocation but "
6992 << **DI->PotentialAllocationCalls.begin() << "\n");
6993 return false;
6994 }
6995
6996 // __kmpc_alloc_shared and __kmpc_free_shared are by construction matched.
6997 if (!AI.IsGlobalizedLocal) {
6998 Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
6999 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7000 LLVM_DEBUG(dbgs() << "[H2S] unique free call might not be executed "
7001 "with the allocation "
7002 << *UniqueFree << "\n");
7003 return false;
7004 }
7005 }
7006 return true;
7007 };
7008
7009 auto UsesCheck = [&](AllocationInfo &AI) {
7010 bool ValidUsesOnly = true;
7011
7012 auto Pred = [&](const Use &U, bool &Follow) -> bool {
7013 Instruction *UserI = cast<Instruction>(U.getUser());
7014 if (isa<LoadInst>(UserI))
7015 return true;
7016 if (auto *SI = dyn_cast<StoreInst>(UserI)) {
7017 if (SI->getValueOperand() == U.get()) {
7019 << "[H2S] escaping store to memory: " << *UserI << "\n");
7020 ValidUsesOnly = false;
7021 } else {
7022 // A store into the malloc'ed memory is fine.
7023 }
7024 return true;
7025 }
7026 if (auto *CB = dyn_cast<CallBase>(UserI)) {
7027 if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
7028 return true;
7029 if (DeallocationInfos.count(CB)) {
7030 AI.PotentialFreeCalls.insert(CB);
7031 return true;
7032 }
7033
7034 unsigned ArgNo = CB->getArgOperandNo(&U);
7035 auto CBIRP = IRPosition::callsite_argument(*CB, ArgNo);
7036
7037 bool IsKnownNoCapture;
7038 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7039 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoCapture);
7040
7041 // If a call site argument use is nofree, we are fine.
7042 bool IsKnownNoFree;
7043 bool IsAssumedNoFree = AA::hasAssumedIRAttr<Attribute::NoFree>(
7044 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoFree);
7045
7046 if (!IsAssumedNoCapture ||
7047 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7048 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7049
7050 // Emit a missed remark if this is missed OpenMP globalization.
7051 auto Remark = [&](OptimizationRemarkMissed ORM) {
7052 return ORM
7053 << "Could not move globalized variable to the stack. "
7054 "Variable is potentially captured in call. Mark "
7055 "parameter as `__attribute__((noescape))` to override.";
7056 };
7057
7058 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7059 A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);
7060
7061 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
7062 ValidUsesOnly = false;
7063 }
7064 return true;
7065 }
7066
7067 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
7068 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
7069 Follow = true;
7070 return true;
7071 }
7072 // Unknown user for which we can not track uses further (in a way that
7073 // makes sense).
7074 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
7075 ValidUsesOnly = false;
7076 return true;
7077 };
7078 if (!A.checkForAllUses(Pred, *this, *AI.CB, /* CheckBBLivenessOnly */ false,
7079 DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,
7080 [&](const Use &OldU, const Use &NewU) {
7081 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7082 return !SI || StackIsAccessibleByOtherThreads ||
7083 AA::isAssumedThreadLocalObject(
7084 A, *SI->getPointerOperand(), *this);
7085 }))
7086 return false;
7087 return ValidUsesOnly;
7088 };
7089
7090 // The actual update starts here. We look at all allocations and depending on
7091 // their status perform the appropriate check(s).
7092 for (auto &It : AllocationInfos) {
7093 AllocationInfo &AI = *It.second;
7094 if (AI.Status == AllocationInfo::INVALID)
7095 continue;
7096
7097 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
7098 std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
7099 if (!APAlign) {
7100 // Can't generate an alloca which respects the required alignment
7101 // on the allocation.
7102 LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB
7103 << "\n");
7104 AI.Status = AllocationInfo::INVALID;
7106 continue;
7107 }
7108 if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
7109 !APAlign->isPowerOf2()) {
7110 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign
7111 << "\n");
7112 AI.Status = AllocationInfo::INVALID;
7114 continue;
7115 }
7116 }
7117
7118 std::optional<APInt> Size = getSize(A, *this, AI);
7119 if (!AI.IsGlobalizedLocal && MaxHeapToStackSize != -1) {
7120 if (!Size || Size->ugt(MaxHeapToStackSize)) {
7121 LLVM_DEBUG({
7122 if (!Size)
7123 dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";
7124 else
7125 dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "
7126 << MaxHeapToStackSize << "\n";
7127 });
7128
7129 AI.Status = AllocationInfo::INVALID;
7131 continue;
7132 }
7133 }
7134
7135 switch (AI.Status) {
7136 case AllocationInfo::STACK_DUE_TO_USE:
7137 if (UsesCheck(AI))
7138 break;
7139 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7140 [[fallthrough]];
7141 case AllocationInfo::STACK_DUE_TO_FREE:
7142 if (FreeCheck(AI))
7143 break;
7144 AI.Status = AllocationInfo::INVALID;
7146 break;
7147 case AllocationInfo::INVALID:
7148 llvm_unreachable("Invalid allocations should never reach this point!");
7149 };
7150
7151 // Check if we still think we can move it into the entry block. If the
7152 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7153 // ignore the potential complications associated with loops.
7154 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7155 if (AI.MoveAllocaIntoEntry &&
7156 (!Size.has_value() ||
7157 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7158 AI.MoveAllocaIntoEntry = false;
7159 }
7160
7161 return Changed;
7162}
7163} // namespace
7164
7165/// ----------------------- Privatizable Pointers ------------------------------
7166namespace {
7167struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
7168 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7169 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7170
7171 ChangeStatus indicatePessimisticFixpoint() override {
7172 AAPrivatizablePtr::indicatePessimisticFixpoint();
7173 PrivatizableType = nullptr;
7174 return ChangeStatus::CHANGED;
7175 }
7176
7177 /// Identify the type we can chose for a private copy of the underlying
7178 /// argument. std::nullopt means it is not clear yet, nullptr means there is
7179 /// none.
7180 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7181
7182 /// Return a privatizable type that encloses both T0 and T1.
7183 /// TODO: This is merely a stub for now as we should manage a mapping as well.
7184 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7185 std::optional<Type *> T1) {
7186 if (!T0)
7187 return T1;
7188 if (!T1)
7189 return T0;
7190 if (T0 == T1)
7191 return T0;
7192 return nullptr;
7193 }
7194
7195 std::optional<Type *> getPrivatizableType() const override {
7196 return PrivatizableType;
7197 }
7198
7199 const std::string getAsStr(Attributor *A) const override {
7200 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7201 }
7202
7203protected:
7204 std::optional<Type *> PrivatizableType;
7205};
7206
7207// TODO: Do this for call site arguments (probably also other values) as well.
7208
7209struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
7210 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7211 : AAPrivatizablePtrImpl(IRP, A) {}
7212
7213 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7214 // If this is a byval argument and we know all the call sites (so we can
7215 // rewrite them), there is no need to check them explicitly.
7216 bool UsedAssumedInformation = false;
7218 A.getAttrs(getIRPosition(), {Attribute::ByVal}, Attrs,
7219 /* IgnoreSubsumingPositions */ true);
7220 if (!Attrs.empty() &&
7221 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
7222 true, UsedAssumedInformation))
7223 return Attrs[0].getValueAsType();
7224
7225 std::optional<Type *> Ty;
7226 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7227
7228 // Make sure the associated call site argument has the same type at all call
7229 // sites and it is an allocation we know is safe to privatize, for now that
7230 // means we only allow alloca instructions.
7231 // TODO: We can additionally analyze the accesses in the callee to create
7232 // the type from that information instead. That is a little more
7233 // involved and will be done in a follow up patch.
7234 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7235 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7236 // Check if a coresponding argument was found or if it is one not
7237 // associated (which can happen for callback calls).
7238 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7239 return false;
7240
7241 // Check that all call sites agree on a type.
7242 auto *PrivCSArgAA =
7243 A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
7244 if (!PrivCSArgAA)
7245 return false;
7246 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7247
7248 LLVM_DEBUG({
7249 dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
7250 if (CSTy && *CSTy)
7251 (*CSTy)->print(dbgs());
7252 else if (CSTy)
7253 dbgs() << "<nullptr>";
7254 else
7255 dbgs() << "<none>";
7256 });
7257
7258 Ty = combineTypes(Ty, CSTy);
7259
7260 LLVM_DEBUG({
7261 dbgs() << " : New Type: ";
7262 if (Ty && *Ty)
7263 (*Ty)->print(dbgs());
7264 else if (Ty)
7265 dbgs() << "<nullptr>";
7266 else
7267 dbgs() << "<none>";
7268 dbgs() << "\n";
7269 });
7270
7271 return !Ty || *Ty;
7272 };
7273
7274 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7275 UsedAssumedInformation))
7276 return nullptr;
7277 return Ty;
7278 }
7279
7280 ChangeStatus updateImpl(Attributor &A) override {
7281 PrivatizableType = identifyPrivatizableType(A);
7282 if (!PrivatizableType)
7283 return ChangeStatus::UNCHANGED;
7284 if (!*PrivatizableType)
7285 return indicatePessimisticFixpoint();
7286
7287 // The dependence is optional so we don't give up once we give up on the
7288 // alignment.
7289 A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
7290 DepClassTy::OPTIONAL);
7291
7292 // Avoid arguments with padding for now.
7293 if (!A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7294 !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
7295 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
7296 return indicatePessimisticFixpoint();
7297 }
7298
7299 // Collect the types that will replace the privatizable type in the function
7300 // signature.
7301 SmallVector<Type *, 16> ReplacementTypes;
7302 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7303
7304 // Verify callee and caller agree on how the promoted argument would be
7305 // passed.
7306 Function &Fn = *getIRPosition().getAnchorScope();
7307 const auto *TTI =
7308 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7309 if (!TTI) {
7310 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
7311 << Fn.getName() << "\n");
7312 return indicatePessimisticFixpoint();
7313 }
7314
7315 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7316 CallBase *CB = ACS.getInstruction();
7317 return TTI->areTypesABICompatible(
7318 CB->getCaller(),
7320 ReplacementTypes);
7321 };
7322 bool UsedAssumedInformation = false;
7323 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7324 UsedAssumedInformation)) {
7325 LLVM_DEBUG(
7326 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
7327 << Fn.getName() << "\n");
7328 return indicatePessimisticFixpoint();
7329 }
7330
7331 // Register a rewrite of the argument.
7332 Argument *Arg = getAssociatedArgument();
7333 if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7334 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");
7335 return indicatePessimisticFixpoint();
7336 }
7337
7338 unsigned ArgNo = Arg->getArgNo();
7339
7340 // Helper to check if for the given call site the associated argument is
7341 // passed to a callback where the privatization would be different.
7342 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7343 SmallVector<const Use *, 4> CallbackUses;
7344 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7345 for (const Use *U : CallbackUses) {
7346 AbstractCallSite CBACS(U);
7347 assert(CBACS && CBACS.isCallbackCall());
7348 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7349 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7350
7351 LLVM_DEBUG({
7352 dbgs()
7353 << "[AAPrivatizablePtr] Argument " << *Arg
7354 << "check if can be privatized in the context of its parent ("
7355 << Arg->getParent()->getName()
7356 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7357 "callback ("
7358 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7359 << ")\n[AAPrivatizablePtr] " << CBArg << " : "
7360 << CBACS.getCallArgOperand(CBArg) << " vs "
7361 << CB.getArgOperand(ArgNo) << "\n"
7362 << "[AAPrivatizablePtr] " << CBArg << " : "
7363 << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";
7364 });
7365
7366 if (CBArgNo != int(ArgNo))
7367 continue;
7368 const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7369 *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
7370 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7371 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7372 if (!CBArgPrivTy)
7373 continue;
7374 if (*CBArgPrivTy == PrivatizableType)
7375 continue;
7376 }
7377
7378 LLVM_DEBUG({
7379 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7380 << " cannot be privatized in the context of its parent ("
7381 << Arg->getParent()->getName()
7382 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7383 "callback ("
7384 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7385 << ").\n[AAPrivatizablePtr] for which the argument "
7386 "privatization is not compatible.\n";
7387 });
7388 return false;
7389 }
7390 }
7391 return true;
7392 };
7393
7394 // Helper to check if for the given call site the associated argument is
7395 // passed to a direct call where the privatization would be different.
7396 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7397 CallBase *DC = cast<CallBase>(ACS.getInstruction());
7398 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7399 assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&
7400 "Expected a direct call operand for callback call operand");
7401
7402 Function *DCCallee =
7404 LLVM_DEBUG({
7405 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7406 << " check if be privatized in the context of its parent ("
7407 << Arg->getParent()->getName()
7408 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7409 "direct call of ("
7410 << DCArgNo << "@" << DCCallee->getName() << ").\n";
7411 });
7412
7413 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7414 const auto *DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7415 *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
7416 DepClassTy::REQUIRED);
7417 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7418 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7419 if (!DCArgPrivTy)
7420 return true;
7421 if (*DCArgPrivTy == PrivatizableType)
7422 return true;
7423 }
7424 }
7425
7426 LLVM_DEBUG({
7427 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7428 << " cannot be privatized in the context of its parent ("
7429 << Arg->getParent()->getName()
7430 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7431 "direct call of ("
7433 << ").\n[AAPrivatizablePtr] for which the argument "
7434 "privatization is not compatible.\n";
7435 });
7436 return false;
7437 };
7438
7439 // Helper to check if the associated argument is used at the given abstract
7440 // call site in a way that is incompatible with the privatization assumed
7441 // here.
7442 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7443 if (ACS.isDirectCall())
7444 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7445 if (ACS.isCallbackCall())
7446 return IsCompatiblePrivArgOfDirectCS(ACS);
7447 return false;
7448 };
7449
7450 if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
7451 UsedAssumedInformation))
7452 return indicatePessimisticFixpoint();
7453
7454 return ChangeStatus::UNCHANGED;
7455 }
7456
7457 /// Given a type to private \p PrivType, collect the constituates (which are
7458 /// used) in \p ReplacementTypes.
7459 static void
7460 identifyReplacementTypes(Type *PrivType,
7461 SmallVectorImpl<Type *> &ReplacementTypes) {
7462 // TODO: For now we expand the privatization type to the fullest which can
7463 // lead to dead arguments that need to be removed later.
7464 assert(PrivType && "Expected privatizable type!");
7465
7466 // Traverse the type, extract constituate types on the outermost level.
7467 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7468 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7469 ReplacementTypes.push_back(PrivStructType->getElementType(u));
7470 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7471 ReplacementTypes.append(PrivArrayType->getNumElements(),
7472 PrivArrayType->getElementType());
7473 } else {
7474 ReplacementTypes.push_back(PrivType);
7475 }
7476 }
7477
7478 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7479 /// The values needed are taken from the arguments of \p F starting at
7480 /// position \p ArgNo.
7481 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7482 unsigned ArgNo, BasicBlock::iterator IP) {
7483 assert(PrivType && "Expected privatizable type!");
7484
7485 IRBuilder<NoFolder> IRB(IP);
7486 const DataLayout &DL = F.getDataLayout();
7487
7488 // Traverse the type, build GEPs and stores.
7489 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7490 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7491 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7492 Value *Ptr =
7493 constructPointer(&Base, PrivStructLayout->getElementOffset(u), IRB);
7494 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7495 }
7496 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7497 Type *PointeeTy = PrivArrayType->getElementType();
7498 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7499 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7500 Value *Ptr = constructPointer(&Base, u * PointeeTySize, IRB);
7501 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7502 }
7503 } else {
7504 new StoreInst(F.getArg(ArgNo), &Base, IP);
7505 }
7506 }
7507
7508 /// Extract values from \p Base according to the type \p PrivType at the
7509 /// call position \p ACS. The values are appended to \p ReplacementValues.
7510 void createReplacementValues(Align Alignment, Type *PrivType,
7511 AbstractCallSite ACS, Value *Base,
7512 SmallVectorImpl<Value *> &ReplacementValues) {
7513 assert(Base && "Expected base value!");
7514 assert(PrivType && "Expected privatizable type!");
7515 Instruction *IP = ACS.getInstruction();
7516
7517 IRBuilder<NoFolder> IRB(IP);
7518 const DataLayout &DL = IP->getDataLayout();
7519
7520 // Traverse the type, build GEPs and loads.
7521 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7522 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7523 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7524 Type *PointeeTy = PrivStructType->getElementType(u);
7525 Value *Ptr =
7526 constructPointer(Base, PrivStructLayout->getElementOffset(u), IRB);
7527 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7528 L->setAlignment(Alignment);
7529 ReplacementValues.push_back(L);
7530 }
7531 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7532 Type *PointeeTy = PrivArrayType->getElementType();
7533 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7534 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7535 Value *Ptr = constructPointer(Base, u * PointeeTySize, IRB);
7536 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7537 L->setAlignment(Alignment);
7538 ReplacementValues.push_back(L);
7539 }
7540 } else {
7541 LoadInst *L = new LoadInst(PrivType, Base, "", IP->getIterator());
7542 L->setAlignment(Alignment);
7543 ReplacementValues.push_back(L);
7544 }
7545 }
7546
7547 ChangeStatus manifest(Attributor &A) override {
7548 if (!PrivatizableType)
7549 return ChangeStatus::UNCHANGED;
7550 assert(*PrivatizableType && "Expected privatizable type!");
7551
7552 // Collect all tail calls in the function as we cannot allow new allocas to
7553 // escape into tail recursion.
7554 // TODO: Be smarter about new allocas escaping into tail calls.
7556 bool UsedAssumedInformation = false;
7557 if (!A.checkForAllInstructions(
7558 [&](Instruction &I) {
7559 CallInst &CI = cast<CallInst>(I);
7560 if (CI.isTailCall())
7561 TailCalls.push_back(&CI);
7562 return true;
7563 },
7564 *this, {Instruction::Call}, UsedAssumedInformation))
7565 return ChangeStatus::UNCHANGED;
7566
7567 Argument *Arg = getAssociatedArgument();
7568 // Query AAAlign attribute for alignment of associated argument to
7569 // determine the best alignment of loads.
7570 const auto *AlignAA =
7571 A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
7572
7573 // Callback to repair the associated function. A new alloca is placed at the
7574 // beginning and initialized with the values passed through arguments. The
7575 // new alloca replaces the use of the old pointer argument.
7577 [=](const Attributor::ArgumentReplacementInfo &ARI,
7578 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7579 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7581 const DataLayout &DL = IP->getDataLayout();
7582 unsigned AS = DL.getAllocaAddrSpace();
7583 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7584 Arg->getName() + ".priv", IP);
7585 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7586 ArgIt->getArgNo(), IP);
7587
7588 if (AI->getType() != Arg->getType())
7589 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7590 AI, Arg->getType(), "", IP);
7591 Arg->replaceAllUsesWith(AI);
7592
7593 for (CallInst *CI : TailCalls)
7594 CI->setTailCall(false);
7595 };
7596
7597 // Callback to repair a call site of the associated function. The elements
7598 // of the privatizable type are loaded prior to the call and passed to the
7599 // new function version.
7601 [=](const Attributor::ArgumentReplacementInfo &ARI,
7602 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7603 // When no alignment is specified for the load instruction,
7604 // natural alignment is assumed.
7605 createReplacementValues(
7606 AlignAA ? AlignAA->getAssumedAlign() : Align(0),
7607 *PrivatizableType, ACS,
7608 ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
7609 NewArgOperands);
7610 };
7611
7612 // Collect the types that will replace the privatizable type in the function
7613 // signature.
7614 SmallVector<Type *, 16> ReplacementTypes;
7615 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7616
7617 // Register a rewrite of the argument.
7618 if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7619 std::move(FnRepairCB),
7620 std::move(ACSRepairCB)))
7621 return ChangeStatus::CHANGED;
7622 return ChangeStatus::UNCHANGED;
7623 }
7624
7625 void trackStatistics() const override {
7626 STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);
7627 }
7628};
7629
7630struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
7631 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7632 : AAPrivatizablePtrImpl(IRP, A) {}
7633
7634 void initialize(Attributor &A) override {
7635 // TODO: We can privatize more than arguments.
7636 indicatePessimisticFixpoint();
7637 }
7638
7639 ChangeStatus updateImpl(Attributor &A) override {
7640 llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
7641 "updateImpl will not be called");
7642 }
7643
7644 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7645 Value *Obj = getUnderlyingObject(&getAssociatedValue());
7646 if (!Obj) {
7647 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
7648 return nullptr;
7649 }
7650
7651 if (auto *AI = dyn_cast<AllocaInst>(Obj))
7652 if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
7653 if (CI->isOne())
7654 return AI->getAllocatedType();
7655 if (auto *Arg = dyn_cast<Argument>(Obj)) {
7656 auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7657 *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
7658 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7659 return PrivArgAA->getPrivatizableType();
7660 }
7661
7662 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
7663 "alloca nor privatizable argument: "
7664 << *Obj << "!\n");
7665 return nullptr;
7666 }
7667
7668 void trackStatistics() const override {
7669 STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);
7670 }
7671};
7672
7673struct AAPrivatizablePtrCallSiteArgument final
7674 : public AAPrivatizablePtrFloating {
7675 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7676 : AAPrivatizablePtrFloating(IRP, A) {}
7677
7678 void initialize(Attributor &A) override {
7679 if (A.hasAttr(getIRPosition(), Attribute::ByVal))
7680 indicateOptimisticFixpoint();
7681 }
7682
7683 ChangeStatus updateImpl(Attributor &A) override {
7684 PrivatizableType = identifyPrivatizableType(A);
7685 if (!PrivatizableType)
7686 return ChangeStatus::UNCHANGED;
7687 if (!*PrivatizableType)
7688 return indicatePessimisticFixpoint();
7689
7690 const IRPosition &IRP = getIRPosition();
7691 bool IsKnownNoCapture;
7692 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7693 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7694 if (!IsAssumedNoCapture) {
7695 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");
7696 return indicatePessimisticFixpoint();
7697 }
7698
7699 bool IsKnownNoAlias;
7701 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7702 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");
7703 return indicatePessimisticFixpoint();
7704 }
7705
7706 bool IsKnown;
7707 if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
7708 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");
7709 return indicatePessimisticFixpoint();
7710 }
7711
7712 return ChangeStatus::UNCHANGED;
7713 }
7714
7715 void trackStatistics() const override {
7716 STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);
7717 }
7718};
7719
7720struct AAPrivatizablePtrCallSiteReturned final
7721 : public AAPrivatizablePtrFloating {
7722 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7723 : AAPrivatizablePtrFloating(IRP, A) {}
7724
7725 void initialize(Attributor &A) override {
7726 // TODO: We can privatize more than arguments.
7727 indicatePessimisticFixpoint();
7728 }
7729
7730 void trackStatistics() const override {
7731 STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);
7732 }
7733};
7734
7735struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
7736 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7737 : AAPrivatizablePtrFloating(IRP, A) {}
7738
7739 void initialize(Attributor &A) override {
7740 // TODO: We can privatize more than arguments.
7741 indicatePessimisticFixpoint();
7742 }
7743
7744 void trackStatistics() const override {
7745 STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);
7746 }
7747};
7748} // namespace
7749
7750/// -------------------- Memory Behavior Attributes ----------------------------
7751/// Includes read-none, read-only, and write-only.
7752/// ----------------------------------------------------------------------------
7753namespace {
7754struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
7755 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7756 : AAMemoryBehavior(IRP, A) {}
7757
7758 void initialize(Attributor &A) override {
7759 intersectAssumedBits(BEST_STATE);
7760 getKnownStateFromValue(A, getIRPosition(), getState());
7761 AAMemoryBehavior::initialize(A);
7762 }
7763
7764 /// Return the memory behavior information encoded in the IR for \p IRP.
7765 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
7766 BitIntegerState &State,
7767 bool IgnoreSubsumingPositions = false) {
7769 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7770 for (const Attribute &Attr : Attrs) {
7771 switch (Attr.getKindAsEnum()) {
7772 case Attribute::ReadNone:
7773 State.addKnownBits(NO_ACCESSES);
7774 break;
7775 case Attribute::ReadOnly:
7776 State.addKnownBits(NO_WRITES);
7777 break;
7778 case Attribute::WriteOnly:
7779 State.addKnownBits(NO_READS);
7780 break;
7781 default:
7782 llvm_unreachable("Unexpected attribute!");
7783 }
7784 }
7785
7786 // Only a call site anchor performs the accesses of the position. A floating
7787 // value is only defined by its anchor, e.g., a loaded pointer may be
7788 // written through even though the load does not write.
7790 if (Kind == IRPosition::IRP_CALL_SITE ||
7792 if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
7793 if (!I->mayReadFromMemory())
7794 State.addKnownBits(NO_READS);
7795 if (!I->mayWriteToMemory())
7796 State.addKnownBits(NO_WRITES);
7797 }
7798 }
7799 }
7800
7801 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
7802 SmallVectorImpl<Attribute> &Attrs) const override {
7803 assert(Attrs.size() == 0);
7804 if (isAssumedReadNone())
7805 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7806 else if (isAssumedReadOnly())
7807 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7808 else if (isAssumedWriteOnly())
7809 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7810 assert(Attrs.size() <= 1);
7811 }
7812
7813 ChangeStatus manifest(Attributor &A) override {
7814 const IRPosition &IRP = getIRPosition();
7815
7816 if (A.hasAttr(IRP, Attribute::ReadNone,
7817 /* IgnoreSubsumingPositions */ true))
7818 return ChangeStatus::UNCHANGED;
7819
7820 // Check if we would improve the existing attributes first.
7821 SmallVector<Attribute, 4> DeducedAttrs;
7822 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
7823 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
7824 return A.hasAttr(IRP, Attr.getKindAsEnum(),
7825 /* IgnoreSubsumingPositions */ true);
7826 }))
7827 return ChangeStatus::UNCHANGED;
7828
7829 // Clear existing attributes.
7830 A.removeAttrs(IRP, AttrKinds);
7831 // Clear conflicting writable attribute.
7832 if (isAssumedReadOnly())
7833 A.removeAttrs(IRP, Attribute::Writable);
7834
7835 // Use the generic manifest method.
7836 return IRAttribute::manifest(A);
7837 }
7838
7839 const std::string getAsStr(Attributor *A) const override {
7840 if (isAssumedReadNone())
7841 return "readnone";
7842 if (isAssumedReadOnly())
7843 return "readonly";
7844 if (isAssumedWriteOnly())
7845 return "writeonly";
7846 return "may-read/write";
7847 }
7848
7849 /// The set of IR attributes AAMemoryBehavior deals with.
7850 static const Attribute::AttrKind AttrKinds[3];
7851};
7852
7853const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7854 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7855
7856/// Memory behavior attribute for a floating value.
7857struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7858 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7859 : AAMemoryBehaviorImpl(IRP, A) {}
7860
7861 ChangeStatus updateImpl(Attributor &A) override;
7862
7863 void trackStatistics() const override {
7864 if (isAssumedReadNone())
7866 else if (isAssumedReadOnly())
7868 else if (isAssumedWriteOnly())
7870 }
7871
7872private:
7873 /// Return true if users of \p UserI might access the underlying
7874 /// variable/location described by \p U and should therefore be analyzed.
7875 bool followUsersOfUseIn(Attributor &A, const Use &U,
7876 const Instruction *UserI);
7877
7878 /// Update the state according to the effect of use \p U in \p UserI.
7879 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
7880};
7881
7882/// Memory behavior attribute for function argument.
7883struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
7884 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
7885 : AAMemoryBehaviorFloating(IRP, A) {}
7886
7887 void initialize(Attributor &A) override {
7888 intersectAssumedBits(BEST_STATE);
7889 const IRPosition &IRP = getIRPosition();
7890 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
7891 // can query it when we use has/getAttr. That would allow us to reuse the
7892 // initialize of the base class here.
7893 bool HasByVal = A.hasAttr(IRP, {Attribute::ByVal},
7894 /* IgnoreSubsumingPositions */ true);
7895 getKnownStateFromValue(A, IRP, getState(),
7896 /* IgnoreSubsumingPositions */ HasByVal);
7897 }
7898
7899 ChangeStatus manifest(Attributor &A) override {
7900 // TODO: Pointer arguments are not supported on vectors of pointers yet.
7901 if (!getAssociatedValue().getType()->isPointerTy())
7902 return ChangeStatus::UNCHANGED;
7903
7904 // TODO: From readattrs.ll: "inalloca parameters are always
7905 // considered written"
7906 if (A.hasAttr(getIRPosition(),
7907 {Attribute::InAlloca, Attribute::Preallocated})) {
7908 removeKnownBits(NO_WRITES);
7909 removeAssumedBits(NO_WRITES);
7910 }
7911 A.removeAttrs(getIRPosition(), AttrKinds);
7912 return AAMemoryBehaviorFloating::manifest(A);
7913 }
7914
7915 void trackStatistics() const override {
7916 if (isAssumedReadNone())
7917 STATS_DECLTRACK_ARG_ATTR(readnone)
7918 else if (isAssumedReadOnly())
7919 STATS_DECLTRACK_ARG_ATTR(readonly)
7920 else if (isAssumedWriteOnly())
7921 STATS_DECLTRACK_ARG_ATTR(writeonly)
7922 }
7923};
7924
7925struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
7926 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
7927 : AAMemoryBehaviorArgument(IRP, A) {}
7928
7929 void initialize(Attributor &A) override {
7930 // If we don't have an associated attribute this is either a variadic call
7931 // or an indirect call, either way, nothing to do here.
7932 Argument *Arg = getAssociatedArgument();
7933 if (!Arg) {
7934 indicatePessimisticFixpoint();
7935 return;
7936 }
7937 if (Arg->hasByValAttr()) {
7938 addKnownBits(NO_WRITES);
7939 removeKnownBits(NO_READS);
7940 removeAssumedBits(NO_READS);
7941 }
7942 AAMemoryBehaviorArgument::initialize(A);
7943 if (getAssociatedFunction()->isDeclaration())
7944 indicatePessimisticFixpoint();
7945 }
7946
7947 ChangeStatus updateImpl(Attributor &A) override {
7948 // TODO: Once we have call site specific value information we can provide
7949 // call site specific liveness liveness information and then it makes
7950 // sense to specialize attributes for call sites arguments instead of
7951 // redirecting requests to the callee argument.
7952 Argument *Arg = getAssociatedArgument();
7953 const IRPosition &ArgPos = IRPosition::argument(*Arg);
7954 auto *ArgAA =
7955 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
7956 if (!ArgAA)
7957 return indicatePessimisticFixpoint();
7958 return clampStateAndIndicateChange(getState(), ArgAA->getState());
7959 }
7960
7961 void trackStatistics() const override {
7962 if (isAssumedReadNone())
7964 else if (isAssumedReadOnly())
7966 else if (isAssumedWriteOnly())
7968 }
7969};
7970
7971/// Memory behavior attribute for a call site return position.
7972struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
7973 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
7974 : AAMemoryBehaviorFloating(IRP, A) {}
7975
7976 void initialize(Attributor &A) override {
7977 AAMemoryBehaviorImpl::initialize(A);
7978 }
7979 ChangeStatus manifest(Attributor &A) override {
7980 // We do not annotate returned values.
7981 return ChangeStatus::UNCHANGED;
7982 }
7983
7984 void trackStatistics() const override {}
7985};
7986
7987/// An AA to represent the memory behavior function attributes.
7988struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
7989 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
7990 : AAMemoryBehaviorImpl(IRP, A) {}
7991
7992 ChangeStatus updateImpl(Attributor &A) override;
7993
7994 ChangeStatus manifest(Attributor &A) override {
7995 // TODO: It would be better to merge this with AAMemoryLocation, so that
7996 // we could determine read/write per location. This would also have the
7997 // benefit of only one place trying to manifest the memory attribute.
7998 Function &F = cast<Function>(getAnchorValue());
8000 if (isAssumedReadNone())
8001 ME = MemoryEffects::none();
8002 else if (isAssumedReadOnly())
8004 else if (isAssumedWriteOnly())
8006
8007 A.removeAttrs(getIRPosition(), AttrKinds);
8008 // Clear conflicting writable attribute.
8009 if (ME.onlyReadsMemory())
8010 for (Argument &Arg : F.args())
8011 A.removeAttrs(IRPosition::argument(Arg), Attribute::Writable);
8012 return A.manifestAttrs(getIRPosition(),
8013 Attribute::getWithMemoryEffects(F.getContext(), ME));
8014 }
8015
8016 void trackStatistics() const override {
8017 if (isAssumedReadNone())
8018 STATS_DECLTRACK_FN_ATTR(readnone)
8019 else if (isAssumedReadOnly())
8020 STATS_DECLTRACK_FN_ATTR(readonly)
8021 else if (isAssumedWriteOnly())
8022 STATS_DECLTRACK_FN_ATTR(writeonly)
8023 }
8024};
8025
8026/// AAMemoryBehavior attribute for call sites.
8027struct AAMemoryBehaviorCallSite final
8028 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8029 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
8030 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP, A) {}
8031
8032 ChangeStatus manifest(Attributor &A) override {
8033 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8034 CallBase &CB = cast<CallBase>(getAnchorValue());
8036 if (isAssumedReadNone())
8037 ME = MemoryEffects::none();
8038 else if (isAssumedReadOnly())
8040 else if (isAssumedWriteOnly())
8042
8043 A.removeAttrs(getIRPosition(), AttrKinds);
8044 // Clear conflicting writable attribute.
8045 if (ME.onlyReadsMemory())
8046 for (Use &U : CB.args())
8047 A.removeAttrs(IRPosition::callsite_argument(CB, U.getOperandNo()),
8048 Attribute::Writable);
8049 return A.manifestAttrs(
8050 getIRPosition(), Attribute::getWithMemoryEffects(CB.getContext(), ME));
8051 }
8052
8053 void trackStatistics() const override {
8054 if (isAssumedReadNone())
8055 STATS_DECLTRACK_CS_ATTR(readnone)
8056 else if (isAssumedReadOnly())
8057 STATS_DECLTRACK_CS_ATTR(readonly)
8058 else if (isAssumedWriteOnly())
8059 STATS_DECLTRACK_CS_ATTR(writeonly)
8060 }
8061};
8062
8063ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8064
8065 // The current assumed state used to determine a change.
8066 auto AssumedState = getAssumed();
8067
8068 auto CheckRWInst = [&](Instruction &I) {
8069 // If the instruction has an own memory behavior state, use it to restrict
8070 // the local state. No further analysis is required as the other memory
8071 // state is as optimistic as it gets.
8072 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8073 const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8075 if (MemBehaviorAA) {
8076 intersectAssumedBits(MemBehaviorAA->getAssumed());
8077 return !isAtFixpoint();
8078 }
8079 }
8080
8081 // Remove access kind modifiers if necessary.
8082 if (I.mayReadFromMemory())
8083 removeAssumedBits(NO_READS);
8084 if (I.mayWriteToMemory())
8085 removeAssumedBits(NO_WRITES);
8086 return !isAtFixpoint();
8087 };
8088
8089 bool UsedAssumedInformation = false;
8090 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8091 UsedAssumedInformation))
8092 return indicatePessimisticFixpoint();
8093
8094 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8096}
8097
8098ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8099
8100 const IRPosition &IRP = getIRPosition();
8101 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8102 AAMemoryBehavior::StateType &S = getState();
8103
8104 // First, check the function scope. We take the known information and we avoid
8105 // work if the assumed information implies the current assumed information for
8106 // this attribute. This is a valid for all but byval arguments.
8107 Argument *Arg = IRP.getAssociatedArgument();
8108 AAMemoryBehavior::base_t FnMemAssumedState =
8110 if (!Arg || !Arg->hasByValAttr()) {
8111 const auto *FnMemAA =
8112 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8113 if (FnMemAA) {
8114 FnMemAssumedState = FnMemAA->getAssumed();
8115 S.addKnownBits(FnMemAA->getKnown());
8116 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8118 }
8119 }
8120
8121 // The current assumed state used to determine a change.
8122 auto AssumedState = S.getAssumed();
8123
8124 // Make sure the value is not captured (except through "return"), if
8125 // it is, any information derived would be irrelevant anyway as we cannot
8126 // check the potential aliases introduced by the capture. However, no need
8127 // to fall back to anythign less optimistic than the function state.
8128 bool IsKnownNoCapture;
8129 const AANoCapture *ArgNoCaptureAA = nullptr;
8130 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
8131 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture, false,
8132 &ArgNoCaptureAA);
8133
8134 if (!IsAssumedNoCapture &&
8135 (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
8136 S.intersectAssumedBits(FnMemAssumedState);
8137 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8139 }
8140
8141 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8142 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8143 Instruction *UserI = cast<Instruction>(U.getUser());
8144 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
8145 << " \n");
8146
8147 // Droppable users, e.g., llvm::assume does not actually perform any action.
8148 if (UserI->isDroppable())
8149 return true;
8150
8151 // Check if the users of UserI should also be visited.
8152 Follow = followUsersOfUseIn(A, U, UserI);
8153
8154 // If UserI might touch memory we analyze the use in detail.
8155 if (UserI->mayReadOrWriteMemory())
8156 analyzeUseIn(A, U, UserI);
8157
8158 return !isAtFixpoint();
8159 };
8160
8161 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8162 return indicatePessimisticFixpoint();
8163
8164 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8166}
8167
8168bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8169 const Instruction *UserI) {
8170 // The loaded value is unrelated to the pointer argument, no need to
8171 // follow the users of the load.
8172 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8173 return false;
8174
8175 // By default we follow all uses assuming UserI might leak information on U,
8176 // we have special handling for call sites operands though.
8177 const auto *CB = dyn_cast<CallBase>(UserI);
8178 if (!CB || !CB->isArgOperand(&U))
8179 return true;
8180
8181 // If the use is a call argument known not to be captured, the users of
8182 // the call do not need to be visited because they have to be unrelated to
8183 // the input. Note that this check is not trivial even though we disallow
8184 // general capturing of the underlying argument. The reason is that the
8185 // call might the argument "through return", which we allow and for which we
8186 // need to check call users.
8187 if (U.get()->getType()->isPointerTy()) {
8188 unsigned ArgNo = CB->getArgOperandNo(&U);
8189 bool IsKnownNoCapture;
8191 A, this, IRPosition::callsite_argument(*CB, ArgNo),
8192 DepClassTy::OPTIONAL, IsKnownNoCapture);
8193 }
8194
8195 return true;
8196}
8197
8198void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8199 const Instruction *UserI) {
8200 assert(UserI->mayReadOrWriteMemory());
8201
8202 switch (UserI->getOpcode()) {
8203 default:
8204 // TODO: Handle all atomics and other side-effect operations we know of.
8205 break;
8206 case Instruction::Load:
8207 // Loads cause the NO_READS property to disappear.
8208 removeAssumedBits(NO_READS);
8209 return;
8210
8211 case Instruction::Store:
8212 // Stores cause the NO_WRITES property to disappear if the use is the
8213 // pointer operand. Note that while capturing was taken care of somewhere
8214 // else we need to deal with stores of the value that is not looked through.
8215 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8216 removeAssumedBits(NO_WRITES);
8217 else
8218 indicatePessimisticFixpoint();
8219 return;
8220
8221 case Instruction::Call:
8222 case Instruction::CallBr:
8223 case Instruction::Invoke: {
8224 // For call sites we look at the argument memory behavior attribute (this
8225 // could be recursive!) in order to restrict our own state.
8226 const auto *CB = cast<CallBase>(UserI);
8227
8228 // Give up on operand bundles.
8229 if (CB->isBundleOperand(&U)) {
8230 indicatePessimisticFixpoint();
8231 return;
8232 }
8233
8234 // Calling a function does read the function pointer, maybe write it if the
8235 // function is self-modifying.
8236 if (CB->isCallee(&U)) {
8237 removeAssumedBits(NO_READS);
8238 break;
8239 }
8240
8241 // Adjust the possible access behavior based on the information on the
8242 // argument.
8243 IRPosition Pos;
8244 if (U.get()->getType()->isPointerTy())
8246 else
8248 const auto *MemBehaviorAA =
8249 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8250 if (!MemBehaviorAA)
8251 break;
8252 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8253 // and at least "known".
8254 intersectAssumedBits(MemBehaviorAA->getAssumed());
8255 return;
8256 }
8257 };
8258
8259 // Generally, look at the "may-properties" and adjust the assumed state if we
8260 // did not trigger special handling before.
8261 if (UserI->mayReadFromMemory())
8262 removeAssumedBits(NO_READS);
8263 if (UserI->mayWriteToMemory())
8264 removeAssumedBits(NO_WRITES);
8265}
8266} // namespace
8267
8268/// -------------------- Memory Locations Attributes ---------------------------
8269/// Includes read-none, argmemonly, inaccessiblememonly,
8270/// inaccessiblememorargmemonly
8271/// ----------------------------------------------------------------------------
8272
8275 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8276 return "all memory";
8278 return "no memory";
8279 std::string S = "memory:";
8280 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8281 S += "stack,";
8282 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8283 S += "constant,";
8285 S += "internal global,";
8287 S += "external global,";
8288 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8289 S += "argument,";
8291 S += "inaccessible,";
8292 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8293 S += "malloced,";
8294 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8295 S += "unknown,";
8296 S.pop_back();
8297 return S;
8298}
8299
8300namespace {
8301struct AAMemoryLocationImpl : public AAMemoryLocation {
8302
8303 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8304 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8305 AccessKind2Accesses.fill(nullptr);
8306 }
8307
8308 ~AAMemoryLocationImpl() override {
8309 // The AccessSets are allocated via a BumpPtrAllocator, we call
8310 // the destructor manually.
8311 for (AccessSet *AS : AccessKind2Accesses)
8312 if (AS)
8313 AS->~AccessSet();
8314 }
8315
8316 void initialize(Attributor &A) override {
8317 intersectAssumedBits(BEST_STATE);
8318 getKnownStateFromValue(A, getIRPosition(), getState());
8319 AAMemoryLocation::initialize(A);
8320 }
8321
8322 /// Return the memory behavior information encoded in the IR for \p IRP.
8323 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8324 BitIntegerState &State,
8325 bool IgnoreSubsumingPositions = false) {
8326 // For internal functions we ignore `argmemonly` and
8327 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8328 // constant propagation. It is unclear if this is the best way but it is
8329 // unlikely this will cause real performance problems. If we are deriving
8330 // attributes for the anchor function we even remove the attribute in
8331 // addition to ignoring it.
8332 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8333 // MemoryEffects::Other as a possible location.
8334 bool UseArgMemOnly = true;
8335 Function *AnchorFn = IRP.getAnchorScope();
8336 if (AnchorFn && A.isRunOn(*AnchorFn))
8337 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8338
8340 A.getAttrs(IRP, {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8341 for (const Attribute &Attr : Attrs) {
8342 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8343 MemoryEffects ME = Attr.getMemoryEffects();
8344 if (ME.doesNotAccessMemory()) {
8345 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8346 continue;
8347 }
8348 if (ME.onlyAccessesInaccessibleMem()) {
8349 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8350 continue;
8351 }
8352 if (ME.onlyAccessesArgPointees()) {
8353 if (UseArgMemOnly)
8354 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8355 else {
8356 // Remove location information, only keep read/write info.
8357 ME = MemoryEffects(ME.getModRef());
8358 A.manifestAttrs(IRP,
8359 Attribute::getWithMemoryEffects(
8360 IRP.getAnchorValue().getContext(), ME),
8361 /*ForceReplace*/ true);
8362 }
8363 continue;
8364 }
8366 if (UseArgMemOnly)
8367 State.addKnownBits(inverseLocation(
8368 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8369 else {
8370 // Remove location information, only keep read/write info.
8371 ME = MemoryEffects(ME.getModRef());
8372 A.manifestAttrs(IRP,
8373 Attribute::getWithMemoryEffects(
8374 IRP.getAnchorValue().getContext(), ME),
8375 /*ForceReplace*/ true);
8376 }
8377 continue;
8378 }
8379 }
8380 }
8381
8382 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
8383 SmallVectorImpl<Attribute> &Attrs) const override {
8384 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8385 assert(Attrs.size() == 0);
8386 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8387 if (isAssumedReadNone())
8388 Attrs.push_back(
8389 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8390 else if (isAssumedInaccessibleMemOnly())
8391 Attrs.push_back(Attribute::getWithMemoryEffects(
8393 else if (isAssumedArgMemOnly())
8394 Attrs.push_back(
8395 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8396 else if (isAssumedInaccessibleOrArgMemOnly())
8397 Attrs.push_back(Attribute::getWithMemoryEffects(
8399 }
8400 assert(Attrs.size() <= 1);
8401 }
8402
8403 ChangeStatus manifest(Attributor &A) override {
8404 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8405 // provide per-location modref information here.
8406 const IRPosition &IRP = getIRPosition();
8407
8408 SmallVector<Attribute, 1> DeducedAttrs;
8409 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
8410 if (DeducedAttrs.size() != 1)
8411 return ChangeStatus::UNCHANGED;
8412 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8413
8414 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8415 IRP.getAnchorValue().getContext(), ME));
8416 }
8417
8418 bool checkForAllAccessesToMemoryKind(
8419 function_ref<bool(const Instruction *, const Value *, AccessKind,
8420 MemoryLocationsKind)>
8421 Pred,
8422 MemoryLocationsKind RequestedMLK) const override {
8423 if (!isValidState())
8424 return false;
8425
8426 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8427 if (AssumedMLK == NO_LOCATIONS)
8428 return true;
8429
8430 unsigned Idx = 0;
8431 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8432 CurMLK *= 2, ++Idx) {
8433 if (CurMLK & RequestedMLK)
8434 continue;
8435
8436 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8437 for (const AccessInfo &AI : *Accesses)
8438 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8439 return false;
8440 }
8441
8442 return true;
8443 }
8444
8445 ChangeStatus indicatePessimisticFixpoint() override {
8446 // If we give up and indicate a pessimistic fixpoint this instruction will
8447 // become an access for all potential access kinds:
8448 // TODO: Add pointers for argmemonly and globals to improve the results of
8449 // checkForAllAccessesToMemoryKind.
8450 bool Changed = false;
8451 MemoryLocationsKind KnownMLK = getKnown();
8452 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8453 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8454 if (!(CurMLK & KnownMLK))
8455 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8456 getAccessKindFromInst(I));
8457 return AAMemoryLocation::indicatePessimisticFixpoint();
8458 }
8459
8460protected:
8461 /// Helper struct to tie together an instruction that has a read or write
8462 /// effect with the pointer it accesses (if any).
8463 struct AccessInfo {
8464
8465 /// The instruction that caused the access.
8466 const Instruction *I;
8467
8468 /// The base pointer that is accessed, or null if unknown.
8469 const Value *Ptr;
8470
8471 /// The kind of access (read/write/read+write).
8473
8474 bool operator==(const AccessInfo &RHS) const {
8475 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8476 }
8477 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8478 if (LHS.I != RHS.I)
8479 return LHS.I < RHS.I;
8480 if (LHS.Ptr != RHS.Ptr)
8481 return LHS.Ptr < RHS.Ptr;
8482 if (LHS.Kind != RHS.Kind)
8483 return LHS.Kind < RHS.Kind;
8484 return false;
8485 }
8486 };
8487
8488 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8489 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8490 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8491 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8492 AccessKind2Accesses;
8493
8494 /// Categorize the pointer arguments of CB that might access memory in
8495 /// AccessedLoc and update the state and access map accordingly.
8496 void
8497 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8498 AAMemoryLocation::StateType &AccessedLocs,
8499 bool &Changed);
8500
8501 /// Return the kind(s) of location that may be accessed by \p V.
8503 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8504
8505 /// Return the access kind as determined by \p I.
8506 AccessKind getAccessKindFromInst(const Instruction *I) {
8507 AccessKind AK = READ_WRITE;
8508 if (I) {
8509 AK = I->mayReadFromMemory() ? READ : NONE;
8510 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8511 }
8512 return AK;
8513 }
8514
8515 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8516 /// an access of kind \p AK to a \p MLK memory location with the access
8517 /// pointer \p Ptr.
8518 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8519 MemoryLocationsKind MLK, const Instruction *I,
8520 const Value *Ptr, bool &Changed,
8521 AccessKind AK = READ_WRITE) {
8522
8523 assert(isPowerOf2_32(MLK) && "Expected a single location set!");
8524 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8525 if (!Accesses)
8526 Accesses = new (Allocator) AccessSet();
8527 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8528 if (MLK == NO_UNKOWN_MEM)
8529 MLK = NO_LOCATIONS;
8530 State.removeAssumedBits(MLK);
8531 }
8532
8533 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8534 /// arguments, and update the state and access map accordingly.
8535 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8536 AAMemoryLocation::StateType &State, bool &Changed,
8537 unsigned AccessAS = 0);
8538
8539 /// Used to allocate access sets.
8541};
8542
8543void AAMemoryLocationImpl::categorizePtrValue(
8544 Attributor &A, const Instruction &I, const Value &Ptr,
8545 AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {
8546 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
8547 << Ptr << " ["
8548 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");
8549
8550 auto Pred = [&](Value &Obj) {
8551 unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();
8552 // TODO: recognize the TBAA used for constant accesses.
8553 MemoryLocationsKind MLK = NO_LOCATIONS;
8554
8555 // Filter accesses to constant (GPU) memory if we have an AS at the access
8556 // site or the object is known to actually have the associated AS.
8557 if (AA::isGPU(A.getModule())) {
8558 if (AA::isGPUConstantAddressSpace(A.getModule(), AccessAS) ||
8559 (AA::isGPUConstantAddressSpace(A.getModule(), ObjectAS) &&
8560 isIdentifiedObject(&Obj)))
8561 return true;
8562 }
8563
8564 if (isa<UndefValue>(&Obj))
8565 return true;
8566 if (isa<Argument>(&Obj)) {
8567 // TODO: For now we do not treat byval arguments as local copies performed
8568 // on the call edge, though, we should. To make that happen we need to
8569 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8570 // would also allow us to mark functions only accessing byval arguments as
8571 // readnone again, arguably their accesses have no effect outside of the
8572 // function, like accesses to allocas.
8573 MLK = NO_ARGUMENT_MEM;
8574 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8575 // Reading constant memory is not treated as a read "effect" by the
8576 // function attr pass so we won't neither. Constants defined by TBAA are
8577 // similar. (We know we do not write it because it is constant.)
8578 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8579 if (GVar->isConstant())
8580 return true;
8581
8582 if (GV->hasLocalLinkage())
8583 MLK = NO_GLOBAL_INTERNAL_MEM;
8584 else
8585 MLK = NO_GLOBAL_EXTERNAL_MEM;
8586 } else if (isa<ConstantPointerNull>(&Obj) && ObjectAS == AccessAS &&
8587 !NullPointerIsDefined(getAssociatedFunction(), AccessAS)) {
8588 // Accessing null is undefined, but not accessing a null pointer cast to
8589 // another address space, which may be a valid address there.
8590 return true;
8591 } else if (isa<AllocaInst>(&Obj)) {
8592 MLK = NO_LOCAL_MEM;
8593 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8594 bool IsKnownNoAlias;
8597 IsKnownNoAlias))
8598 MLK = NO_MALLOCED_MEM;
8599 else
8600 MLK = NO_UNKOWN_MEM;
8601 } else {
8602 MLK = NO_UNKOWN_MEM;
8603 }
8604
8605 assert(MLK != NO_LOCATIONS && "No location specified!");
8606 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
8607 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
8608 updateStateAndAccessesMap(State, MLK, &I, &Obj, Changed,
8609 getAccessKindFromInst(&I));
8610
8611 return true;
8612 };
8613
8614 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
8616 if (!AA || !AA->forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8617 LLVM_DEBUG(
8618 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
8619 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8620 getAccessKindFromInst(&I));
8621 return;
8622 }
8623
8624 LLVM_DEBUG(
8625 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
8626 << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
8627}
8628
8629void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8630 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8631 bool &Changed) {
8632 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8633
8634 // Skip non-pointer arguments.
8635 const Value *ArgOp = CB.getArgOperand(ArgNo);
8636 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8637 continue;
8638
8639 // Skip readnone arguments.
8640 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8641 const auto *ArgOpMemLocationAA =
8642 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8643
8644 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8645 continue;
8646
8647 // Categorize potentially accessed pointer arguments as if there was an
8648 // access instruction with them as pointer.
8649 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8650 }
8651}
8652
8654AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8655 bool &Changed) {
8656 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
8657 << I << "\n");
8658
8659 AAMemoryLocation::StateType AccessedLocs;
8660 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8661
8662 if (auto *CB = dyn_cast<CallBase>(&I)) {
8663
8664 // First check if we assume any memory is access is visible.
8665 const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8667 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
8668 << " [" << CBMemLocationAA << "]\n");
8669 if (!CBMemLocationAA) {
8670 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr,
8671 Changed, getAccessKindFromInst(&I));
8672 return NO_UNKOWN_MEM;
8673 }
8674
8675 if (CBMemLocationAA->isAssumedReadNone())
8676 return NO_LOCATIONS;
8677
8678 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8679 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8680 Changed, getAccessKindFromInst(&I));
8681 return AccessedLocs.getAssumed();
8682 }
8683
8684 uint32_t CBAssumedNotAccessedLocs =
8685 CBMemLocationAA->getAssumedNotAccessedLocation();
8686
8687 // Set the argmemonly and global bit as we handle them separately below.
8688 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8689 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8690
8691 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8692 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8693 continue;
8694 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8695 getAccessKindFromInst(&I));
8696 }
8697
8698 // Now handle global memory if it might be accessed. This is slightly tricky
8699 // as NO_GLOBAL_MEM has multiple bits set.
8700 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8701 if (HasGlobalAccesses) {
8702 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8703 AccessKind Kind, MemoryLocationsKind MLK) {
8704 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8705 getAccessKindFromInst(&I));
8706 return true;
8707 };
8708 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8709 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8710 return AccessedLocs.getWorstState();
8711 }
8712
8713 LLVM_DEBUG(
8714 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
8715 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8716
8717 // Now handle argument memory if it might be accessed.
8718 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8719 if (HasArgAccesses)
8720 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8721
8722 LLVM_DEBUG(
8723 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
8724 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8725
8726 return AccessedLocs.getAssumed();
8727 }
8728
8729 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8730 LLVM_DEBUG(
8731 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
8732 << I << " [" << *Ptr << "]\n");
8733 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed,
8734 Ptr->getType()->getPointerAddressSpace());
8735 return AccessedLocs.getAssumed();
8736 }
8737
8738 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
8739 << I << "\n");
8740 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8741 getAccessKindFromInst(&I));
8742 return AccessedLocs.getAssumed();
8743}
8744
8745/// An AA to represent the memory behavior function attributes.
8746struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8747 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8748 : AAMemoryLocationImpl(IRP, A) {}
8749
8750 ChangeStatus updateImpl(Attributor &A) override {
8751
8752 const auto *MemBehaviorAA =
8753 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8754 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
8755 if (MemBehaviorAA->isKnownReadNone())
8756 return indicateOptimisticFixpoint();
8758 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8759 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8760 return ChangeStatus::UNCHANGED;
8761 }
8762
8763 // The current assumed state used to determine a change.
8764 auto AssumedState = getAssumed();
8765 bool Changed = false;
8766
8767 auto CheckRWInst = [&](Instruction &I) {
8768 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8769 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
8770 << ": " << getMemoryLocationsAsStr(MLK) << "\n");
8771 removeAssumedBits(inverseLocation(MLK, false, false));
8772 // Stop once only the valid bit set in the *not assumed location*, thus
8773 // once we don't actually exclude any memory locations in the state.
8774 return getAssumedNotAccessedLocation() != VALID_STATE;
8775 };
8776
8777 bool UsedAssumedInformation = false;
8778 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8779 UsedAssumedInformation))
8780 return indicatePessimisticFixpoint();
8781
8782 Changed |= AssumedState != getAssumed();
8783 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8784 }
8785
8786 void trackStatistics() const override {
8787 if (isAssumedReadNone())
8788 STATS_DECLTRACK_FN_ATTR(readnone)
8789 else if (isAssumedArgMemOnly())
8790 STATS_DECLTRACK_FN_ATTR(argmemonly)
8791 else if (isAssumedInaccessibleMemOnly())
8792 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
8793 else if (isAssumedInaccessibleOrArgMemOnly())
8794 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
8795 }
8796};
8797
8798/// AAMemoryLocation attribute for call sites.
8799struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8800 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8801 : AAMemoryLocationImpl(IRP, A) {}
8802
8803 ChangeStatus updateImpl(Attributor &A) override {
8804 // TODO: Once we have call site specific value information we can provide
8805 // call site specific liveness liveness information and then it makes
8806 // sense to specialize attributes for call sites arguments instead of
8807 // redirecting requests to the callee argument.
8808 Function *F = getAssociatedFunction();
8809 const IRPosition &FnPos = IRPosition::function(*F);
8810 auto *FnAA =
8811 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
8812 if (!FnAA)
8813 return indicatePessimisticFixpoint();
8814 bool Changed = false;
8815 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8816 AccessKind Kind, MemoryLocationsKind MLK) {
8817 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
8818 getAccessKindFromInst(I));
8819 return true;
8820 };
8821 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8822 return indicatePessimisticFixpoint();
8823 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8824 }
8825
8826 void trackStatistics() const override {
8827 if (isAssumedReadNone())
8828 STATS_DECLTRACK_CS_ATTR(readnone)
8829 }
8830};
8831} // namespace
8832
8833/// ------------------ denormal-fp-math Attribute -------------------------
8834
8835namespace {
8836struct AADenormalFPMathImpl : public AADenormalFPMath {
8837 AADenormalFPMathImpl(const IRPosition &IRP, Attributor &A)
8838 : AADenormalFPMath(IRP, A) {}
8839
8840 const std::string getAsStr(Attributor *A) const override {
8841 std::string Str("AADenormalFPMath[");
8842 raw_string_ostream OS(Str);
8843
8844 DenormalState Known = getKnown();
8845 if (Known.Mode.isValid())
8846 OS << "denormal-fp-math=" << Known.Mode;
8847 else
8848 OS << "invalid";
8849
8850 if (Known.ModeF32.isValid())
8851 OS << " denormal-fp-math-f32=" << Known.ModeF32;
8852 OS << ']';
8853 return Str;
8854 }
8855};
8856
8857struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
8858 AADenormalFPMathFunction(const IRPosition &IRP, Attributor &A)
8859 : AADenormalFPMathImpl(IRP, A) {}
8860
8861 void initialize(Attributor &A) override {
8862 const Function *F = getAnchorScope();
8863 DenormalFPEnv DenormEnv = F->getDenormalFPEnv();
8864
8865 Known = DenormalState{DenormEnv.DefaultMode, DenormEnv.F32Mode};
8866 if (isModeFixed())
8867 indicateFixpoint();
8868 }
8869
8870 ChangeStatus updateImpl(Attributor &A) override {
8871 ChangeStatus Change = ChangeStatus::UNCHANGED;
8872
8873 auto CheckCallSite = [=, &Change, &A](AbstractCallSite CS) {
8874 Function *Caller = CS.getInstruction()->getFunction();
8875 LLVM_DEBUG(dbgs() << "[AADenormalFPMath] Call " << Caller->getName()
8876 << "->" << getAssociatedFunction()->getName() << '\n');
8877
8878 const auto *CallerInfo = A.getAAFor<AADenormalFPMath>(
8879 *this, IRPosition::function(*Caller), DepClassTy::REQUIRED);
8880 if (!CallerInfo)
8881 return false;
8882
8883 Change = Change | clampStateAndIndicateChange(this->getState(),
8884 CallerInfo->getState());
8885 return true;
8886 };
8887
8888 bool AllCallSitesKnown = true;
8889 if (!A.checkForAllCallSites(CheckCallSite, *this, true, AllCallSitesKnown))
8890 return indicatePessimisticFixpoint();
8891
8892 if (Change == ChangeStatus::CHANGED && isModeFixed())
8893 indicateFixpoint();
8894 return Change;
8895 }
8896
8897 ChangeStatus manifest(Attributor &A) override {
8898 LLVMContext &Ctx = getAssociatedFunction()->getContext();
8899
8900 SmallVector<Attribute, 2> AttrToAdd;
8902
8903 // TODO: Change to use DenormalFPEnv everywhere.
8904 DenormalFPEnv KnownEnv(Known.Mode, Known.ModeF32);
8905
8906 if (KnownEnv == DenormalFPEnv::getDefault()) {
8907 AttrToRemove.push_back(Attribute::DenormalFPEnv);
8908 } else {
8909 AttrToAdd.push_back(Attribute::get(
8910 Ctx, Attribute::DenormalFPEnv,
8911 DenormalFPEnv(Known.Mode, Known.ModeF32).toIntValue()));
8912 }
8913
8914 auto &IRP = getIRPosition();
8915
8916 // TODO: There should be a combined add and remove API.
8917 return A.removeAttrs(IRP, AttrToRemove) |
8918 A.manifestAttrs(IRP, AttrToAdd, /*ForceReplace=*/true);
8919 }
8920
8921 void trackStatistics() const override {
8922 STATS_DECLTRACK_FN_ATTR(denormal_fpenv)
8923 }
8924};
8925} // namespace
8926
8927/// ------------------ Value Constant Range Attribute -------------------------
8928
8929namespace {
8930struct AAValueConstantRangeImpl : AAValueConstantRange {
8931 using StateType = IntegerRangeState;
8932 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
8933 : AAValueConstantRange(IRP, A) {}
8934
8935 void initialize(Attributor &A) override {
8936 if (A.hasSimplificationCallback(getIRPosition())) {
8937 indicatePessimisticFixpoint();
8938 return;
8939 }
8940
8941 // Intersect a range given by SCEV.
8942 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
8943
8944 // Intersect a range given by LVI.
8945 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
8946 }
8947
8948 const std::string getAsStr(Attributor *A) const override {
8949 std::string Str;
8950 llvm::raw_string_ostream OS(Str);
8951 OS << "range(" << getBitWidth() << ")<";
8952 getKnown().print(OS);
8953 OS << " / ";
8954 getAssumed().print(OS);
8955 OS << ">";
8956 return Str;
8957 }
8958
8959 /// Helper function to get a SCEV expr for the associated value at program
8960 /// point \p I.
8961 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
8962 if (!getAnchorScope())
8963 return nullptr;
8964
8965 ScalarEvolution *SE =
8966 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8967 *getAnchorScope());
8968
8969 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
8970 *getAnchorScope());
8971
8972 if (!SE || !LI)
8973 return nullptr;
8974
8975 const SCEV *S = SE->getSCEV(&getAssociatedValue());
8976 if (!I)
8977 return S;
8978
8979 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
8980 }
8981
8982 /// Helper function to get a range from SCEV for the associated value at
8983 /// program point \p I.
8984 ConstantRange getConstantRangeFromSCEV(Attributor &A,
8985 const Instruction *I = nullptr) const {
8986 if (!getAnchorScope())
8987 return getWorstState(getBitWidth());
8988
8989 ScalarEvolution *SE =
8990 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8991 *getAnchorScope());
8992
8993 const SCEV *S = getSCEV(A, I);
8994 if (!SE || !S)
8995 return getWorstState(getBitWidth());
8996
8997 return SE->getUnsignedRange(S);
8998 }
8999
9000 /// Helper function to get a range from LVI for the associated value at
9001 /// program point \p I.
9002 ConstantRange
9003 getConstantRangeFromLVI(Attributor &A,
9004 const Instruction *CtxI = nullptr) const {
9005 if (!getAnchorScope())
9006 return getWorstState(getBitWidth());
9007
9008 LazyValueInfo *LVI =
9009 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9010 *getAnchorScope());
9011
9012 if (!LVI || !CtxI)
9013 return getWorstState(getBitWidth());
9014 return LVI->getConstantRange(&getAssociatedValue(),
9015 const_cast<Instruction *>(CtxI),
9016 /*UndefAllowed*/ false);
9017 }
9018
9019 /// Return true if \p CtxI is valid for querying outside analyses.
9020 /// This basically makes sure we do not ask intra-procedural analysis
9021 /// about a context in the wrong function or a context that violates
9022 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
9023 /// if the original context of this AA is OK or should be considered invalid.
9024 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
9025 const Instruction *CtxI,
9026 bool AllowAACtxI) const {
9027 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9028 return false;
9029
9030 // Our context might be in a different function, neither intra-procedural
9031 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
9032 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
9033 return false;
9034
9035 // If the context is not dominated by the value there are paths to the
9036 // context that do not define the value. This cannot be handled by
9037 // LazyValueInfo so we need to bail.
9038 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
9039 InformationCache &InfoCache = A.getInfoCache();
9040 const DominatorTree *DT =
9041 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
9042 *I->getFunction());
9043 return DT && DT->dominates(I, CtxI);
9044 }
9045
9046 return true;
9047 }
9048
9049 ConstantRange
9050 getAssumedConstantRange(Attributor &A,
9051 const Instruction *CtxI = nullptr) const override {
9052 // TODO: Make SCEV use Attributor assumption.
9053 // We may be able to bound a variable range via assumptions in
9054 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
9055 // evolve to x^2 + x, then we can say that y is in [2, 12].
9056 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9057 /* AllowAACtxI */ false))
9058 return getAssumed();
9059
9060 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9061 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9062 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9063 }
9064
9065 /// Helper function to create MDNode for range metadata.
9066 static MDNode *
9067 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
9068 const ConstantRange &AssumedConstantRange) {
9069 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
9070 Ty, AssumedConstantRange.getLower())),
9071 ConstantAsMetadata::get(ConstantInt::get(
9072 Ty, AssumedConstantRange.getUpper()))};
9073 return MDNode::get(Ctx, LowAndHigh);
9074 }
9075
9076 /// Return true if \p Assumed is included in ranges from instruction \p I.
9077 static bool isBetterRange(const ConstantRange &Assumed,
9078 const Instruction &I) {
9079 if (Assumed.isFullSet())
9080 return false;
9081
9082 std::optional<ConstantRange> Known;
9083
9084 if (const auto *CB = dyn_cast<CallBase>(&I)) {
9085 Known = CB->getRange();
9086 } else if (MDNode *KnownRanges = I.getMetadata(LLVMContext::MD_range)) {
9087 // If multiple ranges are annotated in IR, we give up to annotate assumed
9088 // range for now.
9089
9090 // TODO: If there exists a known range which containts assumed range, we
9091 // can say assumed range is better.
9092 if (KnownRanges->getNumOperands() > 2)
9093 return false;
9094
9095 ConstantInt *Lower =
9096 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
9097 ConstantInt *Upper =
9098 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
9099
9100 Known.emplace(Lower->getValue(), Upper->getValue());
9101 }
9102 return !Known || (*Known != Assumed && Known->contains(Assumed));
9103 }
9104
9105 /// Helper function to set range metadata.
9106 static bool
9107 setRangeMetadataIfisBetterRange(Instruction *I,
9108 const ConstantRange &AssumedConstantRange) {
9109 if (isBetterRange(AssumedConstantRange, *I)) {
9110 I->setMetadata(LLVMContext::MD_range,
9111 getMDNodeForConstantRange(I->getType(), I->getContext(),
9112 AssumedConstantRange));
9113 return true;
9114 }
9115 return false;
9116 }
9117 /// Helper function to set range return attribute.
9118 static bool
9119 setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,
9120 Instruction *I,
9121 const ConstantRange &AssumedConstantRange) {
9122 if (isBetterRange(AssumedConstantRange, *I)) {
9123 A.manifestAttrs(IRP,
9124 Attribute::get(I->getContext(), Attribute::Range,
9125 AssumedConstantRange),
9126 /*ForceReplace*/ true);
9127 return true;
9128 }
9129 return false;
9130 }
9131
9132 ChangeStatus manifest(Attributor &A) override {
9133 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9134 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9135 assert(!AssumedConstantRange.isFullSet() && "Invalid state");
9136
9137 auto &V = getAssociatedValue();
9138 if (!AssumedConstantRange.isEmptySet() &&
9139 !AssumedConstantRange.isSingleElement()) {
9140 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9141 assert(I == getCtxI() && "Should not annotate an instruction which is "
9142 "not the context instruction");
9143 if (isa<LoadInst>(I))
9144 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9145 Changed = ChangeStatus::CHANGED;
9146 if (isa<CallInst>(I))
9147 if (setRangeRetAttrIfisBetterRange(A, getIRPosition(), I,
9148 AssumedConstantRange))
9149 Changed = ChangeStatus::CHANGED;
9150 }
9151 }
9152
9153 return Changed;
9154 }
9155};
9156
9157struct AAValueConstantRangeArgument final
9158 : AAArgumentFromCallSiteArguments<
9159 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9160 true /* BridgeCallBaseContext */> {
9161 using Base = AAArgumentFromCallSiteArguments<
9162 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9163 true /* BridgeCallBaseContext */>;
9164 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9165 : Base(IRP, A) {}
9166
9167 void trackStatistics() const override {
9168 STATS_DECLTRACK_ARG_ATTR(value_range)
9169 }
9170};
9171
9172struct AAValueConstantRangeReturned
9173 : AAReturnedFromReturnedValues<AAValueConstantRange,
9174 AAValueConstantRangeImpl,
9175 AAValueConstantRangeImpl::StateType,
9176 /* PropagateCallBaseContext */ true> {
9177 using Base =
9178 AAReturnedFromReturnedValues<AAValueConstantRange,
9179 AAValueConstantRangeImpl,
9180 AAValueConstantRangeImpl::StateType,
9181 /* PropagateCallBaseContext */ true>;
9182 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9183 : Base(IRP, A) {}
9184
9185 void initialize(Attributor &A) override {
9186 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9187 indicatePessimisticFixpoint();
9188 }
9189
9190 void trackStatistics() const override {
9191 STATS_DECLTRACK_FNRET_ATTR(value_range)
9192 }
9193};
9194
9195struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9196 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9197 : AAValueConstantRangeImpl(IRP, A) {}
9198
9199 void initialize(Attributor &A) override {
9200 AAValueConstantRangeImpl::initialize(A);
9201 if (isAtFixpoint())
9202 return;
9203
9204 Value &V = getAssociatedValue();
9205
9206 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9207 unionAssumed(ConstantRange(C->getValue()));
9208 indicateOptimisticFixpoint();
9209 return;
9210 }
9211
9212 if (isa<UndefValue>(&V)) {
9213 // Collapse the undef state to 0.
9214 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9215 indicateOptimisticFixpoint();
9216 return;
9217 }
9218
9219 if (isa<CallBase>(&V))
9220 return;
9221
9222 if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))
9223 return;
9224
9225 // If it is a load instruction with range metadata, use it.
9226 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9227 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9228 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9229 return;
9230 }
9231
9232 // We can work with PHI and select instruction as we traverse their operands
9233 // during update.
9234 if (isa<SelectInst>(V) || isa<PHINode>(V))
9235 return;
9236
9237 // Otherwise we give up.
9238 indicatePessimisticFixpoint();
9239
9240 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
9241 << getAssociatedValue() << "\n");
9242 }
9243
9244 bool calculateBinaryOperator(
9245 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9246 const Instruction *CtxI,
9247 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9248 Value *LHS = BinOp->getOperand(0);
9249 Value *RHS = BinOp->getOperand(1);
9250
9251 // Simplify the operands first.
9252 bool UsedAssumedInformation = false;
9253 const auto &SimplifiedLHS = A.getAssumedSimplified(
9254 IRPosition::value(*LHS, getCallBaseContext()), *this,
9255 UsedAssumedInformation, AA::Interprocedural);
9256 if (!SimplifiedLHS.has_value())
9257 return true;
9258 if (!*SimplifiedLHS)
9259 return false;
9260 LHS = *SimplifiedLHS;
9261
9262 const auto &SimplifiedRHS = A.getAssumedSimplified(
9263 IRPosition::value(*RHS, getCallBaseContext()), *this,
9264 UsedAssumedInformation, AA::Interprocedural);
9265 if (!SimplifiedRHS.has_value())
9266 return true;
9267 if (!*SimplifiedRHS)
9268 return false;
9269 RHS = *SimplifiedRHS;
9270
9271 // TODO: Allow non integers as well.
9272 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9273 return false;
9274
9275 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9276 *this, IRPosition::value(*LHS, getCallBaseContext()),
9277 DepClassTy::REQUIRED);
9278 if (!LHSAA)
9279 return false;
9280 QuerriedAAs.push_back(LHSAA);
9281 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9282
9283 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9284 *this, IRPosition::value(*RHS, getCallBaseContext()),
9285 DepClassTy::REQUIRED);
9286 if (!RHSAA)
9287 return false;
9288 QuerriedAAs.push_back(RHSAA);
9289 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9290
9291 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9292
9293 T.unionAssumed(AssumedRange);
9294
9295 // TODO: Track a known state too.
9296
9297 return T.isValidState();
9298 }
9299
9300 bool calculateCastInst(
9301 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9302 const Instruction *CtxI,
9303 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9304 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
9305 // TODO: Allow non integers as well.
9306 Value *OpV = CastI->getOperand(0);
9307
9308 // Simplify the operand first.
9309 bool UsedAssumedInformation = false;
9310 const auto &SimplifiedOpV = A.getAssumedSimplified(
9311 IRPosition::value(*OpV, getCallBaseContext()), *this,
9312 UsedAssumedInformation, AA::Interprocedural);
9313 if (!SimplifiedOpV.has_value())
9314 return true;
9315 if (!*SimplifiedOpV)
9316 return false;
9317 OpV = *SimplifiedOpV;
9318
9319 if (!OpV->getType()->isIntegerTy())
9320 return false;
9321
9322 auto *OpAA = A.getAAFor<AAValueConstantRange>(
9323 *this, IRPosition::value(*OpV, getCallBaseContext()),
9324 DepClassTy::REQUIRED);
9325 if (!OpAA)
9326 return false;
9327 QuerriedAAs.push_back(OpAA);
9328 T.unionAssumed(OpAA->getAssumed().castOp(CastI->getOpcode(),
9329 getState().getBitWidth()));
9330 return T.isValidState();
9331 }
9332
9333 bool
9334 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9335 const Instruction *CtxI,
9336 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9337 Value *LHS = CmpI->getOperand(0);
9338 Value *RHS = CmpI->getOperand(1);
9339
9340 // Simplify the operands first.
9341 bool UsedAssumedInformation = false;
9342 const auto &SimplifiedLHS = A.getAssumedSimplified(
9343 IRPosition::value(*LHS, getCallBaseContext()), *this,
9344 UsedAssumedInformation, AA::Interprocedural);
9345 if (!SimplifiedLHS.has_value())
9346 return true;
9347 if (!*SimplifiedLHS)
9348 return false;
9349 LHS = *SimplifiedLHS;
9350
9351 const auto &SimplifiedRHS = A.getAssumedSimplified(
9352 IRPosition::value(*RHS, getCallBaseContext()), *this,
9353 UsedAssumedInformation, AA::Interprocedural);
9354 if (!SimplifiedRHS.has_value())
9355 return true;
9356 if (!*SimplifiedRHS)
9357 return false;
9358 RHS = *SimplifiedRHS;
9359
9360 // TODO: Allow non integers as well.
9361 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9362 return false;
9363
9364 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9365 *this, IRPosition::value(*LHS, getCallBaseContext()),
9366 DepClassTy::REQUIRED);
9367 if (!LHSAA)
9368 return false;
9369 QuerriedAAs.push_back(LHSAA);
9370 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9371 *this, IRPosition::value(*RHS, getCallBaseContext()),
9372 DepClassTy::REQUIRED);
9373 if (!RHSAA)
9374 return false;
9375 QuerriedAAs.push_back(RHSAA);
9376 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9377 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9378
9379 // If one of them is empty set, we can't decide.
9380 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9381 return true;
9382
9383 bool MustTrue = false, MustFalse = false;
9384
9385 auto AllowedRegion =
9387
9388 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9389 MustFalse = true;
9390
9391 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9392 MustTrue = true;
9393
9394 assert((!MustTrue || !MustFalse) &&
9395 "Either MustTrue or MustFalse should be false!");
9396
9397 if (MustTrue)
9398 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9399 else if (MustFalse)
9400 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9401 else
9402 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9403
9404 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "
9405 << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))
9406 << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"
9407 << *RHSAA);
9408
9409 // TODO: Track a known state too.
9410 return T.isValidState();
9411 }
9412
9413 ChangeStatus updateImpl(Attributor &A) override {
9414
9415 IntegerRangeState T(getBitWidth());
9416 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9418 if (!I || isa<CallBase>(I)) {
9419
9420 // Simplify the operand first.
9421 bool UsedAssumedInformation = false;
9422 const auto &SimplifiedOpV = A.getAssumedSimplified(
9423 IRPosition::value(V, getCallBaseContext()), *this,
9424 UsedAssumedInformation, AA::Interprocedural);
9425 if (!SimplifiedOpV.has_value())
9426 return true;
9427 if (!*SimplifiedOpV)
9428 return false;
9429 Value *VPtr = *SimplifiedOpV;
9430
9431 // If the value is not instruction, we query AA to Attributor.
9432 const auto *AA = A.getAAFor<AAValueConstantRange>(
9433 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9434 DepClassTy::REQUIRED);
9435
9436 // Clamp operator is not used to utilize a program point CtxI.
9437 if (AA)
9438 T.unionAssumed(AA->getAssumedConstantRange(A, CtxI));
9439 else
9440 return false;
9441
9442 return T.isValidState();
9443 }
9444
9446 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9447 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9448 return false;
9449 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9450 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9451 return false;
9452 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9453 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9454 return false;
9455 } else {
9456 // Give up with other instructions.
9457 // TODO: Add other instructions
9458
9459 T.indicatePessimisticFixpoint();
9460 return false;
9461 }
9462
9463 // Catch circular reasoning in a pessimistic way for now.
9464 // TODO: Check how the range evolves and if we stripped anything, see also
9465 // AADereferenceable or AAAlign for similar situations.
9466 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9467 if (QueriedAA != this)
9468 continue;
9469 // If we are in a stady state we do not need to worry.
9470 if (T.getAssumed() == getState().getAssumed())
9471 continue;
9472 T.indicatePessimisticFixpoint();
9473 }
9474
9475 return T.isValidState();
9476 };
9477
9478 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9479 return indicatePessimisticFixpoint();
9480
9481 // Ensure that long def-use chains can't cause circular reasoning either by
9482 // introducing a cutoff below.
9483 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9484 return ChangeStatus::UNCHANGED;
9485 if (++NumChanges > MaxNumChanges) {
9486 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
9487 << " but only " << MaxNumChanges
9488 << " are allowed to avoid cyclic reasoning.");
9489 return indicatePessimisticFixpoint();
9490 }
9491 return ChangeStatus::CHANGED;
9492 }
9493
9494 void trackStatistics() const override {
9496 }
9497
9498 /// Tracker to bail after too many widening steps of the constant range.
9499 int NumChanges = 0;
9500
9501 /// Upper bound for the number of allowed changes (=widening steps) for the
9502 /// constant range before we give up.
9503 static constexpr int MaxNumChanges = 5;
9504};
9505
9506struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9507 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9508 : AAValueConstantRangeImpl(IRP, A) {}
9509
9510 ChangeStatus updateImpl(Attributor &A) override {
9511 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
9512 "not be called");
9513 }
9514
9515 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
9516};
9517
9518struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9519 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9520 : AAValueConstantRangeFunction(IRP, A) {}
9521
9522 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
9523};
9524
9525struct AAValueConstantRangeCallSiteReturned
9526 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9527 AAValueConstantRangeImpl::StateType,
9528 /* IntroduceCallBaseContext */ true> {
9529 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9530 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9531 AAValueConstantRangeImpl::StateType,
9532 /* IntroduceCallBaseContext */ true>(IRP, A) {}
9533
9534 void initialize(Attributor &A) override {
9535 // If it is a call instruction with range attribute, use the range.
9536 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) {
9537 if (std::optional<ConstantRange> Range = CI->getRange())
9538 intersectKnown(*Range);
9539 }
9540
9541 AAValueConstantRangeImpl::initialize(A);
9542 }
9543
9544 void trackStatistics() const override {
9545 STATS_DECLTRACK_CSRET_ATTR(value_range)
9546 }
9547};
9548struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9549 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9550 : AAValueConstantRangeFloating(IRP, A) {}
9551
9552 ChangeStatus manifest(Attributor &A) override {
9553 return ChangeStatus::UNCHANGED;
9554 }
9555
9556 void trackStatistics() const override {
9557 STATS_DECLTRACK_CSARG_ATTR(value_range)
9558 }
9559};
9560} // namespace
9561
9562/// ------------------ Potential Values Attribute -------------------------
9563
9564namespace {
9565struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9566 using StateType = PotentialConstantIntValuesState;
9567
9568 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9569 : AAPotentialConstantValues(IRP, A) {}
9570
9571 void initialize(Attributor &A) override {
9572 if (A.hasSimplificationCallback(getIRPosition()))
9573 indicatePessimisticFixpoint();
9574 else
9575 AAPotentialConstantValues::initialize(A);
9576 }
9577
9578 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9579 bool &ContainsUndef, bool ForSelf) {
9581 bool UsedAssumedInformation = false;
9582 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9583 UsedAssumedInformation)) {
9584 // Avoid recursion when the caller is computing constant values for this
9585 // IRP itself.
9586 if (ForSelf)
9587 return false;
9588 if (!IRP.getAssociatedType()->isIntegerTy())
9589 return false;
9590 auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9591 *this, IRP, DepClassTy::REQUIRED);
9592 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9593 return false;
9594 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9595 S = PotentialValuesAA->getState().getAssumedSet();
9596 return true;
9597 }
9598
9599 // Copy all the constant values, except UndefValue. ContainsUndef is true
9600 // iff Values contains only UndefValue instances. If there are other known
9601 // constants, then UndefValue is dropped.
9602 ContainsUndef = false;
9603 for (auto &It : Values) {
9604 if (isa<UndefValue>(It.getValue())) {
9605 ContainsUndef = true;
9606 continue;
9607 }
9608 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9609 if (!CI)
9610 return false;
9611 S.insert(CI->getValue());
9612 }
9613 ContainsUndef &= S.empty();
9614
9615 return true;
9616 }
9617
9618 const std::string getAsStr(Attributor *A) const override {
9619 std::string Str;
9620 llvm::raw_string_ostream OS(Str);
9621 OS << getState();
9622 return Str;
9623 }
9624
9625 ChangeStatus updateImpl(Attributor &A) override {
9626 return indicatePessimisticFixpoint();
9627 }
9628};
9629
9630struct AAPotentialConstantValuesArgument final
9631 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9632 AAPotentialConstantValuesImpl,
9633 PotentialConstantIntValuesState> {
9634 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9635 AAPotentialConstantValuesImpl,
9637 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9638 : Base(IRP, A) {}
9639
9640 void trackStatistics() const override {
9641 STATS_DECLTRACK_ARG_ATTR(potential_values)
9642 }
9643};
9644
9645struct AAPotentialConstantValuesReturned
9646 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9647 AAPotentialConstantValuesImpl> {
9648 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9649 AAPotentialConstantValuesImpl>;
9650 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9651 : Base(IRP, A) {}
9652
9653 void initialize(Attributor &A) override {
9654 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9655 indicatePessimisticFixpoint();
9656 Base::initialize(A);
9657 }
9658
9659 void trackStatistics() const override {
9660 STATS_DECLTRACK_FNRET_ATTR(potential_values)
9661 }
9662};
9663
9664struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9665 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9666 : AAPotentialConstantValuesImpl(IRP, A) {}
9667
9668 void initialize(Attributor &A) override {
9669 AAPotentialConstantValuesImpl::initialize(A);
9670 if (isAtFixpoint())
9671 return;
9672
9673 Value &V = getAssociatedValue();
9674
9675 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9676 unionAssumed(C->getValue());
9677 indicateOptimisticFixpoint();
9678 return;
9679 }
9680
9681 if (isa<UndefValue>(&V)) {
9682 unionAssumedWithUndef();
9683 indicateOptimisticFixpoint();
9684 return;
9685 }
9686
9687 if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))
9688 return;
9689
9690 if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))
9691 return;
9692
9693 indicatePessimisticFixpoint();
9694
9695 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
9696 << getAssociatedValue() << "\n");
9697 }
9698
9699 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9700 const APInt &RHS) {
9701 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9702 }
9703
9704 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9705 uint32_t ResultBitWidth) {
9706 Instruction::CastOps CastOp = CI->getOpcode();
9707 switch (CastOp) {
9708 default:
9709 llvm_unreachable("unsupported or not integer cast");
9710 case Instruction::Trunc:
9711 return Src.trunc(ResultBitWidth);
9712 case Instruction::SExt:
9713 return Src.sext(ResultBitWidth);
9714 case Instruction::ZExt:
9715 return Src.zext(ResultBitWidth);
9716 case Instruction::BitCast:
9717 return Src;
9718 }
9719 }
9720
9721 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9722 const APInt &LHS, const APInt &RHS,
9723 bool &SkipOperation, bool &Unsupported) {
9724 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9725 // Unsupported is set to true when the binary operator is not supported.
9726 // SkipOperation is set to true when UB occur with the given operand pair
9727 // (LHS, RHS).
9728 // TODO: we should look at nsw and nuw keywords to handle operations
9729 // that create poison or undef value.
9730 switch (BinOpcode) {
9731 default:
9732 Unsupported = true;
9733 return LHS;
9734 case Instruction::Add:
9735 return LHS + RHS;
9736 case Instruction::Sub:
9737 return LHS - RHS;
9738 case Instruction::Mul:
9739 return LHS * RHS;
9740 case Instruction::UDiv:
9741 if (RHS.isZero()) {
9742 SkipOperation = true;
9743 return LHS;
9744 }
9745 return LHS.udiv(RHS);
9746 case Instruction::SDiv:
9747 if (RHS.isZero()) {
9748 SkipOperation = true;
9749 return LHS;
9750 }
9751 return LHS.sdiv(RHS);
9752 case Instruction::URem:
9753 if (RHS.isZero()) {
9754 SkipOperation = true;
9755 return LHS;
9756 }
9757 return LHS.urem(RHS);
9758 case Instruction::SRem:
9759 if (RHS.isZero()) {
9760 SkipOperation = true;
9761 return LHS;
9762 }
9763 return LHS.srem(RHS);
9764 case Instruction::Shl:
9765 return LHS.shl(RHS);
9766 case Instruction::LShr:
9767 return LHS.lshr(RHS);
9768 case Instruction::AShr:
9769 return LHS.ashr(RHS);
9770 case Instruction::And:
9771 return LHS & RHS;
9772 case Instruction::Or:
9773 return LHS | RHS;
9774 case Instruction::Xor:
9775 return LHS ^ RHS;
9776 }
9777 }
9778
9779 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9780 const APInt &LHS, const APInt &RHS) {
9781 bool SkipOperation = false;
9782 bool Unsupported = false;
9783 APInt Result =
9784 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9785 if (Unsupported)
9786 return false;
9787 // If SkipOperation is true, we can ignore this operand pair (L, R).
9788 if (!SkipOperation)
9789 unionAssumed(Result);
9790 return isValidState();
9791 }
9792
9793 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9794 auto AssumedBefore = getAssumed();
9795 Value *LHS = ICI->getOperand(0);
9796 Value *RHS = ICI->getOperand(1);
9797
9798 bool LHSContainsUndef = false, RHSContainsUndef = false;
9799 SetTy LHSAAPVS, RHSAAPVS;
9800 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9801 LHSContainsUndef, /* ForSelf */ false) ||
9802 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9803 RHSContainsUndef, /* ForSelf */ false))
9804 return indicatePessimisticFixpoint();
9805
9806 // TODO: make use of undef flag to limit potential values aggressively.
9807 bool MaybeTrue = false, MaybeFalse = false;
9808 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
9809 if (LHSContainsUndef && RHSContainsUndef) {
9810 // The result of any comparison between undefs can be soundly replaced
9811 // with undef.
9812 unionAssumedWithUndef();
9813 } else if (LHSContainsUndef) {
9814 for (const APInt &R : RHSAAPVS) {
9815 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9816 MaybeTrue |= CmpResult;
9817 MaybeFalse |= !CmpResult;
9818 if (MaybeTrue & MaybeFalse)
9819 return indicatePessimisticFixpoint();
9820 }
9821 } else if (RHSContainsUndef) {
9822 for (const APInt &L : LHSAAPVS) {
9823 bool CmpResult = calculateICmpInst(ICI, L, Zero);
9824 MaybeTrue |= CmpResult;
9825 MaybeFalse |= !CmpResult;
9826 if (MaybeTrue & MaybeFalse)
9827 return indicatePessimisticFixpoint();
9828 }
9829 } else {
9830 for (const APInt &L : LHSAAPVS) {
9831 for (const APInt &R : RHSAAPVS) {
9832 bool CmpResult = calculateICmpInst(ICI, L, R);
9833 MaybeTrue |= CmpResult;
9834 MaybeFalse |= !CmpResult;
9835 if (MaybeTrue & MaybeFalse)
9836 return indicatePessimisticFixpoint();
9837 }
9838 }
9839 }
9840 if (MaybeTrue)
9841 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
9842 if (MaybeFalse)
9843 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
9844 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9845 : ChangeStatus::CHANGED;
9846 }
9847
9848 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
9849 auto AssumedBefore = getAssumed();
9850 Value *LHS = SI->getTrueValue();
9851 Value *RHS = SI->getFalseValue();
9852
9853 bool UsedAssumedInformation = false;
9854 std::optional<Constant *> C = A.getAssumedConstant(
9855 *SI->getCondition(), *this, UsedAssumedInformation);
9856
9857 // Check if we only need one operand.
9858 bool OnlyLeft = false, OnlyRight = false;
9859 if (C && *C && (*C)->isOneValue())
9860 OnlyLeft = true;
9861 else if (C && *C && (*C)->isNullValue())
9862 OnlyRight = true;
9863
9864 bool LHSContainsUndef = false, RHSContainsUndef = false;
9865 SetTy LHSAAPVS, RHSAAPVS;
9866 if (!OnlyRight &&
9867 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9868 LHSContainsUndef, /* ForSelf */ false))
9869 return indicatePessimisticFixpoint();
9870
9871 if (!OnlyLeft &&
9872 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9873 RHSContainsUndef, /* ForSelf */ false))
9874 return indicatePessimisticFixpoint();
9875
9876 if (OnlyLeft || OnlyRight) {
9877 // select (true/false), lhs, rhs
9878 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9879 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9880
9881 if (Undef)
9882 unionAssumedWithUndef();
9883 else {
9884 for (const auto &It : *OpAA)
9885 unionAssumed(It);
9886 }
9887
9888 } else if (LHSContainsUndef && RHSContainsUndef) {
9889 // select i1 *, undef , undef => undef
9890 unionAssumedWithUndef();
9891 } else {
9892 for (const auto &It : LHSAAPVS)
9893 unionAssumed(It);
9894 for (const auto &It : RHSAAPVS)
9895 unionAssumed(It);
9896 }
9897 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9898 : ChangeStatus::CHANGED;
9899 }
9900
9901 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
9902 auto AssumedBefore = getAssumed();
9903 if (!CI->isIntegerCast())
9904 return indicatePessimisticFixpoint();
9905 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
9906 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
9907 Value *Src = CI->getOperand(0);
9908
9909 bool SrcContainsUndef = false;
9910 SetTy SrcPVS;
9911 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
9912 SrcContainsUndef, /* ForSelf */ false))
9913 return indicatePessimisticFixpoint();
9914
9915 if (SrcContainsUndef)
9916 unionAssumedWithUndef();
9917 else {
9918 for (const APInt &S : SrcPVS) {
9919 APInt T = calculateCastInst(CI, S, ResultBitWidth);
9920 unionAssumed(T);
9921 }
9922 }
9923 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9924 : ChangeStatus::CHANGED;
9925 }
9926
9927 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
9928 auto AssumedBefore = getAssumed();
9929 Value *LHS = BinOp->getOperand(0);
9930 Value *RHS = BinOp->getOperand(1);
9931
9932 bool LHSContainsUndef = false, RHSContainsUndef = false;
9933 SetTy LHSAAPVS, RHSAAPVS;
9934 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9935 LHSContainsUndef, /* ForSelf */ false) ||
9936 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
9937 RHSContainsUndef, /* ForSelf */ false))
9938 return indicatePessimisticFixpoint();
9939
9940 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
9941
9942 // TODO: make use of undef flag to limit potential values aggressively.
9943 if (LHSContainsUndef && RHSContainsUndef) {
9944 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
9945 return indicatePessimisticFixpoint();
9946 } else if (LHSContainsUndef) {
9947 for (const APInt &R : RHSAAPVS) {
9948 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
9949 return indicatePessimisticFixpoint();
9950 }
9951 } else if (RHSContainsUndef) {
9952 for (const APInt &L : LHSAAPVS) {
9953 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
9954 return indicatePessimisticFixpoint();
9955 }
9956 } else {
9957 for (const APInt &L : LHSAAPVS) {
9958 for (const APInt &R : RHSAAPVS) {
9959 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9960 return indicatePessimisticFixpoint();
9961 }
9962 }
9963 }
9964 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9965 : ChangeStatus::CHANGED;
9966 }
9967
9968 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
9969 auto AssumedBefore = getAssumed();
9970 SetTy Incoming;
9971 bool ContainsUndef;
9972 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
9973 ContainsUndef, /* ForSelf */ true))
9974 return indicatePessimisticFixpoint();
9975 if (ContainsUndef) {
9976 unionAssumedWithUndef();
9977 } else {
9978 for (const auto &It : Incoming)
9979 unionAssumed(It);
9980 }
9981 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9982 : ChangeStatus::CHANGED;
9983 }
9984
9985 ChangeStatus updateImpl(Attributor &A) override {
9986 Value &V = getAssociatedValue();
9988
9989 if (auto *ICI = dyn_cast<ICmpInst>(I))
9990 return updateWithICmpInst(A, ICI);
9991
9992 if (auto *SI = dyn_cast<SelectInst>(I))
9993 return updateWithSelectInst(A, SI);
9994
9995 if (auto *CI = dyn_cast<CastInst>(I))
9996 return updateWithCastInst(A, CI);
9997
9998 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
9999 return updateWithBinaryOperator(A, BinOp);
10000
10001 if (isa<PHINode>(I) || isa<LoadInst>(I))
10002 return updateWithInstruction(A, I);
10003
10004 return indicatePessimisticFixpoint();
10005 }
10006
10007 void trackStatistics() const override {
10008 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
10009 }
10010};
10011
10012struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10013 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
10014 : AAPotentialConstantValuesImpl(IRP, A) {}
10015
10016 ChangeStatus updateImpl(Attributor &A) override {
10018 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10019 "not be called");
10020 }
10021
10022 void trackStatistics() const override {
10023 STATS_DECLTRACK_FN_ATTR(potential_values)
10024 }
10025};
10026
10027struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10028 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
10029 : AAPotentialConstantValuesFunction(IRP, A) {}
10030
10031 void trackStatistics() const override {
10032 STATS_DECLTRACK_CS_ATTR(potential_values)
10033 }
10034};
10035
10036struct AAPotentialConstantValuesCallSiteReturned
10037 : AACalleeToCallSite<AAPotentialConstantValues,
10038 AAPotentialConstantValuesImpl> {
10039 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
10040 Attributor &A)
10041 : AACalleeToCallSite<AAPotentialConstantValues,
10042 AAPotentialConstantValuesImpl>(IRP, A) {}
10043
10044 void trackStatistics() const override {
10045 STATS_DECLTRACK_CSRET_ATTR(potential_values)
10046 }
10047};
10048
10049struct AAPotentialConstantValuesCallSiteArgument
10050 : AAPotentialConstantValuesFloating {
10051 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
10052 Attributor &A)
10053 : AAPotentialConstantValuesFloating(IRP, A) {}
10054
10055 void initialize(Attributor &A) override {
10056 AAPotentialConstantValuesImpl::initialize(A);
10057 if (isAtFixpoint())
10058 return;
10059
10060 Value &V = getAssociatedValue();
10061
10062 if (auto *C = dyn_cast<ConstantInt>(&V)) {
10063 unionAssumed(C->getValue());
10064 indicateOptimisticFixpoint();
10065 return;
10066 }
10067
10068 if (isa<UndefValue>(&V)) {
10069 unionAssumedWithUndef();
10070 indicateOptimisticFixpoint();
10071 return;
10072 }
10073 }
10074
10075 ChangeStatus updateImpl(Attributor &A) override {
10076 Value &V = getAssociatedValue();
10077 auto AssumedBefore = getAssumed();
10078 auto *AA = A.getAAFor<AAPotentialConstantValues>(
10079 *this, IRPosition::value(V), DepClassTy::REQUIRED);
10080 if (!AA)
10081 return indicatePessimisticFixpoint();
10082 const auto &S = AA->getAssumed();
10083 unionAssumed(S);
10084 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10085 : ChangeStatus::CHANGED;
10086 }
10087
10088 void trackStatistics() const override {
10089 STATS_DECLTRACK_CSARG_ATTR(potential_values)
10090 }
10091};
10092} // namespace
10093
10094/// ------------------------ NoUndef Attribute ---------------------------------
10096 Attribute::AttrKind ImpliedAttributeKind,
10097 bool IgnoreSubsumingPositions) {
10098 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10099 "Unexpected attribute kind");
10100 if (A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10101 Attribute::NoUndef))
10102 return true;
10103
10104 Value &Val = IRP.getAssociatedValue();
10107 LLVMContext &Ctx = Val.getContext();
10108 A.manifestAttrs(IRP, Attribute::get(Ctx, Attribute::NoUndef));
10109 return true;
10110 }
10111
10112 return false;
10113}
10114
10115namespace {
10116struct AANoUndefImpl : AANoUndef {
10117 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
10118
10119 void initialize(Attributor &A) override {
10120 Value &V = getAssociatedValue();
10121 if (isa<UndefValue>(V))
10122 indicatePessimisticFixpoint();
10123 assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));
10124 }
10125
10126 /// See followUsesInMBEC
10127 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10128 AANoUndef::StateType &State) {
10129 const Value *UseV = U->get();
10130 const DominatorTree *DT = nullptr;
10131 AssumptionCache *AC = nullptr;
10132 InformationCache &InfoCache = A.getInfoCache();
10133 if (Function *F = getAnchorScope()) {
10134 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10135 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10136 }
10137 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10138 bool TrackUse = false;
10139 // Track use for instructions which must produce undef or poison bits when
10140 // at least one operand contains such bits.
10142 TrackUse = true;
10143 return TrackUse;
10144 }
10145
10146 const std::string getAsStr(Attributor *A) const override {
10147 return getAssumed() ? "noundef" : "may-undef-or-poison";
10148 }
10149
10150 ChangeStatus manifest(Attributor &A) override {
10151 // We don't manifest noundef attribute for dead positions because the
10152 // associated values with dead positions would be replaced with undef
10153 // values.
10154 bool UsedAssumedInformation = false;
10155 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10156 UsedAssumedInformation))
10157 return ChangeStatus::UNCHANGED;
10158 // A position whose simplified value does not have any value is
10159 // considered to be dead. We don't manifest noundef in such positions for
10160 // the same reason above.
10161 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10163 .has_value())
10164 return ChangeStatus::UNCHANGED;
10165 return AANoUndef::manifest(A);
10166 }
10167};
10168
10169struct AANoUndefFloating : public AANoUndefImpl {
10170 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10171 : AANoUndefImpl(IRP, A) {}
10172
10173 void initialize(Attributor &A) override {
10174 AANoUndefImpl::initialize(A);
10175 if (!getState().isAtFixpoint() && getAnchorScope() &&
10176 !getAnchorScope()->isDeclaration())
10177 if (Instruction *CtxI = getCtxI())
10178 followUsesInMBEC(*this, A, getState(), *CtxI);
10179 }
10180
10181 ChangeStatus updateImpl(Attributor &A) override {
10182 auto VisitValueCB = [&](const IRPosition &IRP) -> bool {
10183 bool IsKnownNoUndef;
10185 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10186 };
10187
10188 bool Stripped;
10189 bool UsedAssumedInformation = false;
10190 Value *AssociatedValue = &getAssociatedValue();
10192 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10193 AA::AnyScope, UsedAssumedInformation))
10194 Stripped = false;
10195 else
10196 Stripped =
10197 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
10198
10199 if (!Stripped) {
10200 // If we haven't stripped anything we might still be able to use a
10201 // different AA, but only if the IRP changes. Effectively when we
10202 // interpret this not as a call site value but as a floating/argument
10203 // value.
10204 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
10205 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10206 return indicatePessimisticFixpoint();
10207 return ChangeStatus::UNCHANGED;
10208 }
10209
10210 for (const auto &VAC : Values)
10211 if (!VisitValueCB(IRPosition::value(*VAC.getValue())))
10212 return indicatePessimisticFixpoint();
10213
10214 return ChangeStatus::UNCHANGED;
10215 }
10216
10217 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10218};
10219
10220struct AANoUndefReturned final
10221 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10222 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10223 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10224
10225 void initialize(Attributor &A) override {
10226 AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>::initialize(A);
10227 if (isAtFixpoint())
10228 return;
10229
10230 // Returning a value that violates a return attribute, e.g., nonnull, is
10231 // poison.
10232 AttributeMask AM = AttributeFuncs::getPoisonGeneratingAttributes();
10233 AttributeSet RetAttrs =
10234 getAssociatedFunction()->getAttributes().getRetAttrs();
10235 if (any_of(RetAttrs, [&](Attribute Attr) { return AM.contains(Attr); }))
10236 indicatePessimisticFixpoint();
10237 }
10238
10239 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10240};
10241
10242struct AANoUndefArgument final
10243 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10244 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10245 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10246
10247 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
10248};
10249
10250struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10251 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10252 : AANoUndefFloating(IRP, A) {}
10253
10254 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
10255};
10256
10257struct AANoUndefCallSiteReturned final
10258 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10259 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10260 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP, A) {}
10261
10262 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
10263};
10264
10265/// ------------------------ NoFPClass Attribute -------------------------------
10266
10267struct AANoFPClassImpl : AANoFPClass {
10268 AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}
10269
10270 void initialize(Attributor &A) override {
10271 const IRPosition &IRP = getIRPosition();
10272
10273 Value &V = IRP.getAssociatedValue();
10274 if (isa<UndefValue>(V)) {
10275 indicateOptimisticFixpoint();
10276 return;
10277 }
10278
10280 A.getAttrs(getIRPosition(), {Attribute::NoFPClass}, Attrs, false);
10281 for (const auto &Attr : Attrs) {
10282 addKnownBits(Attr.getNoFPClass());
10283 }
10284
10285 Instruction *CtxI = getCtxI();
10286
10287 if (getPositionKind() != IRPosition::IRP_RETURNED) {
10288 const DataLayout &DL = A.getDataLayout();
10289 InformationCache &InfoCache = A.getInfoCache();
10290
10291 const DominatorTree *DT = nullptr;
10292 AssumptionCache *AC = nullptr;
10293 const TargetLibraryInfo *TLI = nullptr;
10294 Function *F = getAnchorScope();
10295 if (F) {
10296 TLI = InfoCache.getTargetLibraryInfoForFunction(*F);
10297 if (!F->isDeclaration()) {
10298 DT =
10299 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10300 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10301 }
10302 }
10303
10304 SimplifyQuery Q(DL, TLI, DT, AC, CtxI);
10305
10306 KnownFPClass KnownFPClass = computeKnownFPClass(&V, fcAllFlags, Q);
10307 addKnownBits(~KnownFPClass.getKnownFPClasses());
10308 }
10309
10310 if (CtxI)
10311 followUsesInMBEC(*this, A, getState(), *CtxI);
10312 }
10313
10314 /// See followUsesInMBEC
10315 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10316 AANoFPClass::StateType &State) {
10317 // TODO: Determine what instructions can be looked through.
10318 auto *CB = dyn_cast<CallBase>(I);
10319 if (!CB)
10320 return false;
10321
10322 if (!CB->isArgOperand(U))
10323 return false;
10324
10325 unsigned ArgNo = CB->getArgOperandNo(U);
10326 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
10327 if (auto *NoFPAA = A.getAAFor<AANoFPClass>(*this, IRP, DepClassTy::NONE))
10328 State.addKnownBits(NoFPAA->getState().getKnown());
10329 return false;
10330 }
10331
10332 const std::string getAsStr(Attributor *A) const override {
10333 std::string Result = "nofpclass";
10334 raw_string_ostream OS(Result);
10335 OS << getKnownNoFPClass() << '/' << getAssumedNoFPClass();
10336 return Result;
10337 }
10338
10339 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
10340 SmallVectorImpl<Attribute> &Attrs) const override {
10341 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10342 }
10343};
10344
10345struct AANoFPClassFloating : public AANoFPClassImpl {
10346 AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
10347 : AANoFPClassImpl(IRP, A) {}
10348
10349 ChangeStatus updateImpl(Attributor &A) override {
10351 bool UsedAssumedInformation = false;
10352 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10353 AA::AnyScope, UsedAssumedInformation)) {
10354 Values.push_back({getAssociatedValue(), getCtxI()});
10355 }
10356
10357 StateType T;
10358 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10359 const auto *AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),
10360 DepClassTy::REQUIRED);
10361 if (!AA || this == AA) {
10362 T.indicatePessimisticFixpoint();
10363 } else {
10364 const AANoFPClass::StateType &S =
10365 static_cast<const AANoFPClass::StateType &>(AA->getState());
10366 T ^= S;
10367 }
10368 return T.isValidState();
10369 };
10370
10371 for (const auto &VAC : Values)
10372 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10373 return indicatePessimisticFixpoint();
10374
10375 return clampStateAndIndicateChange(getState(), T);
10376 }
10377
10378 void trackStatistics() const override {
10380 }
10381};
10382
10383struct AANoFPClassReturned final
10384 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10385 AANoFPClassImpl::StateType, false,
10386 Attribute::None, false> {
10387 AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
10388 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10389 AANoFPClassImpl::StateType, false,
10390 Attribute::None, false>(IRP, A) {}
10391
10392 void trackStatistics() const override {
10394 }
10395};
10396
10397struct AANoFPClassArgument final
10398 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10399 AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
10400 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10401
10402 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }
10403};
10404
10405struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10406 AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
10407 : AANoFPClassFloating(IRP, A) {}
10408
10409 void trackStatistics() const override {
10411 }
10412};
10413
10414struct AANoFPClassCallSiteReturned final
10415 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10416 AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
10417 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10418
10419 void trackStatistics() const override {
10421 }
10422};
10423
10424struct AACallEdgesImpl : public AACallEdges {
10425 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10426
10427 const SetVector<Function *> &getOptimisticEdges() const override {
10428 return CalledFunctions;
10429 }
10430
10431 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10432
10433 bool hasNonAsmUnknownCallee() const override {
10434 return HasUnknownCalleeNonAsm;
10435 }
10436
10437 const std::string getAsStr(Attributor *A) const override {
10438 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10439 std::to_string(CalledFunctions.size()) + "]";
10440 }
10441
10442 void trackStatistics() const override {}
10443
10444protected:
10445 /// Return the callee of \p CB if it is a direct call whose callee has no
10446 /// callback metadata. Such a call only calls its callee.
10447 static Function *getOnlyCallee(const CallBase &CB) {
10449 if (Callee && !Callee->hasMetadata(LLVMContext::MD_callback))
10450 return Callee;
10451 return nullptr;
10452 }
10453
10454 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10455 if (CalledFunctions.insert(Fn)) {
10456 Change = ChangeStatus::CHANGED;
10457 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
10458 << "\n");
10459 }
10460 }
10461
10462 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10463 if (!HasUnknownCallee)
10464 Change = ChangeStatus::CHANGED;
10465 if (NonAsm && !HasUnknownCalleeNonAsm)
10466 Change = ChangeStatus::CHANGED;
10467 HasUnknownCalleeNonAsm |= NonAsm;
10468 HasUnknownCallee = true;
10469 }
10470
10471private:
10472 /// Optimistic set of functions that might be called by this position.
10473 SetVector<Function *> CalledFunctions;
10474
10475 /// Is there any call with a unknown callee.
10476 bool HasUnknownCallee = false;
10477
10478 /// Is there any call with a unknown callee, excluding any inline asm.
10479 bool HasUnknownCalleeNonAsm = false;
10480};
10481
10482struct AACallEdgesCallSite : public AACallEdgesImpl {
10483 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10484 : AACallEdgesImpl(IRP, A) {}
10485
10486 void initialize(Attributor &A) override {
10487 // The only callee of a direct call without callbacks never changes.
10488 if (Function *Callee = getOnlyCallee(cast<CallBase>(getAnchorValue()))) {
10489 ChangeStatus Change = ChangeStatus::UNCHANGED;
10490 addCalledFunction(Callee, Change);
10491 indicateOptimisticFixpoint();
10492 }
10493 }
10494
10495 ChangeStatus updateImpl(Attributor &A) override {
10496 ChangeStatus Change = ChangeStatus::UNCHANGED;
10497
10498 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10499 if (Function *Fn = dyn_cast<Function>(&V)) {
10500 addCalledFunction(Fn, Change);
10501 } else {
10502 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
10503 setHasUnknownCallee(true, Change);
10504 }
10505
10506 // Explore all values.
10507 return true;
10508 };
10509
10511 // Process any value that we might call.
10512 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10513 if (isa<Constant>(V)) {
10514 VisitValue(*V, CtxI);
10515 return;
10516 }
10517
10518 bool UsedAssumedInformation = false;
10519 Values.clear();
10520 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10521 AA::AnyScope, UsedAssumedInformation)) {
10522 Values.push_back({*V, CtxI});
10523 }
10524 for (auto &VAC : Values)
10525 VisitValue(*VAC.getValue(), VAC.getCtxI());
10526 };
10527
10528 CallBase *CB = cast<CallBase>(getCtxI());
10529
10530 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10531 if (IA->hasSideEffects() &&
10532 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10533 !hasAssumption(*CB, "ompx_no_call_asm")) {
10534 setHasUnknownCallee(false, Change);
10535 }
10536 return Change;
10537 }
10538
10539 if (CB->isIndirectCall())
10540 if (auto *IndirectCallAA = A.getAAFor<AAIndirectCallInfo>(
10541 *this, getIRPosition(), DepClassTy::OPTIONAL))
10542 if (IndirectCallAA->foreachCallee(
10543 [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10544 return Change;
10545
10546 // The most simple case.
10547 ProcessCalledOperand(CB->getCalledOperand(), CB);
10548
10549 // Process callback functions.
10550 SmallVector<const Use *, 4u> CallbackUses;
10551 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10552 for (const Use *U : CallbackUses)
10553 ProcessCalledOperand(U->get(), CB);
10554
10555 return Change;
10556 }
10557};
10558
10559struct AACallEdgesFunction : public AACallEdgesImpl {
10560 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10561 : AACallEdgesImpl(IRP, A) {}
10562
10563 ChangeStatus updateImpl(Attributor &A) override {
10564 ChangeStatus Change = ChangeStatus::UNCHANGED;
10565 bool AllCallsDirect = true;
10566
10567 auto ProcessCallInst = [&](Instruction &Inst) {
10568 CallBase &CB = cast<CallBase>(Inst);
10569
10570 // A direct call without callbacks only calls its callee; there is no
10571 // need for a call site attribute.
10572 if (Function *Callee = getOnlyCallee(CB)) {
10573 addCalledFunction(Callee, Change);
10574 return true;
10575 }
10576
10577 AllCallsDirect = false;
10578 auto *CBEdges = A.getAAFor<AACallEdges>(
10579 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10580 if (!CBEdges)
10581 return false;
10582 if (CBEdges->hasNonAsmUnknownCallee())
10583 setHasUnknownCallee(true, Change);
10584 if (CBEdges->hasUnknownCallee())
10585 setHasUnknownCallee(false, Change);
10586
10587 for (Function *F : CBEdges->getOptimisticEdges())
10588 addCalledFunction(F, Change);
10589
10590 return true;
10591 };
10592
10593 // Visit all callable instructions.
10594 bool UsedAssumedInformation = false;
10595 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10596 UsedAssumedInformation,
10597 /* CheckBBLivenessOnly */ true)) {
10598 // If we haven't looked at all call like instructions, assume that there
10599 // are unknown callees.
10600 setHasUnknownCallee(true, Change);
10601 }
10602
10603 // The callees of direct calls in code known to be live do not change.
10604 if (AllCallsDirect && !UsedAssumedInformation)
10605 indicateOptimisticFixpoint();
10606
10607 return Change;
10608 }
10609};
10610
10611/// -------------------AAInterFnReachability Attribute--------------------------
10612
10613struct AAInterFnReachabilityFunction
10614 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10615 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10616 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10617 : Base(IRP, A) {}
10618
10619 bool instructionCanReach(
10620 Attributor &A, const Instruction &From, const Function &To,
10621 const AA::InstExclusionSetTy *ExclusionSet) const override {
10622 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
10623 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10624
10625 RQITy StackRQI(A, From, To, ExclusionSet, false);
10626 RQITy::Reachable Result;
10627 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
10628 return NonConstThis->isReachableImpl(A, StackRQI,
10629 /*IsTemporaryRQI=*/true);
10630 return Result == RQITy::Reachable::Yes;
10631 }
10632
10633 bool isReachableImpl(Attributor &A, RQITy &RQI,
10634 bool IsTemporaryRQI) override {
10635 const Instruction *EntryI =
10636 &RQI.From->getFunction()->getEntryBlock().front();
10637 if (EntryI != RQI.From &&
10638 !instructionCanReach(A, *EntryI, *RQI.To, nullptr))
10639 return rememberResult(A, RQITy::Reachable::No, RQI, false,
10640 IsTemporaryRQI);
10641
10642 auto CheckReachableCallBase = [&](CallBase *CB) {
10643 auto *CBEdges = A.getAAFor<AACallEdges>(
10644 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10645 if (!CBEdges || !CBEdges->getState().isValidState())
10646 return false;
10647 // TODO Check To backwards in this case.
10648 if (CBEdges->hasUnknownCallee())
10649 return false;
10650
10651 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10652 if (Fn == RQI.To)
10653 return false;
10654
10655 if (Fn->isDeclaration()) {
10656 if (Fn->hasFnAttribute(Attribute::NoCallback))
10657 continue;
10658 // TODO Check To backwards in this case.
10659 return false;
10660 }
10661
10662 if (Fn == getAnchorScope()) {
10663 if (EntryI == RQI.From)
10664 continue;
10665 return false;
10666 }
10667
10668 const AAInterFnReachability *InterFnReachability =
10669 A.getAAFor<AAInterFnReachability>(*this, IRPosition::function(*Fn),
10670 DepClassTy::OPTIONAL);
10671
10672 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10673 if (!InterFnReachability ||
10674 InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10675 RQI.ExclusionSet))
10676 return false;
10677 }
10678 return true;
10679 };
10680
10681 const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10682 *this, IRPosition::function(*RQI.From->getFunction()),
10683 DepClassTy::OPTIONAL);
10684
10685 // Determine call like instructions that we can reach from the inst.
10686 auto CheckCallBase = [&](Instruction &CBInst) {
10687 // There are usually less nodes in the call graph, check inter function
10688 // reachability first.
10689 if (CheckReachableCallBase(cast<CallBase>(&CBInst)))
10690 return true;
10691 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10692 A, *RQI.From, CBInst, RQI.ExclusionSet);
10693 };
10694
10695 bool UsedExclusionSet = /* conservative */ true;
10696 bool UsedAssumedInformation = false;
10697 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10698 UsedAssumedInformation,
10699 /* CheckBBLivenessOnly */ true))
10700 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10701 IsTemporaryRQI);
10702
10703 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10704 IsTemporaryRQI);
10705 }
10706
10707 void trackStatistics() const override {}
10708};
10709} // namespace
10710
10711template <typename AAType>
10712static std::optional<Constant *>
10714 const IRPosition &IRP, Type &Ty) {
10715 if (!Ty.isIntegerTy())
10716 return nullptr;
10717
10718 // This will also pass the call base context.
10719 const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10720 if (!AA)
10721 return nullptr;
10722
10723 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
10724
10725 if (!COpt.has_value()) {
10726 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10727 return std::nullopt;
10728 }
10729 if (auto *C = *COpt) {
10730 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10731 return C;
10732 }
10733 return nullptr;
10734}
10735
10737 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10739 Type &Ty = *IRP.getAssociatedType();
10740 std::optional<Value *> V;
10741 for (auto &It : Values) {
10742 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10743 if (V.has_value() && !*V)
10744 break;
10745 }
10746 if (!V.has_value())
10747 return UndefValue::get(&Ty);
10748 return *V;
10749}
10750
10751namespace {
10752struct AAPotentialValuesImpl : AAPotentialValues {
10753 using StateType = PotentialLLVMValuesState;
10754
10755 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10756 : AAPotentialValues(IRP, A) {}
10757
10758 void initialize(Attributor &A) override {
10759 if (A.hasSimplificationCallback(getIRPosition())) {
10760 indicatePessimisticFixpoint();
10761 return;
10762 }
10763 Value *Stripped = getAssociatedValue().stripPointerCasts();
10764 if (isa<Constant>(Stripped) && !isa<ConstantExpr>(Stripped)) {
10765 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10766 getAnchorScope());
10767 indicateOptimisticFixpoint();
10768 return;
10769 }
10770 AAPotentialValues::initialize(A);
10771 }
10772
10773 const std::string getAsStr(Attributor *A) const override {
10774 std::string Str;
10775 llvm::raw_string_ostream OS(Str);
10776 OS << getState();
10777 return Str;
10778 }
10779
10780 template <typename AAType>
10781 static std::optional<Value *> askOtherAA(Attributor &A,
10782 const AbstractAttribute &AA,
10783 const IRPosition &IRP, Type &Ty) {
10785 return &IRP.getAssociatedValue();
10786 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10787 if (!C)
10788 return std::nullopt;
10789 if (*C)
10790 if (auto *CC = AA::getWithType(**C, Ty))
10791 return CC;
10792 return nullptr;
10793 }
10794
10795 virtual void addValue(Attributor &A, StateType &State, Value &V,
10796 const Instruction *CtxI, AA::ValueScope S,
10797 Function *AnchorScope) const {
10798
10799 IRPosition ValIRP = IRPosition::value(V);
10800 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
10801 for (const auto &U : CB->args()) {
10802 if (U.get() != &V)
10803 continue;
10804 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
10805 break;
10806 }
10807 }
10808
10809 Value *VPtr = &V;
10810 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10811 Type &Ty = *getAssociatedType();
10812 std::optional<Value *> SimpleV =
10813 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
10814 if (SimpleV.has_value() && !*SimpleV) {
10815 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10816 *this, ValIRP, DepClassTy::OPTIONAL);
10817 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10818 for (const auto &It : PotentialConstantsAA->getAssumedSet())
10819 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
10820 if (PotentialConstantsAA->undefIsContained())
10821 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
10822 return;
10823 }
10824 }
10825 if (!SimpleV.has_value())
10826 return;
10827
10828 if (*SimpleV)
10829 VPtr = *SimpleV;
10830 }
10831
10832 if (isa<ConstantInt>(VPtr))
10833 CtxI = nullptr;
10834 if (!AA::isValidInScope(*VPtr, AnchorScope))
10836
10837 State.unionAssumed({{*VPtr, CtxI}, S});
10838 }
10839
10840 /// Helper struct to tie a value+context pair together with the scope for
10841 /// which this is the simplified version.
10842 struct ItemInfo {
10843 AA::ValueAndContext I;
10845
10846 bool operator==(const ItemInfo &II) const {
10847 return II.I == I && II.S == S;
10848 };
10849 bool operator<(const ItemInfo &II) const {
10850 return std::tie(I, S) < std::tie(II.I, II.S);
10851 };
10852 };
10853
10854 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
10855 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10856 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
10857 if (!(CS & S))
10858 continue;
10859
10860 bool UsedAssumedInformation = false;
10862 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
10863 UsedAssumedInformation))
10864 return false;
10865
10866 for (auto &It : Values)
10867 ValueScopeMap[It] += CS;
10868 }
10869 for (auto &It : ValueScopeMap)
10870 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
10871 AA::ValueScope(It.second), getAnchorScope());
10872
10873 return true;
10874 }
10875
10876 void giveUpOnIntraprocedural(Attributor &A) {
10877 auto NewS = StateType::getBestState(getState());
10878 for (const auto &It : getAssumedSet()) {
10879 if (It.second == AA::Intraprocedural)
10880 continue;
10881 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
10882 AA::Interprocedural, getAnchorScope());
10883 }
10884 assert(!undefIsContained() && "Undef should be an explicit value!");
10885 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
10886 getAnchorScope());
10887 getState() = NewS;
10888 }
10889
10890 ChangeStatus indicatePessimisticFixpoint() override {
10891 getState() = StateType::getBestState(getState());
10892 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
10893 AAPotentialValues::indicateOptimisticFixpoint();
10894 return ChangeStatus::CHANGED;
10895 }
10896
10897 ChangeStatus updateImpl(Attributor &A) override {
10898 return indicatePessimisticFixpoint();
10899 }
10900
10901 ChangeStatus manifest(Attributor &A) override {
10904 Values.clear();
10905 if (!getAssumedSimplifiedValues(A, Values, S))
10906 continue;
10907 Value &OldV = getAssociatedValue();
10908 if (isa<UndefValue>(OldV))
10909 continue;
10910 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
10911 if (!NewV || NewV == &OldV)
10912 continue;
10913 if (getCtxI() &&
10914 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
10915 continue;
10916 if (A.changeAfterManifest(getIRPosition(), *NewV))
10917 return ChangeStatus::CHANGED;
10918 }
10919 return ChangeStatus::UNCHANGED;
10920 }
10921
10922 bool getAssumedSimplifiedValues(
10923 Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,
10924 AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {
10925 if (!isValidState())
10926 return false;
10927 bool UsedAssumedInformation = false;
10928 for (const auto &It : getAssumedSet())
10929 if (It.second & S) {
10930 if (RecurseForSelectAndPHI && (isa<PHINode>(It.first.getValue()) ||
10931 isa<SelectInst>(It.first.getValue()))) {
10932 if (A.getAssumedSimplifiedValues(
10933 IRPosition::inst(*cast<Instruction>(It.first.getValue())),
10934 this, Values, S, UsedAssumedInformation))
10935 continue;
10936 }
10937 Values.push_back(It.first);
10938 }
10939 assert(!undefIsContained() && "Undef should be an explicit value!");
10940 return true;
10941 }
10942};
10943
10944struct AAPotentialValuesFloating : AAPotentialValuesImpl {
10945 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
10946 : AAPotentialValuesImpl(IRP, A) {}
10947
10948 ChangeStatus updateImpl(Attributor &A) override {
10949 auto AssumedBefore = getAssumed();
10950
10951 genericValueTraversal(A, &getAssociatedValue());
10952
10953 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10954 : ChangeStatus::CHANGED;
10955 }
10956
10957 /// Helper struct to remember which AAIsDead instances we actually used.
10958 struct LivenessInfo {
10959 const AAIsDead *LivenessAA = nullptr;
10960 bool AnyDead = false;
10961 };
10962
10963 /// Check if \p Cmp is a comparison we can simplify.
10964 ///
10965 /// We handle multiple cases, one in which at least one operand is an
10966 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
10967 /// operand. Return true if successful, in that case Worklist will be updated.
10968 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
10969 CmpInst::Predicate Pred, ItemInfo II,
10970 SmallVectorImpl<ItemInfo> &Worklist) {
10971
10972 // Simplify the operands first.
10973 bool UsedAssumedInformation = false;
10974 SmallVector<AA::ValueAndContext> LHSValues, RHSValues;
10975 auto GetSimplifiedValues = [&](Value &V,
10977 if (!A.getAssumedSimplifiedValues(
10978 IRPosition::value(V, getCallBaseContext()), this, Values,
10979 AA::Intraprocedural, UsedAssumedInformation)) {
10980 Values.clear();
10981 Values.push_back(AA::ValueAndContext{V, II.I.getCtxI()});
10982 }
10983 return Values.empty();
10984 };
10985 if (GetSimplifiedValues(*LHS, LHSValues))
10986 return true;
10987 if (GetSimplifiedValues(*RHS, RHSValues))
10988 return true;
10989
10990 LLVMContext &Ctx = LHS->getContext();
10991
10992 InformationCache &InfoCache = A.getInfoCache();
10993 Instruction *CmpI = dyn_cast<Instruction>(&Cmp);
10994 Function *F = CmpI ? CmpI->getFunction() : nullptr;
10995 const auto *DT =
10996 F ? InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F)
10997 : nullptr;
10998 const auto *TLI =
10999 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
11000 auto *AC =
11001 F ? InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F)
11002 : nullptr;
11003
11004 const DataLayout &DL = A.getDataLayout();
11005 SimplifyQuery Q(DL, TLI, DT, AC, CmpI);
11006
11007 auto CheckPair = [&](Value &LHSV, Value &RHSV) {
11008 if (isa<UndefValue>(LHSV) || isa<UndefValue>(RHSV)) {
11009 addValue(A, getState(), *UndefValue::get(Cmp.getType()),
11010 /* CtxI */ nullptr, II.S, getAnchorScope());
11011 return true;
11012 }
11013
11014 // Handle the trivial case first in which we don't even need to think
11015 // about null or non-null.
11016 if (&LHSV == &RHSV &&
11018 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11020 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11021 getAnchorScope());
11022 return true;
11023 }
11024
11025 auto *TypedLHS = AA::getWithType(LHSV, *LHS->getType());
11026 auto *TypedRHS = AA::getWithType(RHSV, *RHS->getType());
11027 if (TypedLHS && TypedRHS) {
11028 Value *NewV = simplifyCmpInst(Pred, TypedLHS, TypedRHS, Q);
11029 if (NewV && NewV != &Cmp) {
11030 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11031 getAnchorScope());
11032 return true;
11033 }
11034 }
11035
11036 // From now on we only handle equalities (==, !=).
11037 if (!CmpInst::isEquality(Pred))
11038 return false;
11039
11040 bool LHSIsNull = isa<ConstantPointerNull>(LHSV);
11041 bool RHSIsNull = isa<ConstantPointerNull>(RHSV);
11042 if (!LHSIsNull && !RHSIsNull)
11043 return false;
11044
11045 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
11046 // non-nullptr operand and if we assume it's non-null we can conclude the
11047 // result of the comparison.
11048 assert((LHSIsNull || RHSIsNull) &&
11049 "Expected nullptr versus non-nullptr comparison at this point");
11050
11051 // The index is the operand that we assume is not null.
11052 unsigned PtrIdx = LHSIsNull;
11053 bool IsKnownNonNull;
11054 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
11055 A, this, IRPosition::value(*(PtrIdx ? &RHSV : &LHSV)),
11056 DepClassTy::REQUIRED, IsKnownNonNull);
11057 if (!IsAssumedNonNull)
11058 return false;
11059
11060 // The new value depends on the predicate, true for != and false for ==.
11061 Constant *NewV =
11062 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
11063 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11064 getAnchorScope());
11065 return true;
11066 };
11067
11068 for (auto &LHSValue : LHSValues)
11069 for (auto &RHSValue : RHSValues)
11070 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11071 return false;
11072 return true;
11073 }
11074
11075 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
11076 SmallVectorImpl<ItemInfo> &Worklist) {
11077 const Instruction *CtxI = II.I.getCtxI();
11078 bool UsedAssumedInformation = false;
11079
11080 std::optional<Constant *> C =
11081 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
11082 bool NoValueYet = !C.has_value();
11083 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
11084 return true;
11085 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
11086 if (CI->isZero())
11087 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11088 else
11089 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11090 } else if (&SI == &getAssociatedValue()) {
11091 // We could not simplify the condition, assume both values.
11092 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11093 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11094 } else {
11095 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11096 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
11097 if (!SimpleV.has_value())
11098 return true;
11099 if (*SimpleV) {
11100 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
11101 return true;
11102 }
11103 return false;
11104 }
11105 return true;
11106 }
11107
11108 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
11109 SmallVectorImpl<ItemInfo> &Worklist) {
11110 SmallSetVector<Value *, 4> PotentialCopies;
11111 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11112 bool UsedAssumedInformation = false;
11113 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
11114 PotentialValueOrigins, *this,
11115 UsedAssumedInformation,
11116 /* OnlyExact */ true)) {
11117 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
11118 "loaded values for load instruction "
11119 << LI << "\n");
11120 return false;
11121 }
11122
11123 // Do not simplify loads that are only used in llvm.assume if we cannot also
11124 // remove all stores that may feed into the load. The reason is that the
11125 // assume is probably worth something as long as the stores are around.
11126 InformationCache &InfoCache = A.getInfoCache();
11127 if (InfoCache.isOnlyUsedByAssume(LI)) {
11128 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
11129 if (!I || isa<AssumeInst>(I))
11130 return true;
11131 if (auto *SI = dyn_cast<StoreInst>(I))
11132 return A.isAssumedDead(SI->getOperandUse(0), this,
11133 /* LivenessAA */ nullptr,
11134 UsedAssumedInformation,
11135 /* CheckBBLivenessOnly */ false);
11136 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
11137 UsedAssumedInformation,
11138 /* CheckBBLivenessOnly */ false);
11139 })) {
11140 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
11141 "and we cannot delete all the stores: "
11142 << LI << "\n");
11143 return false;
11144 }
11145 }
11146
11147 // Values have to be dynamically unique or we loose the fact that a
11148 // single llvm::Value might represent two runtime values (e.g.,
11149 // stack locations in different recursive calls).
11150 const Instruction *CtxI = II.I.getCtxI();
11151 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
11152 bool AllLocal = ScopeIsLocal;
11153 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
11154 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
11155 return AA::isDynamicallyUnique(A, *this, *PC);
11156 });
11157 if (!DynamicallyUnique) {
11158 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
11159 "values are dynamically unique: "
11160 << LI << "\n");
11161 return false;
11162 }
11163
11164 for (auto *PotentialCopy : PotentialCopies) {
11165 if (AllLocal) {
11166 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
11167 } else {
11168 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
11169 }
11170 }
11171 if (!AllLocal && ScopeIsLocal)
11172 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
11173 return true;
11174 }
11175
11176 bool handlePHINode(
11177 Attributor &A, PHINode &PHI, ItemInfo II,
11178 SmallVectorImpl<ItemInfo> &Worklist,
11179 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11180 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
11181 LivenessInfo &LI = LivenessAAs[&F];
11182 if (!LI.LivenessAA)
11183 LI.LivenessAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
11184 DepClassTy::NONE);
11185 return LI;
11186 };
11187
11188 if (&PHI == &getAssociatedValue()) {
11189 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
11190 const auto *CI =
11191 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11192 *PHI.getFunction());
11193
11194 CycleRef C;
11195 bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);
11196 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
11197 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
11198 if (LI.LivenessAA &&
11199 LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
11200 LI.AnyDead = true;
11201 continue;
11202 }
11203 Value *V = PHI.getIncomingValue(u);
11204 if (V == &PHI)
11205 continue;
11206
11207 // If the incoming value is not the PHI but an instruction in the same
11208 // cycle we might have multiple versions of it flying around.
11209 if (CyclePHI && isa<Instruction>(V) &&
11210 (!C || CI->contains(C, cast<Instruction>(V)->getParent())))
11211 return false;
11212
11213 Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});
11214 }
11215 return true;
11216 }
11217
11218 bool UsedAssumedInformation = false;
11219 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11220 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
11221 if (!SimpleV.has_value())
11222 return true;
11223 if (!(*SimpleV))
11224 return false;
11225 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
11226 return true;
11227 }
11228
11229 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
11230 /// simplify any operand of the instruction \p I. Return true if successful,
11231 /// in that case Worklist will be updated.
11232 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
11233 SmallVectorImpl<ItemInfo> &Worklist) {
11234 bool SomeSimplified = false;
11235 bool UsedAssumedInformation = false;
11236
11237 SmallVector<Value *, 8> NewOps(I.getNumOperands());
11238 int Idx = 0;
11239 for (Value *Op : I.operands()) {
11240 const auto &SimplifiedOp = A.getAssumedSimplified(
11241 IRPosition::value(*Op, getCallBaseContext()), *this,
11242 UsedAssumedInformation, AA::Intraprocedural);
11243 // If we are not sure about any operand we are not sure about the entire
11244 // instruction, we'll wait.
11245 if (!SimplifiedOp.has_value())
11246 return true;
11247
11248 if (*SimplifiedOp)
11249 NewOps[Idx] = *SimplifiedOp;
11250 else
11251 NewOps[Idx] = Op;
11252
11253 SomeSimplified |= (NewOps[Idx] != Op);
11254 ++Idx;
11255 }
11256
11257 // We won't bother with the InstSimplify interface if we didn't simplify any
11258 // operand ourselves.
11259 if (!SomeSimplified)
11260 return false;
11261
11262 InformationCache &InfoCache = A.getInfoCache();
11263 Function *F = I.getFunction();
11264 const auto *DT =
11265 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
11266 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
11267 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
11268
11269 const DataLayout &DL = I.getDataLayout();
11270 SimplifyQuery Q(DL, TLI, DT, AC, &I);
11271 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);
11272 if (!NewV || NewV == &I)
11273 return false;
11274
11275 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
11276 << *NewV << "\n");
11277 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
11278 return true;
11279 }
11280
11282 Attributor &A, Instruction &I, ItemInfo II,
11283 SmallVectorImpl<ItemInfo> &Worklist,
11284 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11285 if (auto *CI = dyn_cast<CmpInst>(&I))
11286 return handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
11287 CI->getPredicate(), II, Worklist);
11288
11289 switch (I.getOpcode()) {
11290 case Instruction::Select:
11291 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
11292 case Instruction::PHI:
11293 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
11294 case Instruction::Load:
11295 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
11296 default:
11297 return handleGenericInst(A, I, II, Worklist);
11298 };
11299 return false;
11300 }
11301
11302 void genericValueTraversal(Attributor &A, Value *InitialV) {
11303 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11304
11305 SmallSet<ItemInfo, 16> Visited;
11307 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
11308
11309 int Iteration = 0;
11310 do {
11311 ItemInfo II = Worklist.pop_back_val();
11312 Value *V = II.I.getValue();
11313 assert(V);
11314 const Instruction *CtxI = II.I.getCtxI();
11315 AA::ValueScope S = II.S;
11316
11317 // Check if we should process the current value. To prevent endless
11318 // recursion keep a record of the values we followed!
11319 if (!Visited.insert(II).second)
11320 continue;
11321
11322 // Make sure we limit the compile time for complex expressions.
11323 if (Iteration++ >= MaxPotentialValuesIterations) {
11324 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
11325 << Iteration << "!\n");
11326 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11327 continue;
11328 }
11329
11330 // Explicitly look through calls with a "returned" attribute if we do
11331 // not have a pointer as stripPointerCasts only works on them.
11332 Value *NewV = nullptr;
11333 if (V->getType()->isPointerTy()) {
11334 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
11335 } else {
11336 if (auto *CB = dyn_cast<CallBase>(V))
11337 if (auto *Callee =
11339 for (Argument &Arg : Callee->args())
11340 if (Arg.hasReturnedAttr()) {
11341 NewV = CB->getArgOperand(Arg.getArgNo());
11342 break;
11343 }
11344 }
11345 }
11346 if (NewV && NewV != V) {
11347 Worklist.push_back({{*NewV, CtxI}, S});
11348 continue;
11349 }
11350
11351 if (auto *I = dyn_cast<Instruction>(V)) {
11352 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
11353 continue;
11354 }
11355
11356 if (V != InitialV || isa<Argument>(V))
11357 if (recurseForValue(A, IRPosition::value(*V), II.S))
11358 continue;
11359
11360 // If we haven't stripped anything we give up.
11361 if (V == InitialV && CtxI == getCtxI()) {
11362 indicatePessimisticFixpoint();
11363 return;
11364 }
11365
11366 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11367 } while (!Worklist.empty());
11368
11369 // If we actually used liveness information so we have to record a
11370 // dependence.
11371 for (auto &It : LivenessAAs)
11372 if (It.second.AnyDead)
11373 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
11374 }
11375
11376 void trackStatistics() const override {
11377 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
11378 }
11379};
11380
11381struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11382 using Base = AAPotentialValuesImpl;
11383 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11384 : Base(IRP, A) {}
11385
11386 void initialize(Attributor &A) override {
11387 auto &Arg = cast<Argument>(getAssociatedValue());
11389 indicatePessimisticFixpoint();
11390 }
11391
11392 ChangeStatus updateImpl(Attributor &A) override {
11393 auto AssumedBefore = getAssumed();
11394
11395 unsigned ArgNo = getCalleeArgNo();
11396
11397 bool UsedAssumedInformation = false;
11399 auto CallSitePred = [&](AbstractCallSite ACS) {
11400 const auto CSArgIRP = IRPosition::callsite_argument(ACS, ArgNo);
11401 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11402 return false;
11403
11404 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11406 UsedAssumedInformation))
11407 return false;
11408
11409 return isValidState();
11410 };
11411
11412 if (!A.checkForAllCallSites(CallSitePred, *this,
11413 /* RequireAllCallSites */ true,
11414 UsedAssumedInformation))
11415 return indicatePessimisticFixpoint();
11416
11417 Function *Fn = getAssociatedFunction();
11418 bool AnyNonLocal = false;
11419 for (auto &It : Values) {
11420 if (isa<Constant>(It.getValue())) {
11421 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11422 getAnchorScope());
11423 continue;
11424 }
11425 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11426 return indicatePessimisticFixpoint();
11427
11428 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11429 if (Arg->getParent() == Fn) {
11430 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11431 getAnchorScope());
11432 continue;
11433 }
11434 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11435 getAnchorScope());
11436 AnyNonLocal = true;
11437 }
11438 assert(!undefIsContained() && "Undef should be an explicit value!");
11439 if (AnyNonLocal)
11440 giveUpOnIntraprocedural(A);
11441
11442 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11443 : ChangeStatus::CHANGED;
11444 }
11445
11446 void trackStatistics() const override {
11447 STATS_DECLTRACK_ARG_ATTR(potential_values)
11448 }
11449};
11450
11451struct AAPotentialValuesReturned : public AAPotentialValuesFloating {
11452 using Base = AAPotentialValuesFloating;
11453 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11454 : Base(IRP, A) {}
11455
11456 void initialize(Attributor &A) override {
11457 Function *F = getAssociatedFunction();
11458 if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {
11459 indicatePessimisticFixpoint();
11460 return;
11461 }
11462
11463 for (Argument &Arg : F->args())
11464 if (Arg.hasReturnedAttr()) {
11465 addValue(A, getState(), Arg, nullptr, AA::AnyScope, F);
11466 ReturnedArg = &Arg;
11467 break;
11468 }
11469 if (!A.isFunctionIPOAmendable(*F) ||
11470 A.hasSimplificationCallback(getIRPosition())) {
11471 if (!ReturnedArg)
11472 indicatePessimisticFixpoint();
11473 else
11474 indicateOptimisticFixpoint();
11475 }
11476 }
11477
11478 ChangeStatus updateImpl(Attributor &A) override {
11479 auto AssumedBefore = getAssumed();
11480 bool UsedAssumedInformation = false;
11481
11483 Function *AnchorScope = getAnchorScope();
11484 auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,
11485 bool AddValues) {
11487 Values.clear();
11488 if (!A.getAssumedSimplifiedValues(IRPosition::value(V), this, Values, S,
11489 UsedAssumedInformation,
11490 /* RecurseForSelectAndPHI */ true))
11491 return false;
11492 if (!AddValues)
11493 continue;
11494
11495 bool AllInterAreIntra = false;
11496 if (S == AA::Interprocedural)
11497 AllInterAreIntra =
11498 llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) {
11499 return AA::isValidInScope(*VAC.getValue(), AnchorScope);
11500 });
11501
11502 for (const AA::ValueAndContext &VAC : Values) {
11503 addValue(A, getState(), *VAC.getValue(),
11504 VAC.getCtxI() ? VAC.getCtxI() : CtxI,
11505 AllInterAreIntra ? AA::AnyScope : S, AnchorScope);
11506 }
11507 if (AllInterAreIntra)
11508 break;
11509 }
11510 return true;
11511 };
11512
11513 if (ReturnedArg) {
11514 HandleReturnedValue(*ReturnedArg, nullptr, true);
11515 } else {
11516 auto RetInstPred = [&](Instruction &RetI) {
11517 bool AddValues = true;
11518 if (isa<PHINode>(RetI.getOperand(0)) ||
11519 isa<SelectInst>(RetI.getOperand(0))) {
11520 addValue(A, getState(), *RetI.getOperand(0), &RetI, AA::AnyScope,
11521 AnchorScope);
11522 AddValues = false;
11523 }
11524 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11525 };
11526
11527 if (!A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11528 UsedAssumedInformation,
11529 /* CheckBBLivenessOnly */ true))
11530 return indicatePessimisticFixpoint();
11531 }
11532
11533 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11534 : ChangeStatus::CHANGED;
11535 }
11536
11537 ChangeStatus manifest(Attributor &A) override {
11538 if (ReturnedArg)
11539 return ChangeStatus::UNCHANGED;
11541 if (!getAssumedSimplifiedValues(A, Values, AA::ValueScope::Intraprocedural,
11542 /* RecurseForSelectAndPHI */ true))
11543 return ChangeStatus::UNCHANGED;
11544 Value *NewVal = getSingleValue(A, *this, getIRPosition(), Values);
11545 if (!NewVal)
11546 return ChangeStatus::UNCHANGED;
11547
11548 ChangeStatus Changed = ChangeStatus::UNCHANGED;
11549 if (auto *Arg = dyn_cast<Argument>(NewVal)) {
11550 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
11551 "Number of function with unique return");
11552 Changed |= A.manifestAttrs(
11554 {Attribute::get(Arg->getContext(), Attribute::Returned)});
11555 STATS_DECLTRACK_ARG_ATTR(returned);
11556 }
11557
11558 auto RetInstPred = [&](Instruction &RetI) {
11559 Value *RetOp = RetI.getOperand(0);
11560 if (isa<UndefValue>(RetOp) || RetOp == NewVal)
11561 return true;
11562 if (AA::isValidAtPosition({*NewVal, RetI}, A.getInfoCache()))
11563 if (A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11564 Changed = ChangeStatus::CHANGED;
11565 return true;
11566 };
11567 bool UsedAssumedInformation = false;
11568 (void)A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11569 UsedAssumedInformation,
11570 /* CheckBBLivenessOnly */ true);
11571 return Changed;
11572 }
11573
11574 ChangeStatus indicatePessimisticFixpoint() override {
11575 return AAPotentialValues::indicatePessimisticFixpoint();
11576 }
11577
11578 void trackStatistics() const override{
11579 STATS_DECLTRACK_FNRET_ATTR(potential_values)}
11580
11581 /// The argumented with an existing `returned` attribute.
11582 Argument *ReturnedArg = nullptr;
11583};
11584
11585struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11586 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11587 : AAPotentialValuesImpl(IRP, A) {}
11588
11589 ChangeStatus updateImpl(Attributor &A) override {
11590 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
11591 "not be called");
11592 }
11593
11594 void trackStatistics() const override {
11595 STATS_DECLTRACK_FN_ATTR(potential_values)
11596 }
11597};
11598
11599struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11600 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11601 : AAPotentialValuesFunction(IRP, A) {}
11602
11603 void trackStatistics() const override {
11604 STATS_DECLTRACK_CS_ATTR(potential_values)
11605 }
11606};
11607
11608struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11609 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11610 : AAPotentialValuesImpl(IRP, A) {}
11611
11612 ChangeStatus updateImpl(Attributor &A) override {
11613 auto AssumedBefore = getAssumed();
11614
11615 Function *Callee = getAssociatedFunction();
11616 if (!Callee)
11617 return indicatePessimisticFixpoint();
11618
11619 bool UsedAssumedInformation = false;
11620 auto *CB = cast<CallBase>(getCtxI());
11621 if (CB->isMustTailCall() &&
11622 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11623 UsedAssumedInformation))
11624 return indicatePessimisticFixpoint();
11625
11626 Function *Caller = CB->getCaller();
11627
11628 auto AddScope = [&](AA::ValueScope S) {
11630 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11631 Values, S, UsedAssumedInformation))
11632 return false;
11633
11634 for (auto &It : Values) {
11635 Value *V = It.getValue();
11636 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11637 V, *CB, *this, UsedAssumedInformation);
11638 if (!CallerV.has_value()) {
11639 // Nothing to do as long as no value was determined.
11640 continue;
11641 }
11642 V = *CallerV ? *CallerV : V;
11643 if (*CallerV && AA::isDynamicallyUnique(A, *this, *V)) {
11644 if (recurseForValue(A, IRPosition::value(*V), S))
11645 continue;
11646 }
11647 if (S == AA::Intraprocedural && !AA::isValidInScope(*V, Caller)) {
11648 giveUpOnIntraprocedural(A);
11649 return true;
11650 }
11651 addValue(A, getState(), *V, CB, S, getAnchorScope());
11652 }
11653 return true;
11654 };
11655 if (!AddScope(AA::Intraprocedural))
11656 return indicatePessimisticFixpoint();
11657 if (!AddScope(AA::Interprocedural))
11658 return indicatePessimisticFixpoint();
11659 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11660 : ChangeStatus::CHANGED;
11661 }
11662
11663 ChangeStatus indicatePessimisticFixpoint() override {
11664 return AAPotentialValues::indicatePessimisticFixpoint();
11665 }
11666
11667 void trackStatistics() const override {
11668 STATS_DECLTRACK_CSRET_ATTR(potential_values)
11669 }
11670};
11671
11672struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11673 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11674 : AAPotentialValuesFloating(IRP, A) {}
11675
11676 void trackStatistics() const override {
11677 STATS_DECLTRACK_CSARG_ATTR(potential_values)
11678 }
11679};
11680} // namespace
11681
11682/// ---------------------- Assumption Propagation ------------------------------
11683namespace {
11684struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11685 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11686 const DenseSet<StringRef> &Known)
11687 : AAAssumptionInfo(IRP, A, Known) {}
11688
11689 ChangeStatus manifest(Attributor &A) override {
11690 // Don't manifest a universal set if it somehow made it here.
11691 if (getKnown().isUniversal())
11692 return ChangeStatus::UNCHANGED;
11693
11694 const IRPosition &IRP = getIRPosition();
11695 SmallVector<StringRef, 0> Set(getAssumed().getSet().begin(),
11696 getAssumed().getSet().end());
11697 llvm::sort(Set);
11698 return A.manifestAttrs(IRP,
11699 Attribute::get(IRP.getAnchorValue().getContext(),
11701 llvm::join(Set, ",")),
11702 /*ForceReplace=*/true);
11703 }
11704
11705 bool hasAssumption(const StringRef Assumption) const override {
11706 return isValidState() && setContains(Assumption);
11707 }
11708
11709 const std::string getAsStr(Attributor *A) const override {
11710 const SetContents &Known = getKnown();
11711 const SetContents &Assumed = getAssumed();
11712
11713 SmallVector<StringRef, 0> Set(Known.getSet().begin(), Known.getSet().end());
11714 llvm::sort(Set);
11715 const std::string KnownStr = llvm::join(Set, ",");
11716
11717 std::string AssumedStr = "Universal";
11718 if (!Assumed.isUniversal()) {
11719 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11720 AssumedStr = llvm::join(Set, ",");
11721 }
11722 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11723 }
11724};
11725
11726/// Propagates assumption information from parent functions to all of their
11727/// successors. An assumption can be propagated if the containing function
11728/// dominates the called function.
11729///
11730/// We start with a "known" set of assumptions already valid for the associated
11731/// function and an "assumed" set that initially contains all possible
11732/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11733/// contents as concrete values are known. The concrete values are seeded by the
11734/// first nodes that are either entries into the call graph, or contains no
11735/// assumptions. Each node is updated as the intersection of the assumed state
11736/// with all of its predecessors.
11737struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11738 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11739 : AAAssumptionInfoImpl(IRP, A,
11740 getAssumptions(*IRP.getAssociatedFunction())) {}
11741
11742 ChangeStatus updateImpl(Attributor &A) override {
11743 bool Changed = false;
11744
11745 auto CallSitePred = [&](AbstractCallSite ACS) {
11746 const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11747 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11748 DepClassTy::REQUIRED);
11749 if (!AssumptionAA)
11750 return false;
11751 // Get the set of assumptions shared by all of this function's callers.
11752 Changed |= getIntersection(AssumptionAA->getAssumed());
11753 return !getAssumed().empty() || !getKnown().empty();
11754 };
11755
11756 bool UsedAssumedInformation = false;
11757 // Get the intersection of all assumptions held by this node's predecessors.
11758 // If we don't know all the call sites then this is either an entry into the
11759 // call graph or an empty node. This node is known to only contain its own
11760 // assumptions and can be propagated to its successors.
11761 if (!A.checkForAllCallSites(CallSitePred, *this, true,
11762 UsedAssumedInformation))
11763 return indicatePessimisticFixpoint();
11764
11765 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11766 }
11767
11768 void trackStatistics() const override {}
11769};
11770
11771/// Assumption Info defined for call sites.
11772struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11773
11774 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11775 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11776
11777 void initialize(Attributor &A) override {
11778 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11779 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11780 }
11781
11782 ChangeStatus updateImpl(Attributor &A) override {
11783 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11784 auto *AssumptionAA =
11785 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11786 if (!AssumptionAA)
11787 return indicatePessimisticFixpoint();
11788 bool Changed = getIntersection(AssumptionAA->getAssumed());
11789 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11790 }
11791
11792 void trackStatistics() const override {}
11793
11794private:
11795 /// Helper to initialized the known set as all the assumptions this call and
11796 /// the callee contain.
11797 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11798 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
11799 auto Assumptions = getAssumptions(CB);
11800 if (const Function *F = CB.getCaller())
11801 set_union(Assumptions, getAssumptions(*F));
11802 if (Function *F = IRP.getAssociatedFunction())
11803 set_union(Assumptions, getAssumptions(*F));
11804 return Assumptions;
11805 }
11806};
11807} // namespace
11808
11810 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11811 A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
11812}
11813
11815
11816/// ------------------------ UnderlyingObjects ---------------------------------
11817
11818namespace {
11819struct AAUnderlyingObjectsImpl
11820 : StateWrapper<BooleanState, AAUnderlyingObjects> {
11822 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
11823
11824 const std::string getAsStr(Attributor *A) const override {
11825 if (!isValidState())
11826 return "<invalid>";
11827 std::string Str;
11829 OS << "underlying objects: inter " << InterAssumedUnderlyingObjects.size()
11830 << " objects, intra " << IntraAssumedUnderlyingObjects.size()
11831 << " objects.\n";
11832 if (!InterAssumedUnderlyingObjects.empty()) {
11833 OS << "inter objects:\n";
11834 for (auto *Obj : InterAssumedUnderlyingObjects)
11835 OS << *Obj << '\n';
11836 }
11837 if (!IntraAssumedUnderlyingObjects.empty()) {
11838 OS << "intra objects:\n";
11839 for (auto *Obj : IntraAssumedUnderlyingObjects)
11840 OS << *Obj << '\n';
11841 }
11842 return Str;
11843 }
11844
11845 void trackStatistics() const override {}
11846
11847 ChangeStatus updateImpl(Attributor &A) override {
11848 auto &Ptr = getAssociatedValue();
11849
11850 bool UsedAssumedInformation = false;
11851 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11853 SmallPtrSet<Value *, 8> SeenObjects;
11855
11856 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
11857 Scope, UsedAssumedInformation))
11858 return UnderlyingObjects.insert(&Ptr);
11859
11860 bool Changed = false;
11861
11862 for (unsigned I = 0; I < Values.size(); ++I) {
11863 auto &VAC = Values[I];
11864 auto *Obj = VAC.getValue();
11865 Value *UO = getUnderlyingObject(Obj);
11866 if (!SeenObjects.insert(UO ? UO : Obj).second)
11867 continue;
11868 if (UO && UO != Obj) {
11869 if (isa<AllocaInst>(UO) || isa<GlobalValue>(UO)) {
11870 Changed |= UnderlyingObjects.insert(UO);
11871 continue;
11872 }
11873
11874 const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(
11875 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
11876 auto Pred = [&](Value &V) {
11877 if (&V == UO)
11878 Changed |= UnderlyingObjects.insert(UO);
11879 else
11880 Values.emplace_back(V, nullptr);
11881 return true;
11882 };
11883
11884 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
11886 "The forall call should not return false at this position");
11887 UsedAssumedInformation |= !OtherAA->getState().isAtFixpoint();
11888 continue;
11889 }
11890
11891 if (isa<SelectInst>(Obj)) {
11892 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope,
11893 UsedAssumedInformation);
11894 continue;
11895 }
11896 if (auto *PHI = dyn_cast<PHINode>(Obj)) {
11897 // Explicitly look through PHIs as we do not care about dynamically
11898 // uniqueness.
11899 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
11900 Changed |=
11901 handleIndirect(A, *PHI->getIncomingValue(u), UnderlyingObjects,
11902 Scope, UsedAssumedInformation);
11903 }
11904 continue;
11905 }
11906
11907 Changed |= UnderlyingObjects.insert(Obj);
11908 }
11909
11910 return Changed;
11911 };
11912
11913 bool Changed = false;
11914 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
11915 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
11916 if (!UsedAssumedInformation)
11917 indicateOptimisticFixpoint();
11918 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11919 }
11920
11921 bool forallUnderlyingObjects(
11922 function_ref<bool(Value &)> Pred,
11923 AA::ValueScope Scope = AA::Interprocedural) const override {
11924 if (!isValidState())
11925 return Pred(getAssociatedValue());
11926
11927 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
11928 ? IntraAssumedUnderlyingObjects
11929 : InterAssumedUnderlyingObjects;
11930 for (Value *Obj : AssumedUnderlyingObjects)
11931 if (!Pred(*Obj))
11932 return false;
11933
11934 return true;
11935 }
11936
11937private:
11938 /// Handle the case where the value is not the actual underlying value, such
11939 /// as a phi node or a select instruction.
11940 bool handleIndirect(Attributor &A, Value &V,
11941 SmallSetVector<Value *, 8> &UnderlyingObjects,
11942 AA::ValueScope Scope, bool &UsedAssumedInformation) {
11943 bool Changed = false;
11944 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
11945 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
11946 auto Pred = [&](Value &V) {
11947 Changed |= UnderlyingObjects.insert(&V);
11948 return true;
11949 };
11950 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
11952 "The forall call should not return false at this position");
11953 UsedAssumedInformation |= !AA->getState().isAtFixpoint();
11954 return Changed;
11955 }
11956
11957 /// All the underlying objects collected so far via intra procedural scope.
11958 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11959 /// All the underlying objects collected so far via inter procedural scope.
11960 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11961};
11962
11963struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
11964 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
11965 : AAUnderlyingObjectsImpl(IRP, A) {}
11966};
11967
11968struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
11969 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
11970 : AAUnderlyingObjectsImpl(IRP, A) {}
11971};
11972
11973struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
11974 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
11975 : AAUnderlyingObjectsImpl(IRP, A) {}
11976};
11977
11978struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
11979 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
11980 : AAUnderlyingObjectsImpl(IRP, A) {}
11981};
11982
11983struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
11984 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
11985 : AAUnderlyingObjectsImpl(IRP, A) {}
11986};
11987
11988struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
11989 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
11990 : AAUnderlyingObjectsImpl(IRP, A) {}
11991};
11992
11993struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
11994 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
11995 : AAUnderlyingObjectsImpl(IRP, A) {}
11996};
11997} // namespace
11998
11999/// ------------------------ Global Value Info -------------------------------
12000namespace {
12001struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
12002 AAGlobalValueInfoFloating(const IRPosition &IRP, Attributor &A)
12003 : AAGlobalValueInfo(IRP, A) {}
12004
12005 void initialize(Attributor &A) override {}
12006
12007 bool checkUse(Attributor &A, const Use &U, bool &Follow,
12008 SmallVectorImpl<const Value *> &Worklist) {
12009 Instruction *UInst = dyn_cast<Instruction>(U.getUser());
12010 if (!UInst) {
12011 // Outside a closed world, code outside the module can read an
12012 // externally visible global, so the value escapes through it.
12013 if (auto *GV = dyn_cast<GlobalValue>(U.getUser()))
12014 if (!GV->hasLocalLinkage() && !A.isClosedWorldModule())
12015 return false;
12016 Follow = true;
12017 return true;
12018 }
12019
12020 LLVM_DEBUG(dbgs() << "[AAGlobalValueInfo] Check use: " << *U.get() << " in "
12021 << *UInst << "\n");
12022
12023 if (auto *Cmp = dyn_cast<ICmpInst>(U.getUser())) {
12024 int Idx = &Cmp->getOperandUse(0) == &U;
12025 if (isa<Constant>(Cmp->getOperand(Idx)))
12026 return true;
12027 return U == &getAnchorValue();
12028 }
12029
12030 // Explicitly catch return instructions.
12031 if (isa<ReturnInst>(UInst)) {
12032 auto CallSitePred = [&](AbstractCallSite ACS) {
12033 Worklist.push_back(ACS.getInstruction());
12034 return true;
12035 };
12036 bool UsedAssumedInformation = false;
12037 // TODO: We should traverse the uses or add a "non-call-site" CB.
12038 if (!A.checkForAllCallSites(CallSitePred, *UInst->getFunction(),
12039 /*RequireAllCallSites=*/true, this,
12040 UsedAssumedInformation))
12041 return false;
12042 return true;
12043 }
12044
12045 // For now we only use special logic for call sites. However, the tracker
12046 // itself knows about a lot of other non-capturing cases already.
12047 auto *CB = dyn_cast<CallBase>(UInst);
12048 if (!CB)
12049 return false;
12050 // Direct calls are OK uses.
12051 if (CB->isCallee(&U))
12052 return true;
12053 // Non-argument uses are scary.
12054 if (!CB->isArgOperand(&U))
12055 return false;
12056 // TODO: Iterate callees.
12057 auto *Fn = dyn_cast<Function>(CB->getCalledOperand());
12058 if (!Fn || !A.isFunctionIPOAmendable(*Fn))
12059 return false;
12060
12061 unsigned ArgNo = CB->getArgOperandNo(&U);
12062 Worklist.push_back(Fn->getArg(ArgNo));
12063 return true;
12064 }
12065
12066 ChangeStatus updateImpl(Attributor &A) override {
12067 unsigned NumUsesBefore = Uses.size();
12068
12069 SmallPtrSet<const Value *, 8> Visited;
12071 Worklist.push_back(&getAnchorValue());
12072
12073 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
12074 Uses.insert(&U);
12075 // TODO(captures): Make this more precise.
12076 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
12077 if (CI.isPassthrough()) {
12078 Follow = true;
12079 return true;
12080 }
12081 return checkUse(A, U, Follow, Worklist);
12082 };
12083 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
12084 Uses.insert(&OldU);
12085 return true;
12086 };
12087
12088 while (!Worklist.empty()) {
12089 const Value *V = Worklist.pop_back_val();
12090 if (!Visited.insert(V).second)
12091 continue;
12092 if (!A.checkForAllUses(UsePred, *this, *V,
12093 /* CheckBBLivenessOnly */ true,
12094 DepClassTy::OPTIONAL,
12095 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
12096 return indicatePessimisticFixpoint();
12097 }
12098 }
12099
12100 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12101 : ChangeStatus::CHANGED;
12102 }
12103
12104 bool isPotentialUse(const Use &U) const override {
12105 return !isValidState() || Uses.contains(&U);
12106 }
12107
12108 ChangeStatus manifest(Attributor &A) override {
12109 return ChangeStatus::UNCHANGED;
12110 }
12111
12112 const std::string getAsStr(Attributor *A) const override {
12113 return "[" + std::to_string(Uses.size()) + " uses]";
12114 }
12115
12116 void trackStatistics() const override {
12117 STATS_DECLTRACK_FLOATING_ATTR(GlobalValuesTracked);
12118 }
12119
12120private:
12121 /// Set of (transitive) uses of this GlobalValue.
12122 SmallPtrSet<const Use *, 8> Uses;
12123};
12124} // namespace
12125
12126/// ------------------------ Indirect Call Info -------------------------------
12127namespace {
12128struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12129 AAIndirectCallInfoCallSite(const IRPosition &IRP, Attributor &A)
12130 : AAIndirectCallInfo(IRP, A) {}
12131
12132 void initialize(Attributor &A) override {
12133 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12134 if (!MD && !A.isClosedWorldModule())
12135 return;
12136
12137 if (MD) {
12138 for (const auto &Op : MD->operands())
12140 PotentialCallees.insert(Callee);
12141 } else if (A.isClosedWorldModule()) {
12142 ArrayRef<Function *> IndirectlyCallableFunctions =
12143 A.getInfoCache().getIndirectlyCallableFunctions(A);
12144 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12145 }
12146
12147 if (PotentialCallees.empty())
12148 indicateOptimisticFixpoint();
12149 }
12150
12151 ChangeStatus updateImpl(Attributor &A) override {
12152 CallBase *CB = cast<CallBase>(getCtxI());
12153 const Use &CalleeUse = CB->getCalledOperandUse();
12154 Value *FP = CB->getCalledOperand();
12155
12156 SmallSetVector<Function *, 4> AssumedCalleesNow;
12157 bool AllCalleesKnownNow = AllCalleesKnown;
12158
12159 auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,
12160 bool &UsedAssumedInformation) {
12161 const auto *GIAA = A.getAAFor<AAGlobalValueInfo>(
12162 *this, IRPosition::value(PotentialCallee), DepClassTy::OPTIONAL);
12163 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12164 return true;
12165 UsedAssumedInformation = !GIAA->isAtFixpoint();
12166 return false;
12167 };
12168
12169 auto AddPotentialCallees = [&]() {
12170 for (auto *PotentialCallee : PotentialCallees) {
12171 bool UsedAssumedInformation = false;
12172 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12173 AssumedCalleesNow.insert(PotentialCallee);
12174 }
12175 };
12176
12177 // Use simplification to find potential callees, if !callees was present,
12178 // fallback to that set if necessary.
12179 bool UsedAssumedInformation = false;
12181 if (!A.getAssumedSimplifiedValues(IRPosition::value(*FP), this, Values,
12182 AA::ValueScope::AnyScope,
12183 UsedAssumedInformation)) {
12184 if (PotentialCallees.empty())
12185 return indicatePessimisticFixpoint();
12186 AddPotentialCallees();
12187 }
12188
12189 // Try to find a reason for \p Fn not to be a potential callee. If none was
12190 // found, add it to the assumed callees set.
12191 auto CheckPotentialCallee = [&](Function &Fn) {
12192 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12193 return false;
12194
12195 auto &CachedResult = FilterResults[&Fn];
12196 if (CachedResult.has_value())
12197 return CachedResult.value();
12198
12199 bool UsedAssumedInformation = false;
12200 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12201 if (!UsedAssumedInformation)
12202 CachedResult = false;
12203 return false;
12204 }
12205
12206 int NumFnArgs = Fn.arg_size();
12207 int NumCBArgs = CB->arg_size();
12208
12209 // Check if any excess argument (which we fill up with poison) is known to
12210 // be UB on undef.
12211 for (int I = NumCBArgs; I < NumFnArgs; ++I) {
12212 bool IsKnown = false;
12214 A, this, IRPosition::argument(*Fn.getArg(I)),
12215 DepClassTy::OPTIONAL, IsKnown)) {
12216 if (IsKnown)
12217 CachedResult = false;
12218 return false;
12219 }
12220 }
12221
12222 CachedResult = true;
12223 return true;
12224 };
12225
12226 // Check simplification result, prune known UB callees, also restrict it to
12227 // the !callees set, if present.
12228 for (auto &VAC : Values) {
12229 if (isa<UndefValue>(VAC.getValue()))
12230 continue;
12232 VAC.getValue()->getType()->getPointerAddressSpace() == 0)
12233 continue;
12234 // TODO: Check for known UB, e.g., poison + noundef.
12235 if (auto *VACFn = dyn_cast<Function>(VAC.getValue())) {
12236 if (CheckPotentialCallee(*VACFn))
12237 AssumedCalleesNow.insert(VACFn);
12238 continue;
12239 }
12240 if (!PotentialCallees.empty()) {
12241 AddPotentialCallees();
12242 break;
12243 }
12244 AllCalleesKnownNow = false;
12245 }
12246
12247 if (AssumedCalleesNow == AssumedCallees &&
12248 AllCalleesKnown == AllCalleesKnownNow)
12249 return ChangeStatus::UNCHANGED;
12250
12251 std::swap(AssumedCallees, AssumedCalleesNow);
12252 AllCalleesKnown = AllCalleesKnownNow;
12253 return ChangeStatus::CHANGED;
12254 }
12255
12256 ChangeStatus manifest(Attributor &A) override {
12257 // If we can't specialize at all, give up now.
12258 if (!AllCalleesKnown && AssumedCallees.empty())
12259 return ChangeStatus::UNCHANGED;
12260
12261 CallBase *CB = cast<CallBase>(getCtxI());
12262 bool UsedAssumedInformation = false;
12263 if (A.isAssumedDead(*CB, this, /*LivenessAA=*/nullptr,
12264 UsedAssumedInformation))
12265 return ChangeStatus::UNCHANGED;
12266
12267 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12268 unsigned ProgramAS = CB->getDataLayout().getProgramAddressSpace();
12269 Value *FP = CB->getCalledOperand();
12270 if (FP->getType()->getPointerAddressSpace() != ProgramAS)
12271 FP = new AddrSpaceCastInst(
12272 FP, PointerType::get(FP->getContext(), ProgramAS),
12273 FP->getName() + ".as" + Twine(ProgramAS), CB->getIterator());
12274
12275 bool CBIsVoid = CB->getType()->isVoidTy();
12277 FunctionType *CSFT = CB->getFunctionType();
12278 SmallVector<Value *> CSArgs(CB->args());
12279
12280 // If we know all callees and there are none, the call site is (effectively)
12281 // dead (or UB).
12282 if (AssumedCallees.empty()) {
12283 assert(AllCalleesKnown &&
12284 "Expected all callees to be known if there are none.");
12285 A.changeToUnreachableAfterManifest(CB);
12286 return ChangeStatus::CHANGED;
12287 }
12288
12289 // Special handling for the single callee case.
12290 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12291 auto *NewCallee = AssumedCallees.front();
12292 if (isLegalToPromote(*CB, NewCallee)) {
12293 promoteCall(*CB, NewCallee, nullptr);
12294 NumIndirectCallsPromoted++;
12295 return ChangeStatus::CHANGED;
12296 }
12297 Instruction *NewCall =
12298 CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12299 CB->getName(), CB->getIterator());
12300 if (!CBIsVoid)
12301 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *NewCall);
12302 A.deleteAfterManifest(*CB);
12303 return ChangeStatus::CHANGED;
12304 }
12305
12306 // For each potential value we create a conditional
12307 //
12308 // ```
12309 // if (ptr == value) value(args);
12310 // else ...
12311 // ```
12312 //
12313 bool SpecializedForAnyCallees = false;
12314 bool SpecializedForAllCallees = AllCalleesKnown;
12315 ICmpInst *LastCmp = nullptr;
12316 SmallVector<Function *, 8> SkippedAssumedCallees;
12318 for (Function *NewCallee : AssumedCallees) {
12319 if (!A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,
12320 AssumedCallees.size())) {
12321 SkippedAssumedCallees.push_back(NewCallee);
12322 SpecializedForAllCallees = false;
12323 continue;
12324 }
12325 SpecializedForAnyCallees = true;
12326
12327 LastCmp = new ICmpInst(IP, llvm::CmpInst::ICMP_EQ, FP, NewCallee);
12328 Instruction *ThenTI =
12329 SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false);
12330 BasicBlock *CBBB = CB->getParent();
12331 A.registerManifestAddedBasicBlock(*ThenTI->getParent());
12332 A.registerManifestAddedBasicBlock(*IP->getParent());
12333 auto *SplitTI = cast<CondBrInst>(LastCmp->getNextNode());
12334 BasicBlock *ElseBB;
12335 if (&*IP == CB) {
12336 ElseBB = BasicBlock::Create(ThenTI->getContext(), "",
12337 ThenTI->getFunction(), CBBB);
12338 A.registerManifestAddedBasicBlock(*ElseBB);
12339 IP = UncondBrInst::Create(CBBB, ElseBB)->getIterator();
12340 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12341 } else {
12342 ElseBB = IP->getParent();
12343 ThenTI->replaceUsesOfWith(ElseBB, CBBB);
12344 }
12345 CastInst *RetBC = nullptr;
12346 CallInst *NewCall = nullptr;
12347 if (isLegalToPromote(*CB, NewCallee)) {
12348 auto *CBClone = cast<CallBase>(CB->clone());
12349 CBClone->insertBefore(ThenTI->getIterator());
12350 NewCall = &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));
12351 NumIndirectCallsPromoted++;
12352 } else {
12353 NewCall = CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12354 CB->getName(), ThenTI->getIterator());
12355 }
12356 NewCalls.push_back({NewCall, RetBC});
12357 }
12358
12359 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12360 if (!AllCalleesKnown)
12361 return ChangeStatus::UNCHANGED;
12362 MDBuilder MDB(IndirectCB.getContext());
12363 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12364 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12365 return ChangeStatus::CHANGED;
12366 };
12367
12368 if (!SpecializedForAnyCallees)
12369 return AttachCalleeMetadata(*CB);
12370
12371 // Check if we need the fallback indirect call still.
12372 if (SpecializedForAllCallees) {
12374 LastCmp->eraseFromParent();
12375 new UnreachableInst(IP->getContext(), IP);
12376 IP->eraseFromParent();
12377 } else {
12378 auto *CBClone = cast<CallInst>(CB->clone());
12379 CBClone->setName(CB->getName());
12380 CBClone->insertBefore(*IP->getParent(), IP);
12381 NewCalls.push_back({CBClone, nullptr});
12382 AttachCalleeMetadata(*CBClone);
12383 }
12384
12385 // Check if we need a PHI to merge the results.
12386 if (!CBIsVoid) {
12387 auto *PHI = PHINode::Create(CB->getType(), NewCalls.size(),
12388 CB->getName() + ".phi",
12389 CB->getParent()->getFirstInsertionPt());
12390 for (auto &It : NewCalls) {
12391 CallBase *NewCall = It.first;
12392 Instruction *CallRet = It.second ? It.second : It.first;
12393 if (CallRet->getType() == CB->getType())
12394 PHI->addIncoming(CallRet, CallRet->getParent());
12395 else if (NewCall->getType()->isVoidTy())
12396 PHI->addIncoming(PoisonValue::get(CB->getType()),
12397 NewCall->getParent());
12398 else
12399 llvm_unreachable("Call return should match or be void!");
12400 }
12401 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *PHI);
12402 }
12403
12404 A.deleteAfterManifest(*CB);
12405 Changed = ChangeStatus::CHANGED;
12406
12407 return Changed;
12408 }
12409
12410 const std::string getAsStr(Attributor *A) const override {
12411 return std::string(AllCalleesKnown ? "eliminate" : "specialize") +
12412 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12413 " functions";
12414 }
12415
12416 void trackStatistics() const override {
12417 if (AllCalleesKnown) {
12419 Eliminated, CallSites,
12420 "Number of indirect call sites eliminated via specialization")
12421 } else {
12422 STATS_DECLTRACK(Specialized, CallSites,
12423 "Number of indirect call sites specialized")
12424 }
12425 }
12426
12427 bool foreachCallee(function_ref<bool(Function *)> CB) const override {
12428 return isValidState() && AllCalleesKnown && all_of(AssumedCallees, CB);
12429 }
12430
12431private:
12432 /// Map to remember filter results.
12433 DenseMap<Function *, std::optional<bool>> FilterResults;
12434
12435 /// If the !callee metadata was present, this set will contain all potential
12436 /// callees (superset).
12437 SmallSetVector<Function *, 4> PotentialCallees;
12438
12439 /// This set contains all currently assumed calllees, which might grow over
12440 /// time.
12441 SmallSetVector<Function *, 4> AssumedCallees;
12442
12443 /// Flag to indicate if all possible callees are in the AssumedCallees set or
12444 /// if there could be others.
12445 bool AllCalleesKnown = true;
12446};
12447} // namespace
12448
12449/// --------------------- Invariant Load Pointer -------------------------------
12450namespace {
12451
12452struct AAInvariantLoadPointerImpl
12453 : public StateWrapper<BitIntegerState<uint8_t, 15>,
12454 AAInvariantLoadPointer> {
12455
12456 enum {
12457 // pointer does not alias within the bounds of the function
12458 IS_NOALIAS = 1 << 0,
12459 // pointer is not involved in any effectful instructions within the bounds
12460 // of the function
12461 IS_NOEFFECT = 1 << 1,
12462 // loads are invariant within the bounds of the function
12463 IS_LOCALLY_INVARIANT = 1 << 2,
12464 // memory lifetime is constrained within the bounds of the function
12465 IS_LOCALLY_CONSTRAINED = 1 << 3,
12466
12467 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12468 IS_LOCALLY_CONSTRAINED,
12469 };
12470 static_assert(getBestState() == IS_BEST_STATE, "Unexpected best state");
12471
12472 using Base =
12473 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12474
12475 // the BitIntegerState is optimistic about IS_NOALIAS and IS_NOEFFECT, but
12476 // pessimistic about IS_KNOWN_INVARIANT
12477 AAInvariantLoadPointerImpl(const IRPosition &IRP, Attributor &A)
12478 : Base(IRP) {}
12479
12480 bool isKnownInvariant() const final {
12481 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12482 }
12483
12484 bool isKnownLocallyInvariant() const final {
12485 if (isKnown(IS_LOCALLY_INVARIANT))
12486 return true;
12487 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12488 }
12489
12490 bool isAssumedInvariant() const final {
12491 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12492 }
12493
12494 bool isAssumedLocallyInvariant() const final {
12495 if (isAssumed(IS_LOCALLY_INVARIANT))
12496 return true;
12497 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12498 }
12499
12500 ChangeStatus updateImpl(Attributor &A) override {
12501 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12502
12503 Changed |= updateNoAlias(A);
12504 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12505 return indicatePessimisticFixpoint();
12506
12507 Changed |= updateNoEffect(A);
12508
12509 Changed |= updateLocalInvariance(A);
12510
12511 return Changed;
12512 }
12513
12514 ChangeStatus manifest(Attributor &A) override {
12515 if (!isKnownInvariant())
12516 return ChangeStatus::UNCHANGED;
12517
12518 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12519 const Value *Ptr = &getAssociatedValue();
12520 const auto TagInvariantLoads = [&](const Use &U, bool &) {
12521 if (U.get() != Ptr)
12522 return true;
12523 auto *I = dyn_cast<Instruction>(U.getUser());
12524 if (!I)
12525 return true;
12526
12527 // Ensure that we are only changing uses from the corresponding callgraph
12528 // SSC in the case that the AA isn't run on the entire module
12529 if (!A.isRunOn(I->getFunction()))
12530 return true;
12531
12532 if (I->hasMetadata(LLVMContext::MD_invariant_load))
12533 return true;
12534
12535 if (auto *LI = dyn_cast<LoadInst>(I)) {
12536 LI->setMetadata(LLVMContext::MD_invariant_load,
12537 MDNode::get(LI->getContext(), {}));
12538 Changed = ChangeStatus::CHANGED;
12539 }
12540 return true;
12541 };
12542
12543 (void)A.checkForAllUses(TagInvariantLoads, *this, *Ptr);
12544 return Changed;
12545 }
12546
12547 const std::string getAsStr(Attributor *) const override {
12548 if (isKnownInvariant())
12549 return "load-invariant pointer";
12550 return "non-invariant pointer";
12551 }
12552
12553 void trackStatistics() const override {}
12554
12555private:
12556 /// Indicate that noalias is required for the pointer to be invariant.
12557 bool requiresNoAlias() const {
12558 switch (getPositionKind()) {
12559 default:
12560 // Conservatively default to require noalias.
12561 return true;
12562 case IRP_FLOAT:
12563 case IRP_RETURNED:
12564 case IRP_CALL_SITE:
12565 return false;
12566 case IRP_CALL_SITE_RETURNED: {
12567 const auto &CB = cast<CallBase>(getAnchorValue());
12569 &CB, /*MustPreserveOffset=*/false);
12570 }
12571 case IRP_ARGUMENT: {
12572 const Function *F = getAssociatedFunction();
12573 assert(F && "no associated function for argument");
12574 return !isCallableCC(F->getCallingConv());
12575 }
12576 }
12577 }
12578
12579 bool isExternal() const {
12580 const Function *F = getAssociatedFunction();
12581 if (!F)
12582 return true;
12583 return isCallableCC(F->getCallingConv()) &&
12584 getPositionKind() != IRP_CALL_SITE_RETURNED;
12585 }
12586
12587 ChangeStatus updateNoAlias(Attributor &A) {
12588 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12589 return ChangeStatus::UNCHANGED;
12590
12591 // Try to use AANoAlias.
12592 if (const auto *ANoAlias = A.getOrCreateAAFor<AANoAlias>(
12593 getIRPosition(), this, DepClassTy::REQUIRED)) {
12594 if (ANoAlias->isKnownNoAlias()) {
12595 addKnownBits(IS_NOALIAS);
12596 return ChangeStatus::CHANGED;
12597 }
12598
12599 if (!ANoAlias->isAssumedNoAlias()) {
12600 removeAssumedBits(IS_NOALIAS);
12601 return ChangeStatus::CHANGED;
12602 }
12603
12604 return ChangeStatus::UNCHANGED;
12605 }
12606
12607 // Try to infer noalias from argument attribute, since it is applicable for
12608 // the duration of the function.
12609 if (const Argument *Arg = getAssociatedArgument()) {
12610 if (Arg->hasNoAliasAttr()) {
12611 addKnownBits(IS_NOALIAS);
12612 return ChangeStatus::UNCHANGED;
12613 }
12614
12615 // Noalias information is not provided, and cannot be inferred,
12616 // so we conservatively assume the pointer aliases.
12617 removeAssumedBits(IS_NOALIAS);
12618 return ChangeStatus::CHANGED;
12619 }
12620
12621 return ChangeStatus::UNCHANGED;
12622 }
12623
12624 ChangeStatus updateNoEffect(Attributor &A) {
12625 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12626 return ChangeStatus::UNCHANGED;
12627
12628 if (!getAssociatedFunction())
12629 return indicatePessimisticFixpoint();
12630
12631 if (isa<AllocaInst>(&getAssociatedValue()))
12632 return indicatePessimisticFixpoint();
12633
12634 const auto HasNoEffectLoads = [&](const Use &U, bool &) {
12635 const auto *LI = dyn_cast<LoadInst>(U.getUser());
12636 return !LI || !LI->mayHaveSideEffects();
12637 };
12638 if (!A.checkForAllUses(HasNoEffectLoads, *this, getAssociatedValue()))
12639 return indicatePessimisticFixpoint();
12640
12641 if (const auto *AMemoryBehavior = A.getOrCreateAAFor<AAMemoryBehavior>(
12642 getIRPosition(), this, DepClassTy::REQUIRED)) {
12643 // For non-instructions, try to use AAMemoryBehavior to infer the readonly
12644 // attribute
12645 if (!AMemoryBehavior->isAssumedReadOnly())
12646 return indicatePessimisticFixpoint();
12647
12648 if (AMemoryBehavior->isKnownReadOnly()) {
12649 addKnownBits(IS_NOEFFECT);
12650 return ChangeStatus::UNCHANGED;
12651 }
12652
12653 return ChangeStatus::UNCHANGED;
12654 }
12655
12656 if (const Argument *Arg = getAssociatedArgument()) {
12657 if (Arg->onlyReadsMemory()) {
12658 addKnownBits(IS_NOEFFECT);
12659 return ChangeStatus::UNCHANGED;
12660 }
12661
12662 // Readonly information is not provided, and cannot be inferred from
12663 // AAMemoryBehavior.
12664 return indicatePessimisticFixpoint();
12665 }
12666
12667 return ChangeStatus::UNCHANGED;
12668 }
12669
12670 ChangeStatus updateLocalInvariance(Attributor &A) {
12671 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12672 return ChangeStatus::UNCHANGED;
12673
12674 // try to infer invariance from underlying objects
12675 const auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
12676 getIRPosition(), this, DepClassTy::REQUIRED);
12677 if (!AUO)
12678 return ChangeStatus::UNCHANGED;
12679
12680 bool UsedAssumedInformation = false;
12681 const auto IsLocallyInvariantLoadIfPointer = [&](const Value &V) {
12682 if (!V.getType()->isPointerTy())
12683 return true;
12684 const auto *IsInvariantLoadPointer =
12685 A.getOrCreateAAFor<AAInvariantLoadPointer>(IRPosition::value(V), this,
12686 DepClassTy::REQUIRED);
12687 // Conservatively fail if invariance cannot be inferred.
12688 if (!IsInvariantLoadPointer)
12689 return false;
12690
12691 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12692 return true;
12693 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12694 return false;
12695
12696 UsedAssumedInformation = true;
12697 return true;
12698 };
12699 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12700 return indicatePessimisticFixpoint();
12701
12702 if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue())) {
12704 CB, /*MustPreserveOffset=*/false)) {
12705 for (const Value *Arg : CB->args()) {
12706 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12707 return indicatePessimisticFixpoint();
12708 }
12709 }
12710 }
12711
12712 if (!UsedAssumedInformation) {
12713 // Pointer is known and not just assumed to be locally invariant.
12714 addKnownBits(IS_LOCALLY_INVARIANT);
12715 return ChangeStatus::CHANGED;
12716 }
12717
12718 return ChangeStatus::UNCHANGED;
12719 }
12720};
12721
12722struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12723 AAInvariantLoadPointerFloating(const IRPosition &IRP, Attributor &A)
12724 : AAInvariantLoadPointerImpl(IRP, A) {}
12725};
12726
12727struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12728 AAInvariantLoadPointerReturned(const IRPosition &IRP, Attributor &A)
12729 : AAInvariantLoadPointerImpl(IRP, A) {}
12730
12731 void initialize(Attributor &) override {
12732 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12733 }
12734};
12735
12736struct AAInvariantLoadPointerCallSiteReturned final
12737 : AAInvariantLoadPointerImpl {
12738 AAInvariantLoadPointerCallSiteReturned(const IRPosition &IRP, Attributor &A)
12739 : AAInvariantLoadPointerImpl(IRP, A) {}
12740
12741 void initialize(Attributor &A) override {
12742 // Nothing is known about the result of an indirect call.
12743 const Function *F = getAssociatedFunction();
12744 if (!F) {
12745 indicatePessimisticFixpoint();
12746 return;
12747 }
12748
12749 if (!F->isDeclaration() && !F->isIntrinsic())
12750 return AAInvariantLoadPointerImpl::initialize(A);
12751
12752 const auto &CB = cast<CallBase>(getAnchorValue());
12754 &CB, /*MustPreserveOffset=*/false))
12755 return AAInvariantLoadPointerImpl::initialize(A);
12756
12757 if (F->onlyReadsMemory() && F->hasNoSync())
12758 return AAInvariantLoadPointerImpl::initialize(A);
12759
12760 // At this point, the function is opaque, so we conservatively assume
12761 // non-invariance.
12762 indicatePessimisticFixpoint();
12763 }
12764};
12765
12766struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12767 AAInvariantLoadPointerArgument(const IRPosition &IRP, Attributor &A)
12768 : AAInvariantLoadPointerImpl(IRP, A) {}
12769
12770 void initialize(Attributor &) override {
12771 const Function *F = getAssociatedFunction();
12772 assert(F && "no associated function for argument");
12773
12774 if (!isCallableCC(F->getCallingConv())) {
12775 addKnownBits(IS_LOCALLY_CONSTRAINED);
12776 return;
12777 }
12778
12779 if (!F->hasLocalLinkage())
12780 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12781 }
12782};
12783
12784struct AAInvariantLoadPointerCallSiteArgument final
12785 : AAInvariantLoadPointerImpl {
12786 AAInvariantLoadPointerCallSiteArgument(const IRPosition &IRP, Attributor &A)
12787 : AAInvariantLoadPointerImpl(IRP, A) {}
12788};
12789} // namespace
12790
12791/// ------------------------ Address Space ------------------------------------
12792namespace {
12793
12794template <typename InstType>
12795static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,
12796 Value *OriginalValue, PointerType *NewPtrTy,
12797 bool UseOriginalValue) {
12798 if (U.getOperandNo() != InstType::getPointerOperandIndex())
12799 return false;
12800
12801 if (MemInst->isVolatile()) {
12802 auto *TTI = A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12803 *MemInst->getFunction());
12804 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12805 if (!TTI || !TTI->hasVolatileVariant(MemInst, NewAS))
12806 return false;
12807 }
12808
12809 if (UseOriginalValue) {
12810 A.changeUseAfterManifest(const_cast<Use &>(U), *OriginalValue);
12811 return true;
12812 }
12813
12814 Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12815 CastInst->insertBefore(MemInst->getIterator());
12816 A.changeUseAfterManifest(const_cast<Use &>(U), *CastInst);
12817 return true;
12818}
12819
12820struct AAAddressSpaceImpl : public AAAddressSpace {
12821 AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)
12822 : AAAddressSpace(IRP, A) {}
12823
12824 uint32_t getAddressSpace() const override {
12825 assert(isValidState() && "the AA is invalid");
12826 return AssumedAddressSpace;
12827 }
12828
12829 void initialize(Attributor &A) override {
12830 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
12831 "Associated value is not a pointer");
12832
12833 if (!A.getInfoCache().getFlatAddressSpace().has_value()) {
12834 indicatePessimisticFixpoint();
12835 return;
12836 }
12837
12838 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12839 unsigned AS = getAssociatedType()->getPointerAddressSpace();
12840 if (AS != FlatAS) {
12841 [[maybe_unused]] bool R = takeAddressSpace(AS);
12842 assert(R && "The take should happen");
12843 indicateOptimisticFixpoint();
12844 }
12845 }
12846
12847 ChangeStatus updateImpl(Attributor &A) override {
12848 uint32_t OldAddressSpace = AssumedAddressSpace;
12849 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12850
12851 auto CheckAddressSpace = [&](Value &Obj) {
12852 // Ignore undef.
12853 if (isa<UndefValue>(&Obj))
12854 return true;
12855
12856 // If the object already has a non-flat address space, we simply take it.
12857 unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
12858 if (ObjAS != FlatAS)
12859 return takeAddressSpace(ObjAS);
12860
12861 // At this point, we know Obj is in the flat address space. For a final
12862 // attempt, we want to use getAssumedAddrSpace, but first we must get the
12863 // associated function, if possible.
12864 Function *F = nullptr;
12865 if (auto *Arg = dyn_cast<Argument>(&Obj))
12866 F = Arg->getParent();
12867 else if (auto *I = dyn_cast<Instruction>(&Obj))
12868 F = I->getFunction();
12869
12870 // Use getAssumedAddrSpace if the associated function exists.
12871 if (F) {
12872 auto *TTI =
12873 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
12874 unsigned AssumedAS = TTI->getAssumedAddrSpace(&Obj);
12875 if (AssumedAS != ~0U)
12876 return takeAddressSpace(AssumedAS);
12877 }
12878
12879 // Now we can't do anything else but to take the flat AS.
12880 return takeAddressSpace(FlatAS);
12881 };
12882
12883 auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this,
12884 DepClassTy::REQUIRED);
12885 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
12886 return indicatePessimisticFixpoint();
12887
12888 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
12889 : ChangeStatus::CHANGED;
12890 }
12891
12892 ChangeStatus manifest(Attributor &A) override {
12893 unsigned NewAS = getAddressSpace();
12894
12895 if (NewAS == InvalidAddressSpace ||
12896 NewAS == getAssociatedType()->getPointerAddressSpace())
12897 return ChangeStatus::UNCHANGED;
12898
12899 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
12900
12901 Value *AssociatedValue = &getAssociatedValue();
12902 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
12903
12904 PointerType *NewPtrTy =
12905 PointerType::get(getAssociatedType()->getContext(), NewAS);
12906 bool UseOriginalValue =
12907 OriginalValue->getType()->getPointerAddressSpace() == NewAS;
12908
12909 bool Changed = false;
12910
12911 auto Pred = [&](const Use &U, bool &) {
12912 if (U.get() != AssociatedValue)
12913 return true;
12914 auto *Inst = dyn_cast<Instruction>(U.getUser());
12915 if (!Inst)
12916 return true;
12917 // This is a WA to make sure we only change uses from the corresponding
12918 // CGSCC if the AA is run on CGSCC instead of the entire module.
12919 if (!A.isRunOn(Inst->getFunction()))
12920 return true;
12921 if (auto *LI = dyn_cast<LoadInst>(Inst)) {
12922 Changed |=
12923 makeChange(A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12924 } else if (auto *SI = dyn_cast<StoreInst>(Inst)) {
12925 Changed |=
12926 makeChange(A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12927 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Inst)) {
12928 Changed |=
12929 makeChange(A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
12930 } else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Inst)) {
12931 Changed |=
12932 makeChange(A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
12933 }
12934 return true;
12935 };
12936
12937 // It doesn't matter if we can't check all uses as we can simply
12938 // conservatively ignore those that can not be visited.
12939 (void)A.checkForAllUses(Pred, *this, getAssociatedValue(),
12940 /* CheckBBLivenessOnly */ true);
12941
12942 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12943 }
12944
12945 const std::string getAsStr(Attributor *A) const override {
12946 if (!isValidState())
12947 return "addrspace(<invalid>)";
12948 return "addrspace(" +
12949 (AssumedAddressSpace == InvalidAddressSpace
12950 ? "none"
12951 : std::to_string(AssumedAddressSpace)) +
12952 ")";
12953 }
12954
12955private:
12956 uint32_t AssumedAddressSpace = InvalidAddressSpace;
12957
12958 bool takeAddressSpace(uint32_t AS) {
12959 if (AssumedAddressSpace == InvalidAddressSpace) {
12960 AssumedAddressSpace = AS;
12961 return true;
12962 }
12963 return AssumedAddressSpace == AS;
12964 }
12965
12966 static Value *peelAddrspacecast(Value *V, unsigned FlatAS) {
12967 if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) {
12968 assert(I->getSrcAddressSpace() != FlatAS &&
12969 "there should not be flat AS -> non-flat AS");
12970 return I->getPointerOperand();
12971 }
12972 if (auto *C = dyn_cast<ConstantExpr>(V))
12973 if (C->getOpcode() == Instruction::AddrSpaceCast) {
12974 assert(C->getOperand(0)->getType()->getPointerAddressSpace() !=
12975 FlatAS &&
12976 "there should not be flat AS -> non-flat AS X");
12977 return C->getOperand(0);
12978 }
12979 return V;
12980 }
12981};
12982
12983struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
12984 AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)
12985 : AAAddressSpaceImpl(IRP, A) {}
12986
12987 void trackStatistics() const override {
12989 }
12990};
12991
12992struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
12993 AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)
12994 : AAAddressSpaceImpl(IRP, A) {}
12995
12996 void initialize(Attributor &A) override {
12997 // TODO: we don't rewrite function argument for now because it will need to
12998 // rewrite the function signature and all call sites.
12999 (void)indicatePessimisticFixpoint();
13000 }
13001
13002 void trackStatistics() const override {
13003 STATS_DECLTRACK_FNRET_ATTR(addrspace);
13004 }
13005};
13006
13007struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13008 AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13009 : AAAddressSpaceImpl(IRP, A) {}
13010
13011 void trackStatistics() const override {
13012 STATS_DECLTRACK_CSRET_ATTR(addrspace);
13013 }
13014};
13015
13016struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13017 AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)
13018 : AAAddressSpaceImpl(IRP, A) {}
13019
13020 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }
13021};
13022
13023struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13024 AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13025 : AAAddressSpaceImpl(IRP, A) {}
13026
13027 void initialize(Attributor &A) override {
13028 // TODO: we don't rewrite call site argument for now because it will need to
13029 // rewrite the function signature of the callee.
13030 (void)indicatePessimisticFixpoint();
13031 }
13032
13033 void trackStatistics() const override {
13034 STATS_DECLTRACK_CSARG_ATTR(addrspace);
13035 }
13036};
13037} // namespace
13038
13039/// ------------------------ No Alias Address Space ---------------------------
13040// This attribute assumes flat address space can alias all other address space
13041
13042// TODO: this is similar to AAAddressSpace, most of the code should be merged.
13043// But merging it created failing cased on gateway test that cannot be
13044// reproduced locally. So should open a separated PR to handle the merge of
13045// AANoAliasAddrSpace and AAAddressSpace attribute
13046
13047namespace {
13048struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {
13049 AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)
13050 : AANoAliasAddrSpace(IRP, A) {}
13051
13052 void initialize(Attributor &A) override {
13053 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13054 "Associated value is not a pointer");
13055
13056 resetASRanges(A);
13057
13058 std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();
13059 if (!FlatAS.has_value()) {
13060 indicatePessimisticFixpoint();
13061 return;
13062 }
13063
13064 removeAS(*FlatAS);
13065
13066 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13067 if (AS != *FlatAS) {
13068 removeAS(AS);
13069 indicateOptimisticFixpoint();
13070 }
13071 }
13072
13073 ChangeStatus updateImpl(Attributor &A) override {
13074 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13075 uint32_t OldAssumed = getAssumed();
13076
13077 auto CheckAddressSpace = [&](Value &Obj) {
13078 if (isa<PoisonValue>(&Obj))
13079 return true;
13080
13081 unsigned AS = Obj.getType()->getPointerAddressSpace();
13082 if (AS == FlatAS)
13083 return false;
13084
13085 removeAS(Obj.getType()->getPointerAddressSpace());
13086 return true;
13087 };
13088
13089 const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
13090 getIRPosition(), this, DepClassTy::REQUIRED);
13091 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13092 return indicatePessimisticFixpoint();
13093
13094 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13095 : ChangeStatus::CHANGED;
13096 }
13097
13098 ChangeStatus manifest(Attributor &A) override {
13099 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13100
13101 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13102 if (AS != FlatAS || Map.empty())
13103 return ChangeStatus::UNCHANGED;
13104
13105 LLVMContext &Ctx = getAssociatedValue().getContext();
13106 MDNode *NoAliasASNode = nullptr;
13107 MDBuilder MDB(Ctx);
13108 // Has to use iterator to get the range info.
13109 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13110 if (!I.value())
13111 continue;
13112 unsigned Upper = I.stop();
13113 unsigned Lower = I.start();
13114 if (!NoAliasASNode) {
13115 NoAliasASNode = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13116 continue;
13117 }
13118 MDNode *ASRange = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13119 NoAliasASNode = MDNode::getMostGenericRange(NoAliasASNode, ASRange);
13120 }
13121
13122 Value *AssociatedValue = &getAssociatedValue();
13123 bool Changed = false;
13124
13125 auto AddNoAliasAttr = [&](const Use &U, bool &) {
13126 if (U.get() != AssociatedValue)
13127 return true;
13128 Instruction *Inst = dyn_cast<Instruction>(U.getUser());
13129 if (!Inst || Inst->hasMetadata(LLVMContext::MD_noalias_addrspace))
13130 return true;
13131 if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst) &&
13133 return true;
13134 if (!A.isRunOn(Inst->getFunction()))
13135 return true;
13136 Inst->setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13137 Changed = true;
13138 return true;
13139 };
13140 (void)A.checkForAllUses(AddNoAliasAttr, *this, *AssociatedValue,
13141 /*CheckBBLivenessOnly=*/true);
13142 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13143 }
13144
13145 const std::string getAsStr(Attributor *A) const override {
13146 if (!isValidState())
13147 return "<invalid>";
13148 std::string Str;
13149 raw_string_ostream OS(Str);
13150 OS << "CanNotBeAddrSpace(";
13151 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13152 unsigned Upper = I.stop();
13153 unsigned Lower = I.start();
13154 OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';
13155 }
13156 OS << " )";
13157 return OS.str();
13158 }
13159
13160private:
13161 void removeAS(unsigned AS) {
13162 RangeMap::iterator I = Map.find(AS);
13163
13164 if (I != Map.end()) {
13165 unsigned Upper = I.stop();
13166 unsigned Lower = I.start();
13167 I.erase();
13168 if (Upper == Lower)
13169 return;
13170 if (AS != ~((unsigned)0) && AS + 1 <= Upper)
13171 Map.insert(AS + 1, Upper, /*what ever this variable name is=*/true);
13172 if (AS != 0 && Lower <= AS - 1)
13173 Map.insert(Lower, AS - 1, true);
13174 }
13175 }
13176
13177 void resetASRanges(Attributor &A) {
13178 Map.clear();
13179 Map.insert(0, A.getInfoCache().getMaxAddrSpace(), true);
13180 }
13181};
13182
13183struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13184 AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)
13185 : AANoAliasAddrSpaceImpl(IRP, A) {}
13186
13187 void trackStatistics() const override {
13188 STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);
13189 }
13190};
13191
13192struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13193 AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)
13194 : AANoAliasAddrSpaceImpl(IRP, A) {}
13195
13196 void trackStatistics() const override {
13197 STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);
13198 }
13199};
13200
13201struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13202 AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13203 : AANoAliasAddrSpaceImpl(IRP, A) {}
13204
13205 void trackStatistics() const override {
13206 STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);
13207 }
13208};
13209
13210struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13211 AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)
13212 : AANoAliasAddrSpaceImpl(IRP, A) {}
13213
13214 void trackStatistics() const override {
13215 STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);
13216 }
13217};
13218
13219struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13220 AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13221 : AANoAliasAddrSpaceImpl(IRP, A) {}
13222
13223 void trackStatistics() const override {
13224 STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);
13225 }
13226};
13227} // namespace
13228/// ----------- Allocation Info ----------
13229namespace {
13230struct AAAllocationInfoImpl : public AAAllocationInfo {
13231 AAAllocationInfoImpl(const IRPosition &IRP, Attributor &A)
13232 : AAAllocationInfo(IRP, A) {}
13233
13234 std::optional<TypeSize> getAllocatedSize() const override {
13235 assert(isValidState() && "the AA is invalid");
13236 return AssumedAllocatedSize;
13237 }
13238
13239 std::optional<TypeSize> findInitialAllocationSize(Instruction *I,
13240 const DataLayout &DL) {
13241
13242 // TODO: implement case for malloc like instructions
13243 switch (I->getOpcode()) {
13244 case Instruction::Alloca: {
13245 AllocaInst *AI = cast<AllocaInst>(I);
13246 return AI->getAllocationSize(DL);
13247 }
13248 default:
13249 return std::nullopt;
13250 }
13251 }
13252
13253 ChangeStatus updateImpl(Attributor &A) override {
13254
13255 const IRPosition &IRP = getIRPosition();
13256 Instruction *I = IRP.getCtxI();
13257
13258 // TODO: update check for malloc like calls
13259 if (!isa<AllocaInst>(I))
13260 return indicatePessimisticFixpoint();
13261
13262 bool IsKnownNoCapture;
13264 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13265 return indicatePessimisticFixpoint();
13266
13267 const AAPointerInfo *PI =
13268 A.getOrCreateAAFor<AAPointerInfo>(IRP, *this, DepClassTy::REQUIRED);
13269
13270 if (!PI)
13271 return indicatePessimisticFixpoint();
13272
13273 if (!PI->getState().isValidState() || PI->reachesReturn())
13274 return indicatePessimisticFixpoint();
13275
13276 const DataLayout &DL = A.getDataLayout();
13277 const auto AllocationSize = findInitialAllocationSize(I, DL);
13278
13279 // If allocation size is nullopt, we give up.
13280 if (!AllocationSize)
13281 return indicatePessimisticFixpoint();
13282
13283 // For zero sized allocations, we give up.
13284 // Since we can't reduce further
13285 if (*AllocationSize == 0)
13286 return indicatePessimisticFixpoint();
13287
13288 int64_t BinSize = PI->numOffsetBins();
13289
13290 // TODO: implement for multiple bins
13291 if (BinSize > 1)
13292 return indicatePessimisticFixpoint();
13293
13294 if (BinSize == 0) {
13295 auto NewAllocationSize = std::make_optional<TypeSize>(0, false);
13296 if (!changeAllocationSize(NewAllocationSize))
13297 return ChangeStatus::UNCHANGED;
13298 return ChangeStatus::CHANGED;
13299 }
13300
13301 // TODO: refactor this to be part of multiple bin case
13302 const auto &It = PI->begin();
13303
13304 // TODO: handle if Offset is not zero
13305 if (It->first.Offset != 0)
13306 return indicatePessimisticFixpoint();
13307
13308 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13309
13310 if (SizeOfBin >= *AllocationSize)
13311 return indicatePessimisticFixpoint();
13312
13313 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8, false);
13314
13315 if (!changeAllocationSize(NewAllocationSize))
13316 return ChangeStatus::UNCHANGED;
13317
13318 return ChangeStatus::CHANGED;
13319 }
13320
13321 ChangeStatus manifest(Attributor &A) override {
13322
13323 assert(isValidState() &&
13324 "Manifest should only be called if the state is valid.");
13325
13326 Instruction *I = getIRPosition().getCtxI();
13327
13328 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13329
13330 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13331
13332 switch (I->getOpcode()) {
13333 // TODO: add case for malloc like calls
13334 case Instruction::Alloca: {
13335
13336 AllocaInst *AI = cast<AllocaInst>(I);
13337
13338 Type *CharType = Type::getInt8Ty(I->getContext());
13339
13340 auto *NumBytesToValue =
13341 ConstantInt::get(I->getContext(), APInt(32, NumBytesToAllocate));
13342
13343 BasicBlock::iterator insertPt = AI->getIterator();
13344 insertPt = std::next(insertPt);
13345 AllocaInst *NewAllocaInst =
13346 new AllocaInst(CharType, AI->getAddressSpace(), NumBytesToValue,
13347 AI->getAlign(), AI->getName(), insertPt);
13348
13349 if (A.changeAfterManifest(IRPosition::inst(*AI), *NewAllocaInst))
13350 return ChangeStatus::CHANGED;
13351
13352 break;
13353 }
13354 default:
13355 break;
13356 }
13357
13358 return ChangeStatus::UNCHANGED;
13359 }
13360
13361 const std::string getAsStr(Attributor *A) const override {
13362 if (!isValidState())
13363 return "allocationinfo(<invalid>)";
13364 return "allocationinfo(" +
13365 (AssumedAllocatedSize == HasNoAllocationSize
13366 ? "none"
13367 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13368 ")";
13369 }
13370
13371private:
13372 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13373
13374 // Maintain the computed allocation size of the object.
13375 // Returns (bool) weather the size of the allocation was modified or not.
13376 bool changeAllocationSize(std::optional<TypeSize> Size) {
13377 if (AssumedAllocatedSize == HasNoAllocationSize ||
13378 AssumedAllocatedSize != Size) {
13379 AssumedAllocatedSize = Size;
13380 return true;
13381 }
13382 return false;
13383 }
13384};
13385
13386struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13387 AAAllocationInfoFloating(const IRPosition &IRP, Attributor &A)
13388 : AAAllocationInfoImpl(IRP, A) {}
13389
13390 void trackStatistics() const override {
13391 STATS_DECLTRACK_FLOATING_ATTR(allocationinfo);
13392 }
13393};
13394
13395struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13396 AAAllocationInfoReturned(const IRPosition &IRP, Attributor &A)
13397 : AAAllocationInfoImpl(IRP, A) {}
13398
13399 void initialize(Attributor &A) override {
13400 // TODO: we don't rewrite function argument for now because it will need to
13401 // rewrite the function signature and all call sites
13402 (void)indicatePessimisticFixpoint();
13403 }
13404
13405 void trackStatistics() const override {
13406 STATS_DECLTRACK_FNRET_ATTR(allocationinfo);
13407 }
13408};
13409
13410struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13411 AAAllocationInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
13412 : AAAllocationInfoImpl(IRP, A) {}
13413
13414 void trackStatistics() const override {
13415 STATS_DECLTRACK_CSRET_ATTR(allocationinfo);
13416 }
13417};
13418
13419struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13420 AAAllocationInfoArgument(const IRPosition &IRP, Attributor &A)
13421 : AAAllocationInfoImpl(IRP, A) {}
13422
13423 void trackStatistics() const override {
13424 STATS_DECLTRACK_ARG_ATTR(allocationinfo);
13425 }
13426};
13427
13428struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13429 AAAllocationInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
13430 : AAAllocationInfoImpl(IRP, A) {}
13431
13432 void initialize(Attributor &A) override {
13433
13434 (void)indicatePessimisticFixpoint();
13435 }
13436
13437 void trackStatistics() const override {
13438 STATS_DECLTRACK_CSARG_ATTR(allocationinfo);
13439 }
13440};
13441} // namespace
13442
13443const char AANoUnwind::ID = 0;
13444const char AANoSync::ID = 0;
13445const char AANoFree::ID = 0;
13446const char AANonNull::ID = 0;
13447const char AAMustProgress::ID = 0;
13448const char AANoRecurse::ID = 0;
13449const char AANonConvergent::ID = 0;
13450const char AAWillReturn::ID = 0;
13451const char AAUndefinedBehavior::ID = 0;
13452const char AANoAlias::ID = 0;
13453const char AAIntraFnReachability::ID = 0;
13454const char AANoReturn::ID = 0;
13455const char AAIsDead::ID = 0;
13456const char AADereferenceable::ID = 0;
13457const char AAAlign::ID = 0;
13458const char AAInstanceInfo::ID = 0;
13459const char AANoCapture::ID = 0;
13460const char AAValueSimplify::ID = 0;
13461const char AAHeapToStack::ID = 0;
13462const char AAPrivatizablePtr::ID = 0;
13463const char AAMemoryBehavior::ID = 0;
13464const char AAMemoryLocation::ID = 0;
13465const char AAValueConstantRange::ID = 0;
13466const char AAPotentialConstantValues::ID = 0;
13467const char AAPotentialValues::ID = 0;
13468const char AANoUndef::ID = 0;
13469const char AANoFPClass::ID = 0;
13470const char AACallEdges::ID = 0;
13471const char AAInterFnReachability::ID = 0;
13472const char AAPointerInfo::ID = 0;
13473const char AAAssumptionInfo::ID = 0;
13474const char AAUnderlyingObjects::ID = 0;
13475const char AAInvariantLoadPointer::ID = 0;
13476const char AAAddressSpace::ID = 0;
13477const char AANoAliasAddrSpace::ID = 0;
13478const char AAAllocationInfo::ID = 0;
13479const char AAIndirectCallInfo::ID = 0;
13480const char AAGlobalValueInfo::ID = 0;
13481const char AADenormalFPMath::ID = 0;
13482
13483// Macro magic to create the static generator function for attributes that
13484// follow the naming scheme.
13485
13486#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13487 case IRPosition::PK: \
13488 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13489
13490#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13491 case IRPosition::PK: \
13492 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13493 ++NumAAs; \
13494 break;
13495
13496#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13497 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13498 CLASS *AA = nullptr; \
13499 switch (IRP.getPositionKind()) { \
13500 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13501 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13502 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13503 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13504 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13505 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13506 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13507 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13508 } \
13509 return *AA; \
13510 }
13511
13512#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13513 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13514 CLASS *AA = nullptr; \
13515 switch (IRP.getPositionKind()) { \
13516 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13517 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13518 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13519 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13520 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13521 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13522 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13523 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13524 } \
13525 return *AA; \
13526 }
13527
13528#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13529 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13530 CLASS *AA = nullptr; \
13531 switch (IRP.getPositionKind()) { \
13532 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13533 default: \
13534 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13535 " position!"); \
13536 } \
13537 return *AA; \
13538 }
13539
13540#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13541 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13542 CLASS *AA = nullptr; \
13543 switch (IRP.getPositionKind()) { \
13544 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13545 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13546 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13547 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13548 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13549 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13550 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13551 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13552 } \
13553 return *AA; \
13554 }
13555
13556#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13557 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13558 CLASS *AA = nullptr; \
13559 switch (IRP.getPositionKind()) { \
13560 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13561 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13562 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13563 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13564 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13565 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13566 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13567 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13568 } \
13569 return *AA; \
13570 }
13571
13572#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13573 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13574 CLASS *AA = nullptr; \
13575 switch (IRP.getPositionKind()) { \
13576 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13577 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
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_CALL_SITE_RETURNED, CallSiteReturned) \
13583 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13584 } \
13585 return *AA; \
13586 }
13587
13597
13615
13620
13625
13632
13634
13635#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13636#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13637#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13638#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13639#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13640#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13641#undef SWITCH_PK_CREATE
13642#undef SWITCH_PK_INV
#define Success
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
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 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)
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 * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2092
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:470
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2909
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.
bool mayReadOrWriteMemory() const
Return true if this instruction may read or write memory.
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.
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:79
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:549
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:315
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
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:164
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:326
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:165
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:185
@ Intraprocedural
Definition Attributor.h:186
@ Interprocedural
Definition Attributor.h:187
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:388
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:1721
@ 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:376
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:476
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:488
@ NONE
Do not track a dependence between source and target.
Definition Attributor.h:489
@ REQUIRED
The target cannot be valid if the source is not.
Definition Attributor.h:487
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:244
static constexpr int64_t Unknown
Definition Attributor.h:323
static RangeTy getUnknown()
Definition Attributor.h:250
Value * getValue() const
Definition Attributor.h:197
const Instruction * getCtxI() const
Definition Attributor.h:198
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:572
Function * getAssociatedFunction() const
Return the associated function, if any.
Definition Attributor.h:703
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
Definition Attributor.h:640
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
Definition Attributor.h:622
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:596
CallBase CallBaseContext
Definition Attributor.h:575
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
Definition Attributor.h:790
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
Definition Attributor.h:608
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
Definition Attributor.h:645
Kind
The positions we distinguish in the IR.
Definition Attributor.h:578
@ IRP_ARGUMENT
An attribute for a function argument.
Definition Attributor.h:586
@ IRP_RETURNED
An attribute for the function return value.
Definition Attributor.h:582
@ IRP_CALL_SITE
An attribute for a call site (function scope).
Definition Attributor.h:585
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
Definition Attributor.h:583
@ IRP_FUNCTION
An attribute for a function (scope).
Definition Attributor.h:584
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
Definition Attributor.h:587
@ IRP_INVALID
An invalid position.
Definition Attributor.h:579
Instruction * getCtxI() const
Return the context instruction, if any.
Definition Attributor.h:756
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
Definition Attributor.h:629
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
Definition Attributor.h:779
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
Definition Attributor.h:615
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Definition Attributor.h:896
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Definition Attributor.h:770
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
Definition Attributor.h:689
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
Definition Attributor.h:799
static const IRPosition function_scope(const IRPosition &IRP, const CallBaseContext *CBContext=nullptr)
Create a position with function scope matching the "context" of IRP.
Definition Attributor.h:668
Kind getPositionKind() const
Return the associated position kind.
Definition Attributor.h:846
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
Definition Attributor.h:878
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Definition Attributor.h:635
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
Definition Attributor.h:744
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.